diff --git a/backend/internal/database/keys.go b/backend/internal/database/keys.go index 5c224bc2..b61a7474 100644 --- a/backend/internal/database/keys.go +++ b/backend/internal/database/keys.go @@ -147,29 +147,32 @@ func (db *Database) CountAPIKeys() (int, error) { // reads this at pool creation time; runtime changes require pool recreation // (restart Orva, or wait for the pool to be torn down). type PoolConfig struct { - FunctionID string `json:"function_id"` - MinWarm int `json:"min_warm"` - MaxWarm int `json:"max_warm"` - IdleTTLS int `json:"idle_ttl_seconds"` - TargetConcurrency int `json:"target_concurrency"` // req/worker before scale-up considered (Knative-style) - ScaleToZero bool `json:"scale_to_zero"` // if true, scale down to 0 when idle (cold-start on next req) + FunctionID string `json:"function_id"` + MinWarm int `json:"min_warm"` + MaxWarm int `json:"max_warm"` + IdleTTLS int `json:"idle_ttl_seconds"` + ScaleToZero bool `json:"scale_to_zero"` } func (db *Database) UpsertPoolConfig(cfg *PoolConfig) error { + if cfg.ScaleToZero { + cfg.MinWarm = 0 + } else if cfg.MinWarm < 1 { + cfg.MinWarm = 1 + } sc := 0 if cfg.ScaleToZero { sc = 1 } _, err := db.write.Exec(` - INSERT INTO pool_config (function_id, min_warm, max_warm, idle_ttl_s, target_concurrency, scale_to_zero) - VALUES (?, ?, ?, ?, ?, ?) + INSERT INTO pool_config (function_id, min_warm, max_warm, idle_ttl_s, scale_to_zero) + VALUES (?, ?, ?, ?, ?) ON CONFLICT(function_id) DO UPDATE SET min_warm = excluded.min_warm, max_warm = excluded.max_warm, idle_ttl_s = excluded.idle_ttl_s, - target_concurrency = excluded.target_concurrency, scale_to_zero = excluded.scale_to_zero`, - cfg.FunctionID, cfg.MinWarm, cfg.MaxWarm, cfg.IdleTTLS, cfg.TargetConcurrency, sc, + cfg.FunctionID, cfg.MinWarm, cfg.MaxWarm, cfg.IdleTTLS, sc, ) return err } @@ -179,9 +182,9 @@ func (db *Database) GetPoolConfig(functionID string) (*PoolConfig, error) { var sc int err := db.read.QueryRow(` SELECT function_id, min_warm, max_warm, idle_ttl_s, - COALESCE(target_concurrency, 10), COALESCE(scale_to_zero, 0) + COALESCE(scale_to_zero, 0) FROM pool_config WHERE function_id = ?`, functionID, - ).Scan(&cfg.FunctionID, &cfg.MinWarm, &cfg.MaxWarm, &cfg.IdleTTLS, &cfg.TargetConcurrency, &sc) + ).Scan(&cfg.FunctionID, &cfg.MinWarm, &cfg.MaxWarm, &cfg.IdleTTLS, &sc) if err != nil { return nil, err } diff --git a/backend/internal/database/migrations.go b/backend/internal/database/migrations.go index 813115ec..114ee6d7 100644 --- a/backend/internal/database/migrations.go +++ b/backend/internal/database/migrations.go @@ -61,10 +61,9 @@ CREATE TABLE IF NOT EXISTS execution_logs ( CREATE TABLE IF NOT EXISTS pool_config ( function_id TEXT PRIMARY KEY, min_warm INTEGER NOT NULL DEFAULT 1, - max_warm INTEGER NOT NULL DEFAULT 50, -- Knative-style soft cap; autoscaler respects mem/cpu budget + max_warm INTEGER NOT NULL DEFAULT 50, idle_ttl_s INTEGER NOT NULL DEFAULT 600, max_use_count INTEGER NOT NULL DEFAULT 1000, - target_concurrency INTEGER NOT NULL DEFAULT 10, -- Knative target concurrency per worker scale_to_zero INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (function_id) REFERENCES functions(id) ON DELETE CASCADE ); @@ -536,7 +535,6 @@ PRAGMA foreign_keys = ON; // Additive columns for the smart autoscaler. Idempotent — SQLite errors // if the column already exists, which we ignore. for _, stmt := range []string{ - "ALTER TABLE pool_config ADD COLUMN target_concurrency INTEGER NOT NULL DEFAULT 10", "ALTER TABLE pool_config ADD COLUMN scale_to_zero INTEGER NOT NULL DEFAULT 0", "ALTER TABLE api_keys ADD COLUMN key_prefix TEXT NOT NULL DEFAULT ''", "ALTER TABLE deployments ADD COLUMN code_hash TEXT NOT NULL DEFAULT ''", @@ -785,6 +783,14 @@ PRAGMA foreign_keys = ON; } } + // Pool controller v2 removes the public target_concurrency knob. Rebuild + // the table because SQLite cannot DROP COLUMN safely across all supported + // versions. The copy normalizes the scale contract at the same time: + // scale-to-zero rows own min_warm=0; active-minimum rows own min_warm>=1. + if err := migratePoolConfigV2(db); err != nil { + return fmt.Errorf("pool config v2 migration: %w", err) + } + // v0.4 A3 fix: drop the legacy FK on execution_requests.execution_id // for databases that were created before the FK-removal change. SQLite // has no ALTER TABLE DROP CONSTRAINT, so the only way to remove an FK @@ -865,6 +871,69 @@ PRAGMA foreign_keys = ON; return nil } +func migratePoolConfigV2(db *Database) error { + rows, err := db.read.Query(`PRAGMA table_info(pool_config)`) + if err != nil { + return err + } + hasTarget := false + for rows.Next() { + var cid, notNull, pk int + var name, typ string + var defaultValue any + if err := rows.Scan(&cid, &name, &typ, ¬Null, &defaultValue, &pk); err != nil { + _ = rows.Close() + return err + } + if name == "target_concurrency" { + hasTarget = true + } + } + if err := rows.Close(); err != nil { + return err + } + if !hasTarget { + // Keep legacy-but-valid rows aligned even after a prior successful + // rebuild; this also makes the migration idempotent after interruption. + _, err := db.write.Exec(`UPDATE pool_config SET min_warm = CASE + WHEN scale_to_zero = 1 THEN 0 + WHEN min_warm < 1 THEN 1 + ELSE min_warm END`) + return err + } + + tx, err := db.write.Begin() + if err != nil { + return err + } + defer func() { _ = tx.Rollback() }() + for _, stmt := range []string{ + `DROP TABLE IF EXISTS pool_config_v2`, + `CREATE TABLE pool_config_v2 ( + function_id TEXT PRIMARY KEY, + min_warm INTEGER NOT NULL DEFAULT 1, + max_warm INTEGER NOT NULL DEFAULT 50, + idle_ttl_s INTEGER NOT NULL DEFAULT 600, + max_use_count INTEGER NOT NULL DEFAULT 1000, + scale_to_zero INTEGER NOT NULL DEFAULT 0, + FOREIGN KEY (function_id) REFERENCES functions(id) ON DELETE CASCADE + )`, + `INSERT INTO pool_config_v2 + (function_id, min_warm, max_warm, idle_ttl_s, max_use_count, scale_to_zero) + SELECT function_id, + CASE WHEN scale_to_zero = 1 THEN 0 WHEN min_warm < 1 THEN 1 ELSE min_warm END, + max_warm, idle_ttl_s, max_use_count, scale_to_zero + FROM pool_config`, + `DROP TABLE pool_config`, + `ALTER TABLE pool_config_v2 RENAME TO pool_config`, + } { + if _, err := tx.Exec(stmt); err != nil { + return err + } + } + return tx.Commit() +} + // dropExecutionRequestsFK rebuilds the execution_requests table without // the legacy FK on execution_id. Idempotent: if the stored CREATE TABLE // no longer contains a REFERENCES clause we skip the rebuild. The proxy diff --git a/backend/internal/database/pool_config_v2_test.go b/backend/internal/database/pool_config_v2_test.go new file mode 100644 index 00000000..181b48f4 --- /dev/null +++ b/backend/internal/database/pool_config_v2_test.go @@ -0,0 +1,83 @@ +package database + +import ( + "path/filepath" + "testing" +) + +func TestPoolConfigV2RebuildPreservesRowsAndForeignKey(t *testing.T) { + db, err := New(filepath.Join(t.TempDir(), "pool-v2.db")) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.Migrate(); err != nil { + t.Fatal(err) + } + fn := &Function{Name: "legacy-pool", Runtime: "node", Entrypoint: "handler.js", MemoryMB: 64, CPUs: 1, TimeoutMS: 1000, Status: "active"} + if err := db.InsertFunction(fn); err != nil { + t.Fatal(err) + } + for _, stmt := range []string{ + `DROP TABLE pool_config`, + `CREATE TABLE pool_config ( + function_id TEXT PRIMARY KEY, min_warm INTEGER NOT NULL, max_warm INTEGER NOT NULL, + idle_ttl_s INTEGER NOT NULL, max_use_count INTEGER NOT NULL, + target_concurrency INTEGER NOT NULL, scale_to_zero INTEGER NOT NULL, + FOREIGN KEY (function_id) REFERENCES functions(id) ON DELETE CASCADE)`, + `INSERT INTO pool_config VALUES ('` + fn.ID + `', 7, 23, 321, 777, 9, 1)`, + } { + if _, err := db.write.Exec(stmt); err != nil { + t.Fatal(err) + } + } + if err := db.Migrate(); err != nil { + t.Fatal(err) + } + cfg, err := db.GetPoolConfig(fn.ID) + if err != nil { + t.Fatal(err) + } + if cfg.MinWarm != 0 || cfg.MaxWarm != 23 || cfg.IdleTTLS != 321 || !cfg.ScaleToZero { + t.Fatalf("migrated config mismatch: %+v", cfg) + } + var targetColumns int + if err := db.read.QueryRow(`SELECT COUNT(*) FROM pragma_table_info('pool_config') WHERE name='target_concurrency'`).Scan(&targetColumns); err != nil { + t.Fatal(err) + } + if targetColumns != 0 { + t.Fatal("target_concurrency survived rebuild") + } + if _, err := db.write.Exec(`DELETE FROM functions WHERE id=?`, fn.ID); err != nil { + t.Fatal(err) + } + var rows int + if err := db.read.QueryRow(`SELECT COUNT(*) FROM pool_config WHERE function_id=?`, fn.ID).Scan(&rows); err != nil { + t.Fatal(err) + } + if rows != 0 { + t.Fatal("pool_config foreign-key cascade was not preserved") + } +} + +func TestPoolConfigNormalization(t *testing.T) { + db := newTestDB(t) + fn := &Function{Name: "normalize-pool", Runtime: "node", Entrypoint: "handler.js", MemoryMB: 64, CPUs: 1, TimeoutMS: 1000, Status: "active"} + if err := db.InsertFunction(fn); err != nil { + t.Fatal(err) + } + cfg := &PoolConfig{FunctionID: fn.ID, MinWarm: 4, MaxWarm: 10, IdleTTLS: 600, ScaleToZero: true} + if err := db.UpsertPoolConfig(cfg); err != nil { + t.Fatal(err) + } + if got, _ := db.GetPoolConfig(fn.ID); got.MinWarm != 0 { + t.Fatalf("scale-to-zero min=%d", got.MinWarm) + } + cfg.ScaleToZero = false + if err := db.UpsertPoolConfig(cfg); err != nil { + t.Fatal(err) + } + if got, _ := db.GetPoolConfig(fn.ID); got.MinWarm != 1 { + t.Fatalf("active min=%d", got.MinWarm) + } +} diff --git a/backend/internal/mcp/reference.md b/backend/internal/mcp/reference.md index abf7d458..216455ad 100644 --- a/backend/internal/mcp/reference.md +++ b/backend/internal/mcp/reference.md @@ -1243,7 +1243,7 @@ Failed deliveries (non-2xx, timeout, network) retry up to 5× with exponential b - Network is OFF by default — sandbox has only loopback (no DNS, no outbound TCP). The user must flip "Allow outbound network" in the editor's Settings modal to call external HTTPS APIs (Stripe, OpenAI, a remote DB). Tell the user to do this whenever your code makes outbound calls. - orva.kv / orva.invoke / orva.jobs ALSO require egress — the SDK reaches orvad over the bridge network via HTTP, so a function with `network_mode: "none"` will see every SDK call fail with ENETUNREACH / OrvaUnavailableError. If the handler imports the orva module, set `network_mode: "egress"` at create time (or update later) — the editor's deploy step will warn you when the import meets `none`. - When egress IS enabled, the operator can still block specific destinations with the egress policy, and can pin resolvers / host overrides with the sandbox DNS settings (both on the dashboard's Egress controls page). A destination blocked by policy fails with ECONNREFUSED — distinct from the ENETUNREACH you get with `network_mode: "none"`. Handle both. -- Concurrency: each warm worker handles one request at a time. The pool autoscales workers up to the function's max_concurrent setting. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. +- Concurrency: each warm worker handles one request at a time. Pool Controller v2 sizes workers from arrival rate, queue pressure, service time, and cold-start time, bounded by the function's pool ceiling and effective host CPU/memory capacity. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. diff --git a/backend/internal/mcp/tools_pool.go b/backend/internal/mcp/tools_pool.go index 86351250..d5339287 100644 --- a/backend/internal/mcp/tools_pool.go +++ b/backend/internal/mcp/tools_pool.go @@ -2,18 +2,18 @@ package mcp import ( "context" + "fmt" "github.com/Harsh-2002/Orva/backend/internal/database" mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" ) type PoolConfigView struct { - FunctionID string `json:"function_id"` - MinWarm int `json:"min_warm"` - MaxWarm int `json:"max_warm"` - IdleTTLSeconds int `json:"idle_ttl_seconds"` - TargetConcurrency int `json:"target_concurrency"` - ScaleToZero bool `json:"scale_to_zero"` + FunctionID string `json:"function_id"` + MinWarm int `json:"min_warm"` + MaxWarm int `json:"max_warm"` + IdleTTLSeconds int `json:"idle_ttl_seconds"` + ScaleToZero bool `json:"scale_to_zero"` } type GetPoolConfigInput struct { @@ -21,19 +21,18 @@ type GetPoolConfigInput struct { } type SetPoolConfigInput struct { - FunctionID string `json:"function_id"` - MinWarm *int `json:"min_warm,omitempty"` - MaxWarm *int `json:"max_warm,omitempty"` - IdleTTLSeconds *int `json:"idle_ttl_seconds,omitempty"` - TargetConcurrency *int `json:"target_concurrency,omitempty" jsonschema:"req per worker before scale-up considered"` - ScaleToZero *bool `json:"scale_to_zero,omitempty"` + FunctionID string `json:"function_id"` + MinWarm *int `json:"min_warm,omitempty"` + MaxWarm *int `json:"max_warm,omitempty"` + IdleTTLSeconds *int `json:"idle_ttl_seconds,omitempty"` + ScaleToZero *bool `json:"scale_to_zero,omitempty"` } func toPoolConfigView(c *database.PoolConfig) PoolConfigView { return PoolConfigView{ FunctionID: c.FunctionID, MinWarm: c.MinWarm, MaxWarm: c.MaxWarm, - IdleTTLSeconds: c.IdleTTLS, TargetConcurrency: c.TargetConcurrency, - ScaleToZero: c.ScaleToZero, + IdleTTLSeconds: c.IdleTTLS, + ScaleToZero: c.ScaleToZero, } } @@ -44,7 +43,7 @@ func registerPoolTools(rc *regCtx) { &mcpsdk.Tool{ Name: "get_pool_config", Title: "Get Pool Config", - Description: "Get the autoscaler pool config for a function (min_warm, max_warm, idle_ttl, target_concurrency, scale_to_zero). Returns nulls/defaults if no override is configured.", + Description: "Get the Pool Controller v2 config for a function (min_warm, max_warm, idle_ttl, scale_to_zero). Returns defaults if no override is configured.", Annotations: &mcpsdk.ToolAnnotations{ReadOnlyHint: true, OpenWorldHint: ptrFalse()}, }, func(_ context.Context, _ *mcpsdk.CallToolRequest, in GetPoolConfigInput) (*mcpsdk.CallToolResult, PoolConfigView, error) { @@ -57,7 +56,7 @@ func registerPoolTools(rc *regCtx) { // no row = use defaults return nil, PoolConfigView{ FunctionID: fn.ID, MinWarm: 1, MaxWarm: 50, - IdleTTLSeconds: 600, TargetConcurrency: 10, + IdleTTLSeconds: 600, }, nil } return nil, toPoolConfigView(cfg), nil @@ -80,7 +79,7 @@ func registerPoolTools(rc *regCtx) { if err != nil { cfg = &database.PoolConfig{ FunctionID: fn.ID, MinWarm: 1, MaxWarm: 50, - IdleTTLS: 600, TargetConcurrency: 10, + IdleTTLS: 600, } } if in.MinWarm != nil { @@ -92,12 +91,27 @@ func registerPoolTools(rc *regCtx) { if in.IdleTTLSeconds != nil { cfg.IdleTTLS = *in.IdleTTLSeconds } - if in.TargetConcurrency != nil { - cfg.TargetConcurrency = *in.TargetConcurrency - } if in.ScaleToZero != nil { cfg.ScaleToZero = *in.ScaleToZero } + if in.MinWarm != nil { + if cfg.ScaleToZero && cfg.MinWarm != 0 { + return nil, PoolConfigView{}, fmt.Errorf("scale_to_zero=true requires min_warm=0") + } + if !cfg.ScaleToZero && cfg.MinWarm < 1 { + return nil, PoolConfigView{}, fmt.Errorf("scale_to_zero=false requires min_warm>=1") + } + } + if in.ScaleToZero != nil && in.MinWarm == nil { + if cfg.ScaleToZero { + cfg.MinWarm = 0 + } else if cfg.MinWarm < 1 { + cfg.MinWarm = 1 + } + } + if cfg.MaxWarm < 1 || cfg.MinWarm > cfg.MaxWarm || cfg.IdleTTLS < 0 { + return nil, PoolConfigView{}, fmt.Errorf("require min_warm <= max_warm, max_warm >= 1, and idle_ttl_seconds >= 0") + } if err := deps.DB.UpsertPoolConfig(cfg); err != nil { return nil, PoolConfigView{}, err } diff --git a/backend/internal/mcp/tools_system.go b/backend/internal/mcp/tools_system.go index edb2d7e2..afd3c8c0 100644 --- a/backend/internal/mcp/tools_system.go +++ b/backend/internal/mcp/tools_system.go @@ -134,9 +134,15 @@ type SystemMetricsOutput struct { ActiveRequests int64 `json:"active_requests"` SandboxActive int64 `json:"sandbox_active"` BuildQueue MetricsBuildQ `json:"build_queue"` + Host MetricsHost `json:"host"` Pools []MetricsPool `json:"pools"` } +type MetricsHost struct { + EffectiveCPUWorkers int `json:"effective_cpu_workers"` + EffectiveMemoryMB int64 `json:"effective_memory_capacity_mb"` +} + type MetricsTotals struct { Invocations int64 `json:"invocations"` ColdStarts int64 `json:"cold_starts"` @@ -157,13 +163,20 @@ type MetricsBuildQ struct { } type MetricsPool struct { - FunctionID string `json:"function_id"` - Idle int `json:"idle"` - Busy int64 `json:"busy"` - Spawned int64 `json:"spawned"` - Killed int64 `json:"killed"` - RateEWMA float64 `json:"rate_ewma"` - LatencyEWMAms float64 `json:"latency_ewma_ms"` + FunctionID string `json:"function_id"` + Idle int `json:"idle"` + Busy int64 `json:"busy"` + Queued int64 `json:"queued"` + Spawning int64 `json:"spawning"` + DesiredWorkers int64 `json:"desired_workers"` + EffectiveMax int64 `json:"effective_max"` + QueueWaitP95MS float64 `json:"queue_wait_p95_ms"` + ServiceP95MS float64 `json:"service_p95_ms"` + ColdStartP95MS float64 `json:"cold_start_p95_ms"` + LimitingReason string `json:"limiting_reason"` + Arrivals int64 `json:"arrivals"` + Rejections int64 `json:"rejections"` + CapacityTimeouts int64 `json:"capacity_timeouts"` } func buildSystemMetrics(deps Deps) SystemMetricsOutput { @@ -189,15 +202,18 @@ func buildSystemMetrics(deps Deps) SystemMetricsOutput { out.BuildQueue = MetricsBuildQ{Pending: deps.BuildQueue.QueuedDepth(), Workers: deps.BuildQueue.Workers()} } if deps.PoolMgr != nil { + out.Host = MetricsHost{ + EffectiveCPUWorkers: deps.PoolMgr.EffectiveCPUCapacity(), + EffectiveMemoryMB: deps.PoolMgr.EffectiveMemoryCapacity() / 1024 / 1024, + } for _, s := range deps.PoolMgr.Stats() { out.Pools = append(out.Pools, MetricsPool{ - FunctionID: s.FunctionID, - Idle: s.Idle, - Busy: s.Busy, - Spawned: s.Spawned, - Killed: s.Killed, - RateEWMA: s.RateEWMA, - LatencyEWMAms: s.LatencyEWMAms, + FunctionID: s.FunctionID, Idle: s.Idle, Busy: s.Busy, + Queued: s.Queued, Spawning: s.Spawning, + DesiredWorkers: s.Desired, EffectiveMax: s.EffectiveMax, + QueueWaitP95MS: s.QueueWaitP95MS, ServiceP95MS: s.ServiceP95MS, + ColdStartP95MS: s.ColdStartP95MS, LimitingReason: s.LimitingReason, + Arrivals: s.Arrivals, Rejections: s.Rejections, CapacityTimeouts: s.CapacityTimeouts, }) } } diff --git a/backend/internal/pool/autoscaler.go b/backend/internal/pool/autoscaler.go index e8ed7969..e788627b 100644 --- a/backend/internal/pool/autoscaler.go +++ b/backend/internal/pool/autoscaler.go @@ -4,255 +4,298 @@ import ( "context" "log/slog" "math" - "runtime" + "sort" + "sync" "time" ) -// Autoscaler parameters — these match Knative KPA defaults and are tuned -// for ~100s of per-function pools on a single host. const ( - scalerTick = 2 * time.Second - stableWindow = 60 * time.Second - panicWindow = 6 * time.Second - panicThreshold = 2.0 - utilFactor = 0.7 - scaleDownStep = 0.5 // at most 50% shrink per tick — release path also prunes, - // so this is just the catch-up rate for stragglers - scaleDownGrace = 1 // 1 tick (~20s) below target before scale-down. Was 3 ticks - // (60 s) which left burst-spawned idle workers parked - // long enough to noticeably slow down the UI on small hosts. + scalerTick = 2 * time.Second + stableWindow = 60 * time.Second + panicWindow = 6 * time.Second + utilFactor = 0.70 + scaleDownStep = 0.20 + scaleDownGrace = 30 * time.Second + maxConcurrentSpawnsPerPool = 4 ) -// scaler owns the control loop; one per Manager. +// scaler is the global admission scheduler. It evaluates pools in a rotating +// order so a hot function cannot monopolize every newly available worker +// slot. Each functionPool is its own coordinator and accounts spawning before +// launch, making repeated ticks and request-path cold starts single-flight. type scaler struct { pm *Manager tick time.Duration stop chan struct{} + runDone chan struct{} + wake chan struct{} hostMem *hostMemTracker - // samplesPerWindow is the ring-buffer depth for the stable window. - samplesPerWindow int - panicSamples int + spawnWG sync.WaitGroup + + mu sync.Mutex + cursor int } func newScaler(pm *Manager, hm *hostMemTracker) *scaler { - return &scaler{ - pm: pm, - hostMem: hm, - tick: scalerTick, - stop: make(chan struct{}), - samplesPerWindow: int(stableWindow / scalerTick), // 30 - panicSamples: int(panicWindow / scalerTick), // 3 - } + return &scaler{pm: pm, hostMem: hm, tick: scalerTick, stop: make(chan struct{}), runDone: make(chan struct{}), wake: make(chan struct{}, 1)} } func (s *scaler) run() { t := time.NewTicker(s.tick) defer t.Stop() - slog.Info("autoscaler started", - "tick", s.tick, "stable_window", stableWindow, "panic_window", panicWindow) - + defer close(s.runDone) + slog.Info("pool controller v2 started", "tick", s.tick, "stable_window", stableWindow, "burst_window", panicWindow) for { select { case <-t.C: s.evaluateAll() + case <-s.wake: + s.evaluateAll() case <-s.stop: - slog.Info("autoscaler stopped") + slog.Info("pool controller v2 stopped") return } } } +func (s *scaler) nudge() { + select { + case s.wake <- struct{}{}: + default: + } +} + func (s *scaler) shutdown() { select { case <-s.stop: default: close(s.stop) } + <-s.runDone + s.spawnWG.Wait() } -// evaluateAll ticks every pool and runs the scale decision. func (s *scaler) evaluateAll() { - bucketSec := s.tick.Seconds() - s.pm.pools.Range(func(k, v any) bool { - p := v.(*functionPool) - if p.closing.Load() { - return true + pools := make([]*functionPool, 0) + s.pm.pools.Range(func(_, value any) bool { + p := value.(*functionPool) + if !p.closing.Load() { + pools = append(pools, p) } - // Roll the 1-sec bucket forward and snapshot inflight. - p.tick(bucketSec) - s.evaluate(p) return true }) -} - -// evaluate is the per-pool decision. Called from the scaler goroutine only. -func (s *scaler) evaluate(p *functionPool) { - desired, reason := s.computeDesired(p) - current := int(p.busy.Load()) + len(p.idle) - - switch { - case desired > current: - want := desired - current - go s.scaleUp(p, want, reason) - case desired < current: - // Rate-limit shrink: at most 20% per tick AND require stable window - // to have been below target for `scaleDownGrace` consecutive ticks. - maxShrink := int(math.Ceil(float64(current) * scaleDownStep)) - if maxShrink < 1 { - maxShrink = 1 - } - shrink := current - desired - if shrink > maxShrink { - shrink = maxShrink - } - // Only scale down when the cooldown has elapsed. - if p.belowTargetTicks < scaleDownGrace { - return - } - s.scaleDown(p, shrink, reason) + if len(pools) == 0 { + return + } + sort.Slice(pools, func(i, j int) bool { return pools[i].fnID < pools[j].fnID }) + s.mu.Lock() + start := s.cursor % len(pools) + s.cursor = (start + 1) % len(pools) + s.mu.Unlock() + for i := range pools { + s.evaluate(pools[(start+i)%len(pools)], time.Now()) } } -// computeDesired returns the worker count the pool "should" have based on -// Knative two-window smoothing + Little's-Law floor + operator/memory caps. -// Also updates p.belowTargetTicks for scale-down gating. -func (s *scaler) computeDesired(p *functionPool) (int, string) { - // Samples. - stableConc := p.windowMean(s.samplesPerWindow) - panicConc := p.windowMean(s.panicSamples) - - target := float64(p.target) - if target <= 0 { - target = 10 +func (s *scaler) evaluate(p *functionPool, now time.Time) { + desired, reason := s.computeDesiredAt(p, now) + current := int(p.busy.Load()+p.spawning.Load()) + len(p.idle) + capacityLimited := reason == "memory_capacity" || reason == "cpu_capacity" + if p.queued.Load() > 0 && capacityLimited && desired <= current && s.reclaimBorrowedIdle(p) { + // Recompute after returning the donor's reservation. This queued pool + // gets the newly available slot in the same rotating evaluation pass. + desired, reason = s.computeDesiredAt(p, now) } - perWorker := target * utilFactor - - desiredStable := int(math.Ceil(stableConc / perWorker)) - desiredPanic := int(math.Ceil(panicConc / perWorker)) + p.desired.Store(int64(desired)) + p.sigMu.Lock() + p.limitingReason = reason + p.sigMu.Unlock() - // Panic mode: ratio = recent concurrency / current workers. - cur := int(p.busy.Load()) + len(p.idle) - if cur < 1 { - cur = 1 + if desired > current { + p.sigMu.Lock() + p.belowTargetSince = time.Time{} + p.sigMu.Unlock() + s.scaleUp(p, desired-current, reason) + return } - ratio := panicConc / float64(cur) - inPanic := ratio >= panicThreshold - - desired := desiredStable - reason := "stable" - if inPanic && desiredPanic > desired { - desired = desiredPanic - reason = "panic" + if desired >= current { + p.sigMu.Lock() + p.belowTargetSince = time.Time{} + p.sigMu.Unlock() + return } - // Little's-Law floor: if request rate and latency are known, ensure we - // have enough workers to absorb steady-state demand. - rate, latMs := p.snapshotSignals() - if rate > 0 && latMs > 0 { - w := latMs / 1000.0 - ll := int(math.Ceil((rate * w) / utilFactor)) - if ll > desired { - desired = ll - reason = "littles-law" - } + p.sigMu.Lock() + if p.belowTargetSince.IsZero() { + p.belowTargetSince = now + } + belowSince := p.belowTargetSince + p.sigMu.Unlock() + if now.Sub(belowSince) < scaleDownGrace { + return + } + maxShrink := int(math.Ceil(float64(current) * scaleDownStep)) + if maxShrink < 1 { + maxShrink = 1 + } + shrink := current - desired + if shrink > maxShrink { + shrink = maxShrink } + s.scaleDown(p, shrink, reason) +} - // min / max / memory / cpu caps. - minWarm := p.min - if minWarm < 0 { - minWarm = 0 +// computeDesiredAt implements the controller's documented signals. Workers +// are single-request processes, so Little's Law gives required concurrency as +// arrival-rate × wall time. Dividing by 70% leaves deliberate burst headroom. +func (s *scaler) computeDesiredAt(p *functionPool, now time.Time) (int, string) { + d := p.snapshotDemand(now) + serviceSeconds := d.ServiceP95.Seconds() + spawnSeconds := d.SpawnP95.Seconds() + stable := int(math.Ceil(d.StableRate * serviceSeconds / utilFactor)) + burst := int(math.Ceil(d.BurstRate * (serviceSeconds + spawnSeconds) / utilFactor)) + pressure := int(math.Ceil(float64(p.busy.Load()+p.queued.Load()) / utilFactor)) + + desired := stable + reason := "stable_rate" + if burst > desired { + desired, reason = burst, "burst_rate" } + if pressure > desired { + desired, reason = pressure, "immediate_pressure" + } + minWarm := p.min if !p.scaleToZero && minWarm < 1 { minWarm = 1 } if desired < minWarm { - desired = minWarm + desired, reason = minWarm, "configured_min" + } + if p.scaleToZero && desired == 0 { + fullyIdle := p.busy.Load() == 0 && p.queued.Load() == 0 + idleLongEnough := d.LastArrival.IsZero() || now.Sub(d.LastArrival) >= p.idleTTL + if !fullyIdle || !idleLongEnough { + desired, reason = 1, "idle_ttl" + } else { + reason = "scale_to_zero" + } } - dyn := s.dynamicMax(p) - p.dynamicMax.Store(int64(dyn)) - if desired > dyn { - desired = dyn + cap, capReason := s.dynamicMax(p, d.MemoryP95) + p.dynamicMax.Store(int64(cap)) + if desired > cap { + desired, reason = cap, capReason } if desired < 0 { desired = 0 } - - // Update the below-target counter for scale-down gating. Uses stable - // window only (panicConc is deliberately volatile). - if stableConc < target*utilFactor { - p.belowTargetTicks++ - } else { - p.belowTargetTicks = 0 - } - return desired, reason } -// dynamicMax bounds the pool by operator cap, memory, and CPU headroom. -// It adds back the function's own current reserved workers so we're asking -// "how large could this pool be", not "how much free memory is left after -// counting ourselves". -func (s *scaler) dynamicMax(p *functionPool) int { +func (s *scaler) computeDesired(p *functionPool) (int, string) { + return s.computeDesiredAt(p, time.Now()) +} + +func (s *scaler) dynamicMax(p *functionPool, observedMemoryP95 int64) (int, string) { opCap := p.max - if opCap <= 0 { - opCap = 5 + if opCap < 1 { + opCap = 1 } - cpuCap := runtime.NumCPU() * 8 - if opCap < cpuCap { - cpuCap = opCap + cpuUnits := p.cpuUnits + if cpuUnits < 1 { + cpuUnits = 1000 } - - if s.hostMem == nil || p.memoryBytes <= 0 { - return cpuCap - } - // Headroom = currently-available-for-workers + my own current reservation. - cur := int64(p.busy.Load()) + int64(len(p.idle)) - myReserved := cur * p.memoryBytes - avail := s.hostMem.availableForWorkers() + myReserved - memFit := int(avail / p.memoryBytes) - if memFit < 0 { - memFit = 0 - } - capped := cpuCap - if memFit < capped { - capped = memFit - } - return capped + current := int64(p.busy.Load()+p.spawning.Load()) + int64(len(p.idle)) + cpuCap := int((s.hostMem.availableCPUUnits() + current*cpuUnits) / cpuUnits) + if cpuCap < 1 { + cpuCap = 1 + } + effectiveCap, reason := opCap, "operator_max" + if p.concSem != nil && cap(p.concSem) < effectiveCap { + effectiveCap, reason = cap(p.concSem), "function_concurrency" + } + if cpuCap < effectiveCap { + effectiveCap, reason = cpuCap, "cpu_capacity" + } + workerBytes := p.memoryBytes + if observedMemoryP95 > 0 && observedMemoryP95 < workerBytes { + workerBytes = observedMemoryP95 + } + if workerBytes > 0 { + fit := int((s.hostMem.availableForWorkers() + current*workerBytes) / workerBytes) + if fit < effectiveCap { + effectiveCap, reason = fit, "memory_capacity" + } + } + if effectiveCap < 0 { + effectiveCap = 0 + } + return effectiveCap, reason } -// scaleUp spawns up to `want` new workers, bounded by hostMem reservation. -// Runs in its own goroutine because spawn is slow (nsjail fork + VM boot). func (s *scaler) scaleUp(p *functionPool, want int, reason string) { - if want <= 0 { - return + if want > maxConcurrentSpawnsPerPool { + want = maxConcurrentSpawnsPerPool } - spawned := 0 for i := 0; i < want; i++ { - if p.closing.Load() { - break + if !s.startSpawn(p, reason) { + return } - // Memory admission: skip if budget is gone. - if p.memoryBytes > 0 && s.hostMem != nil { - if !s.hostMem.reserve(p.memoryBytes) { - break - } + } +} + +func (s *scaler) startSpawn(p *functionPool, reason string) bool { + p.mu.Lock() + cap := int(p.dynamicMax.Load()) + if cap > p.max { + cap = p.max + } + if cap < 0 { + cap = 0 + } + total := int(p.busy.Load()+p.spawning.Load()) + len(p.idle) + if p.closing.Load() || total >= cap { + p.mu.Unlock() + return false + } + select { + case p.spawnSlots <- struct{}{}: + p.spawning.Add(1) // publish before launch: repeated ticks see it + default: + p.mu.Unlock() + return false + } + p.mu.Unlock() + + reservation := workerReservation{memoryBytes: p.admissionBytes(), cpuUnits: p.cpuUnits} + if !s.hostMem.reserve(reservation.memoryBytes, reservation.cpuUnits) { + if !s.reclaimBorrowedIdle(p) || !s.hostMem.reserve(reservation.memoryBytes, reservation.cpuUnits) { + p.spawning.Add(-1) + <-p.spawnSlots + p.sigMu.Lock() + p.limitingReason = "memory_capacity" + p.sigMu.Unlock() + return false } - // Bookkeeping: bump busy so we reflect "worker exists" during spawn; - // it'll flip to idle when we push to the channel. + } + s.spawnWG.Add(1) + go func() { + defer s.spawnWG.Done() + defer func() { <-p.spawnSlots }() + started := time.Now() w, err := p.spawnFn(context.Background()) + p.spawning.Add(-1) if err != nil { - if p.memoryBytes > 0 && s.hostMem != nil { - s.hostMem.release(p.memoryBytes) - } - slog.Warn("autoscaler spawn failed", "fn", p.fnID, "err", err) - break + s.hostMem.release(reservation.memoryBytes, reservation.cpuUnits) + p.sigMu.Lock() + p.limitingReason = "spawn_error" + p.sigMu.Unlock() + slog.Warn("pool worker spawn failed", "fn", p.fnID, "err", err) + return } + p.recordSpawn(time.Since(started)) p.spawned.Add(1) - // Push to idle non-blockingly; if the channel is full we're racing - // another scale-up — kill the excess to keep the invariant clean. - // The lock makes the closing check + publication atomic with pool - // retirement, preventing a stale worker from arriving after its drain. + p.workerReservations.Store(w, reservation) p.mu.Lock() parked := false if !p.closing.Load() { @@ -263,52 +306,60 @@ func (s *scaler) scaleUp(p *functionPool, want int, reason string) { } } p.mu.Unlock() - if parked { - spawned++ - } else { + if !parked { p.killWorker(w) + return + } + slog.Debug("pool scaled up", "fn", p.fnID, "reason", reason) + }() + return true +} + +// reclaimBorrowedIdle frees one worker above a pool's configured active +// minimum, choosing the largest borrower first. Busy workers are never +// touched and configured minimums are never crossed. +func (s *scaler) reclaimBorrowedIdle(requester *functionPool) bool { + var donor *functionPool + bestBorrowed := 0 + s.pm.pools.Range(func(_, value any) bool { + p := value.(*functionPool) + if p == requester || p.closing.Load() { + return true + } + current := int(p.busy.Load()+p.spawning.Load()) + len(p.idle) + borrowed := current - p.min + if borrowed > len(p.idle) { + borrowed = len(p.idle) } + if borrowed > bestBorrowed { + donor, bestBorrowed = p, borrowed + } + return true + }) + if donor == nil { + return false } - if spawned > 0 { - p.scaleUps.Add(int64(spawned)) - slog.Debug("pool scaled up", "fn", p.fnID, "spawned", spawned, "reason", reason) + select { + case w := <-donor.idle: + donor.killWorker(w) + return true + default: + return false } } -// scaleDown kills up to `want` idle workers (oldest first in the FIFO sense -// of the channel, meaning just pop them off and don't re-insert). Never -// touches busy workers. Releases memory reservations. func (s *scaler) scaleDown(p *functionPool, want int, reason string) { - if want <= 0 { - return - } killed := 0 for i := 0; i < want; i++ { select { case w := <-p.idle: - _ = w.Quit(200 * time.Millisecond) - if p.memoryBytes > 0 && s.hostMem != nil { - s.hostMem.release(p.memoryBytes) - } - p.killed.Add(1) + p.killWorker(w) killed++ default: - // No idle workers to kill right now; stop. i = want } } if killed > 0 { - p.scaleDowns.Add(int64(killed)) slog.Debug("pool scaled down", "fn", p.fnID, "killed", killed, "reason", reason) } } - -// ensureSignals lazily initialises the per-pool signal ring once we know -// how long the stable window is. Called at pool-creation time. -func (s *scaler) ensureSignals(p *functionPool) { - p.sigMu.Lock() - defer p.sigMu.Unlock() - if p.inflightSamples == nil { - p.inflightSamples = make([]int64, s.samplesPerWindow) - } -} diff --git a/backend/internal/pool/autoscaler_v2_test.go b/backend/internal/pool/autoscaler_v2_test.go new file mode 100644 index 00000000..2d404578 --- /dev/null +++ b/backend/internal/pool/autoscaler_v2_test.go @@ -0,0 +1,266 @@ +package pool + +import ( + "context" + "sync/atomic" + "testing" + "time" + + "github.com/Harsh-2002/Orva/backend/internal/database" + "github.com/Harsh-2002/Orva/backend/internal/sandbox" +) + +func controllerTestPool() (*functionPool, *hostMemTracker) { + hm := &hostMemTracker{totalBytes: 64 << 30, reservationPct: 0.8, cpuWorkers: 128} + hm.availBytes.Store(64 << 30) + p := &functionPool{ + fnID: "fn-test", min: 1, max: 50, idleTTL: 10 * time.Minute, + memoryBytes: 64 << 20, cpuUnits: 1000, hostMem: hm, + idle: make(chan *sandbox.Worker, 50), spawnSlots: make(chan struct{}, 4), + retired: make(chan struct{}), + } + p.dynamicMax.Store(50) + return p, hm +} + +func TestControllerV2CPUCapacityIsGlobalAndFunctionWeighted(t *testing.T) { + hm := &hostMemTracker{totalBytes: 64 << 30, reservationPct: 0.8, cpuWorkers: 4} + hm.availBytes.Store(64 << 30) + if !hm.reserve(64<<20, 3000) { + t.Fatal("initial three-CPU reservation failed") + } + p, _ := controllerTestPool() + p.hostMem = hm + p.cpuUnits = 500 + p.max = 50 + s := newScaler(&Manager{hostMem: hm}, hm) + if got, reason := s.dynamicMax(p, 0); got != 2 || reason != "cpu_capacity" { + t.Fatalf("weighted global CPU cap=%d/%s, want 2/cpu_capacity", got, reason) + } +} + +func TestControllerV2RespectsFunctionConcurrency(t *testing.T) { + p, hm := controllerTestPool() + p.concSem = make(chan struct{}, 3) + s := newScaler(&Manager{hostMem: hm}, hm) + if got, reason := s.dynamicMax(p, 0); got != 3 || reason != "function_concurrency" { + t.Fatalf("function concurrency cap=%d/%s, want 3/function_concurrency", got, reason) + } +} + +func TestControllerV2DemandFormula(t *testing.T) { + p, hm := controllerTestPool() + m := &Manager{hostMem: hm} + s := newScaler(m, hm) + now := time.Now() + for i := 0; i < 60; i++ { + p.recordArrival(now.Add(-time.Duration(i) * time.Second)) + } + p.recordLatency(time.Second) + desired, reason := s.computeDesiredAt(p, now) + if desired != 2 || reason != "stable_rate" { + t.Fatalf("stable formula: got desired=%d reason=%q, want 2/stable_rate", desired, reason) + } + + p.recordSpawn(time.Second) + for i := 0; i < 6; i++ { + p.recordArrival(now.Add(-time.Duration(i) * 100 * time.Millisecond)) + } + desired, reason = s.computeDesiredAt(p, now) + if desired < 3 || reason != "burst_rate" { + t.Fatalf("burst formula: got desired=%d reason=%q, want at least 3/burst_rate", desired, reason) + } + + p.busy.Store(7) + desired, reason = s.computeDesiredAt(p, now) + if desired != 10 || reason != "immediate_pressure" { + t.Fatalf("pressure formula: got desired=%d reason=%q, want 10/immediate_pressure", desired, reason) + } +} + +func TestControllerV2ScaleToZeroHonorsIdleTTL(t *testing.T) { + p, hm := controllerTestPool() + p.min = 0 + p.scaleToZero = true + p.idleTTL = 10 * time.Minute + s := newScaler(&Manager{hostMem: hm}, hm) + now := time.Now() + p.recordArrival(now.Add(-9 * time.Minute)) + if desired, reason := s.computeDesiredAt(p, now); desired != 1 || reason != "idle_ttl" { + t.Fatalf("inside idle TTL: got %d/%s", desired, reason) + } + if desired, reason := s.computeDesiredAt(p, now.Add(2*time.Minute)); desired != 0 || reason != "scale_to_zero" { + t.Fatalf("after idle TTL: got %d/%s", desired, reason) + } +} + +func TestAdmissionUsesDeclaredLimitUntilMemoryP95Exists(t *testing.T) { + p, _ := controllerTestPool() + if got := p.admissionBytes(); got != p.memoryBytes { + t.Fatalf("unobserved admission=%d, want declared limit %d", got, p.memoryBytes) + } + p.sigMu.Lock() + p.memSamples = []int64{24 << 20, 32 << 20, 40 << 20} + p.sigMu.Unlock() + if got := p.admissionBytes(); got != 40<<20 { + t.Fatalf("observed admission=%d, want p95 40 MiB", got) + } +} + +func TestControllerV2NeverOverlapsMoreThanFourSpawns(t *testing.T) { + p, hm := controllerTestPool() + m := &Manager{hostMem: hm} + m.pools.Store(p.fnID, p) + s := newScaler(m, hm) + started := make(chan struct{}, 10) + release := make(chan struct{}) + var active atomic.Int64 + var peak atomic.Int64 + p.spawnFn = func(context.Context) (*sandbox.Worker, error) { + current := active.Add(1) + for old := peak.Load(); current > old && !peak.CompareAndSwap(old, current); old = peak.Load() { + } + started <- struct{}{} + <-release + active.Add(-1) + return &sandbox.Worker{}, nil + } + s.scaleUp(p, 20, "test") + for i := 0; i < 4; i++ { + select { + case <-started: + case <-time.After(time.Second): + t.Fatal("expected four concurrent starts") + } + } + if got := p.spawning.Load(); got != 4 { + t.Fatalf("spawning=%d, want 4", got) + } + s.scaleUp(p, 20, "repeat") + if got := p.spawning.Load(); got != 4 { + t.Fatalf("repeat evaluation duplicated starts: spawning=%d", got) + } + close(release) + deadline := time.Now().Add(time.Second) + for p.spawning.Load() != 0 && time.Now().Before(deadline) { + time.Sleep(time.Millisecond) + } + if peak.Load() != 4 { + t.Fatalf("peak starts=%d, want 4", peak.Load()) + } +} + +func TestControllerV2ScaleDownNeedsThirtySecondsAndCapsTwentyPercent(t *testing.T) { + p, hm := controllerTestPool() + for i := 0; i < 10; i++ { + p.idle <- nil + } + s := newScaler(&Manager{hostMem: hm}, hm) + now := time.Now() + s.evaluate(p, now) + if len(p.idle) != 10 { + t.Fatal("scaled down before hysteresis") + } + s.evaluate(p, now.Add(29*time.Second)) + if len(p.idle) != 10 { + t.Fatal("scaled down before 30 seconds") + } + s.evaluate(p, now.Add(30*time.Second)) + if len(p.idle) != 8 { + t.Fatalf("idle=%d, want 8 after one 20%% evaluation", len(p.idle)) + } +} + +func TestControllerV2ScaleUpBreaksBelowTargetContinuity(t *testing.T) { + p, hm := controllerTestPool() + p.belowTargetSince = time.Now().Add(-time.Minute) + p.queued.Store(20) + p.spawnFn = func(context.Context) (*sandbox.Worker, error) { + return nil, context.Canceled + } + s := newScaler(&Manager{hostMem: hm}, hm) + s.evaluate(p, time.Now()) + p.sigMu.Lock() + below := p.belowTargetSince + p.sigMu.Unlock() + if !below.IsZero() { + t.Fatal("scale-up demand did not reset below-target hysteresis") + } + s.spawnWG.Wait() +} + +func TestControllerV2ReclaimCountsBusyWorkersTowardMinimum(t *testing.T) { + donor, hm := controllerTestPool() + donor.fnID = "donor" + donor.min = 2 + donor.busy.Store(2) + donor.idle <- nil + requester, _ := controllerTestPool() + requester.fnID = "requester" + m := &Manager{hostMem: hm} + m.pools.Store(donor.fnID, donor) + m.pools.Store(requester.fnID, requester) + s := newScaler(m, hm) + if !s.reclaimBorrowedIdle(requester) { + t.Fatal("idle worker above a busy-satisfied minimum was not reclaimed") + } + if len(donor.idle) != 0 { + t.Fatal("reclaimed worker remained idle") + } +} + +func TestControllerV2ReclaimsBorrowedIdleCapacityForQueuedFunction(t *testing.T) { + m, reg := egressTestManager(t) + m.tmpl = fakeSandboxTemplate(t) + hm := &hostMemTracker{totalBytes: 120 << 20, reservationPct: 0.8, cpuWorkers: 8, stop: make(chan struct{})} + hm.availBytes.Store(120 << 20) + m.hostMem = hm + m.scaler = newScaler(m, hm) + go m.scaler.run() + t.Cleanup(func() { + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 2*time.Second) + defer shutdownCancel() + _ = m.Shutdown(shutdownCtx) + }) + + first := registerFn(t, reg, "fair-first", "none") + second := registerFn(t, reg, "fair-second", "none") + for _, fn := range []*database.Function{first, second} { + if err := m.db.UpsertPoolConfig(&database.PoolConfig{ + FunctionID: fn.ID, MinWarm: 0, MaxWarm: 4, IdleTTLS: 600, ScaleToZero: true, + }); err != nil { + t.Fatal(err) + } + } + + ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second) + defer cancel() + firstAcquired := make(chan *AcquireResult, 1) + firstErr := make(chan error, 1) + go func() { + acq, err := m.Acquire(ctx, first.ID) + if err == nil { + firstAcquired <- acq + } else { + firstErr <- err + } + }() + var acq1 *AcquireResult + select { + case acq1 = <-firstAcquired: + case err := <-firstErr: + t.Fatalf("first acquire: %v", err) + case <-ctx.Done(): + t.Fatal("first function never received the only host slot") + } + m.Release(acq1, nil) + + acq2, err := m.Acquire(ctx, second.ID) + if err != nil { + t.Fatalf("queued second function did not receive reclaimed capacity: %v", err) + } + m.Release(acq2, nil) + if got := poolOf(t, m, first.ID).busy.Load(); got != 0 { + t.Fatalf("reclamation touched busy first-function workers: %d", got) + } +} diff --git a/backend/internal/pool/egress_retire_test.go b/backend/internal/pool/egress_retire_test.go index 22defd93..f5627262 100644 --- a/backend/internal/pool/egress_retire_test.go +++ b/backend/internal/pool/egress_retire_test.go @@ -51,7 +51,11 @@ func egressTestManager(t *testing.T) (*Manager, *registry.Registry) { // Stops the reapers getOrCreatePool starts, before the DB cleanup below it // tears the connections down. t.Cleanup(func() { - close(m.shutdown) + select { + case <-m.shutdown: + default: + close(m.shutdown) + } m.wg.Wait() }) return m, m.reg diff --git a/backend/internal/pool/function_pool.go b/backend/internal/pool/function_pool.go index 0b3b9f68..2eb3476c 100644 --- a/backend/internal/pool/function_pool.go +++ b/backend/internal/pool/function_pool.go @@ -2,6 +2,7 @@ package pool import ( "context" + "sort" "sync" "sync/atomic" "time" @@ -19,37 +20,42 @@ type functionPool struct { maxUses int64 // Autoscaler inputs — set at creation time, read by scaler evaluate(). - target int // target_concurrency per worker (pool_config, default 10) memoryBytes int64 // per-worker memory.max budget for admission accounting + cpuUnits int64 // thousandths of a declared CPU per worker scaleToZero bool // pool_config.scale_to_zero // hostMem is the global tracker for admission control. We need a - // back-reference here (not just on the autoscaler) so the request-path - // lazy spawn in acquire() can reserve memory at the same time it - // promotes the worker. Without this, mem_reserved underreports for the - // first ~2s of a hot pool until the autoscaler's tick catches up. + // back-reference here (not just on the controller) so every coordinator + // spawn reserves memory before launch and releases the exact admitted + // amount when that worker exits. hostMem *hostMemTracker - idle chan *sandbox.Worker - busy atomic.Int64 // workers currently handling a request + idle chan *sandbox.Worker + busy atomic.Int64 // workers currently handling a request + queued atomic.Int64 + spawning atomic.Int64 + spawnSlots chan struct{} // at most four concurrent starts for this pool + workerReservations sync.Map // *sandbox.Worker -> workerReservation // Autoscaler signal state — guarded by sigMu. sigMu sync.Mutex - rateEWMA float64 // req/s, α=0.2 on tick-sec buckets - latencyEWMAms float64 // dispatch duration, α=0.2 - memUsedEWMA float64 // memory.current at release (bytes), α=0.2 - cpuFracEWMA float64 // CPU fraction per invocation (0–1), α=0.2 - inflightSamples []int64 // ring of recent busy counts (len = stableWindow/tick) - inflightHead int - bucketCount int64 - belowTargetTicks int // # of consecutive ticks below target (for scale-down gating) + arrivals []time.Time + serviceSamples []time.Duration + spawnSamples []time.Duration + queueWaitSamples []time.Duration + lastArrival time.Time + belowTargetSince time.Time + limitingReason string + memSamples []int64 // Lifetime counters for metrics. - spawned atomic.Int64 - killed atomic.Int64 - scaleUps atomic.Int64 - scaleDowns atomic.Int64 - dynamicMax atomic.Int64 // last computed memory/cpu/operator cap (published for metrics) + spawned atomic.Int64 + killed atomic.Int64 + dynamicMax atomic.Int64 // last computed memory/cpu/operator cap (published for metrics) + desired atomic.Int64 + rejections atomic.Int64 + capacityTimeouts atomic.Int64 + arrivalsTotal atomic.Int64 // mu guards the slow paths (spawn decision, drain). The fast path is // channel-only and lock-free. @@ -67,7 +73,9 @@ type functionPool struct { concSem chan struct{} concPolicy string - spawnFn func(ctx context.Context) (*sandbox.Worker, error) + spawnFn func(ctx context.Context) (*sandbox.Worker, error) + reclaimFn func() bool + requestSpawn func() } // acquireSlot tries to occupy a concurrency slot. Returns nil on success @@ -120,102 +128,153 @@ func (p *functionPool) releaseSlot() { } } -// recordAcquire bumps the rate EWMA. Called from Manager.Acquire on every -// successful worker handout. Cheap atomic-ish bookkeeping — the heavy -// EWMA decay happens in tick() under sigMu. -func (p *functionPool) recordAcquire() { +func (p *functionPool) recordArrival(now time.Time) { + p.arrivalsTotal.Add(1) p.sigMu.Lock() - p.bucketCount++ + p.arrivals = append(p.arrivals, now) + p.lastArrival = now + p.pruneArrivalsLocked(now) p.sigMu.Unlock() } -// recordLatency feeds a dispatch duration into the latency EWMA. func (p *functionPool) recordLatency(d time.Duration) { - ms := float64(d.Milliseconds()) p.sigMu.Lock() - if p.latencyEWMAms == 0 { - p.latencyEWMAms = ms - } else { - p.latencyEWMAms = 0.2*ms + 0.8*p.latencyEWMAms - } + p.serviceSamples = appendDurationSample(p.serviceSamples, d, 512) p.sigMu.Unlock() } -// tick rolls the 1-second bucket: folds this second's count into the EWMA -// and snapshots current inflight into the sliding window. Called by the -// autoscaler on its scaler tick (2s). First-call safe. -func (p *functionPool) tick(bucketSec float64) { +func (p *functionPool) recordQueueWait(d time.Duration) { p.sigMu.Lock() - defer p.sigMu.Unlock() + p.queueWaitSamples = appendDurationSample(p.queueWaitSamples, d, 512) + p.sigMu.Unlock() +} - // Rate EWMA: α = 0.2 over bucketSec-sec observations. - rate := float64(p.bucketCount) / bucketSec - if p.rateEWMA == 0 { - p.rateEWMA = rate - } else { - p.rateEWMA = 0.2*rate + 0.8*p.rateEWMA - } - p.bucketCount = 0 +func (p *functionPool) recordSpawn(d time.Duration) { + p.sigMu.Lock() + p.spawnSamples = appendDurationSample(p.spawnSamples, d, 256) + p.sigMu.Unlock() +} - // Ring buffer of inflight samples. - if len(p.inflightSamples) == 0 { - return // not initialised yet +func appendDurationSample(samples []time.Duration, d time.Duration, limit int) []time.Duration { + if d < 0 { + d = 0 + } + samples = append(samples, d) + if len(samples) > limit { + samples = append([]time.Duration(nil), samples[len(samples)-limit:]...) } - p.inflightSamples[p.inflightHead] = p.busy.Load() - p.inflightHead = (p.inflightHead + 1) % len(p.inflightSamples) + return samples } -// windowMean returns the mean of the last `n` samples in the ring; used for -// the stable and panic windows. n is clamped to the ring size. -func (p *functionPool) windowMean(n int) float64 { - p.sigMu.Lock() - defer p.sigMu.Unlock() - if len(p.inflightSamples) == 0 { +func durationP95(samples []time.Duration) time.Duration { + if len(samples) == 0 { return 0 } - if n > len(p.inflightSamples) { - n = len(p.inflightSamples) + copyOf := append([]time.Duration(nil), samples...) + sort.Slice(copyOf, func(i, j int) bool { return copyOf[i] < copyOf[j] }) + idx := (95*len(copyOf)+99)/100 - 1 + if idx < 0 { + idx = 0 } - var sum int64 - // Walk backward from the current head — most recent n samples. - for i := 0; i < n; i++ { - idx := (p.inflightHead - 1 - i + len(p.inflightSamples)) % len(p.inflightSamples) - sum += p.inflightSamples[idx] + return copyOf[idx] +} + +func (p *functionPool) pruneArrivalsLocked(now time.Time) { + cutoff := now.Add(-stableWindow) + i := 0 + for i < len(p.arrivals) && p.arrivals[i].Before(cutoff) { + i++ + } + if i > 0 { + p.arrivals = append([]time.Time(nil), p.arrivals[i:]...) } - return float64(sum) / float64(n) } -// snapshotSignals returns a point-in-time view for logging/metrics. -func (p *functionPool) snapshotSignals() (rate, latMs float64) { - p.sigMu.Lock() - defer p.sigMu.Unlock() - return p.rateEWMA, p.latencyEWMAms +type demandSnapshot struct { + StableRate float64 + BurstRate float64 + ServiceP95, SpawnP95, QueueWaitP95 time.Duration + LastArrival time.Time + MemoryP95 int64 } -// snapshotResourceUsage returns the per-invocation resource EWMA values. -// memBytes is 0 and cpuFrac is 0 until at least one invocation completes -// with cgroup v2 delegation enabled. -func (p *functionPool) snapshotResourceUsage() (memBytes int64, cpuFrac float64) { +type workerReservation struct { + memoryBytes int64 + cpuUnits int64 +} + +func (p *functionPool) snapshotDemand(now time.Time) demandSnapshot { p.sigMu.Lock() defer p.sigMu.Unlock() - return int64(p.memUsedEWMA), p.cpuFracEWMA + p.pruneArrivalsLocked(now) + burstCutoff := now.Add(-panicWindow) + burst := 0 + for _, at := range p.arrivals { + if !at.Before(burstCutoff) { + burst++ + } + } + mem := append([]int64(nil), p.memSamples...) + sort.Slice(mem, func(i, j int) bool { return mem[i] < mem[j] }) + var memP95 int64 + if len(mem) > 0 { + memP95 = mem[(95*len(mem)+99)/100-1] + } + return demandSnapshot{ + StableRate: float64(len(p.arrivals)) / stableWindow.Seconds(), + BurstRate: float64(burst) / panicWindow.Seconds(), + ServiceP95: durationP95(p.serviceSamples), SpawnP95: durationP95(p.spawnSamples), + QueueWaitP95: durationP95(p.queueWaitSamples), LastArrival: p.lastArrival, + MemoryP95: memP95, + } } -// stampAcquire records the wall time and cumulative CPU usage on the worker -// just before it is handed to a caller. The pool reads these back at release -// to compute per-invocation resource EWMA metrics. -func stampAcquire(w *sandbox.Worker) { - w.AcquireAt = time.Now() - w.AcquireUsec = sandbox.ReadCgroupCPUUsec(w.GetCgroupPath()) +func (p *functionPool) admissionBytes() int64 { + d := p.snapshotDemand(time.Now()) + if d.MemoryP95 <= 0 { + return p.memoryBytes + } + bytes := d.MemoryP95 + if bytes < 16<<20 { + bytes = 16 << 20 + } + if bytes > p.memoryBytes { + bytes = p.memoryBytes + } + return bytes } -// acquire returns an idle worker or spawns a new one up to max. If at max -// it blocks on the idle channel or ctx cancellation. +// acquire returns an idle worker or asks the global coordinator to admit one. +// If the effective cap is reached it waits for an idle worker or cancellation. func (p *functionPool) acquire(ctx context.Context) (*AcquireResult, error) { if p.closing.Load() { return nil, errPoolRetired } // Fast path: non-blocking pop from idle. + select { + case w := <-p.idle: + if p.closing.Load() { + p.killWorker(w) + return nil, errPoolRetired + } + if p.isUnusable(w) { + p.killWorker(w) + return p.acquire(ctx) + } + p.busy.Add(1) + return &AcquireResult{Worker: w, ColdStart: false}, nil + default: + } + // Production pools route every new worker through the manager's global + // round-robin scheduler. Hand-built unit-test pools retain direct spawn. + if p.requestSpawn != nil { + p.requestSpawn() + return p.waitForIdle(ctx) + } + return p.acquireDirect(ctx) +} + +func (p *functionPool) acquireDirect(ctx context.Context) (*AcquireResult, error) { select { case w := <-p.idle: if p.closing.Load() { @@ -226,53 +285,62 @@ func (p *functionPool) acquire(ctx context.Context) (*AcquireResult, error) { // Fall through to spawn below. } else { p.busy.Add(1) - stampAcquire(w) return &AcquireResult{Worker: w, ColdStart: false}, nil } default: } - // Decide whether to spawn. Cap by the autoscaler's dynamic_max (CPU / + // Decide whether to spawn. Cap by the controller's effective maximum (CPU / // memory / operator-cap min), not just the operator hard cap. Without - // this, a burst can blow past what the host can comfortably hold — - // e.g. on a 2-CPU box the autoscaler picks dynamic_max=16 but lazy - // spawn would happily grow to operator p.max (default 50), leaving - // dozens of idle workers that take 60-70 s for the scale-down loop - // to clean up. Capping here turns excess load into fast 503s - // (POOL_AT_CAPACITY) which is the correct backpressure signal. + // this, a hand-built test pool could grow past the capacity calculated by + // the controller. Production pools never use this direct path. dyn := int(p.dynamicMax.Load()) cap := p.max if dyn > 0 && dyn < cap { cap = dyn } p.mu.Lock() - total := int(p.busy.Load()) + len(p.idle) + total := int(p.busy.Load()+p.spawning.Load()) + len(p.idle) canSpawn := total < cap && !p.closing.Load() if canSpawn { - p.busy.Add(1) + select { + case p.spawnSlots <- struct{}{}: + p.spawning.Add(1) + default: + canSpawn = false + } } p.mu.Unlock() if canSpawn { + started := time.Now() + defer func() { <-p.spawnSlots }() // Reserve the worker's memory budget *before* the spawn so the host // memory accounting reflects the new worker immediately. The - // autoscaler does the same in scaleUp(); without it here, lazy - // growth from cold traffic showed mem_reserved=0 for ~2s. - if p.memoryBytes > 0 && p.hostMem != nil { - if !p.hostMem.reserve(p.memoryBytes) { - p.busy.Add(-1) - return nil, ErrMemoryExhausted + // autoscaler does the same in scaleUp(). + reservation := workerReservation{memoryBytes: p.admissionBytes(), cpuUnits: p.cpuUnits} + if p.hostMem != nil { + if !p.hostMem.reserve(reservation.memoryBytes, reservation.cpuUnits) { + reclaimed := p.reclaimFn != nil && p.reclaimFn() + if !reclaimed || !p.hostMem.reserve(reservation.memoryBytes, reservation.cpuUnits) { + p.spawning.Add(-1) + return nil, ErrMemoryExhausted + } } } w, err := p.spawnFn(ctx) if err != nil { - p.busy.Add(-1) - if p.memoryBytes > 0 && p.hostMem != nil { - p.hostMem.release(p.memoryBytes) + p.spawning.Add(-1) + if p.hostMem != nil { + p.hostMem.release(reservation.memoryBytes, reservation.cpuUnits) } return nil, err } + p.spawning.Add(-1) + p.busy.Add(1) + p.recordSpawn(time.Since(started)) p.spawned.Add(1) + p.workerReservations.Store(w, reservation) // Retirement may have happened while spawnFn was starting the // process. Never hand that stale worker to the caller; release its // accounting and let Manager.Acquire retry on the new generation. @@ -284,19 +352,13 @@ func (p *functionPool) acquire(ctx context.Context) (*AcquireResult, error) { p.killWorker(w) return nil, errPoolRetired } - // Count lazy growth as a scale-up event too. Operators watching the - // autoscaler metric want "how often did this pool grow" — which - // includes both the predictive scaler and request-path expansion. - p.scaleUps.Add(1) - stampAcquire(w) return &AcquireResult{Worker: w, ColdStart: true}, nil } - // At max — block until someone releases or ctx fires. ctx-fire here - // specifically means "the pool didn't free up in time" — surface as - // ErrPoolAtCapacity rather than the generic ctx err so the proxy can - // distinguish it from per-fn TimeoutMS expiry (which fires on a - // derived ctx and surfaces as ErrTimeout from Worker.Dispatch). + return p.waitForIdle(ctx) +} + +func (p *functionPool) waitForIdle(ctx context.Context) (*AcquireResult, error) { select { case w := <-p.idle: if p.closing.Load() { @@ -309,11 +371,11 @@ func (p *functionPool) acquire(ctx context.Context) (*AcquireResult, error) { return p.acquire(ctx) } p.busy.Add(1) - stampAcquire(w) - return &AcquireResult{Worker: w, ColdStart: false}, nil + return &AcquireResult{Worker: w, ColdStart: w.Served.Load() == 0}, nil case <-p.retired: return nil, errPoolRetired case <-ctx.Done(): + p.capacityTimeouts.Add(1) return nil, ErrPoolAtCapacity } } @@ -327,35 +389,21 @@ func (p *functionPool) markRetired() { } // release returns the worker to the pool unless it errored or is unusable. -// Also kills the worker when the idle channel already holds at least -// `dynamicMax` workers — this prunes excess capacity from a prior burst as -// soon as their busy work finishes, instead of waiting 60-70 s for the -// autoscaler's scale-down loop to converge. Without this, a 30 s c=200 -// burst left 60+ idle workers parked on a 2-CPU host and made the UI -// feel sluggish for over a minute afterward. +// Also kills the worker when the idle channel already holds at least the +// effective host/operator cap, preventing a completed burst from parking +// workers that the controller can no longer admit. func (p *functionPool) release(w *sandbox.Worker, reqErr error) { p.busy.Add(-1) - // Sample cgroup v2 resource usage for per-function EWMA metrics. + // Sample cgroup v2 memory for observed worker-memory p95 admission. cgPath := w.GetCgroupPath() - if cgPath != "" && !w.AcquireAt.IsZero() { + if cgPath != "" { memCur := sandbox.ReadCgroupMemCurrent(cgPath) - cpuNow := sandbox.ReadCgroupCPUUsec(cgPath) - elapsedUsec := time.Since(w.AcquireAt).Microseconds() p.sigMu.Lock() if memCur > 0 { - if p.memUsedEWMA == 0 { - p.memUsedEWMA = float64(memCur) - } else { - p.memUsedEWMA = 0.2*float64(memCur) + 0.8*p.memUsedEWMA - } - } - if cpuNow > w.AcquireUsec && elapsedUsec > 0 { - frac := float64(cpuNow-w.AcquireUsec) / float64(elapsedUsec) - if p.cpuFracEWMA == 0 { - p.cpuFracEWMA = frac - } else { - p.cpuFracEWMA = 0.2*frac + 0.8*p.cpuFracEWMA + p.memSamples = append(p.memSamples, memCur) + if len(p.memSamples) > 256 { + p.memSamples = append([]int64(nil), p.memSamples[len(p.memSamples)-256:]...) } } p.sigMu.Unlock() @@ -398,7 +446,9 @@ func (p *functionPool) isUnusable(w *sandbox.Worker) bool { if w == nil || w.IsDead() { return true } - if w.IsExpired(p.idleTTL, p.maxUses) { + // idleTTL is a pool-level no-demand signal owned by the controller. A + // worker's age is not idle time and must not silently violate min_warm. + if w.IsExpired(0, p.maxUses) { return true } return false @@ -413,13 +463,17 @@ func (p *functionPool) killWorker(w *sandbox.Worker) { } _ = w.Kill() p.killed.Add(1) - if p.memoryBytes > 0 && p.hostMem != nil { - p.hostMem.release(p.memoryBytes) + reservation := workerReservation{memoryBytes: p.memoryBytes, cpuUnits: p.cpuUnits} + if value, ok := p.workerReservations.LoadAndDelete(w); ok { + reservation = value.(workerReservation) + } + if p.hostMem != nil { + p.hostMem.release(reservation.memoryBytes, reservation.cpuUnits) } } -// sweep walks the idle channel, killing expired workers and putting live -// ones back. Called periodically by the manager's reaper. +// sweep walks the idle channel, killing dead/max-use workers and putting live +// ones back. Pool idle expiry and scale-down are controller decisions. func (p *functionPool) sweep(defaultMaxUses int64) { p.mu.Lock() defer p.mu.Unlock() diff --git a/backend/internal/pool/hostmem.go b/backend/internal/pool/hostmem.go index db06b566..379b0d2e 100644 --- a/backend/internal/pool/hostmem.go +++ b/backend/internal/pool/hostmem.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "os" + "runtime" "strconv" "strings" "sync" @@ -11,18 +12,31 @@ import ( "time" ) -// hostMemTracker polls /proc/meminfo at 1 Hz and exposes the free-memory -// budget to the autoscaler. It also tracks per-function reservations so -// we can check "can this pool grow" without racing. +// workerSlotsPerCPU permits I/O-bound sandboxes to overlap while bounding +// aggregate runnable processes. The demand controller's 70% target provides +// the per-pool operating headroom inside this global ceiling. +const workerSlotsPerCPU = 8 + +// hostMemTracker polls the current cgroup v2 memory usage at 1 Hz when Orva +// is constrained, falling back to /proc/meminfo only on an unconstrained +// host. It also tracks per-worker reservations so concurrent coordinators +// cannot over-admit while a new process is still starting. type hostMemTracker struct { // Static — filled at construction. - totalBytes int64 + totalBytes int64 + cgroupConstrained bool + cgroupCurrentPath string + cpuWorkers int // Dynamic — refreshed by the poller goroutine. availBytes atomic.Int64 // MemAvailable from /proc/meminfo // Tracked reservations (bytes) — sum of (memory.max budget) across all // workers the scaler has promised to spawn. Updated by reserve/release. reserved atomic.Int64 + // CPU reservations are thousandths of a CPU. cpuWorkers is the internal + // count of one-CPU worker slots after applying the cgroup quota. + reservedCPU atomic.Int64 + capacityMu sync.Mutex // reservationPct is the share of host RAM we let workers collectively // claim. 80% by default — leaves headroom for OS + Orva + SQLite. @@ -32,18 +46,28 @@ type hostMemTracker struct { once sync.Once } -// newHostMemTracker reads total RAM and launches the poller. Safe to call -// even in containers — it reads /proc/meminfo which reflects the cgroup -// memory limit on modern kernels (when `memory.max` is set on the cgroup). +// newHostMemTracker discovers the current cgroup v2 hard limit and launches +// the poller. /proc/meminfo is used only when memory.max is absent, unlimited, +// or no tighter than the physical host. func newHostMemTracker(reservationPct float64) (*hostMemTracker, error) { t := &hostMemTracker{ reservationPct: reservationPct, stop: make(chan struct{}), } + hostTotal, _ := readMeminfo("MemTotal") + limit, constrained := readCgroupMemoryLimit(hostTotal) + if constrained { + t.totalBytes = limit + t.cgroupConstrained = true + t.cgroupCurrentPath = "/sys/fs/cgroup/memory.current" + } else { + t.totalBytes = hostTotal + } + t.cpuWorkers = effectiveCPUWorkers() if err := t.refresh(); err != nil { return nil, err } - total, _ := readMeminfo("MemTotal") + total := t.totalBytes if total <= 0 { return nil, errors.New("MemTotal is 0 — /proc/meminfo unavailable?") } @@ -66,10 +90,26 @@ func (t *hostMemTracker) run() { } func (t *hostMemTracker) close() { - t.once.Do(func() { close(t.stop) }) + t.once.Do(func() { + if t.stop != nil { + close(t.stop) + } + }) } func (t *hostMemTracker) refresh() error { + if t.cgroupConstrained { + current, err := readIntFile(t.cgroupCurrentPath) + if err != nil { + return err + } + avail := t.totalBytes - current + if avail < 0 { + avail = 0 + } + t.availBytes.Store(avail) + return nil + } avail, err := readMeminfo("MemAvailable") if err != nil { return err @@ -85,53 +125,80 @@ func (t *hostMemTracker) availableForWorkers() int64 { if total <= 0 { return 0 } - // Reserve reservationPct of total for workers; the rest stays for OS, - // Orva's own heap, SQLite page cache. + // Two independent gates protect the declared/observed reservation budget + // and live physical headroom. Reservations are subtracted from both so a + // worker that is still spawning cannot be admitted twice before its RSS is + // visible in memory.current. budget := int64(float64(total) * t.reservationPct) - avail := t.availBytes.Load() - // Don't let budget exceed what's physically available right now. - if avail < budget { - budget = avail + reserved := t.reserved.Load() + logical := budget - reserved + physical := t.availBytes.Load() + if t.cgroupConstrained { + physical -= total - budget + } + physical -= reserved + out := logical + if physical < out { + out = physical } - out := budget - t.reserved.Load() if out < 0 { out = 0 } return out } +func (t *hostMemTracker) effectiveCPUWorkers() int { + if t == nil || t.cpuWorkers < 1 { + return 1 + } + return t.cpuWorkers +} + +func (t *hostMemTracker) availableCPUUnits() int64 { + available := int64(t.effectiveCPUWorkers())*1000 - t.reservedCPU.Load() + if available < 0 { + return 0 + } + return available +} + // reserve tries to claim `bytes` of RAM. Returns true on success. The // scaler calls this before spawning; if false, scale-up is denied this tick. -func (t *hostMemTracker) reserve(bytes int64) bool { - if bytes <= 0 { - return true +func (t *hostMemTracker) reserve(bytes, cpuUnits int64) bool { + t.capacityMu.Lock() + defer t.capacityMu.Unlock() + if bytes > 0 && t.availableForWorkers() < bytes { + return false } - for { - cur := t.reserved.Load() - avail := t.availableForWorkers() - if avail < bytes { - return false - } - if t.reserved.CompareAndSwap(cur, cur+bytes) { - return true - } + if cpuUnits > 0 && t.availableCPUUnits() < cpuUnits { + return false } + if bytes > 0 { + t.reserved.Add(bytes) + } + if cpuUnits > 0 { + t.reservedCPU.Add(cpuUnits) + } + return true } -// release returns `bytes` to the budget when a worker dies. -func (t *hostMemTracker) release(bytes int64) { - if bytes <= 0 { - return - } - for { - cur := t.reserved.Load() - next := cur - bytes +// release returns a worker's exact memory and CPU reservation. +func (t *hostMemTracker) release(bytes, cpuUnits int64) { + t.capacityMu.Lock() + defer t.capacityMu.Unlock() + if bytes > 0 { + next := t.reserved.Load() - bytes if next < 0 { next = 0 } - if t.reserved.CompareAndSwap(cur, next) { - return + t.reserved.Store(next) + } + if cpuUnits > 0 { + next := t.reservedCPU.Load() - cpuUnits + if next < 0 { + next = 0 } + t.reservedCPU.Store(next) } } @@ -166,3 +233,62 @@ func readMeminfo(key string) (int64, error) { } return 0, errors.New(key + " not found in /proc/meminfo") } + +func readIntFile(path string) (int64, error) { + b, err := os.ReadFile(path) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64) +} + +func readCgroupMemoryLimit(hostTotal int64) (int64, bool) { + b, err := os.ReadFile("/sys/fs/cgroup/memory.max") + if err != nil { + return 0, false + } + return parseCgroupMemoryLimit(string(b), hostTotal) +} + +func parseCgroupMemoryLimit(value string, hostTotal int64) (int64, bool) { + raw := strings.TrimSpace(value) + if raw == "max" { + return 0, false + } + limit, err := strconv.ParseInt(raw, 10, 64) + if err != nil || limit <= 0 || (hostTotal > 0 && limit >= hostTotal) { + return 0, false + } + return limit, true +} + +func effectiveCPUWorkers() int { + return parseCPUQuota(runtime.NumCPU(), readCPUQuota()) +} + +func readCPUQuota() string { + if b, err := os.ReadFile("/sys/fs/cgroup/cpu.max"); err == nil { + return string(b) + } + return "max 100000" +} + +func parseCPUQuota(hostCPUs int, value string) int { + cores := float64(hostCPUs) + fields := strings.Fields(value) + if len(fields) == 2 && fields[0] != "max" { + quota, qerr := strconv.ParseFloat(fields[0], 64) + period, perr := strconv.ParseFloat(fields[1], 64) + if qerr == nil && perr == nil && quota > 0 && period > 0 { + limited := quota / period + if limited < cores { + cores = limited + } + } + } + workers := int(cores * workerSlotsPerCPU) + if workers < 1 { + workers = 1 + } + return workers +} diff --git a/backend/internal/pool/hostmem_v2_test.go b/backend/internal/pool/hostmem_v2_test.go new file mode 100644 index 00000000..371004e4 --- /dev/null +++ b/backend/internal/pool/hostmem_v2_test.go @@ -0,0 +1,42 @@ +package pool + +import "testing" + +func TestCgroupMemoryCapacityKeepsHeadroomAndPendingReservations(t *testing.T) { + hm := &hostMemTracker{totalBytes: 1000, reservationPct: 0.8, cgroupConstrained: true} + hm.availBytes.Store(700) // memory.current=300; 200 bytes remain reserved as host headroom + hm.reserved.Store(100) + if got := hm.availableForWorkers(); got != 400 { + t.Fatalf("available=%d, want physical 500 minus pending reservations 100", got) + } + if !hm.reserve(400, 1000) { + t.Fatal("exact remaining cgroup worker capacity was rejected") + } + if hm.reserve(1, 1) { + t.Fatal("reservation exceeded effective cgroup capacity") + } +} + +func TestUnconstrainedMemoryFallsBackToMemAvailable(t *testing.T) { + hm := &hostMemTracker{totalBytes: 1000, reservationPct: 0.8} + hm.availBytes.Store(600) + hm.reserved.Store(100) + if got := hm.availableForWorkers(); got != 500 { + t.Fatalf("available=%d, want MemAvailable 600 minus reservations 100", got) + } +} + +func TestCgroupLimitAndCPUQuotaParsing(t *testing.T) { + if got, ok := parseCgroupMemoryLimit("536870912\n", 2<<30); !ok || got != 512<<20 { + t.Fatalf("memory limit=%d/%v", got, ok) + } + if _, ok := parseCgroupMemoryLimit("max\n", 2<<30); ok { + t.Fatal("unlimited memory reported as constrained") + } + if got := parseCPUQuota(8, "200000 100000\n"); got != 16 { + t.Fatalf("two-core quota worker slots=%d, want 16", got) + } + if got := parseCPUQuota(4, "max 100000\n"); got != 32 { + t.Fatalf("unlimited quota worker slots=%d, want 32", got) + } +} diff --git a/backend/internal/pool/pool.go b/backend/internal/pool/pool.go index d08260ea..3a3c4412 100644 --- a/backend/internal/pool/pool.go +++ b/backend/internal/pool/pool.go @@ -13,7 +13,7 @@ import ( "errors" "fmt" "log/slog" - "runtime" + "math" "sync" "sync/atomic" "time" @@ -102,6 +102,17 @@ func maxPidsOr(v, fallback int) int { return fallback } +func workerCPUUnits(cpus float64) int64 { + if cpus <= 0 { + return 1000 + } + units := int64(math.Ceil(cpus * 1000)) + if units < 1 { + return 1 + } + return units +} + // Manager owns all function-scoped pools. type Manager struct { cfg ManagerConfig @@ -121,8 +132,7 @@ type Manager struct { // same function (which would race the symlink retarget). fnLocks sync.Map // fnID -> *sync.Mutex - // Autoscaler — Knative-KPA-inspired per-function scaler. Drives - // spawn/kill based on EWMA request rate + concurrency window. + // Pool Controller v2 — demand formulas plus global round-robin admission. scaler *scaler hostMem *hostMemTracker } @@ -157,19 +167,24 @@ type AcquireResult struct { // PoolStats is a point-in-time snapshot for metrics. type PoolStats struct { - FunctionID string - Idle int - Busy int64 - Spawned int64 - Killed int64 - ScaleUps int64 - ScaleDowns int64 - RateEWMA float64 // req/s - LatencyEWMAms float64 // dispatch p-avg in ms - DynamicMax int64 // current memory+cpu-derived cap - Target int - MemUsedAvgBytes int64 // EWMA of memory.current at release; 0 if cgroups disabled - CPUFracAvg float64 // EWMA of CPU fraction per invocation (0–1); 0 if cgroups disabled + FunctionID string + Idle int + Busy int64 + Queued int64 + Spawning int64 + Arrivals int64 + Spawned int64 + Killed int64 + Desired int64 + EffectiveMax int64 + StableRate float64 + BurstRate float64 + QueueWaitP95MS float64 + ServiceP95MS float64 + ColdStartP95MS float64 + LimitingReason string + Rejections int64 + CapacityTimeouts int64 } // SetSecretsLookup wires the secrets fetcher into the pool template after @@ -225,6 +240,22 @@ func (m *Manager) HostMemStats() (total, avail, reserved int64) { return m.hostMem.stats() } +func (m *Manager) EffectiveCPUCapacity() int { + if m.hostMem == nil { + return 1 + } + return m.hostMem.effectiveCPUWorkers() +} + +// EffectiveMemoryCapacity returns the bytes still available for worker +// admission after cgroup headroom and all in-flight/live reservations. +func (m *Manager) EffectiveMemoryCapacity() int64 { + if m.hostMem == nil { + return 0 + } + return m.hostMem.availableForWorkers() +} + var ( // ErrManagerClosed is returned from Acquire after Shutdown. ErrManagerClosed = errors.New("pool manager closed") @@ -258,17 +289,12 @@ func NewManager(cfg ManagerConfig, tmpl SandboxTemplate, db *database.Database, cfg.DefaultMin = 1 } if cfg.DefaultMax <= 0 { - cfg.DefaultMax = 5 + cfg.DefaultMax = 50 } if cfg.DefaultIdleTTL <= 0 { - // 2 min — long enough that a function with steady traffic always - // keeps its warm pool alive, short enough that workers from a - // one-off burst don't loiter for ten minutes. The release-path - // prune above handles the burst case directly; this catches - // trickier scenarios like "warm pool grew, then traffic dropped - // to a slow trickle that keeps the pool from being idle but - // doesn't justify the scaled-up size." - cfg.DefaultIdleTTL = 2 * time.Minute + // Public/default contract: ten minutes before an opted-in + // scale-to-zero pool may discard its final warm worker. + cfg.DefaultIdleTTL = 10 * time.Minute } if cfg.ReapInterval <= 0 { cfg.ReapInterval = 30 * time.Second @@ -301,27 +327,37 @@ func (m *Manager) Acquire(ctx context.Context, fnID string) (*AcquireResult, err return nil, ErrManagerClosed } - // Respect the host-wide concurrency ceiling first. This prevents the + p, err := m.getOrCreatePool(fnID) + if err != nil { + return nil, err + } + arrivedAt := time.Now() + p.recordArrival(arrivedAt) + p.queued.Add(1) + finishQueue := func(pool *functionPool, rejected bool) { + pool.queued.Add(-1) + pool.recordQueueWait(time.Since(arrivedAt)) + if rejected { + pool.rejections.Add(1) + } + } + + // Respect the host-wide concurrency ceiling after recording demand. // sum of every pool's max_warm from overwhelming the box even if each // pool is within its own limit. TryAcquire returns ErrTooManyRequests // after a 250ms grace — long enough to ride out micro-spikes, short // enough to fail fast under sustained saturation. if m.limiter != nil { if err := m.limiter.TryAcquire(ctx, 250*time.Millisecond); err != nil { + p.capacityTimeouts.Add(1) + finishQueue(p, true) return nil, err } } for { if err := ctx.Err(); err != nil { - if m.limiter != nil { - m.limiter.Release() - } - return nil, err - } - - p, err := m.getOrCreatePool(fnID) - if err != nil { + finishQueue(p, true) if m.limiter != nil { m.limiter.Release() } @@ -333,8 +369,21 @@ func (m *Manager) Acquire(ctx context.Context, fnID string) (*AcquireResult, err // out. A generation retired while waiting is retried transparently. if err := p.acquireSlot(ctx); err != nil { if errors.Is(err, errPoolRetired) { + p.queued.Add(-1) + p, err = m.getOrCreatePool(fnID) + if err != nil { + if m.limiter != nil { + m.limiter.Release() + } + return nil, err + } + p.queued.Add(1) continue } + if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { + p.capacityTimeouts.Add(1) + } + finishQueue(p, true) if m.limiter != nil { m.limiter.Release() } @@ -345,33 +394,32 @@ func (m *Manager) Acquire(ctx context.Context, fnID string) (*AcquireResult, err if err != nil { p.releaseSlot() if errors.Is(err, errPoolRetired) { + p.queued.Add(-1) + p, err = m.getOrCreatePool(fnID) + if err != nil { + if m.limiter != nil { + m.limiter.Release() + } + return nil, err + } + p.queued.Add(1) continue } + finishQueue(p, true) if m.limiter != nil { m.limiter.Release() } return nil, err } res.pool = p - // Bump autoscaler signal so rate EWMA reflects real traffic. - // - // v0.4 C1 caveat (streaming): every Acquire bumps the rate counter - // once, but a streaming request holds the worker for the full - // response duration (potentially up to stream_max_seconds = 300s). - // The autoscaler will see "1 req/burst" and a long latency EWMA, so - // Little's-Law floor inflates apparent target concurrency. For - // mixed streaming + non-streaming workloads this can over-provision. - // We accept the tradeoff for v1; if it becomes a real problem we - // could weight streaming acquires differently or sample inflight - // concurrency separately. — TODO(autoscaler-streaming-weight) - p.recordAcquire() + finishQueue(p, false) return res, nil } } -// RecordLatency feeds a per-request dispatch latency sample into the -// function's EWMA. Called by the proxy after Dispatch returns (success or -// error). Non-blocking, safe from any goroutine. +// RecordLatency feeds a per-request service-time sample into the +// function's rolling p95. Every dispatch path calls it after user code returns +// or fails. Non-blocking and safe from any goroutine. func (m *Manager) RecordLatency(acq *AcquireResult, d time.Duration) { if acq != nil && acq.pool != nil { acq.pool.recordLatency(d) @@ -520,30 +568,38 @@ func (m *Manager) Stats() []PoolStats { out := make([]PoolStats, 0) m.pools.Range(func(k, v any) bool { p := v.(*functionPool) - rate, lat := p.snapshotSignals() - memUsed, cpuFrac := p.snapshotResourceUsage() + demand := p.snapshotDemand(time.Now()) + p.sigMu.Lock() + reason := p.limitingReason + p.sigMu.Unlock() out = append(out, PoolStats{ - FunctionID: k.(string), - Idle: len(p.idle), - Busy: p.busy.Load(), - Spawned: p.spawned.Load(), - Killed: p.killed.Load(), - ScaleUps: p.scaleUps.Load(), - ScaleDowns: p.scaleDowns.Load(), - RateEWMA: rate, - LatencyEWMAms: lat, - DynamicMax: p.dynamicMax.Load(), - Target: p.target, - MemUsedAvgBytes: memUsed, - CPUFracAvg: cpuFrac, + FunctionID: k.(string), + Idle: len(p.idle), + Busy: p.busy.Load(), + Queued: p.queued.Load(), + Spawning: p.spawning.Load(), + Arrivals: p.arrivalsTotal.Load(), + Spawned: p.spawned.Load(), + Killed: p.killed.Load(), + Desired: p.desired.Load(), + EffectiveMax: p.dynamicMax.Load(), + StableRate: demand.StableRate, + BurstRate: demand.BurstRate, + QueueWaitP95MS: float64(demand.QueueWaitP95.Microseconds()) / 1000, + ServiceP95MS: float64(demand.ServiceP95.Microseconds()) / 1000, + ColdStartP95MS: float64(demand.SpawnP95.Microseconds()) / 1000, + LimitingReason: reason, + Rejections: p.rejections.Load(), + CapacityTimeouts: p.capacityTimeouts.Load(), }) return true }) return out } -// PrewarmAll spawns min_warm workers for every active function. Runs with -// bounded parallelism (NumCPU*2) so startup doesn't monopolize the box. +// PrewarmAll registers every active pool, then lets the global coordinator +// fill configured minimums in round-robin order. It returns when each pool is +// warm or its effective host cap proves the minimum cannot currently fit. func (m *Manager) PrewarmAll(ctx context.Context) { if !m.cfg.EagerWarmup || m.reg == nil { return @@ -554,57 +610,47 @@ func (m *Manager) PrewarmAll(ctx context.Context) { } slog.Info("pool prewarm starting", "functions", len(fns)) - sem := make(chan struct{}, runtime.NumCPU()*2) - var wg sync.WaitGroup + pools := make([]*functionPool, 0, len(fns)) for _, fn := range fns { - wg.Add(1) - go func(fnID string) { - defer wg.Done() - sem <- struct{}{} - defer func() { <-sem }() - - p, err := m.getOrCreatePool(fnID) - if err != nil { - slog.Warn("prewarm: get pool failed", "fn", fnID, "err", err) - return - } - p.mu.Lock() - min := p.min - p.mu.Unlock() - for i := 0; i < min; i++ { - if p.memoryBytes > 0 && p.hostMem != nil { - if !p.hostMem.reserve(p.memoryBytes) { - return - } - } - w, err := p.spawnFn(ctx) - if err != nil { - if p.memoryBytes > 0 && p.hostMem != nil { - p.hostMem.release(p.memoryBytes) - } - slog.Warn("prewarm spawn failed", "fn", fnID, "err", err) - return - } - p.spawned.Add(1) - p.mu.Lock() - parked := false - if !p.closing.Load() { - select { - case p.idle <- w: - parked = true - default: - } - } - p.mu.Unlock() - if parked { - continue - } - p.killWorker(w) - return + p, err := m.getOrCreatePool(fn.ID) + if err != nil { + slog.Warn("prewarm: get pool failed", "fn", fn.ID, "err", err) + continue + } + pools = append(pools, p) + } + if m.scaler == nil { + slog.Warn("pool prewarm skipped: host capacity coordinator unavailable") + return + } + m.scaler.nudge() + waitLimit := time.NewTimer(30 * time.Second) + defer waitLimit.Stop() + ticker := time.NewTicker(50 * time.Millisecond) + defer ticker.Stop() + for { + settled := true + for _, p := range pools { + current := int(p.busy.Load()+p.spawning.Load()) + len(p.idle) + effective := int(p.dynamicMax.Load()) + if current < p.min && (effective >= p.min || p.spawning.Load() > 0) { + settled = false + break } - }(fn.ID) + } + if settled { + break + } + select { + case <-ctx.Done(): + slog.Warn("pool prewarm stopped", "err", ctx.Err()) + return + case <-waitLimit.C: + slog.Warn("pool prewarm timed out; coordinator will continue in background") + return + case <-ticker.C: + } } - wg.Wait() slog.Info("pool prewarm complete") } @@ -643,21 +689,13 @@ func (m *Manager) getOrCreatePool(fnID string) (*functionPool, error) { minWarm := m.cfg.DefaultMin maxWarm := m.cfg.DefaultMax idleTTL := m.cfg.DefaultIdleTTL - targetConc := 10 // pool_config default; Knative-style target concurrency per worker scaleToZero := false if cfg, err := m.db.GetPoolConfig(fnID); err == nil && cfg != nil { - if cfg.MinWarm > 0 { - minWarm = cfg.MinWarm - } + minWarm = cfg.MinWarm if cfg.MaxWarm > 0 { maxWarm = cfg.MaxWarm } - if cfg.IdleTTLS > 0 { - idleTTL = time.Duration(cfg.IdleTTLS) * time.Second - } - if cfg.TargetConcurrency > 0 { - targetConc = cfg.TargetConcurrency - } + idleTTL = time.Duration(cfg.IdleTTLS) * time.Second scaleToZero = cfg.ScaleToZero } @@ -677,13 +715,24 @@ func (m *Manager) getOrCreatePool(fnID string) (*functionPool, error) { if memoryBytes < 16*1024*1024 { memoryBytes = 16 * 1024 * 1024 // 16MB floor so the budget math doesn't go wild on tiny fns } + cpuUnits := workerCPUUnits(fn.CPUs) - // Dynamic channel size: let the scaler grow up to a safe ceiling far - // beyond the operator's cap. If the operator's max_warm is raised at - // runtime (future feature), we won't need to rebuild the channel. + // Allocate idle-worker storage from effective host capacity. max_warm is + // still a hard operator ceiling, but never directly controls allocation. channelCap := maxWarm - if channelCap < 64 { - channelCap = 64 + if m.hostMem != nil { + if cpuCap := int(int64(m.hostMem.effectiveCPUWorkers()) * 1000 / cpuUnits); cpuCap < channelCap { + channelCap = cpuCap + } + if memoryBytes > 0 { + total, _, _ := m.hostMem.stats() + if memCap := int(float64(total)*0.8) / int(memoryBytes); memCap < channelCap { + channelCap = memCap + } + } + } + if channelCap < 1 { + channelCap = 1 } // Per-function concurrency cap: if set, gate every Acquire on a @@ -703,11 +752,12 @@ func (m *Manager) getOrCreatePool(fnID string) (*functionPool, error) { max: maxWarm, idleTTL: idleTTL, maxUses: m.cfg.DefaultMaxUses, - target: targetConc, memoryBytes: memoryBytes, + cpuUnits: cpuUnits, scaleToZero: scaleToZero, hostMem: m.hostMem, idle: make(chan *sandbox.Worker, channelCap), + spawnSlots: make(chan struct{}, maxConcurrentSpawnsPerPool), retired: make(chan struct{}), concSem: concSem, concPolicy: concPolicy, @@ -784,6 +834,11 @@ func (m *Manager) getOrCreatePool(fnID string) (*functionPool, error) { return w, err }, } + p.dynamicMax.Store(int64(channelCap)) + if m.scaler != nil { + p.reclaimFn = func() bool { return m.scaler.reclaimBorrowedIdle(p) } + p.requestSpawn = m.scaler.nudge + } // Store — but if another goroutine raced us, discard our pool. actual, loaded := m.pools.LoadOrStore(fnID, p) @@ -791,11 +846,6 @@ func (m *Manager) getOrCreatePool(fnID string) (*functionPool, error) { return actual.(*functionPool), nil } - // Initialise the autoscaler signal ring for this pool. - if m.scaler != nil { - m.scaler.ensureSignals(p) - } - // Start the background reaper for this pool. m.wg.Add(1) go m.reap(p) diff --git a/backend/internal/pool/pool_generation_test.go b/backend/internal/pool/pool_generation_test.go index 14002f22..d68d99b3 100644 --- a/backend/internal/pool/pool_generation_test.go +++ b/backend/internal/pool/pool_generation_test.go @@ -169,6 +169,7 @@ func testPool(fnID string, hm *hostMemTracker, memoryBytes int64) *functionPool memoryBytes: memoryBytes, hostMem: hm, idle: make(chan *sandbox.Worker, 4), + spawnSlots: make(chan struct{}, 4), retired: make(chan struct{}), concSem: make(chan struct{}, 1), } diff --git a/backend/internal/sandbox/sandbox.go b/backend/internal/sandbox/sandbox.go index fb2d4b12..cfea90a1 100644 --- a/backend/internal/sandbox/sandbox.go +++ b/backend/internal/sandbox/sandbox.go @@ -571,22 +571,3 @@ func ReadCgroupMemCurrent(cgPath string) int64 { v, _ := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) return v } - -// ReadCgroupCPUUsec reads the cumulative usage_usec from cpu.stat in a -// cgroup v2 directory. Returns 0 on any error. -func ReadCgroupCPUUsec(cgPath string) int64 { - if cgPath == "" { - return 0 - } - data, err := os.ReadFile(filepath.Join(cgPath, "cpu.stat")) - if err != nil { - return 0 - } - for _, line := range strings.Split(string(data), "\n") { - if strings.HasPrefix(line, "usage_usec ") { - v, _ := strconv.ParseInt(strings.TrimPrefix(line, "usage_usec "), 10, 64) - return v - } - } - return 0 -} diff --git a/backend/internal/sandbox/worker.go b/backend/internal/sandbox/worker.go index 61c4443b..8f622189 100644 --- a/backend/internal/sandbox/worker.go +++ b/backend/internal/sandbox/worker.go @@ -36,12 +36,8 @@ type Worker struct { // CgroupPath is resolved asynchronously after Spawn (nsjail names the // cgroup after its jailed child's PID, which isn't known until after fork). - // AcquireUsec and AcquireAt are stamped by the pool before handing the - // worker to a caller and read at release for per-function EWMA metrics. cgroupPathMu sync.Mutex CgroupPath string - AcquireUsec int64 - AcquireAt time.Time // mu serializes Dispatch calls defensively. The pool contract is that // only one goroutine holds a Worker at a time, so the lock is just a diff --git a/backend/internal/scheduler/scheduler.go b/backend/internal/scheduler/scheduler.go index 88ccab9f..fae6a82d 100644 --- a/backend/internal/scheduler/scheduler.go +++ b/backend/internal/scheduler/scheduler.go @@ -390,7 +390,9 @@ func (s *Scheduler) fireCron(parent context.Context, row *database.CronSchedule) releaseExecution := s.sdkAuth.BindExecution(execID, fn.ID, traceID, spanID, ranAt) defer releaseExecution() + dispatchStarted := time.Now() respJSON, stderr, err := acq.Worker.Dispatch(ctx, eventJSON) + s.pool.RecordLatency(acq, time.Since(dispatchStarted)) if err != nil { reqErr = err errMsg := err.Error() @@ -697,7 +699,9 @@ func (s *Scheduler) runJob(parent context.Context, j *database.Job) { releaseExecution := s.sdkAuth.BindExecution(execID, fn.ID, traceID, spanID, startedAt) defer releaseExecution() + dispatchStarted := time.Now() respJSON, stderr, err := acq.Worker.Dispatch(ctx, eventJSON) + s.pool.RecordLatency(acq, time.Since(dispatchStarted)) if err != nil { reqErr = err s.recordExecution(execID, fn.ID, "error", 0, startedAt, stderr, err.Error(), diff --git a/backend/internal/server/handlers/errmap.go b/backend/internal/server/handlers/errmap.go index b5467a40..047ba42a 100644 --- a/backend/internal/server/handlers/errmap.go +++ b/backend/internal/server/handlers/errmap.go @@ -47,12 +47,12 @@ func invokeError(err error, fn *database.Function, requestID string) (status int } } return http.StatusTooManyRequests, respond.ErrorOpts{ - Code: "FUNCTION_BUSY", - Message: fmt.Sprintf("function %s is at its concurrency cap", funcLabel(fn)), - RequestID: requestID, - Hint: "raise functions.max_concurrency or switch the policy to 'queue' to wait for a slot", + Code: "FUNCTION_BUSY", + Message: fmt.Sprintf("function %s is at its concurrency cap", funcLabel(fn)), + RequestID: requestID, + Hint: "raise functions.max_concurrency or switch the policy to 'queue' to wait for a slot", RetryAfterS: 1, - Details: details, + Details: details, } case errors.Is(err, pool.ErrPoolAtCapacity): @@ -62,27 +62,27 @@ func invokeError(err error, fn *database.Function, requestID string) (status int details["function_name"] = fn.Name } return http.StatusServiceUnavailable, respond.ErrorOpts{ - Code: "POOL_AT_CAPACITY", - Message: fmt.Sprintf("function pool at capacity for %s", funcLabel(fn)), - RequestID: requestID, - Hint: "raise pool_config.max_warm via PUT /api/v1/pool/config or reduce client concurrency", + Code: "POOL_AT_CAPACITY", + Message: fmt.Sprintf("function pool at capacity for %s", funcLabel(fn)), + RequestID: requestID, + Hint: "inspect pool limiting_reason; raise max_warm only for operator_max, otherwise add host capacity or reduce worker limits", RetryAfterS: 5, - Details: details, + Details: details, } case errors.Is(err, pool.ErrMemoryExhausted): return http.StatusServiceUnavailable, respond.ErrorOpts{ Code: "MEMORY_EXHAUSTED", Message: "host memory budget exhausted", - RequestID: requestID, - Hint: "deploy fewer concurrent functions or increase host RAM; see /api/v1/system/metrics.json host.mem_*", + RequestID: requestID, + Hint: "deploy fewer concurrent functions or increase host RAM; see /api/v1/system/metrics.json host.mem_*", RetryAfterS: 30, } case errors.Is(err, sandbox.ErrTooManyRequests): return http.StatusTooManyRequests, respond.ErrorOpts{ Code: "TOO_MANY_REQUESTS", Message: "host concurrency cap reached", - RequestID: requestID, - Hint: "back off briefly and retry; raise cfg.Sandbox.MaxConcurrent if persistent", + RequestID: requestID, + Hint: "back off briefly and retry; raise cfg.Sandbox.MaxConcurrent if persistent", RetryAfterS: 1, } @@ -94,10 +94,10 @@ func invokeError(err error, fn *database.Function, requestID string) (status int // Retry-After tracks the manager's 10s recompile tick. case errors.Is(err, firewall.ErrPolicyUnavailable), errors.Is(err, sandbox.ErrEgressPolicyMissing): return http.StatusServiceUnavailable, respond.ErrorOpts{ - Code: "EGRESS_POLICY_UNAVAILABLE", - Message: "no sandbox egress policy is in force; refusing to start an unfiltered egress worker", - RequestID: requestID, - Hint: "see GET /api/v1/firewall/status (last_compile_error) — fix the offending rule, then POST /api/v1/firewall/resolve", + Code: "EGRESS_POLICY_UNAVAILABLE", + Message: "no sandbox egress policy is in force; refusing to start an unfiltered egress worker", + RequestID: requestID, + Hint: "see GET /api/v1/firewall/status (last_compile_error) — fix the offending rule, then POST /api/v1/firewall/resolve", RetryAfterS: 10, } @@ -162,8 +162,8 @@ func deployError(err error, requestID string, queueDepth int) (status int, opts retry = 300 } return http.StatusServiceUnavailable, respond.ErrorOpts{ - Code: "BUILD_QUEUE_FULL", - Message: fmt.Sprintf("build queue full (%d pending)", queueDepth), + Code: "BUILD_QUEUE_FULL", + Message: fmt.Sprintf("build queue full (%d pending)", queueDepth), RequestID: requestID, Hint: "wait for current builds to drain; consider raising NumCPU or staggering deploys", RetryAfterS: retry, @@ -176,8 +176,8 @@ func deployError(err error, requestID string, queueDepth int) (status int, opts } case errors.Is(err, builder.ErrInsufficientDisk): return http.StatusServiceUnavailable, respond.ErrorOpts{ - Code: "INSUFFICIENT_DISK", - Message: "insufficient free disk space to start the build", + Code: "INSUFFICIENT_DISK", + Message: "insufficient free disk space to start the build", RequestID: requestID, Hint: "free space on the data volume or lower system_config.min_free_disk_mb; see docs/CAPACITY.md", } diff --git a/backend/internal/server/handlers/inbound_webhook_trigger.go b/backend/internal/server/handlers/inbound_webhook_trigger.go index b2c4851e..526461e5 100644 --- a/backend/internal/server/handlers/inbound_webhook_trigger.go +++ b/backend/internal/server/handlers/inbound_webhook_trigger.go @@ -187,7 +187,9 @@ func (h *InboundTriggerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request releaseExecution := h.SDKAuth.BindExecution(execID, fn.ID, traceID, spanID, startedAt) defer releaseExecution() + dispatchStarted := time.Now() respJSON, stderr, err := acq.Worker.Dispatch(ctx, eventJSON) + h.Pool.RecordLatency(acq, time.Since(dispatchStarted)) durationMS := time.Since(startedAt).Milliseconds() if err != nil { reqErr = err diff --git a/backend/internal/server/handlers/internal_invoke.go b/backend/internal/server/handlers/internal_invoke.go index 5e57fd2c..3b66b99b 100644 --- a/backend/internal/server/handlers/internal_invoke.go +++ b/backend/internal/server/handlers/internal_invoke.go @@ -153,7 +153,9 @@ func (h *InternalInvokeHandler) Invoke(w http.ResponseWriter, r *http.Request) { } eventJSON, _ := json.Marshal(event) + dispatchStarted := time.Now() respJSON, _, err := acq.Worker.Dispatch(ctx, eventJSON) + h.Pool.RecordLatency(acq, time.Since(dispatchStarted)) durationMS := time.Since(start).Milliseconds() if err != nil { reqErr = err @@ -323,7 +325,9 @@ func (h *InternalInvokeHandler) InvokeStream(w http.ResponseWriter, r *http.Requ } eventJSON, _ := json.Marshal(event) + dispatchStarted := time.Now() dres, err := acq.Worker.DispatchEx(ctx, eventJSON) + h.Pool.RecordLatency(acq, time.Since(dispatchStarted)) if err != nil { reqErr = err errMsg := err.Error() diff --git a/backend/internal/server/handlers/pool.go b/backend/internal/server/handlers/pool.go index 46a9aa70..994e8776 100644 --- a/backend/internal/server/handlers/pool.go +++ b/backend/internal/server/handlers/pool.go @@ -18,12 +18,11 @@ type PoolConfigHandler struct { } type poolConfigBody struct { - FunctionID string `json:"function_id"` - MinWarm *int `json:"min_warm"` - MaxWarm *int `json:"max_warm"` - IdleTTLSeconds *int `json:"idle_ttl_seconds"` - TargetConcurrency *int `json:"target_concurrency"` - ScaleToZero *bool `json:"scale_to_zero"` + FunctionID string `json:"function_id"` + MinWarm *int `json:"min_warm"` + MaxWarm *int `json:"max_warm"` + IdleTTLSeconds *int `json:"idle_ttl_seconds"` + ScaleToZero *bool `json:"scale_to_zero"` } // Get handles GET /api/v1/pool/config?function_id=. @@ -53,8 +52,18 @@ func (h *PoolConfigHandler) Get(w http.ResponseWriter, r *http.Request) { func (h *PoolConfigHandler) Upsert(w http.ResponseWriter, r *http.Request) { reqID := r.Header.Get("X-Request-ID") + var raw map[string]json.RawMessage + if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10)).Decode(&raw); err != nil { + respond.Error(w, http.StatusBadRequest, "INVALID_JSON", "invalid request body", reqID) + return + } + if _, stale := raw["target_concurrency"]; stale { + respond.Error(w, http.StatusBadRequest, "VALIDATION", "target_concurrency was removed; Pool Controller v2 sizes workers automatically from arrival rate, service time, and spawn time", reqID) + return + } + encoded, _ := json.Marshal(raw) var body poolConfigBody - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + if err := json.Unmarshal(encoded, &body); err != nil { respond.Error(w, http.StatusBadRequest, "INVALID_JSON", "invalid request body", reqID) return } @@ -71,12 +80,8 @@ func (h *PoolConfigHandler) Upsert(w http.ResponseWriter, r *http.Request) { cfg, err := h.DB.GetPoolConfig(body.FunctionID) if err != nil || cfg == nil { cfg = &database.PoolConfig{ - FunctionID: body.FunctionID, - MinWarm: 1, - MaxWarm: 50, - IdleTTLS: 600, - TargetConcurrency: 10, - ScaleToZero: false, + FunctionID: body.FunctionID, + MinWarm: 1, MaxWarm: 50, IdleTTLS: 600, ScaleToZero: false, } } @@ -89,12 +94,26 @@ func (h *PoolConfigHandler) Upsert(w http.ResponseWriter, r *http.Request) { if body.IdleTTLSeconds != nil { cfg.IdleTTLS = *body.IdleTTLSeconds } - if body.TargetConcurrency != nil { - cfg.TargetConcurrency = *body.TargetConcurrency - } if body.ScaleToZero != nil { cfg.ScaleToZero = *body.ScaleToZero } + if body.MinWarm != nil { + if cfg.ScaleToZero && cfg.MinWarm != 0 { + respond.Error(w, http.StatusBadRequest, "VALIDATION", "scale_to_zero=true requires min_warm=0", reqID) + return + } + if !cfg.ScaleToZero && cfg.MinWarm < 1 { + respond.Error(w, http.StatusBadRequest, "VALIDATION", "scale_to_zero=false requires min_warm>=1", reqID) + return + } + } + if body.ScaleToZero != nil && body.MinWarm == nil { + if cfg.ScaleToZero { + cfg.MinWarm = 0 + } else if cfg.MinWarm < 1 { + cfg.MinWarm = 1 + } + } if cfg.MinWarm < 0 || cfg.MaxWarm < 1 || cfg.MinWarm > cfg.MaxWarm { respond.Error(w, http.StatusBadRequest, "VALIDATION", "require 0 <= min_warm <= max_warm and max_warm >= 1", reqID) @@ -104,11 +123,6 @@ func (h *PoolConfigHandler) Upsert(w http.ResponseWriter, r *http.Request) { respond.Error(w, http.StatusBadRequest, "VALIDATION", "idle_ttl_seconds must be >= 0", reqID) return } - if cfg.TargetConcurrency < 1 { - respond.Error(w, http.StatusBadRequest, "VALIDATION", "target_concurrency must be >= 1", reqID) - return - } - if err := h.DB.UpsertPoolConfig(cfg); err != nil { respond.Error(w, http.StatusInternalServerError, "INTERNAL", "failed to upsert pool config", reqID) return diff --git a/backend/internal/server/handlers/pool_v2_test.go b/backend/internal/server/handlers/pool_v2_test.go new file mode 100644 index 00000000..5887f6cc --- /dev/null +++ b/backend/internal/server/handlers/pool_v2_test.go @@ -0,0 +1,91 @@ +package handlers + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "path/filepath" + "strings" + "testing" + + "github.com/Harsh-2002/Orva/backend/internal/database" + "github.com/Harsh-2002/Orva/backend/internal/registry" +) + +func poolV2Handler(t *testing.T) (*PoolConfigHandler, *database.Function) { + t.Helper() + db, err := database.New(filepath.Join(t.TempDir(), "pool-handler.db")) + if err != nil { + t.Fatal(err) + } + if err := db.Migrate(); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = db.Close() }) + reg := registry.New(db) + fn := &database.Function{Name: "pool-handler", Runtime: "node", Entrypoint: "handler.js", MemoryMB: 64, CPUs: 1, TimeoutMS: 1000, Status: "active"} + if err := reg.Set(fn); err != nil { + t.Fatal(err) + } + return &PoolConfigHandler{DB: db, Registry: reg}, fn +} + +func putPoolConfig(t *testing.T, h *PoolConfigHandler, body any) *httptest.ResponseRecorder { + t.Helper() + b, err := json.Marshal(body) + if err != nil { + t.Fatal(err) + } + req := httptest.NewRequest(http.MethodPut, "/api/v1/pool/config", bytes.NewReader(b)) + w := httptest.NewRecorder() + h.Upsert(w, req) + return w +} + +func TestPoolConfigRejectsRemovedTargetConcurrency(t *testing.T) { + h, fn := poolV2Handler(t) + w := putPoolConfig(t, h, map[string]any{"function_id": fn.ID, "target_concurrency": 4}) + if w.Code != http.StatusBadRequest { + t.Fatalf("status=%d body=%s", w.Code, w.Body.String()) + } + if !strings.Contains(w.Body.String(), "Pool Controller v2") || !strings.Contains(w.Body.String(), "VALIDATION") { + t.Fatalf("missing migration guidance: %s", w.Body.String()) + } +} + +func TestPoolConfigScaleContract(t *testing.T) { + h, fn := poolV2Handler(t) + w := putPoolConfig(t, h, map[string]any{"function_id": fn.ID, "scale_to_zero": true}) + if w.Code != http.StatusOK { + t.Fatalf("enable: %d %s", w.Code, w.Body.String()) + } + var cfg database.PoolConfig + if err := json.Unmarshal(w.Body.Bytes(), &cfg); err != nil { + t.Fatal(err) + } + if cfg.MinWarm != 0 || !cfg.ScaleToZero { + t.Fatalf("enable result: %+v", cfg) + } + + w = putPoolConfig(t, h, map[string]any{"function_id": fn.ID, "scale_to_zero": false}) + if w.Code != http.StatusOK { + t.Fatalf("disable: %d %s", w.Code, w.Body.String()) + } + if err := json.Unmarshal(w.Body.Bytes(), &cfg); err != nil { + t.Fatal(err) + } + if cfg.MinWarm != 1 || cfg.ScaleToZero { + t.Fatalf("disable result: %+v", cfg) + } + + w = putPoolConfig(t, h, map[string]any{"function_id": fn.ID, "scale_to_zero": true, "min_warm": 2}) + if w.Code != http.StatusBadRequest { + t.Fatalf("incompatible pair status=%d", w.Code) + } + + w = putPoolConfig(t, h, map[string]any{"function_id": fn.ID, "min_warm": 0}) + if w.Code != http.StatusBadRequest { + t.Fatalf("active min zero status=%d", w.Code) + } +} diff --git a/backend/internal/server/handlers/replay.go b/backend/internal/server/handlers/replay.go index 1adc4627..ce0bf950 100644 --- a/backend/internal/server/handlers/replay.go +++ b/backend/internal/server/handlers/replay.go @@ -183,7 +183,9 @@ func (h *ReplayHandler) Replay(w http.ResponseWriter, r *http.Request) { releaseExecution := h.SDKAuth.BindExecution(newExecID, fn.ID, traceID, spanID, start) defer releaseExecution() + dispatchStarted := time.Now() respJSON, stderr, err := acq.Worker.Dispatch(ctx, eventJSON) + h.Pool.RecordLatency(acq, time.Since(dispatchStarted)) duration := time.Since(start) if h.Metrics != nil { h.Metrics.RecordDuration(duration) diff --git a/backend/internal/server/handlers/system.go b/backend/internal/server/handlers/system.go index d2f0c2ce..0ca6b67c 100644 --- a/backend/internal/server/handlers/system.go +++ b/backend/internal/server/handlers/system.go @@ -53,12 +53,14 @@ type MetricsJSONShape struct { } type hostBlock struct { - NumCPU int `json:"num_cpu"` - NumGoroutines int `json:"num_goroutines"` - OrvaAllocMB int64 `json:"orva_alloc_mb"` - MemTotalMB int64 `json:"mem_total_mb"` - MemAvailableMB int64 `json:"mem_available_mb"` - MemReservedMB int64 `json:"mem_reserved_mb"` + NumCPU int `json:"num_cpu"` + EffectiveCPUWorkers int `json:"effective_cpu_workers"` + NumGoroutines int `json:"num_goroutines"` + OrvaAllocMB int64 `json:"orva_alloc_mb"` + MemTotalMB int64 `json:"mem_total_mb"` + MemAvailableMB int64 `json:"mem_available_mb"` + MemReservedMB int64 `json:"mem_reserved_mb"` + EffectiveMemoryMB int64 `json:"effective_memory_capacity_mb"` } type totalsBlock struct { @@ -90,22 +92,27 @@ type buildQueueBlock struct { } type poolBlock struct { - FunctionID string `json:"function_id"` - FunctionName string `json:"function_name"` - Idle int `json:"idle"` - Busy int64 `json:"busy"` - Spawned int64 `json:"spawned"` - Killed int64 `json:"killed"` - ScaleUps int64 `json:"scale_ups"` - ScaleDowns int64 `json:"scale_downs"` - RateEWMA float64 `json:"rate_ewma"` - LatencyEWMAms float64 `json:"latency_ewma_ms"` - DynamicMax int64 `json:"dynamic_max"` - Target int `json:"target"` - MemUsedAvgMB float64 `json:"mem_used_avg_mb"` // EWMA of memory.current at release; 0 if cgroups disabled - CPUFracAvg float64 `json:"cpu_frac_avg"` // EWMA of CPU fraction per invocation (0–1) - MemLimitMB int64 `json:"mem_limit_mb"` // configured memory_mb for this function - CPULimit float64 `json:"cpu_limit"` // configured cpus for this function (0 = uncapped) + FunctionID string `json:"function_id"` + FunctionName string `json:"function_name"` + Idle int `json:"idle"` + Busy int64 `json:"busy"` + Queued int64 `json:"queued"` + Spawning int64 `json:"spawning"` + Arrivals int64 `json:"arrivals"` + Spawned int64 `json:"spawned"` + Killed int64 `json:"killed"` + DesiredWorkers int64 `json:"desired_workers"` + EffectiveMax int64 `json:"effective_max"` + StableRate float64 `json:"stable_rate"` + BurstRate float64 `json:"burst_rate"` + QueueWaitP95MS float64 `json:"queue_wait_p95_ms"` + ServiceP95MS float64 `json:"service_p95_ms"` + ColdStartP95MS float64 `json:"cold_start_p95_ms"` + LimitingReason string `json:"limiting_reason"` + Rejections int64 `json:"rejections"` + CapacityTimeouts int64 `json:"capacity_timeouts"` + MemLimitMB int64 `json:"mem_limit_mb"` + CPULimit float64 `json:"cpu_limit"` } // Health handles GET /api/v1/system/health. @@ -299,32 +306,35 @@ func (h *SystemHandler) GetMetrics(w http.ResponseWriter, r *http.Request) { if h.PoolMgr != nil { promHeader(w, "orva_pool_idle", "gauge", "Idle warm workers per function.") promHeader(w, "orva_pool_busy", "gauge", "Busy workers per function.") + promHeader(w, "orva_pool_queued", "gauge", "Invocations waiting for capacity per function.") + promHeader(w, "orva_pool_spawning", "gauge", "Workers currently starting per function.") + promHeader(w, "orva_pool_arrivals_total", "counter", "Invocation arrivals observed before capacity waits.") promHeader(w, "orva_pool_spawned_total", "counter", "Workers spawned per function.") promHeader(w, "orva_pool_killed_total", "counter", "Workers killed per function.") - promHeader(w, "orva_pool_scale_events_total", "counter", "Autoscaler scale events per function and direction.") - promHeader(w, "orva_pool_rate_ewma", "gauge", "EWMA of request rate per function.") - promHeader(w, "orva_pool_latency_ewma_ms", "gauge", "EWMA of invocation latency per function (ms).") - promHeader(w, "orva_pool_max_dynamic", "gauge", "Dynamic max pool size per function.") - promHeader(w, "orva_pool_target_concurrency", "gauge", "Target concurrency per function.") - promHeader(w, "orva_pool_mem_used_avg_bytes", "gauge", "EWMA of memory used per invocation (bytes).") - promHeader(w, "orva_pool_cpu_frac_avg", "gauge", "EWMA of CPU fraction per invocation.") + promHeader(w, "orva_pool_desired_workers", "gauge", "Controller desired workers per function.") + promHeader(w, "orva_pool_effective_max", "gauge", "Effective host and operator capacity per function.") + promHeader(w, "orva_pool_queue_wait_p95_ms", "gauge", "Observed queue-wait p95 per function.") + promHeader(w, "orva_pool_service_p95_ms", "gauge", "Observed service-time p95 per function.") + promHeader(w, "orva_pool_cold_start_p95_ms", "gauge", "Observed worker start p95 per function.") + promHeader(w, "orva_pool_rejections_total", "counter", "Pool admission rejections per function.") + promHeader(w, "orva_pool_capacity_timeouts_total", "counter", "Capacity waits that reached their deadline.") + promHeader(w, "orva_pool_limiting_reason", "gauge", "Current limiting reason as a labeled one-hot gauge.") for _, s := range h.PoolMgr.Stats() { fmt.Fprintf(w, "orva_pool_idle{function_id=%q} %d\n", s.FunctionID, s.Idle) fmt.Fprintf(w, "orva_pool_busy{function_id=%q} %d\n", s.FunctionID, s.Busy) + fmt.Fprintf(w, "orva_pool_queued{function_id=%q} %d\n", s.FunctionID, s.Queued) + fmt.Fprintf(w, "orva_pool_spawning{function_id=%q} %d\n", s.FunctionID, s.Spawning) + fmt.Fprintf(w, "orva_pool_arrivals_total{function_id=%q} %d\n", s.FunctionID, s.Arrivals) fmt.Fprintf(w, "orva_pool_spawned_total{function_id=%q} %d\n", s.FunctionID, s.Spawned) fmt.Fprintf(w, "orva_pool_killed_total{function_id=%q} %d\n", s.FunctionID, s.Killed) - fmt.Fprintf(w, "orva_pool_scale_events_total{function_id=%q,direction=\"up\"} %d\n", s.FunctionID, s.ScaleUps) - fmt.Fprintf(w, "orva_pool_scale_events_total{function_id=%q,direction=\"down\"} %d\n", s.FunctionID, s.ScaleDowns) - fmt.Fprintf(w, "orva_pool_rate_ewma{function_id=%q} %.2f\n", s.FunctionID, s.RateEWMA) - fmt.Fprintf(w, "orva_pool_latency_ewma_ms{function_id=%q} %.2f\n", s.FunctionID, s.LatencyEWMAms) - fmt.Fprintf(w, "orva_pool_max_dynamic{function_id=%q} %d\n", s.FunctionID, s.DynamicMax) - fmt.Fprintf(w, "orva_pool_target_concurrency{function_id=%q} %d\n", s.FunctionID, s.Target) - if s.MemUsedAvgBytes > 0 { - fmt.Fprintf(w, "orva_pool_mem_used_avg_bytes{function_id=%q} %d\n", s.FunctionID, s.MemUsedAvgBytes) - } - if s.CPUFracAvg > 0 { - fmt.Fprintf(w, "orva_pool_cpu_frac_avg{function_id=%q} %.4f\n", s.FunctionID, s.CPUFracAvg) - } + fmt.Fprintf(w, "orva_pool_desired_workers{function_id=%q} %d\n", s.FunctionID, s.Desired) + fmt.Fprintf(w, "orva_pool_effective_max{function_id=%q} %d\n", s.FunctionID, s.EffectiveMax) + fmt.Fprintf(w, "orva_pool_queue_wait_p95_ms{function_id=%q} %.3f\n", s.FunctionID, s.QueueWaitP95MS) + fmt.Fprintf(w, "orva_pool_service_p95_ms{function_id=%q} %.3f\n", s.FunctionID, s.ServiceP95MS) + fmt.Fprintf(w, "orva_pool_cold_start_p95_ms{function_id=%q} %.3f\n", s.FunctionID, s.ColdStartP95MS) + fmt.Fprintf(w, "orva_pool_rejections_total{function_id=%q} %d\n", s.FunctionID, s.Rejections) + fmt.Fprintf(w, "orva_pool_capacity_timeouts_total{function_id=%q} %d\n", s.FunctionID, s.CapacityTimeouts) + fmt.Fprintf(w, "orva_pool_limiting_reason{function_id=%q,reason=%q} 1\n", s.FunctionID, s.LimitingReason) } tot, avail, res := h.PoolMgr.HostMemStats() promHeader(w, "orva_host_mem_total_bytes", "gauge", "Total host memory (bytes).") @@ -333,6 +343,10 @@ func (h *SystemHandler) GetMetrics(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "orva_host_mem_available_bytes %d\n", avail) promHeader(w, "orva_host_mem_reserved_bytes", "gauge", "Host memory reserved by warm pools (bytes).") fmt.Fprintf(w, "orva_host_mem_reserved_bytes %d\n", res) + promHeader(w, "orva_host_effective_cpu_workers", "gauge", "Effective worker capacity derived from cgroup v2 CPU quota.") + fmt.Fprintf(w, "orva_host_effective_cpu_workers %d\n", h.PoolMgr.EffectiveCPUCapacity()) + promHeader(w, "orva_host_effective_memory_capacity_bytes", "gauge", "Memory currently available for additional worker admission.") + fmt.Fprintf(w, "orva_host_effective_memory_capacity_bytes %d\n", h.PoolMgr.EffectiveMemoryCapacity()) } } @@ -392,6 +406,8 @@ func (h *SystemHandler) BuildMetricsSnapshot() MetricsJSONShape { if h.PoolMgr != nil { tot, avail, res := h.PoolMgr.HostMemStats() + out.Host.EffectiveCPUWorkers = h.PoolMgr.EffectiveCPUCapacity() + out.Host.EffectiveMemoryMB = h.PoolMgr.EffectiveMemoryCapacity() / 1024 / 1024 out.Host.MemTotalMB = tot / 1024 / 1024 out.Host.MemAvailableMB = avail / 1024 / 1024 out.Host.MemReservedMB = res / 1024 / 1024 @@ -412,22 +428,15 @@ func (h *SystemHandler) BuildMetricsSnapshot() MetricsJSONShape { } } out.Pools = append(out.Pools, poolBlock{ - FunctionID: s.FunctionID, - FunctionName: name, - Idle: s.Idle, - Busy: s.Busy, - Spawned: s.Spawned, - Killed: s.Killed, - ScaleUps: s.ScaleUps, - ScaleDowns: s.ScaleDowns, - RateEWMA: s.RateEWMA, - LatencyEWMAms: s.LatencyEWMAms, - DynamicMax: s.DynamicMax, - Target: s.Target, - MemUsedAvgMB: float64(s.MemUsedAvgBytes) / 1024 / 1024, - CPUFracAvg: s.CPUFracAvg, - MemLimitMB: memLimitMB, - CPULimit: cpuLimit, + FunctionID: s.FunctionID, FunctionName: name, + Idle: s.Idle, Busy: s.Busy, Queued: s.Queued, Spawning: s.Spawning, + Arrivals: s.Arrivals, Spawned: s.Spawned, Killed: s.Killed, + DesiredWorkers: s.Desired, EffectiveMax: s.EffectiveMax, + StableRate: s.StableRate, BurstRate: s.BurstRate, + QueueWaitP95MS: s.QueueWaitP95MS, ServiceP95MS: s.ServiceP95MS, + ColdStartP95MS: s.ColdStartP95MS, LimitingReason: s.LimitingReason, + Rejections: s.Rejections, CapacityTimeouts: s.CapacityTimeouts, + MemLimitMB: memLimitMB, CPULimit: cpuLimit, }) } } diff --git a/backend/internal/server/ui_dist/assets/AI-De72Ye8u.js b/backend/internal/server/ui_dist/assets/AI-5L2rM3_1.js similarity index 99% rename from backend/internal/server/ui_dist/assets/AI-De72Ye8u.js rename to backend/internal/server/ui_dist/assets/AI-5L2rM3_1.js index e32d6979..805020f9 100644 --- a/backend/internal/server/ui_dist/assets/AI-De72Ye8u.js +++ b/backend/internal/server/ui_dist/assets/AI-5L2rM3_1.js @@ -1,4 +1,4 @@ -import{r as e}from"./axios-DVDuIpRy.js";import{C as t,D as n,E as r,F as i,G as a,I as o,M as s,P as c,S as l,T as u,Z as d,c as f,d as p,gt as m,h,k as g,l as _,m as v,r as y,s as b,u as x,vt as S,x as C}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as w}from"./check-BNre7JFR.js";import{t as T}from"./copy-BqdwwcxC.js";import{i as E,n as D,r as O,t as k}from"./ModelMenu-BtMjUXcx.js";import{t as ee}from"./pencil-Do2I7soU.js";import{t as te}from"./rotate-ccw-DWwjKCqh.js";import{t as ne}from"./sparkles-DTHEIS5T.js";import{t as re}from"./trash-2-DaeYqnW_.js";import{t as ie}from"./zap-BXGoxm_a.js";import{Bt as ae,Dt as oe,Lt as se,Mt as ce,St as le,_t as A,bt as ue,gt as de,jt as j,mt as fe,ut as pe}from"./index-DTqMKlE1.js";import{t as me}from"./Drawer-B98TBytl.js";import{a as M,i as he,n as ge,r as _e,t as ve}from"./github-dark-D7LxIVih.js";import{t as ye}from"./clipboard-D_9N0yai.js";var be=j(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]),xe=j(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]),Se=j(`ban`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M4.929 4.929 19.07 19.071`,key:`196cmz`}]]),Ce=j(`brain`,[[`path`,{d:`M12 18V5`,key:`adv99a`}],[`path`,{d:`M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4`,key:`1e3is1`}],[`path`,{d:`M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5`,key:`1gqd8o`}],[`path`,{d:`M17.997 5.125a4 4 0 0 1 2.526 5.77`,key:`iwvgf7`}],[`path`,{d:`M18 18a4 4 0 0 0 2-7.464`,key:`efp6ie`}],[`path`,{d:`M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517`,key:`1gq6am`}],[`path`,{d:`M6 18a4 4 0 0 1-2-7.464`,key:`k1g0md`}],[`path`,{d:`M6.003 5.125a4 4 0 0 0-2.526 5.77`,key:`q97ue3`}]]),we=j(`chevrons-down-up`,[[`path`,{d:`m7 20 5-5 5 5`,key:`13a0gw`}],[`path`,{d:`m7 4 5 5 5-5`,key:`1kwcof`}]]),Te=j(`chevrons-up-down`,[[`path`,{d:`m7 15 5 5 5-5`,key:`1hf1tw`}],[`path`,{d:`m7 9 5-5 5 5`,key:`sgt6xg`}]]),Ee=j(`loader-circle`,[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,key:`13zald`}]]),De=j(`message-square`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]),Oe=j(`panel-left`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M9 3v18`,key:`fh3hqa`}]]),ke=j(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]),Ae=j(`wrench`,[[`path`,{d:`M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z`,key:`1ngwbx`}]]),je={class:`flex h-16 shrink-0 items-center justify-between gap-3 border-b border-border px-4`},Me={class:`flex min-w-0 items-center gap-2`},Ne={class:`truncate text-sm font-semibold tracking-tight text-white`},Pe={class:`flex items-center gap-0.5`},Fe={__name:`ChatHeader`,props:{title:{type:String,default:`Assistant`},canExport:{type:Boolean,default:!1}},emits:[`toggle-rail`,`export`],setup(e){return(t,r)=>(n(),p(`header`,je,[f(`div`,Me,[f(`button`,{class:`touch-expand-iconbtn -ml-1 rounded-md p-2 text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background md:hidden`,"aria-label":`Conversations`,onClick:r[0]||=e=>t.$emit(`toggle-rail`)},[h(d(Oe),{class:`h-4 w-4`})]),h(d(De),{class:`hidden h-4 w-4 shrink-0 text-foreground-muted md:block`}),f(`h1`,Ne,S(e.title),1)]),f(`div`,Pe,[e.canExport?(n(),p(`button`,{key:0,class:`touch-expand-iconbtn -mr-1 rounded-md p-2 text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,"aria-label":`Export conversation as Markdown`,title:`Export conversation`,onClick:r[1]||=e=>t.$emit(`export`)},[h(d(E),{class:`h-4 w-4`})])):x(``,!0)])]))}},Ie={class:`flex h-full flex-col`},Le={key:0,class:`flex h-16 shrink-0 items-center justify-between px-4 border-b border-border`},Re={class:`flex-1 overflow-y-auto scrollable p-2 space-y-0.5`},ze=[`aria-current`,`onClick`],Be={class:`flex-1 truncate`},Ve=[`onClick`],He=[`onClick`],Ue={key:1,class:`px-2.5 py-2 text-xs text-foreground-muted`},We={key:1,class:`shrink-0 border-t border-border p-2`},Ge={key:0,class:`px-2.5 pb-1.5 text-xs leading-snug text-danger-fg`,role:`alert`},Ke=[`disabled`],qe={__name:`ConversationRail`,props:{embedded:{type:Boolean,default:!1}},emits:[`select`],setup(e,{emit:t}){let r=O(),o=de(),s=a(!1),c=a(``);async function l(e){let t=await o.prompt({title:`Rename conversation`,defaultValue:e.title||``,placeholder:`Conversation name`,confirmLabel:`Rename`});t!=null&&t.trim()&&r.renameConversation(e.id,t.trim())}async function u(e){await o.ask({title:`Delete conversation?`,message:`This permanently deletes the conversation and all its messages.`,danger:!0,confirmLabel:`Delete`})&&r.deleteConversation(e)}async function b(){let e=r.conversations.length;if(!e||s.value)return;let t=e===1?`chat`:`chats`;if(await o.ask({title:`Clear all chats?`,message:`This permanently deletes all ${e} ${t} and their messages. This cannot be undone.`,danger:!0,confirmLabel:`Clear all`})){s.value=!0,c.value=``;try{await r.clearConversations(),C(`select`)}catch(e){c.value=e?.response?.status===409?`A chat is still responding. Stop it and try again.`:`Chats could not be cleared. Try again.`}finally{s.value=!1}}}let C=t;function w(){r.newConversation(),C(`select`)}function T(e){r.openConversation(e),C(`select`)}return(t,a)=>(n(),p(`div`,Ie,[e.embedded?x(``,!0):(n(),p(`div`,Le,[a[1]||=f(`span`,{class:`text-sm font-semibold tracking-tight text-white`},`Conversations`,-1),h(A,{size:`xs`,variant:`secondary`,onClick:w},{default:i(()=>[h(d(le),{class:`h-3.5 w-3.5`}),a[0]||=v(` New `,-1)]),_:1})])),f(`div`,Re,[e.embedded?(n(),p(`button`,{key:0,class:`touch-expand-sm mb-1 flex w-full items-center gap-2 rounded-md border border-border px-2.5 py-2 text-left text-sm text-foreground transition-colors hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,onClick:w},[h(d(le),{class:`h-3.5 w-3.5 shrink-0`}),a[2]||=v(` New conversation `,-1)])):x(``,!0),(n(!0),p(y,null,g(d(r).conversations,e=>(n(),p(`div`,{key:e.id,class:m([`group flex w-full items-center gap-0.5 rounded-md pr-1 transition-colors`,e.id===d(r).activeId?`bg-primary/15`:`hover:bg-surface-hover`])},[f(`button`,{class:m([`touch-expand-sm flex min-w-0 flex-1 items-center gap-2 rounded-md px-2.5 py-2 text-left text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,e.id===d(r).activeId?`text-white`:`text-foreground-muted group-hover:text-white`]),"aria-current":e.id===d(r).activeId?`page`:void 0,onClick:t=>T(e.id)},[h(d(De),{class:`h-3.5 w-3.5 shrink-0 opacity-70`}),f(`span`,Be,S(e.title||`New conversation`),1)],10,ze),f(`button`,{type:`button`,class:`touch-expand-iconbtn shrink-0 rounded-md p-2 text-foreground-muted opacity-0 transition-opacity hover:bg-surface-hover hover:text-white focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary group-hover:opacity-100 max-md:opacity-100`,title:`Rename conversation`,"aria-label":`Rename conversation`,onClick:ae(t=>l(e),[`stop`])},[h(d(ee),{class:`h-3.5 w-3.5`})],8,Ve),f(`button`,{type:`button`,class:`touch-expand-iconbtn shrink-0 rounded-md p-2 text-foreground-muted opacity-0 transition-opacity hover:bg-surface-hover hover:text-danger-fg focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary group-hover:opacity-100 max-md:opacity-100`,title:`Delete conversation`,"aria-label":`Delete conversation`,onClick:ae(t=>u(e.id),[`stop`])},[h(d(re),{class:`h-3.5 w-3.5`})],8,He)],2))),128)),d(r).conversations.length?x(``,!0):(n(),p(`p`,Ue,` No conversations yet. `))]),d(r).conversations.length?(n(),p(`div`,We,[c.value?(n(),p(`p`,Ge,S(c.value),1)):x(``,!0),f(`button`,{type:`button`,class:`touch-expand-sm flex h-8 w-full items-center gap-2 rounded-md px-2.5 text-left text-xs text-foreground-muted transition-colors hover:bg-surface-hover hover:text-danger-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50`,disabled:s.value,onClick:b},[s.value?(n(),_(d(Ee),{key:0,class:`h-3.5 w-3.5 shrink-0 animate-spin motion-reduce:animate-none`})):(n(),_(d(re),{key:1,class:`h-3.5 w-3.5 shrink-0`})),v(` `+S(s.value?`Clearing…`:`Clear all chats`),1)],8,Ke)])):x(``,!0)]))}},Je={class:`text-center`},Ye={class:`mx-auto mt-5 flex max-w-xl flex-wrap justify-center gap-2`},Xe=[`onClick`],Ze={class:`line-clamp-2`},Qe={__name:`EmptyState`,emits:[`pick`],setup(e){let t=[`How many functions do I have?`,`Which function ran most recently?`,`Any errors in the last 24 hours?`,`Show my most recent executions.`,`List my deployed functions.`,`Summarize today’s invocation errors.`,`Show failed deployments and why.`,`What’s my system health right now?`,`Show storage usage for my instance.`,`List my cron schedules.`,`Are any background jobs failing?`,`Check for failed webhook deliveries.`,`Which runtimes are available?`,`Show my slowest functions by duration.`,`Which functions have egress enabled?`,`List my secrets by name only.`,`Write a Python function that returns the current UTC time.`,`Write a Node function that echoes the request body.`,`Create an hourly cron schedule for a function.`,`Walk me through deploying a new function.`];function r(e,t){let n=[...e];for(let e=n.length-1;e>0;e--){let t=Math.floor(Math.random()*(e+1));[n[e],n[t]]=[n[t],n[e]]}return n.slice(0,t)}let i=a(r(t,3));return(e,t)=>(n(),p(`div`,Je,[t[0]||=f(`h2`,{class:`text-lg font-semibold tracking-tight text-white`},` What would you like to do? `,-1),t[1]||=f(`p`,{class:`mx-auto mt-1.5 max-w-md text-sm leading-relaxed text-foreground-muted`},` Ask about this instance or operate it with natural language. `,-1),f(`div`,Ye,[(n(!0),p(y,null,g(i.value,(t,r)=>(n(),p(`button`,{key:r,type:`button`,class:`rounded-md px-3 py-2 text-left text-xs leading-snug text-foreground-muted transition-colors hover:bg-surface-hover hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,onClick:n=>e.$emit(`pick`,t)},[f(`span`,Ze,S(t),1)],8,Xe))),128))])]))}},$e=`[A-Za-z$_][0-9A-Za-z$_]*`,et=`as.in.of.if.for.while.finally.var.new.function.do.return.void.else.break.catch.instanceof.with.throw.case.default.try.switch.continue.typeof.delete.let.yield.const.class.debugger.async.await.static.import.from.export.extends.using`.split(`.`),tt=[`true`,`false`,`null`,`undefined`,`NaN`,`Infinity`],nt=`Object.Function.Boolean.Symbol.Math.Date.Number.BigInt.String.RegExp.Array.Float32Array.Float64Array.Int8Array.Uint8Array.Uint8ClampedArray.Int16Array.Int32Array.Uint16Array.Uint32Array.BigInt64Array.BigUint64Array.Set.Map.WeakSet.WeakMap.ArrayBuffer.SharedArrayBuffer.Atomics.DataView.JSON.Promise.Generator.GeneratorFunction.AsyncFunction.Reflect.Proxy.Intl.WebAssembly`.split(`.`),rt=[`Error`,`EvalError`,`InternalError`,`RangeError`,`ReferenceError`,`SyntaxError`,`TypeError`,`URIError`],it=[`setInterval`,`setTimeout`,`clearInterval`,`clearTimeout`,`require`,`exports`,`eval`,`isFinite`,`isNaN`,`parseFloat`,`parseInt`,`decodeURI`,`decodeURIComponent`,`encodeURI`,`encodeURIComponent`,`escape`,`unescape`],at=[`arguments`,`this`,`super`,`console`,`window`,`document`,`localStorage`,`sessionStorage`,`module`,`global`],ot=[].concat(it,nt,rt);function st(e){let t=e.regex,n=(e,{after:t})=>{let n=``,end:``},a=/<[A-Za-z0-9\\._:-]+\s*\/>/,o={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,t)=>{let r=e[0].length+e.index,i=e.input[r];if(i===`<`||i===`,`){t.ignoreMatch();return}i===`>`&&(n(e,{after:r})||t.ignoreMatch());let a,o=e.input.substring(r);if(a=o.match(/^\s*=/)){t.ignoreMatch();return}if((a=o.match(/^\s+extends\s+/))&&a.index===0){t.ignoreMatch();return}}},s={$pattern:$e,keyword:et,literal:tt,built_in:ot,"variable.language":at},c=`[0-9](_?[0-9])*`,l=`\\.(${c})`,u=`0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`,d={className:`number`,variants:[{begin:`(\\b(${u})((${l})|\\.)?|(${l}))[eE][+-]?(${c})\\b`},{begin:`\\b(${u})\\b((${l})\\b|\\.)?|(${l})\\b`},{begin:`\\b(0|[1-9](_?[0-9])*)n\\b`},{begin:`\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b`},{begin:`\\b0[bB][0-1](_?[0-1])*n?\\b`},{begin:`\\b0[oO][0-7](_?[0-7])*n?\\b`},{begin:`\\b0[0-7]+n?\\b`}],relevance:0},f={className:`subst`,begin:`\\$\\{`,end:`\\}`,keywords:s,contains:[]},p={begin:".?html`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`xml`}},m={begin:".?css`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`css`}},h={begin:".?gql`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`graphql`}},g={className:`string`,begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,f]},_={className:`comment`,variants:[e.COMMENT(/\/\*\*(?!\/)/,`\\*/`,{relevance:0,contains:[{begin:`(?=@[A-Za-z]+)`,relevance:0,contains:[{className:`doctag`,begin:`@[A-Za-z]+`},{className:`type`,begin:`\\{`,end:`\\}`,excludeEnd:!0,excludeBegin:!0,relevance:0},{className:`variable`,begin:`[A-Za-z$_][0-9A-Za-z$_]*(?=\\s*(-)|$)`,endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]},v=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,p,m,h,g,{match:/\$\d+/},d];f.contains=v.concat({begin:/\{/,end:/\}/,keywords:s,contains:[`self`].concat(v)});let y=[].concat(_,f.contains),b=y.concat([{begin:/(\s*)\(/,end:/\)/,keywords:s,contains:[`self`].concat(y)}]),x={className:`params`,begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,contains:b},S={variants:[{match:[/class/,/\s+/,r,/\s+/,/extends/,/\s+/,t.concat(r,`(`,t.concat(/\./,r),`)*`)],scope:{1:`keyword`,3:`title.class`,5:`keyword`,7:`title.class.inherited`}},{match:[/class/,/\s+/,r],scope:{1:`keyword`,3:`title.class`}}]},C={relevance:0,match:t.either(/\bJSON/,/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/),className:`title.class`,keywords:{_:[...nt,...rt]}},w={label:`use_strict`,className:`meta`,relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},T={variants:[{match:[/function/,/\s+/,r,/(?=\s*\()/]},{match:[/function/,/\s*(?=\()/]}],className:{1:`keyword`,3:`title.function`},label:`func.def`,contains:[x],illegal:/%/},E={relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:`variable.constant`};function D(e){return t.concat(`(?!`,e.join(`|`),`)`)}let O={match:t.concat(/\b/,D([...it,`super`,`import`].map(e=>`${e}\\s*\\(`)),r,t.lookahead(/\s*\(/)),className:`title.function`,relevance:0},k={begin:t.concat(/\./,t.lookahead(t.concat(r,/(?![0-9A-Za-z$_(])/))),end:r,excludeBegin:!0,keywords:`prototype`,className:`property`,relevance:0},ee={match:[/get|set/,/\s+/,r,/(?=\()/],className:{1:`keyword`,3:`title.function`},contains:[{begin:/\(\)/},x]},te=`(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|`+e.UNDERSCORE_IDENT_RE+`)\\s*=>`,ne={match:[/const|var|let/,/\s+/,r,/\s*/,/=\s*/,/(async\s*)?/,t.lookahead(te)],keywords:`async`,className:{1:`keyword`,3:`title.function`},contains:[x]};return{name:`JavaScript`,aliases:[`js`,`jsx`,`mjs`,`cjs`],keywords:s,exports:{PARAMS_CONTAINS:b,CLASS_REFERENCE:C},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:`shebang`,binary:`node`,relevance:5}),w,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,p,m,h,g,_,{match:/\$\d+/},d,C,{scope:`attr`,match:r+t.lookahead(`:`),relevance:0},ne,{begin:`(`+e.RE_STARTERS_RE+`|\\b(case|return|throw)\\b)\\s*`,keywords:`return throw case`,relevance:0,contains:[_,e.REGEXP_MODE,{className:`function`,begin:te,returnBegin:!0,end:`\\s*=>`,contains:[{className:`params`,variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,contains:b}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:i.begin,end:i.end},{match:a},{begin:o.begin,"on:begin":o.isTrulyOpeningTag,end:o.end}],subLanguage:`xml`,contains:[{begin:o.begin,end:o.end,skip:!0,contains:[`self`]}]}]},T,{beginKeywords:`while if switch catch for`},{begin:`\\b(?!function)`+e.UNDERSCORE_IDENT_RE+`\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{`,returnBegin:!0,label:`func.def`,contains:[x,e.inherit(e.TITLE_MODE,{begin:r,className:`title.function`})]},{match:/\.\.\./,relevance:0},k,{match:`\\$[A-Za-z$_][0-9A-Za-z$_]*`,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:`title.function`},contains:[x]},O,E,S,ee,{match:/\$[(.]/}]}}function ct(e){let t=e.regex,n=st(e),r=$e,i=[`any`,`void`,`number`,`boolean`,`string`,`object`,`never`,`symbol`,`bigint`,`unknown`],a={begin:[/namespace/,/\s+/,e.IDENT_RE],beginScope:{1:`keyword`,3:`title.class`}},o={beginKeywords:`interface`,end:/\{/,excludeEnd:!0,keywords:{keyword:`interface extends`,built_in:i},contains:[n.exports.CLASS_REFERENCE]},s={className:`meta`,relevance:10,begin:/^\s*['"]use strict['"]/},c={$pattern:$e,keyword:et.concat([`type`,`interface`,`public`,`private`,`protected`,`implements`,`declare`,`abstract`,`readonly`,`enum`,`override`,`satisfies`]),literal:tt,built_in:ot.concat(i),"variable.language":at},l={className:`meta`,begin:`@[A-Za-z$_][0-9A-Za-z$_]*`},u=(e,t,n)=>{let r=e.contains.findIndex(e=>e.label===t);if(r===-1)throw Error(`can not find mode to replace`);e.contains.splice(r,1,n)};Object.assign(n.keywords,c),n.exports.PARAMS_CONTAINS.push(l);let d=n.contains.find(e=>e.scope===`attr`),f=Object.assign({},d,{match:t.concat(r,t.lookahead(/\s*\?:/))});n.exports.PARAMS_CONTAINS.push([n.exports.CLASS_REFERENCE,d,f]),n.contains=n.contains.concat([l,a,o,f]),u(n,`shebang`,e.SHEBANG()),u(n,`use_strict`,s);let p=n.contains.find(e=>e.label===`func.def`);return p.relevance=0,Object.assign(n,{name:`TypeScript`,aliases:[`ts`,`tsx`,`mts`,`cts`]}),n}function lt(e){let t=e.regex,n=t.concat(/[\p{L}_]/u,t.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),r=/[\p{L}0-9._:-]+/u,i={className:`symbol`,begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:`keyword`,begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},o=e.inherit(a,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:`string`}),c=e.inherit(e.QUOTE_STRING_MODE,{className:`string`}),l={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:`HTML, XML`,aliases:[`html`,`xhtml`,`rss`,`atom`,`xjb`,`xsd`,`xsl`,`plist`,`wsf`,`svg`],case_insensitive:!0,unicodeRegex:!0,contains:[{className:`meta`,begin://,relevance:10,contains:[a,c,s,o,{begin:/\[/,end:/\]/,contains:[{className:`meta`,begin://,contains:[a,o,c,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},i,{className:`meta`,end:/\?>/,variants:[{begin:/<\?xml/,relevance:10,contains:[c]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:`tag`,begin:/)/,end:/>/,keywords:{name:`style`},contains:[l],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:[`css`,`xml`]}},{className:`tag`,begin:/)/,end:/>/,keywords:{name:`script`},contains:[l],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:[`javascript`,`handlebars`,`xml`]}},{className:`tag`,begin:/<>|<\/>/},{className:`tag`,begin:t.concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:`name`,begin:n,relevance:0,starts:l}]},{className:`tag`,begin:t.concat(/<\//,t.lookahead(t.concat(n,/>/))),contains:[{className:`name`,begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}var ut=e=>({IMPORTANT:{scope:`meta`,begin:`!important`},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:`number`,begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:`built_in`,begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:`selector-attr`,begin:/\[/,end:/\]/,illegal:`$`,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:`number`,begin:e.NUMBER_RE+`(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?`,relevance:0},CSS_VARIABLE:{className:`attr`,begin:/--[A-Za-z_][A-Za-z0-9_-]*/}}),dt=`a.abbr.address.article.aside.audio.b.blockquote.body.button.canvas.caption.cite.code.dd.del.details.dfn.div.dl.dt.em.fieldset.figcaption.figure.footer.form.h1.h2.h3.h4.h5.h6.header.hgroup.html.i.iframe.img.input.ins.kbd.label.legend.li.main.mark.menu.nav.object.ol.optgroup.option.p.picture.q.quote.samp.section.select.source.span.strong.summary.sup.table.tbody.td.textarea.tfoot.th.thead.time.tr.ul.var.video`.split(`.`),ft=`defs.g.marker.mask.pattern.svg.switch.symbol.feBlend.feColorMatrix.feComponentTransfer.feComposite.feConvolveMatrix.feDiffuseLighting.feDisplacementMap.feFlood.feGaussianBlur.feImage.feMerge.feMorphology.feOffset.feSpecularLighting.feTile.feTurbulence.linearGradient.radialGradient.stop.circle.ellipse.image.line.path.polygon.polyline.rect.text.use.textPath.tspan.foreignObject.clipPath`.split(`.`),pt=[...dt,...ft],mt=`any-hover.any-pointer.aspect-ratio.color.color-gamut.color-index.device-aspect-ratio.device-height.device-width.display-mode.forced-colors.grid.height.hover.inverted-colors.monochrome.orientation.overflow-block.overflow-inline.pointer.prefers-color-scheme.prefers-contrast.prefers-reduced-motion.prefers-reduced-transparency.resolution.scan.scripting.update.width.min-width.max-width.min-height.max-height`.split(`.`).sort().reverse(),ht=`active.any-link.blank.checked.current.default.defined.dir.disabled.drop.empty.enabled.first.first-child.first-of-type.fullscreen.future.focus.focus-visible.focus-within.has.host.host-context.hover.indeterminate.in-range.invalid.is.lang.last-child.last-of-type.left.link.local-link.not.nth-child.nth-col.nth-last-child.nth-last-col.nth-last-of-type.nth-of-type.only-child.only-of-type.optional.out-of-range.past.placeholder-shown.read-only.read-write.required.right.root.scope.target.target-within.user-invalid.valid.visited.where`.split(`.`).sort().reverse(),gt=[`after`,`backdrop`,`before`,`cue`,`cue-region`,`first-letter`,`first-line`,`grammar-error`,`marker`,`part`,`placeholder`,`selection`,`slotted`,`spelling-error`].sort().reverse(),_t=`accent-color.align-content.align-items.align-self.alignment-baseline.all.anchor-name.animation.animation-composition.animation-delay.animation-direction.animation-duration.animation-fill-mode.animation-iteration-count.animation-name.animation-play-state.animation-range.animation-range-end.animation-range-start.animation-timeline.animation-timing-function.appearance.aspect-ratio.backdrop-filter.backface-visibility.background.background-attachment.background-blend-mode.background-clip.background-color.background-image.background-origin.background-position.background-position-x.background-position-y.background-repeat.background-size.baseline-shift.block-size.border.border-block.border-block-color.border-block-end.border-block-end-color.border-block-end-style.border-block-end-width.border-block-start.border-block-start-color.border-block-start-style.border-block-start-width.border-block-style.border-block-width.border-bottom.border-bottom-color.border-bottom-left-radius.border-bottom-right-radius.border-bottom-style.border-bottom-width.border-collapse.border-color.border-end-end-radius.border-end-start-radius.border-image.border-image-outset.border-image-repeat.border-image-slice.border-image-source.border-image-width.border-inline.border-inline-color.border-inline-end.border-inline-end-color.border-inline-end-style.border-inline-end-width.border-inline-start.border-inline-start-color.border-inline-start-style.border-inline-start-width.border-inline-style.border-inline-width.border-left.border-left-color.border-left-style.border-left-width.border-radius.border-right.border-right-color.border-right-style.border-right-width.border-spacing.border-start-end-radius.border-start-start-radius.border-style.border-top.border-top-color.border-top-left-radius.border-top-right-radius.border-top-style.border-top-width.border-width.bottom.box-align.box-decoration-break.box-direction.box-flex.box-flex-group.box-lines.box-ordinal-group.box-orient.box-pack.box-shadow.box-sizing.break-after.break-before.break-inside.caption-side.caret-color.clear.clip.clip-path.clip-rule.color.color-interpolation.color-interpolation-filters.color-profile.color-rendering.color-scheme.column-count.column-fill.column-gap.column-rule.column-rule-color.column-rule-style.column-rule-width.column-span.column-width.columns.contain.contain-intrinsic-block-size.contain-intrinsic-height.contain-intrinsic-inline-size.contain-intrinsic-size.contain-intrinsic-width.container.container-name.container-type.content.content-visibility.counter-increment.counter-reset.counter-set.cue.cue-after.cue-before.cursor.cx.cy.direction.display.dominant-baseline.empty-cells.enable-background.field-sizing.fill.fill-opacity.fill-rule.filter.flex.flex-basis.flex-direction.flex-flow.flex-grow.flex-shrink.flex-wrap.float.flood-color.flood-opacity.flow.font.font-display.font-family.font-feature-settings.font-kerning.font-language-override.font-optical-sizing.font-palette.font-size.font-size-adjust.font-smooth.font-smoothing.font-stretch.font-style.font-synthesis.font-synthesis-position.font-synthesis-small-caps.font-synthesis-style.font-synthesis-weight.font-variant.font-variant-alternates.font-variant-caps.font-variant-east-asian.font-variant-emoji.font-variant-ligatures.font-variant-numeric.font-variant-position.font-variation-settings.font-weight.forced-color-adjust.gap.glyph-orientation-horizontal.glyph-orientation-vertical.grid.grid-area.grid-auto-columns.grid-auto-flow.grid-auto-rows.grid-column.grid-column-end.grid-column-start.grid-gap.grid-row.grid-row-end.grid-row-start.grid-template.grid-template-areas.grid-template-columns.grid-template-rows.hanging-punctuation.height.hyphenate-character.hyphenate-limit-chars.hyphens.icon.image-orientation.image-rendering.image-resolution.ime-mode.initial-letter.initial-letter-align.inline-size.inset.inset-area.inset-block.inset-block-end.inset-block-start.inset-inline.inset-inline-end.inset-inline-start.isolation.justify-content.justify-items.justify-self.kerning.left.letter-spacing.lighting-color.line-break.line-height.line-height-step.list-style.list-style-image.list-style-position.list-style-type.margin.margin-block.margin-block-end.margin-block-start.margin-bottom.margin-inline.margin-inline-end.margin-inline-start.margin-left.margin-right.margin-top.margin-trim.marker.marker-end.marker-mid.marker-start.marks.mask.mask-border.mask-border-mode.mask-border-outset.mask-border-repeat.mask-border-slice.mask-border-source.mask-border-width.mask-clip.mask-composite.mask-image.mask-mode.mask-origin.mask-position.mask-repeat.mask-size.mask-type.masonry-auto-flow.math-depth.math-shift.math-style.max-block-size.max-height.max-inline-size.max-width.min-block-size.min-height.min-inline-size.min-width.mix-blend-mode.nav-down.nav-index.nav-left.nav-right.nav-up.none.normal.object-fit.object-position.offset.offset-anchor.offset-distance.offset-path.offset-position.offset-rotate.opacity.order.orphans.outline.outline-color.outline-offset.outline-style.outline-width.overflow.overflow-anchor.overflow-block.overflow-clip-margin.overflow-inline.overflow-wrap.overflow-x.overflow-y.overlay.overscroll-behavior.overscroll-behavior-block.overscroll-behavior-inline.overscroll-behavior-x.overscroll-behavior-y.padding.padding-block.padding-block-end.padding-block-start.padding-bottom.padding-inline.padding-inline-end.padding-inline-start.padding-left.padding-right.padding-top.page.page-break-after.page-break-before.page-break-inside.paint-order.pause.pause-after.pause-before.perspective.perspective-origin.place-content.place-items.place-self.pointer-events.position.position-anchor.position-visibility.print-color-adjust.quotes.r.resize.rest.rest-after.rest-before.right.rotate.row-gap.ruby-align.ruby-position.scale.scroll-behavior.scroll-margin.scroll-margin-block.scroll-margin-block-end.scroll-margin-block-start.scroll-margin-bottom.scroll-margin-inline.scroll-margin-inline-end.scroll-margin-inline-start.scroll-margin-left.scroll-margin-right.scroll-margin-top.scroll-padding.scroll-padding-block.scroll-padding-block-end.scroll-padding-block-start.scroll-padding-bottom.scroll-padding-inline.scroll-padding-inline-end.scroll-padding-inline-start.scroll-padding-left.scroll-padding-right.scroll-padding-top.scroll-snap-align.scroll-snap-stop.scroll-snap-type.scroll-timeline.scroll-timeline-axis.scroll-timeline-name.scrollbar-color.scrollbar-gutter.scrollbar-width.shape-image-threshold.shape-margin.shape-outside.shape-rendering.speak.speak-as.src.stop-color.stop-opacity.stroke.stroke-dasharray.stroke-dashoffset.stroke-linecap.stroke-linejoin.stroke-miterlimit.stroke-opacity.stroke-width.tab-size.table-layout.text-align.text-align-all.text-align-last.text-anchor.text-combine-upright.text-decoration.text-decoration-color.text-decoration-line.text-decoration-skip.text-decoration-skip-ink.text-decoration-style.text-decoration-thickness.text-emphasis.text-emphasis-color.text-emphasis-position.text-emphasis-style.text-indent.text-justify.text-orientation.text-overflow.text-rendering.text-shadow.text-size-adjust.text-transform.text-underline-offset.text-underline-position.text-wrap.text-wrap-mode.text-wrap-style.timeline-scope.top.touch-action.transform.transform-box.transform-origin.transform-style.transition.transition-behavior.transition-delay.transition-duration.transition-property.transition-timing-function.translate.unicode-bidi.user-modify.user-select.vector-effect.vertical-align.view-timeline.view-timeline-axis.view-timeline-inset.view-timeline-name.view-transition-name.visibility.voice-balance.voice-duration.voice-family.voice-pitch.voice-range.voice-rate.voice-stress.voice-volume.white-space.white-space-collapse.widows.width.will-change.word-break.word-spacing.word-wrap.writing-mode.x.y.z-index.zoom`.split(`.`).sort().reverse();function vt(e){let t=e.regex,n=ut(e),r={begin:/-(webkit|moz|ms|o)-(?=[a-z])/},i=/@-?\w[\w]*(-\w+)*/,a=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:`CSS`,case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:`from to`},classNameAliases:{keyframePosition:`selector-tag`},contains:[n.BLOCK_COMMENT,r,n.CSS_NUMBER_MODE,{className:`selector-id`,begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:`selector-class`,begin:`\\.[a-zA-Z-][a-zA-Z0-9_-]*`,relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:`selector-pseudo`,variants:[{begin:`:(`+ht.join(`|`)+`)`},{begin:`:(:)?(`+gt.join(`|`)+`)`}]},n.CSS_VARIABLE,{className:`attribute`,begin:`\\b(`+_t.join(`|`)+`)\\b`},{begin:/:/,end:/[;}{]/,contains:[n.BLOCK_COMMENT,n.HEXCOLOR,n.IMPORTANT,n.CSS_NUMBER_MODE,...a,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:`url data-uri`},contains:[...a,{className:`string`,begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},n.FUNCTION_DISPATCH]},{begin:t.lookahead(/@/),end:`[{;]`,relevance:0,illegal:/:/,contains:[{className:`keyword`,begin:i},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:`and or not only`,attribute:mt.join(` `)},contains:[{begin:/[a-z-]+(?=:)/,className:`attribute`},...a,n.CSS_NUMBER_MODE]}]},{className:`selector-tag`,begin:`\\b(`+pt.join(`|`)+`)\\b`}]}}function yt(e){let t=`true false yes no null`,n={className:`attr`,variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},r={className:`template-variable`,variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]},i={className:`string`,relevance:0,begin:/'/,end:/'/,contains:[{match:/''/,scope:`char.escape`,relevance:0}]},a={className:`string`,relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,r]},o=e.inherit(a,{variants:[{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),s={className:`number`,begin:`\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b`},c={end:`,`,endsWithParent:!0,excludeEnd:!0,keywords:t,relevance:0},l={begin:/\{/,end:/\}/,contains:[c],illegal:`\\n`,relevance:0},u={begin:`\\[`,end:`\\]`,contains:[c],illegal:`\\n`,relevance:0},d=[n,{className:`meta`,begin:`^---\\s*$`,relevance:10},{className:`string`,begin:`[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*`},{begin:`<%[%=-]?`,end:`[%-]?%>`,subLanguage:`ruby`,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:`type`,begin:`!\\w+![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`type`,begin:`!<[\\w#;/?:@&=+$,.~*'()[\\]]+>`},{className:`type`,begin:`![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`type`,begin:`!![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`meta`,begin:`&`+e.UNDERSCORE_IDENT_RE+`$`},{className:`meta`,begin:`\\*`+e.UNDERSCORE_IDENT_RE+`$`},{className:`bullet`,begin:`-(?=[ ]|$)`,relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:t,keywords:{literal:t}},s,{className:`number`,begin:e.C_NUMBER_RE+`\\b`,relevance:0},l,u,i,a],f=[...d];return f.pop(),f.push(o),c.contains=f,{name:`YAML`,case_insensitive:!0,aliases:[`yml`],contains:d}}M.registerLanguage(`javascript`,he),M.registerLanguage(`typescript`,ct),M.registerLanguage(`python`,_e),M.registerLanguage(`json`,ge),M.registerLanguage(`bash`,ve),M.registerLanguage(`xml`,lt),M.registerLanguage(`css`,vt),M.registerLanguage(`yaml`,yt);var bt={js:`javascript`,ts:`typescript`,py:`python`,sh:`bash`,shell:`bash`,yml:`yaml`,html:`xml`};function xt(e){return e.replace(/&/g,`&`).replace(//g,`>`)}function St(e,t){let n=bt[(t||``).toLowerCase()]||(t||``).toLowerCase();if(n&&M.getLanguage(n))try{return M.highlight(e,{language:n,ignoreIllegals:!0}).value}catch{}return xt(e)}var Ct=M,wt={};function Tt(e){let t=wt[e];if(t)return t;t=wt[e]=[];for(let e=0;e<128;e++){let n=String.fromCharCode(e);t.push(n)}for(let n=0;n=55296&&e<=57343?`���`:String.fromCharCode(e),r+=6;continue}}if((a&248)==240&&r+91114111?t+=`����`:(e-=65536,t+=String.fromCharCode(55296+(e>>10),56320+(e&1023))),r+=9;continue}}t+=`�`}return t})}N.defaultChars=`;/?:@&=+$,#`,N.componentChars=``;var Et={};function Dt(e){let t=Et[e];if(t)return t;t=Et[e]=[];for(let e=0;e<128;e++){let n=String.fromCharCode(e);/^[0-9a-z]$/i.test(n)?t.push(n):t.push(`%`+(`0`+e.toString(16).toUpperCase()).slice(-2))}for(let n=0;n=55296&&o<=57343){if(o>=55296&&o<=56319&&t+1=56320&&n<=57343){i+=encodeURIComponent(e[t]+e[t+1]),t++;continue}}i+=`%EF%BF%BD`;continue}i+=encodeURIComponent(e[t])}return i}P.defaultChars=`;/?:@&=+$,-_.!~*'()#`,P.componentChars=`-_.!~*'()`;function Ot(e){let t=``;return t+=e.protocol||``,t+=e.slashes?`//`:``,t+=e.auth?e.auth+`@`:``,e.hostname&&e.hostname.indexOf(`:`)!==-1?t+=`[`+e.hostname+`]`:t+=e.hostname||``,t+=e.port?`:`+e.port:``,t+=e.pathname||``,t+=e.search||``,t+=e.hash||``,t}function kt(){this.protocol=null,this.slashes=null,this.auth=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.pathname=null}var At=/^([a-z0-9.+-]+:)/i,jt=/:[0-9]*$/,Mt=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,Nt=[`%`,`/`,`?`,`;`,`#`,`'`,`{`,`}`,`|`,`\\`,`^`,"`",`<`,`>`,`"`,"`",` `,`\r`,` +import{r as e}from"./axios-DVDuIpRy.js";import{C as t,D as n,E as r,F as i,G as a,I as o,M as s,P as c,S as l,T as u,Z as d,c as f,d as p,gt as m,h,k as g,l as _,m as v,r as y,s as b,u as x,vt as S,x as C}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as w}from"./check-CZmR72iA.js";import{t as T}from"./copy-3UAsea5P.js";import{i as E,n as D,r as O,t as k}from"./ModelMenu-D7Iysg0v.js";import{t as ee}from"./pencil-BmuCVcyO.js";import{t as te}from"./rotate-ccw-DgujV-4F.js";import{t as ne}from"./sparkles-BZcVxan3.js";import{t as re}from"./trash-2-Cz9PSE2q.js";import{t as ie}from"./zap-BF0H8u1s.js";import{Bt as ae,Dt as oe,Lt as se,Mt as ce,St as le,_t as A,bt as ue,gt as de,jt as j,mt as fe,ut as pe}from"./index-pE9wnfTb.js";import{t as me}from"./Drawer-CSwYBfhJ.js";import{a as M,i as he,n as ge,r as _e,t as ve}from"./github-dark-D7LxIVih.js";import{t as ye}from"./clipboard-D_9N0yai.js";var be=j(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]),xe=j(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]),Se=j(`ban`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M4.929 4.929 19.07 19.071`,key:`196cmz`}]]),Ce=j(`brain`,[[`path`,{d:`M12 18V5`,key:`adv99a`}],[`path`,{d:`M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4`,key:`1e3is1`}],[`path`,{d:`M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5`,key:`1gqd8o`}],[`path`,{d:`M17.997 5.125a4 4 0 0 1 2.526 5.77`,key:`iwvgf7`}],[`path`,{d:`M18 18a4 4 0 0 0 2-7.464`,key:`efp6ie`}],[`path`,{d:`M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517`,key:`1gq6am`}],[`path`,{d:`M6 18a4 4 0 0 1-2-7.464`,key:`k1g0md`}],[`path`,{d:`M6.003 5.125a4 4 0 0 0-2.526 5.77`,key:`q97ue3`}]]),we=j(`chevrons-down-up`,[[`path`,{d:`m7 20 5-5 5 5`,key:`13a0gw`}],[`path`,{d:`m7 4 5 5 5-5`,key:`1kwcof`}]]),Te=j(`chevrons-up-down`,[[`path`,{d:`m7 15 5 5 5-5`,key:`1hf1tw`}],[`path`,{d:`m7 9 5-5 5 5`,key:`sgt6xg`}]]),Ee=j(`loader-circle`,[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,key:`13zald`}]]),De=j(`message-square`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]),Oe=j(`panel-left`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M9 3v18`,key:`fh3hqa`}]]),ke=j(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]),Ae=j(`wrench`,[[`path`,{d:`M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z`,key:`1ngwbx`}]]),je={class:`flex h-16 shrink-0 items-center justify-between gap-3 border-b border-border px-4`},Me={class:`flex min-w-0 items-center gap-2`},Ne={class:`truncate text-sm font-semibold tracking-tight text-white`},Pe={class:`flex items-center gap-0.5`},Fe={__name:`ChatHeader`,props:{title:{type:String,default:`Assistant`},canExport:{type:Boolean,default:!1}},emits:[`toggle-rail`,`export`],setup(e){return(t,r)=>(n(),p(`header`,je,[f(`div`,Me,[f(`button`,{class:`touch-expand-iconbtn -ml-1 rounded-md p-2 text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background md:hidden`,"aria-label":`Conversations`,onClick:r[0]||=e=>t.$emit(`toggle-rail`)},[h(d(Oe),{class:`h-4 w-4`})]),h(d(De),{class:`hidden h-4 w-4 shrink-0 text-foreground-muted md:block`}),f(`h1`,Ne,S(e.title),1)]),f(`div`,Pe,[e.canExport?(n(),p(`button`,{key:0,class:`touch-expand-iconbtn -mr-1 rounded-md p-2 text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,"aria-label":`Export conversation as Markdown`,title:`Export conversation`,onClick:r[1]||=e=>t.$emit(`export`)},[h(d(E),{class:`h-4 w-4`})])):x(``,!0)])]))}},Ie={class:`flex h-full flex-col`},Le={key:0,class:`flex h-16 shrink-0 items-center justify-between px-4 border-b border-border`},Re={class:`flex-1 overflow-y-auto scrollable p-2 space-y-0.5`},ze=[`aria-current`,`onClick`],Be={class:`flex-1 truncate`},Ve=[`onClick`],He=[`onClick`],Ue={key:1,class:`px-2.5 py-2 text-xs text-foreground-muted`},We={key:1,class:`shrink-0 border-t border-border p-2`},Ge={key:0,class:`px-2.5 pb-1.5 text-xs leading-snug text-danger-fg`,role:`alert`},Ke=[`disabled`],qe={__name:`ConversationRail`,props:{embedded:{type:Boolean,default:!1}},emits:[`select`],setup(e,{emit:t}){let r=O(),o=de(),s=a(!1),c=a(``);async function l(e){let t=await o.prompt({title:`Rename conversation`,defaultValue:e.title||``,placeholder:`Conversation name`,confirmLabel:`Rename`});t!=null&&t.trim()&&r.renameConversation(e.id,t.trim())}async function u(e){await o.ask({title:`Delete conversation?`,message:`This permanently deletes the conversation and all its messages.`,danger:!0,confirmLabel:`Delete`})&&r.deleteConversation(e)}async function b(){let e=r.conversations.length;if(!e||s.value)return;let t=e===1?`chat`:`chats`;if(await o.ask({title:`Clear all chats?`,message:`This permanently deletes all ${e} ${t} and their messages. This cannot be undone.`,danger:!0,confirmLabel:`Clear all`})){s.value=!0,c.value=``;try{await r.clearConversations(),C(`select`)}catch(e){c.value=e?.response?.status===409?`A chat is still responding. Stop it and try again.`:`Chats could not be cleared. Try again.`}finally{s.value=!1}}}let C=t;function w(){r.newConversation(),C(`select`)}function T(e){r.openConversation(e),C(`select`)}return(t,a)=>(n(),p(`div`,Ie,[e.embedded?x(``,!0):(n(),p(`div`,Le,[a[1]||=f(`span`,{class:`text-sm font-semibold tracking-tight text-white`},`Conversations`,-1),h(A,{size:`xs`,variant:`secondary`,onClick:w},{default:i(()=>[h(d(le),{class:`h-3.5 w-3.5`}),a[0]||=v(` New `,-1)]),_:1})])),f(`div`,Re,[e.embedded?(n(),p(`button`,{key:0,class:`touch-expand-sm mb-1 flex w-full items-center gap-2 rounded-md border border-border px-2.5 py-2 text-left text-sm text-foreground transition-colors hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,onClick:w},[h(d(le),{class:`h-3.5 w-3.5 shrink-0`}),a[2]||=v(` New conversation `,-1)])):x(``,!0),(n(!0),p(y,null,g(d(r).conversations,e=>(n(),p(`div`,{key:e.id,class:m([`group flex w-full items-center gap-0.5 rounded-md pr-1 transition-colors`,e.id===d(r).activeId?`bg-primary/15`:`hover:bg-surface-hover`])},[f(`button`,{class:m([`touch-expand-sm flex min-w-0 flex-1 items-center gap-2 rounded-md px-2.5 py-2 text-left text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,e.id===d(r).activeId?`text-white`:`text-foreground-muted group-hover:text-white`]),"aria-current":e.id===d(r).activeId?`page`:void 0,onClick:t=>T(e.id)},[h(d(De),{class:`h-3.5 w-3.5 shrink-0 opacity-70`}),f(`span`,Be,S(e.title||`New conversation`),1)],10,ze),f(`button`,{type:`button`,class:`touch-expand-iconbtn shrink-0 rounded-md p-2 text-foreground-muted opacity-0 transition-opacity hover:bg-surface-hover hover:text-white focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary group-hover:opacity-100 max-md:opacity-100`,title:`Rename conversation`,"aria-label":`Rename conversation`,onClick:ae(t=>l(e),[`stop`])},[h(d(ee),{class:`h-3.5 w-3.5`})],8,Ve),f(`button`,{type:`button`,class:`touch-expand-iconbtn shrink-0 rounded-md p-2 text-foreground-muted opacity-0 transition-opacity hover:bg-surface-hover hover:text-danger-fg focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary group-hover:opacity-100 max-md:opacity-100`,title:`Delete conversation`,"aria-label":`Delete conversation`,onClick:ae(t=>u(e.id),[`stop`])},[h(d(re),{class:`h-3.5 w-3.5`})],8,He)],2))),128)),d(r).conversations.length?x(``,!0):(n(),p(`p`,Ue,` No conversations yet. `))]),d(r).conversations.length?(n(),p(`div`,We,[c.value?(n(),p(`p`,Ge,S(c.value),1)):x(``,!0),f(`button`,{type:`button`,class:`touch-expand-sm flex h-8 w-full items-center gap-2 rounded-md px-2.5 text-left text-xs text-foreground-muted transition-colors hover:bg-surface-hover hover:text-danger-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50`,disabled:s.value,onClick:b},[s.value?(n(),_(d(Ee),{key:0,class:`h-3.5 w-3.5 shrink-0 animate-spin motion-reduce:animate-none`})):(n(),_(d(re),{key:1,class:`h-3.5 w-3.5 shrink-0`})),v(` `+S(s.value?`Clearing…`:`Clear all chats`),1)],8,Ke)])):x(``,!0)]))}},Je={class:`text-center`},Ye={class:`mx-auto mt-5 flex max-w-xl flex-wrap justify-center gap-2`},Xe=[`onClick`],Ze={class:`line-clamp-2`},Qe={__name:`EmptyState`,emits:[`pick`],setup(e){let t=[`How many functions do I have?`,`Which function ran most recently?`,`Any errors in the last 24 hours?`,`Show my most recent executions.`,`List my deployed functions.`,`Summarize today’s invocation errors.`,`Show failed deployments and why.`,`What’s my system health right now?`,`Show storage usage for my instance.`,`List my cron schedules.`,`Are any background jobs failing?`,`Check for failed webhook deliveries.`,`Which runtimes are available?`,`Show my slowest functions by duration.`,`Which functions have egress enabled?`,`List my secrets by name only.`,`Write a Python function that returns the current UTC time.`,`Write a Node function that echoes the request body.`,`Create an hourly cron schedule for a function.`,`Walk me through deploying a new function.`];function r(e,t){let n=[...e];for(let e=n.length-1;e>0;e--){let t=Math.floor(Math.random()*(e+1));[n[e],n[t]]=[n[t],n[e]]}return n.slice(0,t)}let i=a(r(t,3));return(e,t)=>(n(),p(`div`,Je,[t[0]||=f(`h2`,{class:`text-lg font-semibold tracking-tight text-white`},` What would you like to do? `,-1),t[1]||=f(`p`,{class:`mx-auto mt-1.5 max-w-md text-sm leading-relaxed text-foreground-muted`},` Ask about this instance or operate it with natural language. `,-1),f(`div`,Ye,[(n(!0),p(y,null,g(i.value,(t,r)=>(n(),p(`button`,{key:r,type:`button`,class:`rounded-md px-3 py-2 text-left text-xs leading-snug text-foreground-muted transition-colors hover:bg-surface-hover hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,onClick:n=>e.$emit(`pick`,t)},[f(`span`,Ze,S(t),1)],8,Xe))),128))])]))}},$e=`[A-Za-z$_][0-9A-Za-z$_]*`,et=`as.in.of.if.for.while.finally.var.new.function.do.return.void.else.break.catch.instanceof.with.throw.case.default.try.switch.continue.typeof.delete.let.yield.const.class.debugger.async.await.static.import.from.export.extends.using`.split(`.`),tt=[`true`,`false`,`null`,`undefined`,`NaN`,`Infinity`],nt=`Object.Function.Boolean.Symbol.Math.Date.Number.BigInt.String.RegExp.Array.Float32Array.Float64Array.Int8Array.Uint8Array.Uint8ClampedArray.Int16Array.Int32Array.Uint16Array.Uint32Array.BigInt64Array.BigUint64Array.Set.Map.WeakSet.WeakMap.ArrayBuffer.SharedArrayBuffer.Atomics.DataView.JSON.Promise.Generator.GeneratorFunction.AsyncFunction.Reflect.Proxy.Intl.WebAssembly`.split(`.`),rt=[`Error`,`EvalError`,`InternalError`,`RangeError`,`ReferenceError`,`SyntaxError`,`TypeError`,`URIError`],it=[`setInterval`,`setTimeout`,`clearInterval`,`clearTimeout`,`require`,`exports`,`eval`,`isFinite`,`isNaN`,`parseFloat`,`parseInt`,`decodeURI`,`decodeURIComponent`,`encodeURI`,`encodeURIComponent`,`escape`,`unescape`],at=[`arguments`,`this`,`super`,`console`,`window`,`document`,`localStorage`,`sessionStorage`,`module`,`global`],ot=[].concat(it,nt,rt);function st(e){let t=e.regex,n=(e,{after:t})=>{let n=``,end:``},a=/<[A-Za-z0-9\\._:-]+\s*\/>/,o={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,t)=>{let r=e[0].length+e.index,i=e.input[r];if(i===`<`||i===`,`){t.ignoreMatch();return}i===`>`&&(n(e,{after:r})||t.ignoreMatch());let a,o=e.input.substring(r);if(a=o.match(/^\s*=/)){t.ignoreMatch();return}if((a=o.match(/^\s+extends\s+/))&&a.index===0){t.ignoreMatch();return}}},s={$pattern:$e,keyword:et,literal:tt,built_in:ot,"variable.language":at},c=`[0-9](_?[0-9])*`,l=`\\.(${c})`,u=`0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`,d={className:`number`,variants:[{begin:`(\\b(${u})((${l})|\\.)?|(${l}))[eE][+-]?(${c})\\b`},{begin:`\\b(${u})\\b((${l})\\b|\\.)?|(${l})\\b`},{begin:`\\b(0|[1-9](_?[0-9])*)n\\b`},{begin:`\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b`},{begin:`\\b0[bB][0-1](_?[0-1])*n?\\b`},{begin:`\\b0[oO][0-7](_?[0-7])*n?\\b`},{begin:`\\b0[0-7]+n?\\b`}],relevance:0},f={className:`subst`,begin:`\\$\\{`,end:`\\}`,keywords:s,contains:[]},p={begin:".?html`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`xml`}},m={begin:".?css`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`css`}},h={begin:".?gql`",end:``,starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,f],subLanguage:`graphql`}},g={className:`string`,begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,f]},_={className:`comment`,variants:[e.COMMENT(/\/\*\*(?!\/)/,`\\*/`,{relevance:0,contains:[{begin:`(?=@[A-Za-z]+)`,relevance:0,contains:[{className:`doctag`,begin:`@[A-Za-z]+`},{className:`type`,begin:`\\{`,end:`\\}`,excludeEnd:!0,excludeBegin:!0,relevance:0},{className:`variable`,begin:`[A-Za-z$_][0-9A-Za-z$_]*(?=\\s*(-)|$)`,endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]},v=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,p,m,h,g,{match:/\$\d+/},d];f.contains=v.concat({begin:/\{/,end:/\}/,keywords:s,contains:[`self`].concat(v)});let y=[].concat(_,f.contains),b=y.concat([{begin:/(\s*)\(/,end:/\)/,keywords:s,contains:[`self`].concat(y)}]),x={className:`params`,begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,contains:b},S={variants:[{match:[/class/,/\s+/,r,/\s+/,/extends/,/\s+/,t.concat(r,`(`,t.concat(/\./,r),`)*`)],scope:{1:`keyword`,3:`title.class`,5:`keyword`,7:`title.class.inherited`}},{match:[/class/,/\s+/,r],scope:{1:`keyword`,3:`title.class`}}]},C={relevance:0,match:t.either(/\bJSON/,/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/),className:`title.class`,keywords:{_:[...nt,...rt]}},w={label:`use_strict`,className:`meta`,relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},T={variants:[{match:[/function/,/\s+/,r,/(?=\s*\()/]},{match:[/function/,/\s*(?=\()/]}],className:{1:`keyword`,3:`title.function`},label:`func.def`,contains:[x],illegal:/%/},E={relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:`variable.constant`};function D(e){return t.concat(`(?!`,e.join(`|`),`)`)}let O={match:t.concat(/\b/,D([...it,`super`,`import`].map(e=>`${e}\\s*\\(`)),r,t.lookahead(/\s*\(/)),className:`title.function`,relevance:0},k={begin:t.concat(/\./,t.lookahead(t.concat(r,/(?![0-9A-Za-z$_(])/))),end:r,excludeBegin:!0,keywords:`prototype`,className:`property`,relevance:0},ee={match:[/get|set/,/\s+/,r,/(?=\()/],className:{1:`keyword`,3:`title.function`},contains:[{begin:/\(\)/},x]},te=`(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|`+e.UNDERSCORE_IDENT_RE+`)\\s*=>`,ne={match:[/const|var|let/,/\s+/,r,/\s*/,/=\s*/,/(async\s*)?/,t.lookahead(te)],keywords:`async`,className:{1:`keyword`,3:`title.function`},contains:[x]};return{name:`JavaScript`,aliases:[`js`,`jsx`,`mjs`,`cjs`],keywords:s,exports:{PARAMS_CONTAINS:b,CLASS_REFERENCE:C},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:`shebang`,binary:`node`,relevance:5}),w,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,p,m,h,g,_,{match:/\$\d+/},d,C,{scope:`attr`,match:r+t.lookahead(`:`),relevance:0},ne,{begin:`(`+e.RE_STARTERS_RE+`|\\b(case|return|throw)\\b)\\s*`,keywords:`return throw case`,relevance:0,contains:[_,e.REGEXP_MODE,{className:`function`,begin:te,returnBegin:!0,end:`\\s*=>`,contains:[{className:`params`,variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,contains:b}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:i.begin,end:i.end},{match:a},{begin:o.begin,"on:begin":o.isTrulyOpeningTag,end:o.end}],subLanguage:`xml`,contains:[{begin:o.begin,end:o.end,skip:!0,contains:[`self`]}]}]},T,{beginKeywords:`while if switch catch for`},{begin:`\\b(?!function)`+e.UNDERSCORE_IDENT_RE+`\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{`,returnBegin:!0,label:`func.def`,contains:[x,e.inherit(e.TITLE_MODE,{begin:r,className:`title.function`})]},{match:/\.\.\./,relevance:0},k,{match:`\\$[A-Za-z$_][0-9A-Za-z$_]*`,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:`title.function`},contains:[x]},O,E,S,ee,{match:/\$[(.]/}]}}function ct(e){let t=e.regex,n=st(e),r=$e,i=[`any`,`void`,`number`,`boolean`,`string`,`object`,`never`,`symbol`,`bigint`,`unknown`],a={begin:[/namespace/,/\s+/,e.IDENT_RE],beginScope:{1:`keyword`,3:`title.class`}},o={beginKeywords:`interface`,end:/\{/,excludeEnd:!0,keywords:{keyword:`interface extends`,built_in:i},contains:[n.exports.CLASS_REFERENCE]},s={className:`meta`,relevance:10,begin:/^\s*['"]use strict['"]/},c={$pattern:$e,keyword:et.concat([`type`,`interface`,`public`,`private`,`protected`,`implements`,`declare`,`abstract`,`readonly`,`enum`,`override`,`satisfies`]),literal:tt,built_in:ot.concat(i),"variable.language":at},l={className:`meta`,begin:`@[A-Za-z$_][0-9A-Za-z$_]*`},u=(e,t,n)=>{let r=e.contains.findIndex(e=>e.label===t);if(r===-1)throw Error(`can not find mode to replace`);e.contains.splice(r,1,n)};Object.assign(n.keywords,c),n.exports.PARAMS_CONTAINS.push(l);let d=n.contains.find(e=>e.scope===`attr`),f=Object.assign({},d,{match:t.concat(r,t.lookahead(/\s*\?:/))});n.exports.PARAMS_CONTAINS.push([n.exports.CLASS_REFERENCE,d,f]),n.contains=n.contains.concat([l,a,o,f]),u(n,`shebang`,e.SHEBANG()),u(n,`use_strict`,s);let p=n.contains.find(e=>e.label===`func.def`);return p.relevance=0,Object.assign(n,{name:`TypeScript`,aliases:[`ts`,`tsx`,`mts`,`cts`]}),n}function lt(e){let t=e.regex,n=t.concat(/[\p{L}_]/u,t.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),r=/[\p{L}0-9._:-]+/u,i={className:`symbol`,begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:`keyword`,begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},o=e.inherit(a,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:`string`}),c=e.inherit(e.QUOTE_STRING_MODE,{className:`string`}),l={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:`HTML, XML`,aliases:[`html`,`xhtml`,`rss`,`atom`,`xjb`,`xsd`,`xsl`,`plist`,`wsf`,`svg`],case_insensitive:!0,unicodeRegex:!0,contains:[{className:`meta`,begin://,relevance:10,contains:[a,c,s,o,{begin:/\[/,end:/\]/,contains:[{className:`meta`,begin://,contains:[a,o,c,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},i,{className:`meta`,end:/\?>/,variants:[{begin:/<\?xml/,relevance:10,contains:[c]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:`tag`,begin:/)/,end:/>/,keywords:{name:`style`},contains:[l],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:[`css`,`xml`]}},{className:`tag`,begin:/)/,end:/>/,keywords:{name:`script`},contains:[l],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:[`javascript`,`handlebars`,`xml`]}},{className:`tag`,begin:/<>|<\/>/},{className:`tag`,begin:t.concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:`name`,begin:n,relevance:0,starts:l}]},{className:`tag`,begin:t.concat(/<\//,t.lookahead(t.concat(n,/>/))),contains:[{className:`name`,begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}var ut=e=>({IMPORTANT:{scope:`meta`,begin:`!important`},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:`number`,begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:`built_in`,begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:`selector-attr`,begin:/\[/,end:/\]/,illegal:`$`,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:`number`,begin:e.NUMBER_RE+`(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?`,relevance:0},CSS_VARIABLE:{className:`attr`,begin:/--[A-Za-z_][A-Za-z0-9_-]*/}}),dt=`a.abbr.address.article.aside.audio.b.blockquote.body.button.canvas.caption.cite.code.dd.del.details.dfn.div.dl.dt.em.fieldset.figcaption.figure.footer.form.h1.h2.h3.h4.h5.h6.header.hgroup.html.i.iframe.img.input.ins.kbd.label.legend.li.main.mark.menu.nav.object.ol.optgroup.option.p.picture.q.quote.samp.section.select.source.span.strong.summary.sup.table.tbody.td.textarea.tfoot.th.thead.time.tr.ul.var.video`.split(`.`),ft=`defs.g.marker.mask.pattern.svg.switch.symbol.feBlend.feColorMatrix.feComponentTransfer.feComposite.feConvolveMatrix.feDiffuseLighting.feDisplacementMap.feFlood.feGaussianBlur.feImage.feMerge.feMorphology.feOffset.feSpecularLighting.feTile.feTurbulence.linearGradient.radialGradient.stop.circle.ellipse.image.line.path.polygon.polyline.rect.text.use.textPath.tspan.foreignObject.clipPath`.split(`.`),pt=[...dt,...ft],mt=`any-hover.any-pointer.aspect-ratio.color.color-gamut.color-index.device-aspect-ratio.device-height.device-width.display-mode.forced-colors.grid.height.hover.inverted-colors.monochrome.orientation.overflow-block.overflow-inline.pointer.prefers-color-scheme.prefers-contrast.prefers-reduced-motion.prefers-reduced-transparency.resolution.scan.scripting.update.width.min-width.max-width.min-height.max-height`.split(`.`).sort().reverse(),ht=`active.any-link.blank.checked.current.default.defined.dir.disabled.drop.empty.enabled.first.first-child.first-of-type.fullscreen.future.focus.focus-visible.focus-within.has.host.host-context.hover.indeterminate.in-range.invalid.is.lang.last-child.last-of-type.left.link.local-link.not.nth-child.nth-col.nth-last-child.nth-last-col.nth-last-of-type.nth-of-type.only-child.only-of-type.optional.out-of-range.past.placeholder-shown.read-only.read-write.required.right.root.scope.target.target-within.user-invalid.valid.visited.where`.split(`.`).sort().reverse(),gt=[`after`,`backdrop`,`before`,`cue`,`cue-region`,`first-letter`,`first-line`,`grammar-error`,`marker`,`part`,`placeholder`,`selection`,`slotted`,`spelling-error`].sort().reverse(),_t=`accent-color.align-content.align-items.align-self.alignment-baseline.all.anchor-name.animation.animation-composition.animation-delay.animation-direction.animation-duration.animation-fill-mode.animation-iteration-count.animation-name.animation-play-state.animation-range.animation-range-end.animation-range-start.animation-timeline.animation-timing-function.appearance.aspect-ratio.backdrop-filter.backface-visibility.background.background-attachment.background-blend-mode.background-clip.background-color.background-image.background-origin.background-position.background-position-x.background-position-y.background-repeat.background-size.baseline-shift.block-size.border.border-block.border-block-color.border-block-end.border-block-end-color.border-block-end-style.border-block-end-width.border-block-start.border-block-start-color.border-block-start-style.border-block-start-width.border-block-style.border-block-width.border-bottom.border-bottom-color.border-bottom-left-radius.border-bottom-right-radius.border-bottom-style.border-bottom-width.border-collapse.border-color.border-end-end-radius.border-end-start-radius.border-image.border-image-outset.border-image-repeat.border-image-slice.border-image-source.border-image-width.border-inline.border-inline-color.border-inline-end.border-inline-end-color.border-inline-end-style.border-inline-end-width.border-inline-start.border-inline-start-color.border-inline-start-style.border-inline-start-width.border-inline-style.border-inline-width.border-left.border-left-color.border-left-style.border-left-width.border-radius.border-right.border-right-color.border-right-style.border-right-width.border-spacing.border-start-end-radius.border-start-start-radius.border-style.border-top.border-top-color.border-top-left-radius.border-top-right-radius.border-top-style.border-top-width.border-width.bottom.box-align.box-decoration-break.box-direction.box-flex.box-flex-group.box-lines.box-ordinal-group.box-orient.box-pack.box-shadow.box-sizing.break-after.break-before.break-inside.caption-side.caret-color.clear.clip.clip-path.clip-rule.color.color-interpolation.color-interpolation-filters.color-profile.color-rendering.color-scheme.column-count.column-fill.column-gap.column-rule.column-rule-color.column-rule-style.column-rule-width.column-span.column-width.columns.contain.contain-intrinsic-block-size.contain-intrinsic-height.contain-intrinsic-inline-size.contain-intrinsic-size.contain-intrinsic-width.container.container-name.container-type.content.content-visibility.counter-increment.counter-reset.counter-set.cue.cue-after.cue-before.cursor.cx.cy.direction.display.dominant-baseline.empty-cells.enable-background.field-sizing.fill.fill-opacity.fill-rule.filter.flex.flex-basis.flex-direction.flex-flow.flex-grow.flex-shrink.flex-wrap.float.flood-color.flood-opacity.flow.font.font-display.font-family.font-feature-settings.font-kerning.font-language-override.font-optical-sizing.font-palette.font-size.font-size-adjust.font-smooth.font-smoothing.font-stretch.font-style.font-synthesis.font-synthesis-position.font-synthesis-small-caps.font-synthesis-style.font-synthesis-weight.font-variant.font-variant-alternates.font-variant-caps.font-variant-east-asian.font-variant-emoji.font-variant-ligatures.font-variant-numeric.font-variant-position.font-variation-settings.font-weight.forced-color-adjust.gap.glyph-orientation-horizontal.glyph-orientation-vertical.grid.grid-area.grid-auto-columns.grid-auto-flow.grid-auto-rows.grid-column.grid-column-end.grid-column-start.grid-gap.grid-row.grid-row-end.grid-row-start.grid-template.grid-template-areas.grid-template-columns.grid-template-rows.hanging-punctuation.height.hyphenate-character.hyphenate-limit-chars.hyphens.icon.image-orientation.image-rendering.image-resolution.ime-mode.initial-letter.initial-letter-align.inline-size.inset.inset-area.inset-block.inset-block-end.inset-block-start.inset-inline.inset-inline-end.inset-inline-start.isolation.justify-content.justify-items.justify-self.kerning.left.letter-spacing.lighting-color.line-break.line-height.line-height-step.list-style.list-style-image.list-style-position.list-style-type.margin.margin-block.margin-block-end.margin-block-start.margin-bottom.margin-inline.margin-inline-end.margin-inline-start.margin-left.margin-right.margin-top.margin-trim.marker.marker-end.marker-mid.marker-start.marks.mask.mask-border.mask-border-mode.mask-border-outset.mask-border-repeat.mask-border-slice.mask-border-source.mask-border-width.mask-clip.mask-composite.mask-image.mask-mode.mask-origin.mask-position.mask-repeat.mask-size.mask-type.masonry-auto-flow.math-depth.math-shift.math-style.max-block-size.max-height.max-inline-size.max-width.min-block-size.min-height.min-inline-size.min-width.mix-blend-mode.nav-down.nav-index.nav-left.nav-right.nav-up.none.normal.object-fit.object-position.offset.offset-anchor.offset-distance.offset-path.offset-position.offset-rotate.opacity.order.orphans.outline.outline-color.outline-offset.outline-style.outline-width.overflow.overflow-anchor.overflow-block.overflow-clip-margin.overflow-inline.overflow-wrap.overflow-x.overflow-y.overlay.overscroll-behavior.overscroll-behavior-block.overscroll-behavior-inline.overscroll-behavior-x.overscroll-behavior-y.padding.padding-block.padding-block-end.padding-block-start.padding-bottom.padding-inline.padding-inline-end.padding-inline-start.padding-left.padding-right.padding-top.page.page-break-after.page-break-before.page-break-inside.paint-order.pause.pause-after.pause-before.perspective.perspective-origin.place-content.place-items.place-self.pointer-events.position.position-anchor.position-visibility.print-color-adjust.quotes.r.resize.rest.rest-after.rest-before.right.rotate.row-gap.ruby-align.ruby-position.scale.scroll-behavior.scroll-margin.scroll-margin-block.scroll-margin-block-end.scroll-margin-block-start.scroll-margin-bottom.scroll-margin-inline.scroll-margin-inline-end.scroll-margin-inline-start.scroll-margin-left.scroll-margin-right.scroll-margin-top.scroll-padding.scroll-padding-block.scroll-padding-block-end.scroll-padding-block-start.scroll-padding-bottom.scroll-padding-inline.scroll-padding-inline-end.scroll-padding-inline-start.scroll-padding-left.scroll-padding-right.scroll-padding-top.scroll-snap-align.scroll-snap-stop.scroll-snap-type.scroll-timeline.scroll-timeline-axis.scroll-timeline-name.scrollbar-color.scrollbar-gutter.scrollbar-width.shape-image-threshold.shape-margin.shape-outside.shape-rendering.speak.speak-as.src.stop-color.stop-opacity.stroke.stroke-dasharray.stroke-dashoffset.stroke-linecap.stroke-linejoin.stroke-miterlimit.stroke-opacity.stroke-width.tab-size.table-layout.text-align.text-align-all.text-align-last.text-anchor.text-combine-upright.text-decoration.text-decoration-color.text-decoration-line.text-decoration-skip.text-decoration-skip-ink.text-decoration-style.text-decoration-thickness.text-emphasis.text-emphasis-color.text-emphasis-position.text-emphasis-style.text-indent.text-justify.text-orientation.text-overflow.text-rendering.text-shadow.text-size-adjust.text-transform.text-underline-offset.text-underline-position.text-wrap.text-wrap-mode.text-wrap-style.timeline-scope.top.touch-action.transform.transform-box.transform-origin.transform-style.transition.transition-behavior.transition-delay.transition-duration.transition-property.transition-timing-function.translate.unicode-bidi.user-modify.user-select.vector-effect.vertical-align.view-timeline.view-timeline-axis.view-timeline-inset.view-timeline-name.view-transition-name.visibility.voice-balance.voice-duration.voice-family.voice-pitch.voice-range.voice-rate.voice-stress.voice-volume.white-space.white-space-collapse.widows.width.will-change.word-break.word-spacing.word-wrap.writing-mode.x.y.z-index.zoom`.split(`.`).sort().reverse();function vt(e){let t=e.regex,n=ut(e),r={begin:/-(webkit|moz|ms|o)-(?=[a-z])/},i=/@-?\w[\w]*(-\w+)*/,a=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:`CSS`,case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:`from to`},classNameAliases:{keyframePosition:`selector-tag`},contains:[n.BLOCK_COMMENT,r,n.CSS_NUMBER_MODE,{className:`selector-id`,begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:`selector-class`,begin:`\\.[a-zA-Z-][a-zA-Z0-9_-]*`,relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:`selector-pseudo`,variants:[{begin:`:(`+ht.join(`|`)+`)`},{begin:`:(:)?(`+gt.join(`|`)+`)`}]},n.CSS_VARIABLE,{className:`attribute`,begin:`\\b(`+_t.join(`|`)+`)\\b`},{begin:/:/,end:/[;}{]/,contains:[n.BLOCK_COMMENT,n.HEXCOLOR,n.IMPORTANT,n.CSS_NUMBER_MODE,...a,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:`url data-uri`},contains:[...a,{className:`string`,begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},n.FUNCTION_DISPATCH]},{begin:t.lookahead(/@/),end:`[{;]`,relevance:0,illegal:/:/,contains:[{className:`keyword`,begin:i},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:`and or not only`,attribute:mt.join(` `)},contains:[{begin:/[a-z-]+(?=:)/,className:`attribute`},...a,n.CSS_NUMBER_MODE]}]},{className:`selector-tag`,begin:`\\b(`+pt.join(`|`)+`)\\b`}]}}function yt(e){let t=`true false yes no null`,n={className:`attr`,variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},r={className:`template-variable`,variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]},i={className:`string`,relevance:0,begin:/'/,end:/'/,contains:[{match:/''/,scope:`char.escape`,relevance:0}]},a={className:`string`,relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,r]},o=e.inherit(a,{variants:[{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),s={className:`number`,begin:`\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b`},c={end:`,`,endsWithParent:!0,excludeEnd:!0,keywords:t,relevance:0},l={begin:/\{/,end:/\}/,contains:[c],illegal:`\\n`,relevance:0},u={begin:`\\[`,end:`\\]`,contains:[c],illegal:`\\n`,relevance:0},d=[n,{className:`meta`,begin:`^---\\s*$`,relevance:10},{className:`string`,begin:`[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*`},{begin:`<%[%=-]?`,end:`[%-]?%>`,subLanguage:`ruby`,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:`type`,begin:`!\\w+![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`type`,begin:`!<[\\w#;/?:@&=+$,.~*'()[\\]]+>`},{className:`type`,begin:`![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`type`,begin:`!![\\w#;/?:@&=+$,.~*'()[\\]]+`},{className:`meta`,begin:`&`+e.UNDERSCORE_IDENT_RE+`$`},{className:`meta`,begin:`\\*`+e.UNDERSCORE_IDENT_RE+`$`},{className:`bullet`,begin:`-(?=[ ]|$)`,relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:t,keywords:{literal:t}},s,{className:`number`,begin:e.C_NUMBER_RE+`\\b`,relevance:0},l,u,i,a],f=[...d];return f.pop(),f.push(o),c.contains=f,{name:`YAML`,case_insensitive:!0,aliases:[`yml`],contains:d}}M.registerLanguage(`javascript`,he),M.registerLanguage(`typescript`,ct),M.registerLanguage(`python`,_e),M.registerLanguage(`json`,ge),M.registerLanguage(`bash`,ve),M.registerLanguage(`xml`,lt),M.registerLanguage(`css`,vt),M.registerLanguage(`yaml`,yt);var bt={js:`javascript`,ts:`typescript`,py:`python`,sh:`bash`,shell:`bash`,yml:`yaml`,html:`xml`};function xt(e){return e.replace(/&/g,`&`).replace(//g,`>`)}function St(e,t){let n=bt[(t||``).toLowerCase()]||(t||``).toLowerCase();if(n&&M.getLanguage(n))try{return M.highlight(e,{language:n,ignoreIllegals:!0}).value}catch{}return xt(e)}var Ct=M,wt={};function Tt(e){let t=wt[e];if(t)return t;t=wt[e]=[];for(let e=0;e<128;e++){let n=String.fromCharCode(e);t.push(n)}for(let n=0;n=55296&&e<=57343?`���`:String.fromCharCode(e),r+=6;continue}}if((a&248)==240&&r+91114111?t+=`����`:(e-=65536,t+=String.fromCharCode(55296+(e>>10),56320+(e&1023))),r+=9;continue}}t+=`�`}return t})}N.defaultChars=`;/?:@&=+$,#`,N.componentChars=``;var Et={};function Dt(e){let t=Et[e];if(t)return t;t=Et[e]=[];for(let e=0;e<128;e++){let n=String.fromCharCode(e);/^[0-9a-z]$/i.test(n)?t.push(n):t.push(`%`+(`0`+e.toString(16).toUpperCase()).slice(-2))}for(let n=0;n=55296&&o<=57343){if(o>=55296&&o<=56319&&t+1=56320&&n<=57343){i+=encodeURIComponent(e[t]+e[t+1]),t++;continue}}i+=`%EF%BF%BD`;continue}i+=encodeURIComponent(e[t])}return i}P.defaultChars=`;/?:@&=+$,-_.!~*'()#`,P.componentChars=`-_.!~*'()`;function Ot(e){let t=``;return t+=e.protocol||``,t+=e.slashes?`//`:``,t+=e.auth?e.auth+`@`:``,e.hostname&&e.hostname.indexOf(`:`)!==-1?t+=`[`+e.hostname+`]`:t+=e.hostname||``,t+=e.port?`:`+e.port:``,t+=e.pathname||``,t+=e.search||``,t+=e.hash||``,t}function kt(){this.protocol=null,this.slashes=null,this.auth=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.pathname=null}var At=/^([a-z0-9.+-]+:)/i,jt=/:[0-9]*$/,Mt=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,Nt=[`%`,`/`,`?`,`;`,`#`,`'`,`{`,`}`,`|`,`\\`,`^`,"`",`<`,`>`,`"`,"`",` `,`\r`,` `,` `],Pt=[`/`,`?`,`#`],Ft=255,It=/^[+a-z0-9A-Z_-]{0,63}$/,Lt=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,Rt={javascript:!0,"javascript:":!0},zt={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0};function Bt(e,t){if(e&&e instanceof kt)return e;let n=new kt;return n.parse(e,t),n}kt.prototype.parse=function(e,t){let n,r,i,a=e;if(a=a.trim(),!t&&e.split(`#`).length===1){let e=Mt.exec(a);if(e)return this.pathname=e[1],e[2]&&(this.search=e[2]),this}let o=At.exec(a);if(o&&(o=o[0],n=o.toLowerCase(),this.protocol=o,a=a.substr(o.length)),(t||o||a.match(/^\/\/[^@\/]+@[^@\/]+/))&&(i=a.substr(0,2)===`//`,i&&!(o&&Rt[o])&&(a=a.substr(2),this.slashes=!0)),!Rt[o]&&(i||o&&!zt[o])){let e=-1;for(let t=0;t127?r+=`x`:r+=n[e];if(!r.match(It)){let r=e.slice(0,t),i=e.slice(t+1),o=n.match(Lt);o&&(r.push(o[1]),i.unshift(o[2])),i.length&&(a=i.join(`.`)+a),this.hostname=r.join(`.`);break}}}}this.hostname.length>Ft&&(this.hostname=``),o&&(this.hostname=this.hostname.substr(1,this.hostname.length-2))}let s=a.indexOf(`#`);s!==-1&&(this.hash=a.substr(s),a=a.slice(0,s));let c=a.indexOf(`?`);return c!==-1&&(this.search=a.substr(c),a=a.slice(0,c)),a&&(this.pathname=a),zt[n]&&this.hostname&&!this.pathname&&(this.pathname=``),this},kt.prototype.parseHost=function(e){let t=jt.exec(e);t&&(t=t[0],t!==`:`&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)};var Vt=e({decode:()=>N,encode:()=>P,format:()=>Ot,parse:()=>Bt}),Ht=e({Any:()=>Ut,Cc:()=>Wt,Cf:()=>Gt,P:()=>Kt,S:()=>qt,Z:()=>Jt}),Ut=/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,Wt=/[\0-\x1F\x7F-\x9F]/,Gt=/[\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC3F]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/,Kt=/[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B4E\u1B4F\u1B5A-\u1B60\u1B7D-\u1B7F\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDD6E\uDEAD\uDED0\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9\uDFD4\uDFD5\uDFD7\uDFD8]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09\uDFE1]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDD6D-\uDD6F\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD839\uDDFF|\uD83A[\uDD5E\uDD5F]/,qt=/[\$\+<->\^`\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C1\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2429\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFF\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E5\u31EF\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD]|\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD803[\uDD8E\uDD8F\uDED1-\uDED8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDC00-\uDCEF\uDCFA-\uDCFC\uDD00-\uDEB3\uDEBA-\uDED0\uDEE0-\uDEF0\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED8\uDEDC-\uDEEC\uDEF0-\uDEFC\uDF00-\uDFD9\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0-\uDCBB\uDCC0\uDCC1\uDCD0-\uDCD8\uDD00-\uDE57\uDE60-\uDE6D\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF-\uDEF8\uDF00-\uDF92\uDF94-\uDFEF\uDFFA]/,Jt=/[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/,Yt=new Map([[0,65533],[128,8364],[130,8218],[131,402],[132,8222],[133,8230],[134,8224],[135,8225],[136,710],[137,8240],[138,352],[139,8249],[140,338],[142,381],[145,8216],[146,8217],[147,8220],[148,8221],[149,8226],[150,8211],[151,8212],[152,732],[153,8482],[154,353],[155,8250],[156,339],[158,382],[159,376]]);function Xt(e){return e>=55296&&e<=57343||e>1114111?65533:Yt.get(e)??e}function Zt(e){let t=atob(e),n=t.length&-2,r=new Uint16Array(n/2);for(let e=0,i=0;e=I.ZERO&&e<=I.NINE}function tn(e){return e>=I.UPPER_A&&e<=I.UPPER_F||e>=I.LOWER_A&&e<=I.LOWER_F}function nn(e){return e>=I.UPPER_A&&e<=I.UPPER_Z||e>=I.LOWER_A&&e<=I.LOWER_Z||en(e)}function rn(e){return e===I.EQUALS||nn(e)}var L;(function(e){e[e.EntityStart=0]=`EntityStart`,e[e.NumericStart=1]=`NumericStart`,e[e.NumericDecimal=2]=`NumericDecimal`,e[e.NumericHex=3]=`NumericHex`,e[e.NamedEntity=4]=`NamedEntity`})(L||={});var R;(function(e){e[e.Legacy=0]=`Legacy`,e[e.Strict=1]=`Strict`,e[e.Attribute=2]=`Attribute`})(R||={});var an=class{decodeTree;emitCodePoint;errors;constructor(e,t,n){this.decodeTree=e,this.emitCodePoint=t,this.errors=n}state=L.EntityStart;consumed=1;result=0;treeIndex=0;excess=1;decodeMode=R.Strict;runConsumed=0;startEntity(e){this.decodeMode=e,this.state=L.EntityStart,this.result=0,this.treeIndex=0,this.excess=1,this.consumed=1,this.runConsumed=0}write(e,t){switch(this.state){case L.EntityStart:return e.charCodeAt(t)===I.NUM?(this.state=L.NumericStart,this.consumed+=1,this.stateNumericStart(e,t+1)):(this.state=L.NamedEntity,this.stateNamedEntity(e,t));case L.NumericStart:return this.stateNumericStart(e,t);case L.NumericDecimal:return this.stateNumericDecimal(e,t);case L.NumericHex:return this.stateNumericHex(e,t);case L.NamedEntity:return this.stateNamedEntity(e,t)}}stateNumericStart(e,t){return t>=e.length?-1:(e.charCodeAt(t)|$t)===I.LOWER_X?(this.state=L.NumericHex,this.consumed+=1,this.stateNumericHex(e,t+1)):(this.state=L.NumericDecimal,this.stateNumericDecimal(e,t))}stateNumericHex(e,t){for(;t>14;for(;t>7;if(this.runConsumed===0){let n=r&F.JUMP_TABLE;if(e.charCodeAt(t)!==n)return this.result===0?0:this.emitNotTerminatedNamedEntity();t++,this.excess++,this.runConsumed++}for(;this.runConsumed=e.length)return-1;let r=this.runConsumed-1,i=n[this.treeIndex+1+(r>>1)],a=r%2==0?i&255:i>>8&255;if(e.charCodeAt(t)!==a)return this.runConsumed=0,this.result===0?0:this.emitNotTerminatedNamedEntity();t++,this.excess++,this.runConsumed++}this.runConsumed=0,this.treeIndex+=1+(a>>1),r=n[this.treeIndex],i=(r&F.VALUE_LENGTH)>>14}if(t>=e.length)break;let a=e.charCodeAt(t);if(a===I.SEMI&&i!==0&&(r&F.FLAG13)!==0)return this.emitNamedEntityData(this.treeIndex,i,this.consumed+this.excess);if(this.treeIndex=sn(n,r,this.treeIndex+Math.max(1,i),a),this.treeIndex<0)return this.result===0||this.decodeMode===R.Attribute&&(i===0||rn(a))?0:this.emitNotTerminatedNamedEntity();if(r=n[this.treeIndex],i=(r&F.VALUE_LENGTH)>>14,i!==0){if(a===I.SEMI)return this.emitNamedEntityData(this.treeIndex,i,this.consumed+this.excess);this.decodeMode!==R.Strict&&(r&F.FLAG13)===0&&(this.result=this.treeIndex,this.consumed+=this.excess,this.excess=0)}t++,this.excess++}return-1}emitNotTerminatedNamedEntity(){let{result:e,decodeTree:t}=this,n=(t[e]&F.VALUE_LENGTH)>>14;return this.emitNamedEntityData(e,n,this.consumed),this.errors?.missingSemicolonAfterCharacterReference(),this.consumed}emitNamedEntityData(e,t,n){let{decodeTree:r}=this;return this.emitCodePoint(t===1?r[e]&~(F.VALUE_LENGTH|F.FLAG13):r[e+1],n),t===3&&this.emitCodePoint(r[e+2],n),n}end(){switch(this.state){case L.NamedEntity:return this.result!==0&&(this.decodeMode!==R.Attribute||this.result===this.treeIndex)?this.emitNotTerminatedNamedEntity():0;case L.NumericDecimal:return this.emitNumericEntity(0,2);case L.NumericHex:return this.emitNumericEntity(0,3);case L.NumericStart:return this.errors?.absenceOfDigitsInNumericCharacterReference(this.consumed),0;case L.EntityStart:return 0}}};function on(e){let t=``,n=new an(e,e=>t+=String.fromCodePoint(e));return function(e,r){let i=0,a=0;for(;(a=e.indexOf(`&`,a))>=0;){t+=e.slice(i,a),n.startEntity(r);let o=n.write(e,a+1);if(o<0){i=a+n.end();break}i=a+o,a=o===0?i+1:i}let o=t+e.slice(i);return t=``,o}}function sn(e,t,n,r){let i=(t&F.BRANCH_LENGTH)>>7,a=t&F.JUMP_TABLE;if(i===0)return a!==0&&r===a?n:-1;if(a){let t=r-a;return t<0||t>=i?-1:e[n+t]-1}let o=i+1>>1,s=0,c=i-1;for(;s<=c;){let t=s+c>>>1,i=e[n+(t>>1)]>>(t&1)*8&255;if(ir)c=t-1;else return e[n+o+t]}return-1}var cn=on(Qt);function ln(e){return cn(e,R.Strict)}var un=class{src_Any=Ut.source;src_Cc=Wt.source;src_Z=Jt.source;src_P=Kt.source;src_ZPCc=[this.src_Z,this.src_P,this.src_Cc].join(`|`);src_ZCc=[this.src_Z,this.src_Cc].join(`|`);cache={};opts={maxLength:1e4,urlAuth:!1,schema_names:[]};constructor(e={}){this.opts={...this.opts,...e}}set(e={}){return this.opts={...this.opts,...e},this.cache={},this}escapeRE(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,`\\$&`)}nestedPairRE(e,t,n=4){let r=this.escapeRE(e),i=this.escapeRE(t),a=`(?:(?!${this.src_ZCc}|${r}|${i}).)`,o=`${r}${a}{0,1000}${i}`;for(let e=2;e<=n;e++)o=`${r}(?:${a}|${o}){0,1000}${i}`;return o}get_text_separators(){return this.cache.text_separators??=/[><\uff5c]/}get_pseudo_letter(){return this.cache.src_pseudo_letter??=RegExp(`(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`)}get_ipv4_addr(){return this.cache.src_ip4??=RegExp(`(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])[.]){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`)}get_ipv6_addr(){let e=`[0-9A-Fa-f]{1,4}`,t=`(?:(?:${e}:${e})|${this.get_ipv4_addr().source})`;return this.cache.src_ip6_addr??=RegExp(`(?:(?:${e}:){6}${t}|::(?:${e}:){5}${t}|(?:${e})?::(?:${e}:){4}${t}|(?:(?:${e}:){0,1}${e})?::(?:${e}:){3}${t}|(?:(?:${e}:){0,2}${e})?::(?:${e}:){2}${t}|(?:(?:${e}:){0,3}${e})?::${e}:${t}|(?:(?:${e}:){0,4}${e})?::${t}|(?:(?:${e}:){0,5}${e})?::${e}|(?:(?:${e}:){0,6}${e})?::)`)}get_ipv6_url_host(){return this.cache.src_ip6_host??=RegExp(`\\[${this.get_ipv6_addr().source}\\]`)}get_ipv6_mail_host(){return this.cache.src_ipv6_mail_host??=RegExp(`\\[IPv6:${this.get_ipv6_addr().source}\\]`)}get_auth(){return this.cache.src_auth??=RegExp(`(?:(?:(?!${this.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`)}get_port(){return this.cache.src_port??=RegExp(`(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?`)}get_host_terminator(){return this.cache.src_host_terminator??=RegExp(`(?=$|${this.get_text_separators().source}|${this.src_ZPCc})(?!${this.opts[`---`]?`-(?!--)|`:`-|`}_|:\\d|\\.-|\\.(?!$|${this.src_ZPCc}))`)}get_path_terminator(){return this.cache.src_path_terminator??=RegExp(`${this.src_ZPCc}|${this.get_text_separators().source}`)}get_path(){return this.cache.src_path??=RegExp(`(?:[/?#](?:${this.nestedPairRE(`[`,`]`)}|${this.nestedPairRE(`(`,`)`)}|${this.nestedPairRE(`{`,`}`)}|\\"(?:(?!${this.src_ZCc}|["]).){1,100}\\"|\\'(?:(?!${this.src_ZCc}|[']).){1,100}\\'|\\'(?=${this.get_pseudo_letter().source}|[-])|\\.{2,20}[:]?[a-zA-Z0-9%/&]|\\.(?!${this.src_ZCc}|[.]|$)|`+(this.opts[`---`]?`\\-(?!--(?:[^-]|$))(?:-{0,19})|`:`\\-{1,20}|`)+`,(?!${this.src_ZCc}|$)|;(?!${this.src_ZCc}|$)|\\!{1,20}(?!${this.src_ZCc}|[!]|$)|\\?(?!${this.src_ZCc}|[?]|$)|`+this.get_path_extra().source+`[\\\\/:%@#&=_~*]|(?!${this.get_path_terminator().source}).){1,${this.opts.maxLength}}|\\/)?`)}get_mail_name(){return this.cache.src_mail_name??=RegExp("[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}")}get_xn(){return this.cache.src_xn??=RegExp(`xn--[a-z0-9\\-]{1,59}`)}get_tld(){if(this.cache.tld)return this.cache.tld;let e=[...new Set(this.opts.tlds||[])].sort().reverse().join(`|`);return this.cache.tld=RegExp(`${e||`$#none#$`}|${this.get_xn().source}`),this.cache.tld}get_domain_root(){return this.cache.src_domain_root??=RegExp(`(?:`+this.get_xn().source+`|${this.get_pseudo_letter().source}{1,63})`)}get_domain(){return this.cache.src_domain??=RegExp(`(?:`+this.get_xn().source+`|(?:${this.get_pseudo_letter().source})|(?:${this.get_pseudo_letter().source}(?:-|${this.get_pseudo_letter().source}){0,61}${this.get_pseudo_letter().source}))`)}get_url_host_port(){return this.cache.url_host_port??=RegExp(`(?:`+this.get_ipv6_url_host().source+`|(?:(?:(?:${this.get_domain().source})\\.){0,10}${this.get_domain().source}))`+this.get_port().source+this.get_host_terminator().source)}get_fuzzy_url_host_port(){return this.cache.fuzzy_url_host_port??=RegExp(`(?:`+(this.opts.fuzzyIP?this.get_ipv4_addr().source+`|`:``)+`(?:(?:(?:${this.get_domain().source})\\.){1,10}(?:${this.get_tld().source})))`+this.get_host_terminator().source)}get_mail_host(){return this.cache.src_mail_host??=RegExp(`(?:`+this.get_ipv6_mail_host().source+`|(?:(?:(?:${this.get_domain().source})\\.){0,4}${this.get_domain().source}))`+this.get_host_terminator().source)}get_fuzzy_mail_host(){return this.cache.src_fuzzy_mail_host??=RegExp(`(?:`+this.get_ipv6_mail_host().source+`|(?:(?:(?:${this.get_domain().source})[.]){1,4}${this.get_domain_root().source}))`+this.get_host_terminator().source)}get_path_extra(){return this.cache.src_path_extra??=RegExp(``)}get_fuzzy_mail_host_search(){return this.cache.mail_fuzzy_host_search??=RegExp(`@${this.get_fuzzy_mail_host().source}`,`ig`)}get_fuzzy_link_search(){return this.cache.link_fuzzy_search??=RegExp(`(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${this.src_ZPCc}))(?:(?![$+<=>^\`|\uff5c])${this.get_fuzzy_url_host_port().source}${this.get_path().source})`,`ig`)}get_http_validator(){return this.cache.http_validator??=RegExp(`\\/\\/`+(this.opts.urlAuth?this.get_auth().source:``)+this.get_url_host_port().source+this.get_path().source,`iy`)}get_relative_proto_validator(){return this.cache.relative_proto_validator??=RegExp((this.opts.urlAuth?this.get_auth().source:``)+`(?:localhost|${this.get_ipv6_url_host().source}|(?:(?:${this.get_domain().source})[.]){1,10}${this.get_domain_root().source})`+this.get_port().source+this.get_host_terminator().source+this.get_path().source,`iy`)}get_mail_name_validator(){return this.cache.mail_name_validator??=RegExp(`(?:^|${this.get_text_separators().source}|"|\\(|${this.src_ZCc})(${this.get_mail_name().source})$`)}get_mailto_validator(){return this.cache.mailto_validator??=RegExp(`${this.get_mail_name().source}@${this.get_mail_host().source}`,`iy`)}get_schema_names(){return this.cache.schema_names??=new RegExp((this.opts.schema_names||[]).map(e=>this.escapeRE(e)).join(`|`))}get_schema_search(){return this.cache.schema_search??=RegExp(`(^|(?!_)(?:[><\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`,`ig`)}get_schema_at_start(){return this.cache.schema_at_start??=RegExp(`^${this.get_schema_search().source}`,`i`)}},dn={validate:(e,t,n)=>{let r=n.re.get_http_validator();r.lastIndex=t;let i=r.exec(e);return i?i[0].length:0},normalize:(e,t)=>t.normalize(e)},fn={"http:":dn,"https:":dn,"ftp:":dn,"//":{validate:function(e,t,n){let r=n.re.get_relative_proto_validator();r.lastIndex=t;let i=r.exec(e);return i?t>=3&&e[t-3]===`:`||t>=3&&e[t-3]===`/`?0:i[0].length:0},normalize:(e,t)=>t.normalize(e)},"mailto:":{validate:function(e,t,n){let r=n.re.get_mailto_validator();r.lastIndex=t;let i=r.exec(e);return i?i[0].length:0},normalize:(e,t)=>t.normalize(e)}},pn=`a:cdefgilmnoqrstuwxz|b:abdefghijmnorstvwyz|c:acdfghiklmnoruvwxyz|d:ejkmoz|e:cegrstu|f:ijkmor|g:abdefghilmnpqrstuwy|h:kmnrtu|i:delmnoqrst|j:emop|k:eghimnprwyz|l:abcikrstuvy|m:acdeghklmnopqrstuvwxyz|n:acefgilopruz|o:m|p:aefghklmnrstwy|q:a|r:eosuw|s:abcdeghijklmnortuvxyz|t:cdfghjklmnortvwz|u:agksyz|v:aceginu|w:fs|y:et|z:amw`,mn=`biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф`;function hn(){let e=mn.split(`|`);return pn.split(`|`).forEach(t=>{let n=t.indexOf(`:`),r=t.slice(0,n);for(let i of t.slice(n+1))e.push(r+i)}),e}var gn={fuzzyLink:!1,fuzzyEmail:!0,fuzzyIP:!1,"---":!1,tlds:hn(),urlAuth:!1,maxLength:1e4},_n=class{schema;index;lastIndex;raw;text;url;constructor(e,t,n,r){let i=e.slice(n,r);this.schema=t.toLowerCase(),this.index=n,this.lastIndex=r,this.raw=i,this.text=i,this.url=i}},vn=class{__opts__;__schemas__;re;constructor(e={}){let{rebuilder:t,...n}=e;this.__opts__={...gn,...n},this.__schemas__={...fn},this.re=t||new un,this.re.set({...this.__opts__,schema_names:Object.keys(this.__schemas__)})}add(e,t=null){if(!t)delete this.__schemas__[e];else{let n={normalize:(e,t)=>t.normalize(e),...t};this.__schemas__[e]=n}return this.re.set({...this.__opts__,schema_names:Object.keys(this.__schemas__)}),this}set(e={}){return this.__opts__={...this.__opts__,...e},this.re.set({...this.__opts__,schema_names:Object.keys(this.__schemas__)}),this}test(e){if(!e.length)return!1;let t,n;for(n=this.re.get_schema_search(),n.lastIndex=0;(t=n.exec(e))!==null;)if(this.testSchemaAt(e,t[2],n.lastIndex))return!0;if(this.__opts__.fuzzyLink&&this.__schemas__[`http:`]&&(n=this.re.get_fuzzy_link_search(),n.lastIndex=0,n.exec(e)!==null))return!0;if(this.__opts__.fuzzyEmail&&this.__schemas__[`mailto:`]&&e.indexOf(`@`)>=0){let n=this.re.get_fuzzy_mail_host_search(),r=this.re.get_mail_name_validator();for(n.lastIndex=0;(t=n.exec(e))!==null;){let n=e.slice(Math.max(0,t.index-65),t.index);if(r.test(n))return!0}}return!1}testSchemaAt(e,t,n){return this.__schemas__[t.toLowerCase()]?this.__schemas__[t.toLowerCase()].validate(e.slice(0,n+this.__opts__.maxLength),n,this):0}match(e){let t=[],n=this.re.get_schema_search(),r,i,a,o,s,c,l=!1,u=!1,d=!1,f=0;if(!e.length)return null;for(n.lastIndex=0,this.__opts__.fuzzyLink&&this.__schemas__[`http:`]&&(r=this.re.get_fuzzy_link_search(),r.lastIndex=0),this.__opts__.fuzzyEmail&&this.__schemas__[`mailto:`]&&(i=this.re.get_fuzzy_mail_host_search(),i.lastIndex=0,a=this.re.get_mail_name_validator());;){let p=Math.max(f-1,0);if(i&&a&&!d&&(!s||s.index=f)break;i.lastIndex=f)break;r.lastIndexm.lastIndex))&&(m=o);let h;if(!l)for(;;){if(!c){n.lastIndexm.index)break;let t=c;c=void 0;let r=this.testSchemaAt(e,t.schema,t.lastIndex);if(r){h={schema:t.schema,index:t.index,lastIndex:t.lastIndex+r};break}}let g=h;if((!g||s&&(s.indexg.lastIndex))&&(g=s),(!g||o&&(o.indexg.lastIndex))&&(g=o),!g)break;g===s?s=void 0:g===o&&(o=void 0);let _=new _n(e,g.schema,g.index,g.lastIndex);_.schema?this.__schemas__[_.schema].normalize(_,this):this.normalize(_),t.push(_),f=g.lastIndex}return t.length?t:null}matchAtStart(e){if(!e.length)return null;let t=this.re.get_schema_at_start().exec(e);if(!t)return null;let n=this.testSchemaAt(e,t[2],t[0].length);if(!n)return null;let r=new _n(e,t[2],t.index+t[1].length,t.index+t[0].length+n);return this.__schemas__[r.schema].normalize(r,this),r}tlds(e,t=!1){return e=Array.isArray(e)?e:[e],t?this.__opts__.tlds=this.__opts__.tlds.concat(e):this.__opts__.tlds=e,this.re.set({...this.__opts__,schema_names:Object.keys(this.__schemas__)}),this}normalize(e){e.schema||(e.url=`http://${e.url}`),e.schema===`mailto:`&&!/^mailto:/i.test(e.url)&&(e.url=`mailto:${e.url}`)}},z=2147483647,B=36,yn=1,bn=26,xn=38,Sn=700,Cn=72,wn=128,Tn=`-`,En=/^xn--/,Dn=/[^\0-\x7F]/,On=/[\x2E\u3002\uFF0E\uFF61]/g,kn={overflow:`Overflow: input needs wider integers to process`,"not-basic":`Illegal input >= 0x80 (not a basic code point)`,"invalid-input":`Invalid input`},An=35,V=Math.floor,jn=String.fromCharCode;function H(e){throw RangeError(kn[e])}function Mn(e,t){let n=[],r=e.length;for(;r--;)n[r]=t(e[r]);return n}function Nn(e,t){let n=e.split(`@`),r=``;n.length>1&&(r=n[0]+`@`,e=n[1]),e=e.replace(On,`.`);let i=Mn(e.split(`.`),t).join(`.`);return r+i}function Pn(e){let t=[],n=0,r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e),In=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:B},Ln=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},Rn=function(e,t,n){let r=0;for(e=n?V(e/Sn):e>>1,e+=V(e/t);e>455;r+=B)e=V(e/An);return V(r+36*e/(e+xn))},zn=function(e){let t=[],n=e.length,r=0,i=wn,a=Cn,o=e.lastIndexOf(Tn);o<0&&(o=0);for(let n=0;n=128&&H(`not-basic`),t.push(e.charCodeAt(n));for(let s=o>0?o+1:0;s=n&&H(`invalid-input`);let o=In(e.charCodeAt(s++));o>=B&&H(`invalid-input`),o>V((z-r)/t)&&H(`overflow`),r+=o*t;let c=i<=a?yn:i>=a+bn?bn:i-a;if(oV(z/l)&&H(`overflow`),t*=l}let c=t.length+1;a=Rn(r-o,c,o==0),V(r/c)>z-i&&H(`overflow`),i+=V(r/c),r%=c,t.splice(r++,0,i)}return String.fromCodePoint(...t)},Bn=function(e){let t=[];e=Pn(e);let n=e.length,r=wn,i=0,a=Cn;for(let n of e)n<128&&t.push(jn(n));let o=t.length,s=o;for(o&&t.push(Tn);s=r&&tV((z-i)/c)&&H(`overflow`),i+=(n-r)*c,r=n;for(let n of e)if(nz&&H(`overflow`),n===r){let e=i;for(let n=B;;n+=B){let r=n<=a?yn:n>=a+bn?bn:n-a;if(e{let n={};for(var r in e)Hn(n,r,{get:e[r],enumerable:!0});return t||Hn(n,Symbol.toStringTag,{value:`Module`}),n},Wn=Un({arrayReplaceAt:()=>Kn,asciiTrim:()=>ur,callable:()=>Gn,escapeHtml:()=>G,escapeRE:()=>ir,fromCodePoint:()=>U,isMdAsciiPunct:()=>sr,isPunctChar:()=>ar,isPunctCharCode:()=>or,isSpace:()=>K,isValidEntityCode:()=>qn,isWhiteSpace:()=>q,lib:()=>dr,normalizeReference:()=>cr,unescapeAll:()=>W,unescapeMd:()=>Qn});function Gn(e){let t=function(...n){return Reflect.construct(e,n,new.target&&new.target!==t?new.target:e)};return Object.defineProperty(t,"name",{value:e.name}),Object.setPrototypeOf(t,e),t.prototype=e.prototype,t}function Kn(e,t,n){return[].concat(e.slice(0,t),n,e.slice(t+1))}function qn(e){return!(e>=55296&&e<=57343||e>=64976&&e<=65007||(e&65535)==65535||(e&65535)==65534||e>=0&&e<=8||e===11||e>=14&&e<=31||e>=127&&e<=159||e>1114111)}function U(e){if(e>65535){e-=65536;let t=55296+(e>>10),n=56320+(e&1023);return String.fromCharCode(t,n)}return String.fromCharCode(e)}var Jn=/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g,Yn=RegExp(`${Jn.source}|&([a-z#][a-z0-9]{1,31});`,`gi`),Xn=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i;function Zn(e,t){if(t.charCodeAt(0)===35&&Xn.test(t)){let n=t[1].toLowerCase()===`x`?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return qn(n)?U(n):e}let n=ln(e);return n===e?e:n}function Qn(e){return e.indexOf(`\\`)<0?e:e.replace(Jn,`$1`)}function W(e){return e.indexOf(`\\`)<0&&e.indexOf(`&`)<0?e:e.replace(Yn,function(e,t,n){return t||Zn(e,n)})}var $n=/[&<>"]/,er=/[&<>"]/g,tr={"&":`&`,"<":`<`,">":`>`,'"':`"`};function nr(e){return tr[e]}function G(e){return $n.test(e)?e.replace(er,nr):e}var rr=/[.?*+^$[\]\\(){}|-]/g;function ir(e){return e.replace(rr,`\\$&`)}function K(e){switch(e){case 9:case 32:return!0}return!1}function q(e){if(e>=8192&&e<=8202)return!0;switch(e){case 9:case 10:case 11:case 12:case 13:case 32:case 160:case 5760:case 8239:case 8287:case 12288:return!0}return!1}function ar(e){return Kt.test(e)||qt.test(e)}function or(e){return ar(U(e))}function sr(e){switch(e){case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 58:case 59:case 60:case 61:case 62:case 63:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 124:case 125:case 126:return!0;default:return!1}}function cr(e){return e=e.trim().replace(/\s+/g,` `),e.toLowerCase().toUpperCase()}function lr(e){return e===32||e===9||e===10||e===13}function ur(e){let t=0;for(;t=t&&lr(e.charCodeAt(n));n--);return e.slice(t,n+1)}var dr={mdurl:Vt,ucmicro:Ht};function fr(e,t,n){let r,i,a,o,s=e.posMax,c=e.pos;for(e.pos=t+1,r=1;e.pos32))return a;if(r===41){if(o===0)break;o--}i++}return t===i||o!==0?a:(a.str=W(e.slice(t,i)),a.pos=i,a.ok=!0,a)}function mr(e,t,n,r){let i,a=t,o={ok:!1,can_continue:!1,pos:0,str:``,marker:0};if(r)o.str=r.str,o.marker=r.marker;else{if(a>=n)return o;let r=e.charCodeAt(a);if(r!==34&&r!==39&&r!==40)return o;t++,a++,r===40&&(r=41),o.marker=r}for(;apr,parseLinkLabel:()=>fr,parseLinkTitle:()=>mr});function gr(e){"@babel/helpers - typeof";return gr=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},gr(e)}function _r(e,t){if(gr(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(gr(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function vr(e){var t=_r(e,`string`);return gr(t)==`symbol`?t:t+``}function J(e,t,n){return(t=vr(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Y=class{constructor(e,t,n){J(this,`map`,null),J(this,`level`,0),J(this,`children`,null),J(this,`content`,``),J(this,`markup`,``),J(this,`info`,``),J(this,`block`,!1),J(this,`hidden`,!1),this.type=e,this.tag=t,this.attrs=null,this.nesting=n,this.meta=null}attrIndex(e){if(!this.attrs)return-1;let t=this.attrs;for(let n=0,r=t.length;n=0&&(n=this.attrs[t][1]),n}attrJoin(e,t){let n=this.attrIndex(e);n<0?this.attrPush([e,t]):this.attrs[n][1]=`${this.attrs[n][1]} ${t}`}},yr=class{constructor(){J(this,`__rules__`,[]),J(this,`__cache__`,null)}__find__(e){for(let t=0;t{t.enabled&&t.alt.forEach(t=>{t&&e.add(t)})}),this.__cache__=Object.create(null),this.__cache__[``]=[],this.__rules__.forEach(e=>{e.enabled&&this.__cache__[``].push(e.fn)}),e.forEach(e=>{this.__cache__[e]=[],this.__rules__.forEach(t=>{t.enabled&&t.alt.indexOf(e)>=0&&this.__cache__[e].push(t.fn)})})}at(e,t,n={}){let r=this.__find__(e);if(r===-1)throw Error(`Parser rule not found: ${e}`);this.__rules__[r].fn=t,this.__rules__[r].alt=n.alt||[],this.__cache__=null}before(e,t,n,r={}){let i=this.__find__(e);if(i===-1)throw Error(`Parser rule not found: ${e}`);this.__rules__.splice(i,0,{name:t,enabled:!0,fn:n,alt:r.alt||[]}),this.__cache__=null}after(e,t,n,r={}){let i=this.__find__(e);if(i===-1)throw Error(`Parser rule not found: ${e}`);this.__rules__.splice(i+1,0,{name:t,enabled:!0,fn:n,alt:r.alt||[]}),this.__cache__=null}push(e,t,n={}){this.__rules__.push({name:e,enabled:!0,fn:t,alt:n.alt||[]}),this.__cache__=null}enable(e,t=!1){Array.isArray(e)||(e=[e]);let n=[];return e.forEach(e=>{let r=this.__find__(e);if(r<0){if(t)return;throw Error(`Rules manager: invalid rule name ${e}`)}this.__rules__[r].enabled=!0,n.push(e)}),this.__cache__=null,n}enableOnly(e,t=!1){Array.isArray(e)||(e=[e]),this.__rules__.forEach(e=>{e.enabled=!1}),this.enable(e,t)}disable(e,t=!1){Array.isArray(e)||(e=[e]);let n=[];return e.forEach(e=>{let r=this.__find__(e);if(r<0){if(t)return;throw Error(`Rules manager: invalid rule name ${e}`)}this.__rules__[r].enabled=!1,n.push(e)}),this.__cache__=null,n}getRules(e){return this.__cache__||this.__compile__(),this.__cache__[e]||[]}},X={};X.code_inline=function(e,t,n,r,i){let a=e[t];return`${G(a.content)}`},X.code_block=function(e,t,n,r,i){let a=e[t];return`${G(e[t].content)}\n`},X.fence=function(e,t,n,r,i){let a=e[t],o=a.info?W(a.info).trim():``,s=``,c=``;if(o){let e=o.split(/(\s+)/g);s=e[0],c=e.slice(2).join(``)}let l;if(l=n.highlight&&n.highlight(a.content,s,c)||G(a.content),l.indexOf(`${l}\n`}return`
${l}
\n`},X.image=function(e,t,n,r,i){let a=e[t];return a.attrs[a.attrIndex(`alt`)][1]=i.renderInlineAsText(a.children,n,r),i.renderToken(e,t,n)},X.hardbreak=function(e,t,n){return n.xhtmlOut?`
`:`
diff --git a/backend/internal/server/ui_dist/assets/Activity-6I8QCc07.js b/backend/internal/server/ui_dist/assets/Activity-BCmI00tZ.js similarity index 98% rename from backend/internal/server/ui_dist/assets/Activity-6I8QCc07.js rename to backend/internal/server/ui_dist/assets/Activity-BCmI00tZ.js index b04419ef..93562cb8 100644 --- a/backend/internal/server/ui_dist/assets/Activity-6I8QCc07.js +++ b/backend/internal/server/ui_dist/assets/Activity-BCmI00tZ.js @@ -1 +1 @@ -import{D as e,E as t,F as n,G as r,I as ee,S as te,T as ne,Z as i,c as a,d as o,gt as re,h as s,k as c,l,m as u,r as d,s as f,u as p,vt as m,w as ie}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ae}from"./chevron-right-CRxFsA9Y.js";import{Lt as oe,N as se,_t as h,jt as g,r as ce,xt as le}from"./index-DTqMKlE1.js";import{t as ue}from"./Drawer-B98TBytl.js";import{t as _}from"./StatusBadge-Baoe7YAb.js";var de=g(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]),v={__name:`SourceTag`,props:{source:{type:String,default:``}},setup(t){let n=t,r=f(()=>{switch(n.source){case`web`:return`text-indigo-300 border-indigo-900/40`;case`api`:return`text-sky-300 border-sky-900/40`;case`mcp`:return`text-violet-300 border-violet-900/40`;case`sdk`:return`text-teal-300 border-teal-900/40`;case`webhook`:return`text-amber-300 border-amber-900/40`;case`cron`:return`text-emerald-300 border-emerald-900/40`;case`internal`:return`text-foreground-muted border-border`;default:return`text-foreground-muted border-border`}});return(n,ee)=>(e(),o(`span`,{class:re([`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono uppercase tracking-wide`,r.value])},m(t.source||i(`—`)),3))}},fe={class:`space-y-6`},pe={class:`flex flex-col sm:flex-row sm:items-center gap-2 sm:flex-wrap`},me={class:`relative w-full sm:flex-1 sm:min-w-[260px] sm:max-w-[420px]`},he={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0`},ge={key:0,class:`ml-1 opacity-60 tabular-nums`},_e={class:`bg-background border border-border rounded-lg overflow-x-auto`},ve={class:`sm:hidden divide-y divide-border`},ye=[`onClick`],be={class:`flex items-start justify-between gap-2`},xe={class:`min-w-0 flex-1`},Se={class:`flex items-center gap-2 flex-wrap`},Ce={class:`mt-1 text-xs font-mono text-white break-all`},we={key:0,class:`mt-1 text-[11px] text-foreground-muted break-words`},Te={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted font-mono`},Ee={key:0},De={key:1,class:`break-all`},Oe={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},y={class:`hidden sm:table w-full text-sm text-left`},b={class:`divide-y divide-border`},x=[`onClick`],S={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},C={class:`px-4 py-2.5`},w={class:`px-4 py-2.5 hidden md:table-cell`},T={class:`text-xs text-white truncate max-w-[200px]`},ke={key:0,class:`text-[10px] text-foreground-muted/70 font-mono truncate`},Ae={class:`px-4 py-2.5 text-xs font-mono text-foreground-muted hidden sm:table-cell`},je={class:`px-4 py-2.5 text-xs font-mono text-white truncate max-w-[440px]`},Me={class:`px-4 py-2.5 hidden sm:table-cell`},Ne={key:1,class:`text-foreground-muted text-xs`},Pe={class:`px-4 py-2.5 text-xs font-mono text-foreground-muted hidden lg:table-cell`},Fe={class:`px-4 py-2.5 text-xs text-foreground-muted truncate max-w-[280px] hidden xl:table-cell`},Ie={key:0},Le={key:0,class:`flex items-center justify-between text-xs`},Re={class:`text-foreground-muted`},ze={class:`flex items-center gap-1`},Be={key:0,class:`p-5 space-y-5 text-sm`},Ve={class:`grid grid-cols-2 gap-3`},He={class:`bg-surface border border-border rounded p-3 min-w-0`},Ue={class:`text-xs text-white font-mono truncate`},We={class:`bg-surface border border-border rounded p-3 min-w-0`},Ge={class:`bg-surface border border-border rounded p-3 min-w-0`},Ke={class:`text-sm text-white truncate`},qe={key:0,class:`text-[11px] text-foreground-muted font-mono truncate mt-0.5`},Je={class:`bg-surface border border-border rounded p-3 min-w-0`},Ye={class:`flex items-center gap-2`},Xe={key:1,class:`text-foreground-muted text-xs`},Ze={key:2,class:`text-xs text-foreground-muted font-mono`},Qe={class:`bg-surface border border-border rounded p-3 min-w-0`},$e={class:`text-xs text-white font-mono truncate`},et={class:`bg-surface border border-border rounded p-3 min-w-0`},tt={class:`text-xs text-white font-mono`},nt={class:`bg-surface border border-border rounded p-3 text-xs text-white font-mono whitespace-pre-wrap break-all`},rt={class:`text-foreground break-words`},it={key:0},at={class:`bg-surface border border-border rounded p-3 text-xs text-foreground-muted font-mono whitespace-pre-wrap break-all`},ot={key:1},st={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-72 whitespace-pre-wrap break-words`},E=100,D=200,O=Object.assign({name:`ActivityView`},{__name:`Activity`,setup(re){let g=ce(),O=[{label:`All`,value:``},{label:`Web`,value:`web`},{label:`API`,value:`api`},{label:`MCP`,value:`mcp`},{label:`SDK`,value:`sdk`},{label:`Webhook`,value:`webhook`},{label:`Internal`,value:`internal`}],ct=[{label:`All`,value:``},{label:`Success`,value:`ok`},{label:`Errors`,value:`err`}],lt=[{label:`5m`,value:`5m`},{label:`1h`,value:`1h`},{label:`24h`,value:`24h`},{label:`7d`,value:`7d`}],k=r({q:``,source:``,statusBucket:``,range:`24h`}),A=r([]),j=r([]),M=r(!1),N=r(null),P=r(0),F=r(!1),I=r(1),L=r([{since:void 0,until:void 0}]),R=f(()=>I.value===1?[...j.value,...A.value]:A.value),z=f(()=>{let e={};for(let t of R.value)e[t.source]=(e[t.source]||0)+1;return e[``]=R.value.length,e}),B=f(()=>Math.max(L.value.length,I.value)),ut=f(()=>{let e=B.value,t=I.value;return[...new Set([1,e,t-1,t,t+1])].filter(t=>t>=1&&t<=e).sort((e,t)=>e-t)}),dt=e=>{switch(e){case`5m`:return 3e5;case`1h`:return 36e5;case`24h`:return 864e5;case`7d`:return 6048e5;default:return 0}},ft=(e={})=>{let t={limit:E};k.value.source&&(t.source=k.value.source),k.value.statusBucket===`err`&&(t.status_min=400),k.value.q&&(t.q=k.value.q);let n=dt(k.value.range);return n&&(t.since=Date.now()-n),Object.assign(t,e)},V=async e=>{if(e<1||e>L.value.length+1)return;let t=L.value[e-1]?.cursor,n=await se(ft(t?{cursor:t}:{}));A.value=n.data?.rows||[];let r=n.data?.next_cursor||0;F.value=r>0,L.value[e-1]||(L.value[e-1]={}),L.value[e-1].cursor=t,r?(L.value[e]||(L.value[e]={}),L.value[e].cursor=r):L.value=L.value.slice(0,e),P.value=(e-1)*E+A.value.length,I.value=e,e>1&&(j.value=[])},H=async()=>{L.value=[{since:void 0,until:void 0}],j.value=[],I.value=1,await V(1)},U=null,pt=e=>{if(k.value.source&&e.source!==k.value.source||k.value.statusBucket===`err`&&(e.status||0)<400)return!1;if(k.value.q){let t=k.value.q.toLowerCase();if(!(e.path+` `+e.summary+` `+e.actor_label).toLowerCase().includes(t))return!1}return!0},W=e=>{pt(e)&&I.value===1&&(j.value.unshift(e),j.value.length>D&&(j.value=j.value.slice(0,D)))},G=null,mt=()=>{clearTimeout(G),G=setTimeout(H,250)},K=e=>{N.value=e,M.value=!0},ht=f(()=>N.value?N.value.summary||N.value.method+` `+N.value.path:`Activity`),q=f(()=>{if(!N.value?.metadata)return``;try{return JSON.stringify(JSON.parse(N.value.metadata),null,2)}catch{return N.value.metadata}}),J=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}):`—`,gt=e=>e?new Date(e).toLocaleString():`—`,Y=e=>e==null?`—`:e<1?`<1ms`:e<1e3?e+`ms`:(e/1e3).toFixed(2)+`s`,X=e=>e?e>=500?`error`:e>=400?`failed`:e>=200?`success`:`pending`:``,Z=e=>e.id?`db-${e.id}`:`live-${e.ts}-${e.request_id}-${e.path}`,Q=()=>{U||(U=g.subscribe(`activity`,W),g.connect())},$=()=>{U&&=(U(),null)};return ne(()=>{Q(),H()}),t($),te(()=>{Q(),H()}),ie($),(t,r)=>(e(),o(`div`,fe,[r[20]||=a(`div`,null,[a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Activity `),a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Every API and MCP request. `)],-1),a(`div`,pe,[a(`div`,me,[s(i(le),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),ee(a(`input`,{"onUpdate:modelValue":r[0]||=e=>k.value.q=e,"aria-label":`Search activity by path, summary, or actor`,placeholder:`Search path, summary, actor…`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-base sm:text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:mt},null,544),[[oe,k.value.q]])]),a(`div`,he,[(e(),o(d,null,c(O,t=>s(h,{key:t.value,variant:`chip`,size:`xs`,active:k.value.source===t.value,class:`shrink-0 snap-start`,onClick:e=>{k.value.source=t.value,H()}},{default:n(()=>[u(m(t.label)+` `,1),z.value[t.value]!=null&&t.value!==``?(e(),o(`span`,ge,m(z.value[t.value]),1)):p(``,!0)]),_:2},1032,[`active`,`onClick`])),64)),r[4]||=a(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),(e(),o(d,null,c(ct,e=>s(h,{key:e.value,variant:`chip`,size:`xs`,active:k.value.statusBucket===e.value,class:`shrink-0 snap-start`,onClick:t=>{k.value.statusBucket=e.value,H()}},{default:n(()=>[u(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64)),r[5]||=a(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),(e(),o(d,null,c(lt,e=>s(h,{key:e.value,variant:`chip`,size:`xs`,active:k.value.range===e.value,class:`shrink-0 snap-start`,onClick:t=>{k.value.range=e.value,H()}},{default:n(()=>[u(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64))])]),a(`div`,_e,[a(`ul`,ve,[(e(!0),o(d,null,c(R.value,t=>(e(),o(`li`,{key:Z(t),class:`px-4 py-3 cursor-pointer hover:bg-surface-hover transition-colors`,onClick:e=>K(t)},[a(`div`,be,[a(`div`,xe,[a(`div`,Se,[s(v,{source:t.source},null,8,[`source`]),t.status?(e(),l(_,{key:0,status:X(t.status)},null,8,[`status`])):p(``,!0)]),a(`div`,Ce,m(t.method?t.method+` `:``)+m(t.path||i(`—`)),1),t.summary?(e(),o(`div`,we,m(t.summary),1)):p(``,!0),a(`div`,Te,[a(`span`,null,m(J(t.ts)),1),t.duration_ms==null?p(``,!0):(e(),o(`span`,Ee,m(Y(t.duration_ms)),1)),t.actor_label||t.actor_id?(e(),o(`span`,De,m(t.actor_label||t.actor_id),1)):p(``,!0)])])])],8,ye))),128)),R.value.length?p(``,!0):(e(),o(`li`,Oe,` Requests and tool calls appear here. `))]),a(`table`,y,[r[7]||=a(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[a(`tr`,null,[a(`th`,{class:`px-4 py-3 w-32`},` Time `),a(`th`,{class:`px-4 py-3 w-24`},` Source `),a(`th`,{class:`px-4 py-3 w-40 hidden md:table-cell`},` Actor `),a(`th`,{class:`px-4 py-3 w-20 hidden sm:table-cell`},` Method `),a(`th`,{class:`px-4 py-3`},` Path / Tool `),a(`th`,{class:`px-4 py-3 w-16 hidden sm:table-cell`},` Status `),a(`th`,{class:`px-4 py-3 w-20 hidden lg:table-cell`},` Duration `),a(`th`,{class:`px-4 py-3 hidden xl:table-cell`},` Summary `)])],-1),a(`tbody`,b,[(e(!0),o(d,null,c(R.value,t=>(e(),o(`tr`,{key:Z(t),class:`hover:bg-surface-hover cursor-pointer transition-colors`,onClick:e=>K(t)},[a(`td`,S,m(J(t.ts)),1),a(`td`,C,[s(v,{source:t.source},null,8,[`source`])]),a(`td`,w,[a(`div`,T,m(t.actor_label||t.actor_id||i(`—`)),1),t.actor_label&&t.actor_id&&t.actor_label!==t.actor_id?(e(),o(`div`,ke,m(t.actor_id),1)):p(``,!0)]),a(`td`,Ae,m(t.method||i(`—`)),1),a(`td`,je,m(t.path||i(`—`)),1),a(`td`,Me,[t.status?(e(),l(_,{key:0,status:X(t.status)},null,8,[`status`])):(e(),o(`span`,Ne,m(i(`—`)),1))]),a(`td`,Pe,m(Y(t.duration_ms)),1),a(`td`,Fe,m(t.summary),1)],8,x))),128)),R.value.length?p(``,!0):(e(),o(`tr`,Ie,[...r[6]||=[a(`td`,{colspan:`8`,class:`px-4 py-12 text-center text-foreground-muted text-sm`},` Requests and tool calls appear here. `,-1)]]))])])]),B.value>1?(e(),o(`div`,Le,[a(`div`,Re,` Page `+m(I.value)+` of `+m(B.value)+` · `+m(P.value)+m(F.value?`+`:``)+` rows `,1),a(`div`,ze,[s(h,{variant:`secondary`,size:`xs`,disabled:I.value<=1,onClick:r[1]||=e=>V(I.value-1)},{default:n(()=>[s(i(de),{class:`w-3.5 h-3.5`}),r[8]||=u(` Prev `,-1)]),_:1},8,[`disabled`]),(e(!0),o(d,null,c(ut.value,t=>(e(),l(h,{key:t,variant:t===I.value?`primary`:`secondary`,size:`xs`,onClick:e=>V(t)},{default:n(()=>[u(m(t),1)]),_:2},1032,[`variant`,`onClick`]))),128)),s(h,{variant:`secondary`,size:`xs`,disabled:I.value>=B.value&&!F.value,onClick:r[2]||=e=>V(I.value+1)},{default:n(()=>[r[9]||=u(` Next `,-1),s(i(ae),{class:`w-3.5 h-3.5`})]),_:1},8,[`disabled`])])])):p(``,!0),s(ue,{modelValue:M.value,"onUpdate:modelValue":r[3]||=e=>M.value=e,title:ht.value,width:`640px`},{default:n(()=>[N.value?(e(),o(`div`,Be,[a(`div`,Ve,[a(`div`,He,[r[10]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Time `,-1),a(`div`,Ue,m(gt(N.value.ts)),1)]),a(`div`,We,[r[11]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Source `,-1),s(v,{source:N.value.source},null,8,[`source`])]),a(`div`,Ge,[r[12]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Actor `,-1),a(`div`,Ke,m(N.value.actor_label||i(`—`)),1),N.value.actor_id?(e(),o(`div`,qe,m(N.value.actor_id),1)):p(``,!0)]),a(`div`,Je,[r[13]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Status `,-1),a(`div`,Ye,[N.value.status?(e(),l(_,{key:0,status:X(N.value.status)},null,8,[`status`])):(e(),o(`span`,Xe,m(i(`—`)),1)),N.value.status?(e(),o(`span`,Ze,`HTTP `+m(N.value.status),1)):p(``,!0)])]),a(`div`,Qe,[r[14]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Method `,-1),a(`div`,$e,m(N.value.method||i(`—`)),1)]),a(`div`,et,[r[15]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Duration `,-1),a(`div`,tt,m(Y(N.value.duration_ms)),1)])]),a(`div`,null,[r[16]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Path / Tool `,-1),a(`pre`,nt,m(N.value.path||i(`—`)),1)]),a(`div`,null,[r[17]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Summary `,-1),a(`div`,rt,m(N.value.summary||i(`—`)),1)]),N.value.request_id?(e(),o(`div`,it,[r[18]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Request ID `,-1),a(`pre`,at,m(N.value.request_id),1)])):p(``,!0),q.value?(e(),o(`div`,ot,[r[19]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Metadata `,-1),a(`pre`,st,m(q.value),1)])):p(``,!0)])):p(``,!0)]),_:1},8,[`modelValue`,`title`])]))}});export{O as default}; \ No newline at end of file +import{D as e,E as t,F as n,G as r,I as ee,S as te,T as ne,Z as i,c as a,d as o,gt as re,h as s,k as c,l,m as u,r as d,s as f,u as p,vt as m,w as ie}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ae}from"./chevron-right-D5C5fM5p.js";import{Lt as oe,N as se,_t as h,jt as g,r as ce,xt as le}from"./index-pE9wnfTb.js";import{t as ue}from"./Drawer-CSwYBfhJ.js";import{t as _}from"./StatusBadge-BpEw6z9Z.js";var de=g(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]),v={__name:`SourceTag`,props:{source:{type:String,default:``}},setup(t){let n=t,r=f(()=>{switch(n.source){case`web`:return`text-indigo-300 border-indigo-900/40`;case`api`:return`text-sky-300 border-sky-900/40`;case`mcp`:return`text-violet-300 border-violet-900/40`;case`sdk`:return`text-teal-300 border-teal-900/40`;case`webhook`:return`text-amber-300 border-amber-900/40`;case`cron`:return`text-emerald-300 border-emerald-900/40`;case`internal`:return`text-foreground-muted border-border`;default:return`text-foreground-muted border-border`}});return(n,ee)=>(e(),o(`span`,{class:re([`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono uppercase tracking-wide`,r.value])},m(t.source||i(`—`)),3))}},fe={class:`space-y-6`},pe={class:`flex flex-col sm:flex-row sm:items-center gap-2 sm:flex-wrap`},me={class:`relative w-full sm:flex-1 sm:min-w-[260px] sm:max-w-[420px]`},he={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0`},ge={key:0,class:`ml-1 opacity-60 tabular-nums`},_e={class:`bg-background border border-border rounded-lg overflow-x-auto`},ve={class:`sm:hidden divide-y divide-border`},ye=[`onClick`],be={class:`flex items-start justify-between gap-2`},xe={class:`min-w-0 flex-1`},Se={class:`flex items-center gap-2 flex-wrap`},Ce={class:`mt-1 text-xs font-mono text-white break-all`},we={key:0,class:`mt-1 text-[11px] text-foreground-muted break-words`},Te={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted font-mono`},Ee={key:0},De={key:1,class:`break-all`},Oe={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},y={class:`hidden sm:table w-full text-sm text-left`},b={class:`divide-y divide-border`},x=[`onClick`],S={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},C={class:`px-4 py-2.5`},w={class:`px-4 py-2.5 hidden md:table-cell`},T={class:`text-xs text-white truncate max-w-[200px]`},ke={key:0,class:`text-[10px] text-foreground-muted/70 font-mono truncate`},Ae={class:`px-4 py-2.5 text-xs font-mono text-foreground-muted hidden sm:table-cell`},je={class:`px-4 py-2.5 text-xs font-mono text-white truncate max-w-[440px]`},Me={class:`px-4 py-2.5 hidden sm:table-cell`},Ne={key:1,class:`text-foreground-muted text-xs`},Pe={class:`px-4 py-2.5 text-xs font-mono text-foreground-muted hidden lg:table-cell`},Fe={class:`px-4 py-2.5 text-xs text-foreground-muted truncate max-w-[280px] hidden xl:table-cell`},Ie={key:0},Le={key:0,class:`flex items-center justify-between text-xs`},Re={class:`text-foreground-muted`},ze={class:`flex items-center gap-1`},Be={key:0,class:`p-5 space-y-5 text-sm`},Ve={class:`grid grid-cols-2 gap-3`},He={class:`bg-surface border border-border rounded p-3 min-w-0`},Ue={class:`text-xs text-white font-mono truncate`},We={class:`bg-surface border border-border rounded p-3 min-w-0`},Ge={class:`bg-surface border border-border rounded p-3 min-w-0`},Ke={class:`text-sm text-white truncate`},qe={key:0,class:`text-[11px] text-foreground-muted font-mono truncate mt-0.5`},Je={class:`bg-surface border border-border rounded p-3 min-w-0`},Ye={class:`flex items-center gap-2`},Xe={key:1,class:`text-foreground-muted text-xs`},Ze={key:2,class:`text-xs text-foreground-muted font-mono`},Qe={class:`bg-surface border border-border rounded p-3 min-w-0`},$e={class:`text-xs text-white font-mono truncate`},et={class:`bg-surface border border-border rounded p-3 min-w-0`},tt={class:`text-xs text-white font-mono`},nt={class:`bg-surface border border-border rounded p-3 text-xs text-white font-mono whitespace-pre-wrap break-all`},rt={class:`text-foreground break-words`},it={key:0},at={class:`bg-surface border border-border rounded p-3 text-xs text-foreground-muted font-mono whitespace-pre-wrap break-all`},ot={key:1},st={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-72 whitespace-pre-wrap break-words`},E=100,D=200,O=Object.assign({name:`ActivityView`},{__name:`Activity`,setup(re){let g=ce(),O=[{label:`All`,value:``},{label:`Web`,value:`web`},{label:`API`,value:`api`},{label:`MCP`,value:`mcp`},{label:`SDK`,value:`sdk`},{label:`Webhook`,value:`webhook`},{label:`Internal`,value:`internal`}],ct=[{label:`All`,value:``},{label:`Success`,value:`ok`},{label:`Errors`,value:`err`}],lt=[{label:`5m`,value:`5m`},{label:`1h`,value:`1h`},{label:`24h`,value:`24h`},{label:`7d`,value:`7d`}],k=r({q:``,source:``,statusBucket:``,range:`24h`}),A=r([]),j=r([]),M=r(!1),N=r(null),P=r(0),F=r(!1),I=r(1),L=r([{since:void 0,until:void 0}]),R=f(()=>I.value===1?[...j.value,...A.value]:A.value),z=f(()=>{let e={};for(let t of R.value)e[t.source]=(e[t.source]||0)+1;return e[``]=R.value.length,e}),B=f(()=>Math.max(L.value.length,I.value)),ut=f(()=>{let e=B.value,t=I.value;return[...new Set([1,e,t-1,t,t+1])].filter(t=>t>=1&&t<=e).sort((e,t)=>e-t)}),dt=e=>{switch(e){case`5m`:return 3e5;case`1h`:return 36e5;case`24h`:return 864e5;case`7d`:return 6048e5;default:return 0}},ft=(e={})=>{let t={limit:E};k.value.source&&(t.source=k.value.source),k.value.statusBucket===`err`&&(t.status_min=400),k.value.q&&(t.q=k.value.q);let n=dt(k.value.range);return n&&(t.since=Date.now()-n),Object.assign(t,e)},V=async e=>{if(e<1||e>L.value.length+1)return;let t=L.value[e-1]?.cursor,n=await se(ft(t?{cursor:t}:{}));A.value=n.data?.rows||[];let r=n.data?.next_cursor||0;F.value=r>0,L.value[e-1]||(L.value[e-1]={}),L.value[e-1].cursor=t,r?(L.value[e]||(L.value[e]={}),L.value[e].cursor=r):L.value=L.value.slice(0,e),P.value=(e-1)*E+A.value.length,I.value=e,e>1&&(j.value=[])},H=async()=>{L.value=[{since:void 0,until:void 0}],j.value=[],I.value=1,await V(1)},U=null,pt=e=>{if(k.value.source&&e.source!==k.value.source||k.value.statusBucket===`err`&&(e.status||0)<400)return!1;if(k.value.q){let t=k.value.q.toLowerCase();if(!(e.path+` `+e.summary+` `+e.actor_label).toLowerCase().includes(t))return!1}return!0},W=e=>{pt(e)&&I.value===1&&(j.value.unshift(e),j.value.length>D&&(j.value=j.value.slice(0,D)))},G=null,mt=()=>{clearTimeout(G),G=setTimeout(H,250)},K=e=>{N.value=e,M.value=!0},ht=f(()=>N.value?N.value.summary||N.value.method+` `+N.value.path:`Activity`),q=f(()=>{if(!N.value?.metadata)return``;try{return JSON.stringify(JSON.parse(N.value.metadata),null,2)}catch{return N.value.metadata}}),J=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}):`—`,gt=e=>e?new Date(e).toLocaleString():`—`,Y=e=>e==null?`—`:e<1?`<1ms`:e<1e3?e+`ms`:(e/1e3).toFixed(2)+`s`,X=e=>e?e>=500?`error`:e>=400?`failed`:e>=200?`success`:`pending`:``,Z=e=>e.id?`db-${e.id}`:`live-${e.ts}-${e.request_id}-${e.path}`,Q=()=>{U||(U=g.subscribe(`activity`,W),g.connect())},$=()=>{U&&=(U(),null)};return ne(()=>{Q(),H()}),t($),te(()=>{Q(),H()}),ie($),(t,r)=>(e(),o(`div`,fe,[r[20]||=a(`div`,null,[a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Activity `),a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Every API and MCP request. `)],-1),a(`div`,pe,[a(`div`,me,[s(i(le),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),ee(a(`input`,{"onUpdate:modelValue":r[0]||=e=>k.value.q=e,"aria-label":`Search activity by path, summary, or actor`,placeholder:`Search path, summary, actor…`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-base sm:text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:mt},null,544),[[oe,k.value.q]])]),a(`div`,he,[(e(),o(d,null,c(O,t=>s(h,{key:t.value,variant:`chip`,size:`xs`,active:k.value.source===t.value,class:`shrink-0 snap-start`,onClick:e=>{k.value.source=t.value,H()}},{default:n(()=>[u(m(t.label)+` `,1),z.value[t.value]!=null&&t.value!==``?(e(),o(`span`,ge,m(z.value[t.value]),1)):p(``,!0)]),_:2},1032,[`active`,`onClick`])),64)),r[4]||=a(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),(e(),o(d,null,c(ct,e=>s(h,{key:e.value,variant:`chip`,size:`xs`,active:k.value.statusBucket===e.value,class:`shrink-0 snap-start`,onClick:t=>{k.value.statusBucket=e.value,H()}},{default:n(()=>[u(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64)),r[5]||=a(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),(e(),o(d,null,c(lt,e=>s(h,{key:e.value,variant:`chip`,size:`xs`,active:k.value.range===e.value,class:`shrink-0 snap-start`,onClick:t=>{k.value.range=e.value,H()}},{default:n(()=>[u(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64))])]),a(`div`,_e,[a(`ul`,ve,[(e(!0),o(d,null,c(R.value,t=>(e(),o(`li`,{key:Z(t),class:`px-4 py-3 cursor-pointer hover:bg-surface-hover transition-colors`,onClick:e=>K(t)},[a(`div`,be,[a(`div`,xe,[a(`div`,Se,[s(v,{source:t.source},null,8,[`source`]),t.status?(e(),l(_,{key:0,status:X(t.status)},null,8,[`status`])):p(``,!0)]),a(`div`,Ce,m(t.method?t.method+` `:``)+m(t.path||i(`—`)),1),t.summary?(e(),o(`div`,we,m(t.summary),1)):p(``,!0),a(`div`,Te,[a(`span`,null,m(J(t.ts)),1),t.duration_ms==null?p(``,!0):(e(),o(`span`,Ee,m(Y(t.duration_ms)),1)),t.actor_label||t.actor_id?(e(),o(`span`,De,m(t.actor_label||t.actor_id),1)):p(``,!0)])])])],8,ye))),128)),R.value.length?p(``,!0):(e(),o(`li`,Oe,` Requests and tool calls appear here. `))]),a(`table`,y,[r[7]||=a(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[a(`tr`,null,[a(`th`,{class:`px-4 py-3 w-32`},` Time `),a(`th`,{class:`px-4 py-3 w-24`},` Source `),a(`th`,{class:`px-4 py-3 w-40 hidden md:table-cell`},` Actor `),a(`th`,{class:`px-4 py-3 w-20 hidden sm:table-cell`},` Method `),a(`th`,{class:`px-4 py-3`},` Path / Tool `),a(`th`,{class:`px-4 py-3 w-16 hidden sm:table-cell`},` Status `),a(`th`,{class:`px-4 py-3 w-20 hidden lg:table-cell`},` Duration `),a(`th`,{class:`px-4 py-3 hidden xl:table-cell`},` Summary `)])],-1),a(`tbody`,b,[(e(!0),o(d,null,c(R.value,t=>(e(),o(`tr`,{key:Z(t),class:`hover:bg-surface-hover cursor-pointer transition-colors`,onClick:e=>K(t)},[a(`td`,S,m(J(t.ts)),1),a(`td`,C,[s(v,{source:t.source},null,8,[`source`])]),a(`td`,w,[a(`div`,T,m(t.actor_label||t.actor_id||i(`—`)),1),t.actor_label&&t.actor_id&&t.actor_label!==t.actor_id?(e(),o(`div`,ke,m(t.actor_id),1)):p(``,!0)]),a(`td`,Ae,m(t.method||i(`—`)),1),a(`td`,je,m(t.path||i(`—`)),1),a(`td`,Me,[t.status?(e(),l(_,{key:0,status:X(t.status)},null,8,[`status`])):(e(),o(`span`,Ne,m(i(`—`)),1))]),a(`td`,Pe,m(Y(t.duration_ms)),1),a(`td`,Fe,m(t.summary),1)],8,x))),128)),R.value.length?p(``,!0):(e(),o(`tr`,Ie,[...r[6]||=[a(`td`,{colspan:`8`,class:`px-4 py-12 text-center text-foreground-muted text-sm`},` Requests and tool calls appear here. `,-1)]]))])])]),B.value>1?(e(),o(`div`,Le,[a(`div`,Re,` Page `+m(I.value)+` of `+m(B.value)+` · `+m(P.value)+m(F.value?`+`:``)+` rows `,1),a(`div`,ze,[s(h,{variant:`secondary`,size:`xs`,disabled:I.value<=1,onClick:r[1]||=e=>V(I.value-1)},{default:n(()=>[s(i(de),{class:`w-3.5 h-3.5`}),r[8]||=u(` Prev `,-1)]),_:1},8,[`disabled`]),(e(!0),o(d,null,c(ut.value,t=>(e(),l(h,{key:t,variant:t===I.value?`primary`:`secondary`,size:`xs`,onClick:e=>V(t)},{default:n(()=>[u(m(t),1)]),_:2},1032,[`variant`,`onClick`]))),128)),s(h,{variant:`secondary`,size:`xs`,disabled:I.value>=B.value&&!F.value,onClick:r[2]||=e=>V(I.value+1)},{default:n(()=>[r[9]||=u(` Next `,-1),s(i(ae),{class:`w-3.5 h-3.5`})]),_:1},8,[`disabled`])])])):p(``,!0),s(ue,{modelValue:M.value,"onUpdate:modelValue":r[3]||=e=>M.value=e,title:ht.value,width:`640px`},{default:n(()=>[N.value?(e(),o(`div`,Be,[a(`div`,Ve,[a(`div`,He,[r[10]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Time `,-1),a(`div`,Ue,m(gt(N.value.ts)),1)]),a(`div`,We,[r[11]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Source `,-1),s(v,{source:N.value.source},null,8,[`source`])]),a(`div`,Ge,[r[12]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Actor `,-1),a(`div`,Ke,m(N.value.actor_label||i(`—`)),1),N.value.actor_id?(e(),o(`div`,qe,m(N.value.actor_id),1)):p(``,!0)]),a(`div`,Je,[r[13]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Status `,-1),a(`div`,Ye,[N.value.status?(e(),l(_,{key:0,status:X(N.value.status)},null,8,[`status`])):(e(),o(`span`,Xe,m(i(`—`)),1)),N.value.status?(e(),o(`span`,Ze,`HTTP `+m(N.value.status),1)):p(``,!0)])]),a(`div`,Qe,[r[14]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Method `,-1),a(`div`,$e,m(N.value.method||i(`—`)),1)]),a(`div`,et,[r[15]||=a(`div`,{class:`text-[10px] uppercase tracking-wider text-foreground-muted mb-1`},` Duration `,-1),a(`div`,tt,m(Y(N.value.duration_ms)),1)])]),a(`div`,null,[r[16]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Path / Tool `,-1),a(`pre`,nt,m(N.value.path||i(`—`)),1)]),a(`div`,null,[r[17]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Summary `,-1),a(`div`,rt,m(N.value.summary||i(`—`)),1)]),N.value.request_id?(e(),o(`div`,it,[r[18]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Request ID `,-1),a(`pre`,at,m(N.value.request_id),1)])):p(``,!0),q.value?(e(),o(`div`,ot,[r[19]||=a(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Metadata `,-1),a(`pre`,st,m(q.value),1)])):p(``,!0)])):p(``,!0)]),_:1},8,[`modelValue`,`title`])]))}});export{O as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/ApiKeys-B5PU7HpA.js b/backend/internal/server/ui_dist/assets/ApiKeys-B1jjrPlM.js similarity index 96% rename from backend/internal/server/ui_dist/assets/ApiKeys-B5PU7HpA.js rename to backend/internal/server/ui_dist/assets/ApiKeys-B1jjrPlM.js index 41f4d07b..c550b76a 100644 --- a/backend/internal/server/ui_dist/assets/ApiKeys-B5PU7HpA.js +++ b/backend/internal/server/ui_dist/assets/ApiKeys-B1jjrPlM.js @@ -1,3 +1,3 @@ -import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,k as l,l as u,m as d,r as f,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ee}from"./check-BNre7JFR.js";import{t as h}from"./copy-BqdwwcxC.js";import{t as g}from"./key-round-BKXtbC85.js";import{t as _}from"./trash-2-DaeYqnW_.js";import{It as te,Lt as ne,P as re,_t as v,d as ie,gt as ae,o as oe,vt as se}from"./index-DTqMKlE1.js";import{t as ce}from"./clipboard-D_9N0yai.js";import{t as y}from"./IconButton-CsCZOqWo.js";import{n as b,t as x}from"./time-D8OmbYzY.js";var S={class:`space-y-6`},C={class:`flex items-start justify-between gap-4`},w={key:0,class:`bg-background border border-amber-700/40 rounded-lg p-4 space-y-2`},T={class:`flex items-start justify-between gap-3`},E={class:`flex items-center gap-2`},D={class:`flex-1 font-mono text-sm text-white break-all bg-surface px-3 py-2 rounded border border-border`},O={key:1,class:`bg-background border border-border rounded-lg p-5 space-y-4`},k={class:`grid grid-cols-1 md:grid-cols-2 gap-3`},A={class:`flex gap-2 pt-1`},j={class:`bg-background border border-border rounded-lg overflow-x-auto`},M={class:`sm:hidden divide-y divide-border`},N={class:`flex items-start justify-between gap-2`},P={class:`min-w-0 flex-1`},F={class:`flex items-center gap-2 flex-wrap`},I={class:`font-medium text-white truncate`},L={key:0,class:`text-[11px] font-mono text-foreground-muted bg-surface px-1.5 py-0.5 rounded`},R={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},z={key:0},B={key:1,class:`text-warning-fg`},V={key:2},H={key:3,class:`text-danger-fg`},U={key:4},W={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},le={class:`hidden sm:table w-full text-sm text-left`},ue={class:`divide-y divide-border`},de={class:`px-6 py-4 text-white font-medium`},fe={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden sm:table-cell`},pe={class:`px-6 py-4 text-foreground-muted hidden xl:table-cell`},me={class:`px-6 py-4 hidden md:table-cell`},he={key:0,class:`text-foreground-muted`},ge={key:1,class:`text-warning-fg text-xs`},_e={class:`px-6 py-4 hidden lg:table-cell`},ve={key:0,class:`text-foreground-muted`},ye={key:1,class:`text-danger-fg text-xs`},be={key:2,class:`text-foreground-muted`},xe={class:`px-6 py-4 text-right`},Se={key:0},Ce={__name:`ApiKeys`,setup(Ce){let G=ae(),K=n([]),q=n(``),J=n(!1),Y=n(!1),X=n(!1),Z=n({name:``,expiresInDays:0}),Q=async()=>{let e=await re();K.value=e.data.keys||[]},we=()=>{Z.value={name:``,expiresInDays:0},Y.value=!0},Te=()=>{Y.value=!1,Z.value={name:``,expiresInDays:0}},Ee=async()=>{X.value=!0;try{let e={name:Z.value.name.trim()};Z.value.expiresInDays>0&&(e.expires_in_days=Z.value.expiresInDays);let t=await oe(e);q.value=t.data.key,J.value=!1,Y.value=!1,await Q()}catch(e){console.error(e),G.notify({title:`Failed to create key`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}finally{X.value=!1}},De=async()=>{await ce(q.value)?(J.value=!0,setTimeout(()=>{J.value=!1},1500)):G.notify({title:`Copy failed`,message:`Could not copy to clipboard. Select the key manually: +import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,k as l,l as u,m as d,r as f,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ee}from"./check-CZmR72iA.js";import{t as h}from"./copy-3UAsea5P.js";import{t as g}from"./key-round-D9wVuhgl.js";import{t as _}from"./trash-2-Cz9PSE2q.js";import{It as te,Lt as ne,P as re,_t as v,d as ie,gt as ae,o as oe,vt as se}from"./index-pE9wnfTb.js";import{t as ce}from"./clipboard-D_9N0yai.js";import{t as y}from"./IconButton-CsCZOqWo.js";import{n as b,t as x}from"./time-D8OmbYzY.js";var S={class:`space-y-6`},C={class:`flex items-start justify-between gap-4`},w={key:0,class:`bg-background border border-amber-700/40 rounded-lg p-4 space-y-2`},T={class:`flex items-start justify-between gap-3`},E={class:`flex items-center gap-2`},D={class:`flex-1 font-mono text-sm text-white break-all bg-surface px-3 py-2 rounded border border-border`},O={key:1,class:`bg-background border border-border rounded-lg p-5 space-y-4`},k={class:`grid grid-cols-1 md:grid-cols-2 gap-3`},A={class:`flex gap-2 pt-1`},j={class:`bg-background border border-border rounded-lg overflow-x-auto`},M={class:`sm:hidden divide-y divide-border`},N={class:`flex items-start justify-between gap-2`},P={class:`min-w-0 flex-1`},F={class:`flex items-center gap-2 flex-wrap`},I={class:`font-medium text-white truncate`},L={key:0,class:`text-[11px] font-mono text-foreground-muted bg-surface px-1.5 py-0.5 rounded`},R={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},z={key:0},B={key:1,class:`text-warning-fg`},V={key:2},H={key:3,class:`text-danger-fg`},U={key:4},W={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},le={class:`hidden sm:table w-full text-sm text-left`},ue={class:`divide-y divide-border`},de={class:`px-6 py-4 text-white font-medium`},fe={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden sm:table-cell`},pe={class:`px-6 py-4 text-foreground-muted hidden xl:table-cell`},me={class:`px-6 py-4 hidden md:table-cell`},he={key:0,class:`text-foreground-muted`},ge={key:1,class:`text-warning-fg text-xs`},_e={class:`px-6 py-4 hidden lg:table-cell`},ve={key:0,class:`text-foreground-muted`},ye={key:1,class:`text-danger-fg text-xs`},be={key:2,class:`text-foreground-muted`},xe={class:`px-6 py-4 text-right`},Se={key:0},Ce={__name:`ApiKeys`,setup(Ce){let G=ae(),K=n([]),q=n(``),J=n(!1),Y=n(!1),X=n(!1),Z=n({name:``,expiresInDays:0}),Q=async()=>{let e=await re();K.value=e.data.keys||[]},we=()=>{Z.value={name:``,expiresInDays:0},Y.value=!0},Te=()=>{Y.value=!1,Z.value={name:``,expiresInDays:0}},Ee=async()=>{X.value=!0;try{let e={name:Z.value.name.trim()};Z.value.expiresInDays>0&&(e.expires_in_days=Z.value.expiresInDays);let t=await oe(e);q.value=t.data.key,J.value=!1,Y.value=!1,await Q()}catch(e){console.error(e),G.notify({title:`Failed to create key`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}finally{X.value=!1}},De=async()=>{await ce(q.value)?(J.value=!0,setTimeout(()=>{J.value=!1},1500)):G.notify({title:`Copy failed`,message:`Could not copy to clipboard. Select the key manually: `+q.value})},$=async e=>{if(await G.ask({title:`Delete API key?`,message:`"${e.name||e.id}" will stop working immediately. This cannot be undone.`,confirmLabel:`Delete`,danger:!0}))try{await ie(e.id),await Q()}catch(e){console.error(e),G.notify({title:`Failed to delete key`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}},Oe=e=>new Date(e).toLocaleString();return i(Q),(n,i)=>(e(),s(`div`,S,[o(`div`,C,[i[4]||=o(`div`,null,[o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` API Keys `),o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Tokens for REST and MCP clients. Secrets are shown once. `)],-1),c(v,{onClick:we},{default:t(()=>[c(a(g),{class:`w-4 h-4`}),i[3]||=d(` New Key `,-1)]),_:1})]),q.value?(e(),s(`div`,w,[o(`div`,T,[i[5]||=o(`div`,null,[o(`h2`,{class:`text-xs font-bold text-amber-300 uppercase tracking-wider`},` Copy this key now `),o(`div`,{class:`text-xs text-foreground-muted mt-0.5`},` Store it securely. This secret will not be shown again. `)],-1),o(`button`,{class:`text-foreground-muted hover:text-white`,title:`Dismiss`,"aria-label":`Dismiss API key`,onClick:i[0]||=e=>q.value=``},[c(a(se),{class:`w-4 h-4`})])]),o(`div`,E,[o(`code`,D,m(q.value),1),o(`button`,{class:`px-3 py-2 rounded-md border border-border bg-surface-hover hover:bg-surface text-foreground-muted hover:text-white transition-colors flex items-center gap-1.5 text-xs`,onClick:De},[J.value?(e(),u(a(ee),{key:0,class:`w-3.5 h-3.5 text-success`})):(e(),u(a(h),{key:1,class:`w-3.5 h-3.5`})),d(` `+m(J.value?`Copied`:`Copy`),1)])])])):p(``,!0),Y.value?(e(),s(`div`,O,[i[11]||=o(`div`,{class:`text-sm font-semibold text-white`},` New API Key `,-1),o(`div`,k,[o(`div`,null,[i[6]||=o(`label`,{for:`api-key-name`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Name`,-1),r(o(`input`,{id:`api-key-name`,"onUpdate:modelValue":i[1]||=e=>Z.value.name=e,placeholder:`e.g. ci-deployer`,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:border-white`},null,512),[[ne,Z.value.name]])]),o(`div`,null,[i[8]||=o(`label`,{for:`api-key-expiry`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Expires in`,-1),r(o(`select`,{id:`api-key-expiry`,"onUpdate:modelValue":i[2]||=e=>Z.value.expiresInDays=e,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:border-white`},[...i[7]||=[o(`option`,{value:0},` Never `,-1),o(`option`,{value:1},` 1 day `,-1),o(`option`,{value:7},` 7 days `,-1),o(`option`,{value:30},` 30 days `,-1),o(`option`,{value:90},` 90 days `,-1),o(`option`,{value:365},` 1 year `,-1)]],512),[[te,Z.value.expiresInDays]])])]),o(`div`,A,[c(v,{disabled:!Z.value.name.trim()||X.value,loading:X.value,onClick:Ee},{default:t(()=>[...i[9]||=[d(` Generate Key `,-1)]]),_:1},8,[`disabled`,`loading`]),c(v,{variant:`secondary`,onClick:Te},{default:t(()=>[...i[10]||=[d(` Cancel `,-1)]]),_:1})])])):p(``,!0),o(`div`,j,[o(`ul`,M,[(e(!0),s(f,null,l(K.value,t=>(e(),s(`li`,{key:t.id,class:`px-4 py-3`},[o(`div`,N,[o(`div`,P,[o(`div`,F,[o(`span`,I,m(t.name||`Unnamed`),1),t.prefix?(e(),s(`code`,L,m(t.prefix)+`…`,1)):p(``,!0)]),o(`div`,R,[t.last_used_at?(e(),s(`span`,z,`used `+m(a(x)(t.last_used_at)),1)):(e(),s(`span`,B,`never used`)),t.expires_at?a(b)(t.expires_at)?(e(),s(`span`,H,`expired `+m(a(x)(t.expires_at)),1)):(e(),s(`span`,U,`expires `+m(a(x)(t.expires_at)),1)):(e(),s(`span`,V,`no expiry`))])]),c(y,{icon:a(_),variant:`danger`,title:`Delete key`,onClick:e=>$(t)},null,8,[`icon`,`onClick`])])]))),128)),K.value.length===0?(e(),s(`li`,W,` No API keys yet. `)):p(``,!0)]),o(`table`,le,[i[13]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{scope:`col`,class:`px-6 py-3 font-medium`},` Name `),o(`th`,{scope:`col`,class:`px-6 py-3 font-medium hidden sm:table-cell`},` Prefix `),o(`th`,{scope:`col`,class:`px-6 py-3 font-medium hidden xl:table-cell`},` Created `),o(`th`,{scope:`col`,class:`px-6 py-3 font-medium hidden md:table-cell`},` Last Used `),o(`th`,{scope:`col`,class:`px-6 py-3 font-medium hidden lg:table-cell`},` Expires `),o(`th`,{scope:`col`,class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,ue,[(e(!0),s(f,null,l(K.value,t=>(e(),s(`tr`,{key:t.id,class:`hover:bg-surface/50 transition-colors`},[o(`td`,de,m(t.name||`Unnamed`),1),o(`td`,fe,m(t.prefix?t.prefix+`…`:a(`—`)),1),o(`td`,pe,m(Oe(t.created_at)),1),o(`td`,me,[t.last_used_at?(e(),s(`span`,he,m(a(x)(t.last_used_at)),1)):(e(),s(`span`,ge,`Never used`))]),o(`td`,_e,[t.expires_at?a(b)(t.expires_at)?(e(),s(`span`,ye,`Expired `+m(a(x)(t.expires_at)),1)):(e(),s(`span`,be,m(a(x)(t.expires_at)),1)):(e(),s(`span`,ve,`Never`))]),o(`td`,xe,[c(y,{icon:a(_),variant:`danger`,title:`Delete key`,onClick:e=>$(t)},null,8,[`icon`,`onClick`])])]))),128)),K.value.length===0?(e(),s(`tr`,Se,[...i[12]||=[o(`td`,{colspan:`6`,class:`px-6 py-8 text-center text-foreground-muted`},` No API keys yet. `,-1)]])):p(``,!0)])])])]))}};export{Ce as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Channels-fKQl2oE8.js b/backend/internal/server/ui_dist/assets/Channels-B3r_Mr9x.js similarity index 98% rename from backend/internal/server/ui_dist/assets/Channels-fKQl2oE8.js rename to backend/internal/server/ui_dist/assets/Channels-B3r_Mr9x.js index 5b993e59..934fd801 100644 --- a/backend/internal/server/ui_dist/assets/Channels-fKQl2oE8.js +++ b/backend/internal/server/ui_dist/assets/Channels-B3r_Mr9x.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as _}from"./check-BNre7JFR.js";import{t as v}from"./circle-alert-BnUYYhGE.js";import{t as y}from"./copy-BqdwwcxC.js";import{t as b}from"./rotate-ccw-DWwjKCqh.js";import{t as x}from"./trash-2-DaeYqnW_.js";import{B as S,Bt as C,Ct as w,F as T,It as E,Lt as D,_t as O,f as k,gt as A,kt as j,s as ee,tt as te,vt as M,xt as N}from"./index-DTqMKlE1.js";import{t as ne}from"./clipboard-D_9N0yai.js";import{t as P}from"./IconButton-CsCZOqWo.js";import{n as F,t as I}from"./time-D8OmbYzY.js";var L={class:`w-full max-w-2xl bg-background border border-border rounded-lg shadow-lg flex flex-col max-h-[80vh]`},R={class:`px-5 py-4 border-b border-border flex items-start justify-between gap-3`},z={class:`px-5 py-3 border-b border-border flex items-center gap-2`},B={class:`flex-1 overflow-y-auto`},V={key:0,class:`px-5 py-10 text-center text-xs text-foreground-muted italic`},H={key:1,class:`px-5 py-10 text-center`},U={class:`text-xs text-foreground-muted`},W={key:2,class:`divide-y divide-border`},G=[`onClick`],K=[`checked`,`onClick`],q={class:`flex-1 min-w-0`},J={class:`text-sm font-medium text-white truncate`},Y={key:0,class:`text-xs text-foreground-muted mt-0.5 line-clamp-1`},X={class:`text-[11px] text-foreground-muted font-mono shrink-0`},Z={class:`px-5 py-3 border-t border-border flex items-center justify-between gap-3`},Q={class:`text-xs text-foreground-muted tabular-nums`},re={class:`flex gap-2`},ie={__name:`FunctionPickerModal`,props:{selected:{type:Array,default:()=>[]}},emits:[`close`,`apply`],setup(d,{emit:_}){let v=d,y=_,b=n([]),x=n(!0),w=n(``),T=n(new Set(v.selected)),E=e=>{let t=new Set(T.value);t.has(e)?t.delete(e):t.add(e),T.value=t},k=m(()=>{let e=w.value.trim().toLowerCase();return e?b.value.filter(t=>t.name.toLowerCase().includes(e)||(t.description||``).toLowerCase().includes(e)||(t.runtime||``).toLowerCase().includes(e)):b.value}),A=()=>{y(`apply`,Array.from(T.value))};return i(async()=>{try{let e=await S({limit:200});b.value=e.data.functions||[]}finally{x.value=!1}}),(n,i)=>(e(),s(`div`,{class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm`,onClick:i[3]||=C(e=>n.$emit(`close`),[`self`])},[o(`div`,L,[o(`div`,R,[i[4]||=o(`div`,null,[o(`div`,{class:`text-sm font-semibold text-white`},` Pick functions `),o(`div`,{class:`text-xs text-foreground-muted mt-0.5 max-w-prose leading-relaxed`},` Each selection becomes an MCP tool. Dashes become underscores. `)],-1),o(`button`,{class:`text-foreground-muted hover:text-white transition-colors`,title:`Dismiss`,"aria-label":`Close function picker`,onClick:i[0]||=e=>n.$emit(`close`)},[l(a(M),{class:`w-4 h-4`})])]),o(`div`,z,[l(a(N),{class:`w-4 h-4 text-foreground-muted shrink-0`}),r(o(`input`,{"onUpdate:modelValue":i[1]||=e=>w.value=e,"aria-label":`Search functions`,type:`text`,placeholder:`Filter by name, description, or runtime`,class:`flex-1 bg-transparent text-sm text-foreground placeholder-foreground-muted focus:outline-none`},null,512),[[D,w.value]])]),o(`div`,B,[x.value?(e(),s(`div`,V,` Loading functions… `)):k.value.length===0?(e(),s(`div`,H,[l(a(N),{class:`w-8 h-8 text-foreground-muted mx-auto mb-2 opacity-30`}),o(`p`,U,[b.value.length===0?(e(),s(p,{key:0},[f(` No functions deployed yet. `)],64)):(e(),s(p,{key:1},[f(` No functions match "`+g(w.value)+`". `,1)],64))])])):(e(),s(`ul`,W,[(e(!0),s(p,null,u(k.value,t=>(e(),s(`li`,{key:t.id,class:c([`px-5 py-3 flex items-center gap-3 cursor-pointer transition-colors`,T.value.has(t.id)?`bg-surface/30 hover:bg-surface/50`:`hover:bg-surface/40`]),onClick:e=>E(t.id)},[o(`input`,{type:`checkbox`,checked:T.value.has(t.id),class:`accent-primary cursor-pointer`,onClick:C(e=>E(t.id),[`stop`])},null,8,K),o(`div`,q,[o(`div`,J,g(t.name),1),t.description?(e(),s(`div`,Y,g(t.description),1)):h(``,!0)]),o(`code`,X,g(t.runtime),1)],10,G))),128))]))]),o(`div`,Z,[o(`div`,Q,g(T.value.size)+` of `+g(b.value.length)+` selected `,1),o(`div`,re,[l(O,{variant:`secondary`,onClick:i[2]||=e=>n.$emit(`close`)},{default:t(()=>[...i[5]||=[f(` Cancel `,-1)]]),_:1}),l(O,{disabled:T.value.size===0,onClick:A},{default:t(()=>[...i[6]||=[f(` Apply `,-1)]]),_:1},8,[`disabled`])])])])]))}},ae={class:`space-y-6`},oe={class:`flex items-center justify-between gap-4`},se={key:0,class:`bg-background border border-warning-ring rounded-lg p-4 space-y-3`},ce={class:`flex items-start justify-between gap-3`},le={class:`flex items-center gap-2`},ue={class:`flex-1 font-mono text-sm text-white break-all bg-surface px-3 py-2 rounded border border-border`},de={class:`text-xs text-foreground-muted flex flex-wrap items-center gap-x-3 gap-y-1`},fe={class:`text-foreground bg-surface px-1.5 py-0.5 rounded`},pe={key:1,class:`bg-background border border-border rounded-lg p-5 space-y-4`},me={class:`grid grid-cols-1 md:grid-cols-2 gap-3`},he={class:`flex items-center justify-between mb-1.5`},ge={key:0,class:`text-[11px] text-foreground-muted`},_e={key:0,class:`rounded-md border border-red-700/40 bg-red-950/30 p-3 text-xs text-red-200 flex items-start gap-2`},ve={class:`flex gap-2 pt-1`},ye={class:`bg-background border border-border rounded-lg overflow-x-auto`},be={class:`sm:hidden divide-y divide-border`},xe={class:`flex items-start justify-between gap-2`},Se={class:`min-w-0 flex-1`},Ce={class:`flex items-center gap-2 flex-wrap`},we={class:`font-medium text-white truncate`},Te={class:`inline-flex items-center gap-1 text-[11px] text-foreground-muted`},Ee={key:0,class:`mt-1 text-xs text-foreground-muted line-clamp-2`},De={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},Oe={class:`font-mono`},ke={key:0},Ae={key:1,class:`text-amber-400/80`},je={key:2,class:`text-red-400`},Me={key:3},Ne={class:`flex items-center gap-1 shrink-0`},Pe={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},Fe={class:`hidden sm:table w-full text-sm text-left`},Ie={class:`divide-y divide-border`},Le={class:`px-6 py-4`},Re={class:`font-medium text-white`},ze={key:0,class:`text-xs text-foreground-muted mt-0.5 line-clamp-1 max-w-md`},Be={class:`px-6 py-4`},Ve={class:`inline-flex items-center gap-1.5 text-foreground-muted`},$={class:`tabular-nums`},He={class:`px-6 py-4 hidden sm:table-cell`},Ue={class:`text-foreground-muted font-mono text-xs`},We={class:`px-6 py-4 hidden md:table-cell`},Ge={key:0,class:`text-foreground-muted`},Ke={key:1,class:`text-amber-400/70 text-xs`},qe={class:`px-6 py-4 hidden lg:table-cell`},Je={key:0,class:`text-foreground-muted`},Ye={key:1,class:`text-red-400 text-xs`},Xe={key:2,class:`text-foreground-muted`},Ze={class:`px-6 py-4 text-right`},Qe={class:`inline-flex justify-end gap-1`},$e={key:0},et=Object.assign({name:`ChannelsView`},{__name:`Channels`,setup(c){let S=A(),C=n([]),N=n(``),L=n(!1),R=n(!1),z=n(!1),B=n(``),V=n(!1),H=n({name:``,description:``,expiresInDays:0,functionIds:[]}),U=m(()=>`${window.location.origin}/mcp`),W=m(()=>H.value.name.trim()&&H.value.functionIds.length>0),G=async()=>{let e=await T();C.value=e.data.channels||[]},K=()=>{H.value={name:``,description:``,expiresInDays:0,functionIds:[]},B.value=``,R.value=!0},q=()=>{R.value=!1},J=e=>{H.value.functionIds=e,V.value=!1},Y=async()=>{z.value=!0,B.value=``;try{let e={name:H.value.name.trim(),description:H.value.description.trim(),function_ids:H.value.functionIds};H.value.expiresInDays>0&&(e.expires_in_days=H.value.expiresInDays);let t=await ee(e);N.value=t.data.token,R.value=!1,await G()}catch(e){B.value=e?.response?.data?.error?.message||`Failed to create channel.`}finally{z.value=!1}},X=async()=>{N.value&&await ne(N.value)&&(L.value=!0,setTimeout(()=>{L.value=!1},1500))},Z=async e=>{if(!await S.ask({title:`Rotate ${e.name}?`,message:`A new token will be issued. The previous token stops working immediately. Agents using it will need the new value.`,confirmLabel:`Rotate`,danger:!0}))return;let t=await te(e.id);N.value=t.data.token,await G()},Q=async e=>{await S.ask({title:`Delete ${e.name}?`,message:`${e.name} will lose MCP access immediately. Functions inside are not affected. Re-create the channel if you need it again.`,confirmLabel:`Delete`,danger:!0})&&(await k(e.id),await G())};return i(G),(n,i)=>(e(),s(`div`,ae,[o(`div`,oe,[i[7]||=o(`div`,null,[o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Channels `),o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Expose selected functions as scoped MCP tools. `)],-1),l(O,{onClick:K},{default:t(()=>[l(a(w),{class:`w-4 h-4`}),i[6]||=f(` New channel `,-1)]),_:1})]),N.value?(e(),s(`div`,se,[o(`div`,ce,[i[8]||=o(`div`,null,[o(`h2`,{class:`text-xs font-bold text-warning-fg uppercase tracking-wider`},` Copy this token now `),o(`div`,{class:`text-xs text-foreground-muted mt-0.5`},` Store it securely, then add it to your MCP client. `)],-1),o(`button`,{class:`text-foreground-muted hover:text-white transition-colors`,title:`Dismiss`,"aria-label":`Dismiss channel token`,onClick:i[0]||=e=>N.value=``},[l(a(M),{class:`w-4 h-4`})])]),o(`div`,le,[o(`code`,ue,g(N.value),1),o(`button`,{class:`px-3 py-2 rounded-md border border-border bg-surface-hover hover:bg-surface text-foreground-muted hover:text-white transition-colors flex items-center gap-1.5 text-xs`,onClick:X},[L.value?(e(),d(a(_),{key:0,class:`w-3.5 h-3.5 text-success`})):(e(),d(a(y),{key:1,class:`w-3.5 h-3.5`})),f(` `+g(L.value?`Copied`:`Copy`),1)])]),o(`div`,de,[o(`span`,null,[i[9]||=f(`URL `,-1),o(`code`,fe,g(U.value),1)]),i[10]||=o(`span`,null,[f(`Header `),o(`code`,{class:`text-foreground bg-surface px-1.5 py-0.5 rounded`},`Authorization: Bearer `)],-1)])])):h(``,!0),R.value?(e(),s(`div`,pe,[i[18]||=o(`div`,{class:`text-sm font-semibold text-white`},` New channel `,-1),o(`div`,me,[o(`div`,null,[i[11]||=o(`label`,{for:`channel-name`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Name`,-1),r(o(`input`,{id:`channel-name`,"onUpdate:modelValue":i[1]||=e=>H.value.name=e,placeholder:`e.g. support-bot`,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},null,512),[[D,H.value.name]])]),o(`div`,null,[i[13]||=o(`label`,{for:`channel-expiry`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Expires in`,-1),r(o(`select`,{id:`channel-expiry`,"onUpdate:modelValue":i[2]||=e=>H.value.expiresInDays=e,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},[...i[12]||=[o(`option`,{value:0},` Never `,-1),o(`option`,{value:7},` 7 days `,-1),o(`option`,{value:30},` 30 days `,-1),o(`option`,{value:90},` 90 days `,-1)]],512),[[E,H.value.expiresInDays]])])]),o(`div`,null,[i[14]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Description (optional)`,-1),r(o(`input`,{"onUpdate:modelValue":i[3]||=e=>H.value.description=e,placeholder:`What this channel is for`,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},null,512),[[D,H.value.description]])]),o(`div`,null,[o(`div`,he,[i[15]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Functions`,-1),H.value.functionIds.length>0?(e(),s(`span`,ge,g(H.value.functionIds.length)+` selected`,1)):h(``,!0)]),l(O,{variant:`secondary`,onClick:i[4]||=e=>V.value=!0},{default:t(()=>[l(a(j),{class:`w-4 h-4`}),f(` `+g(H.value.functionIds.length===0?`Pick functions`:`Edit selection`),1)]),_:1})]),B.value?(e(),s(`div`,_e,[l(a(v),{class:`w-4 h-4 text-red-400 shrink-0 mt-0.5`}),o(`span`,null,g(B.value),1)])):h(``,!0),o(`div`,ve,[l(O,{disabled:!W.value||z.value,loading:z.value,onClick:Y},{default:t(()=>[...i[16]||=[f(` Generate token `,-1)]]),_:1},8,[`disabled`,`loading`]),l(O,{variant:`secondary`,onClick:q},{default:t(()=>[...i[17]||=[f(` Cancel `,-1)]]),_:1})])])):h(``,!0),o(`div`,ye,[o(`ul`,be,[(e(!0),s(p,null,u(C.value,t=>(e(),s(`li`,{key:t.id,class:`px-4 py-3`},[o(`div`,xe,[o(`div`,Se,[o(`div`,Ce,[o(`span`,we,g(t.name),1),o(`span`,Te,[l(a(j),{class:`w-3 h-3`}),f(` `+g(t.function_count),1)])]),t.description?(e(),s(`div`,Ee,g(t.description),1)):h(``,!0),o(`div`,De,[o(`code`,Oe,g(t.prefix)+`…`,1),t.last_used_at?(e(),s(`span`,ke,`used `+g(a(I)(t.last_used_at)),1)):(e(),s(`span`,Ae,`never used`)),t.expires_at&&a(F)(t.expires_at)?(e(),s(`span`,je,`expired`)):t.expires_at?(e(),s(`span`,Me,`expires `+g(a(I)(t.expires_at)),1)):h(``,!0)])]),o(`div`,Ne,[l(P,{icon:a(b),title:`Rotate token`,onClick:e=>Z(t)},null,8,[`icon`,`onClick`]),l(P,{icon:a(x),variant:`danger`,title:`Delete channel`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),C.value.length===0?(e(),s(`li`,Pe,` No channels yet. `)):h(``,!0)]),o(`table`,Fe,[i[20]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-6 py-3 font-medium`},` Name `),o(`th`,{class:`px-6 py-3 font-medium`},` Functions `),o(`th`,{class:`px-6 py-3 font-medium hidden sm:table-cell`},` Prefix `),o(`th`,{class:`px-6 py-3 font-medium hidden md:table-cell`},` Last used `),o(`th`,{class:`px-6 py-3 font-medium hidden lg:table-cell`},` Expires `),o(`th`,{class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,Ie,[(e(!0),s(p,null,u(C.value,t=>(e(),s(`tr`,{key:t.id,class:`hover:bg-surface/50 transition-colors`},[o(`td`,Le,[o(`div`,Re,g(t.name),1),t.description?(e(),s(`div`,ze,g(t.description),1)):h(``,!0)]),o(`td`,Be,[o(`span`,Ve,[l(a(j),{class:`w-3.5 h-3.5`}),o(`span`,$,g(t.function_count),1)])]),o(`td`,He,[o(`code`,Ue,g(t.prefix)+`…`,1)]),o(`td`,We,[t.last_used_at?(e(),s(`span`,Ge,g(a(I)(t.last_used_at)),1)):(e(),s(`span`,Ke,`Never used`))]),o(`td`,qe,[t.expires_at?a(F)(t.expires_at)?(e(),s(`span`,Ye,`Expired `+g(a(I)(t.expires_at)),1)):(e(),s(`span`,Xe,g(a(I)(t.expires_at)),1)):(e(),s(`span`,Je,`Never`))]),o(`td`,Ze,[o(`div`,Qe,[l(P,{icon:a(b),title:`Rotate token`,onClick:e=>Z(t)},null,8,[`icon`,`onClick`]),l(P,{icon:a(x),variant:`danger`,title:`Delete channel`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),C.value.length===0?(e(),s(`tr`,$e,[...i[19]||=[o(`td`,{colspan:`6`,class:`px-6 py-8 text-center text-foreground-muted`},[f(` No channels yet. Click `),o(`span`,{class:`text-white`},`New channel`),f(` to bundle functions for an agent. `)],-1)]])):h(``,!0)])])]),V.value?(e(),d(ie,{key:2,selected:H.value.functionIds,onClose:i[5]||=e=>V.value=!1,onApply:J},null,8,[`selected`])):h(``,!0)]))}});export{et as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as _}from"./check-CZmR72iA.js";import{t as v}from"./circle-alert-CwieDBHo.js";import{t as y}from"./copy-3UAsea5P.js";import{t as b}from"./rotate-ccw-DgujV-4F.js";import{t as x}from"./trash-2-Cz9PSE2q.js";import{B as S,Bt as C,Ct as w,F as T,It as E,Lt as D,_t as O,f as k,gt as A,kt as j,s as ee,tt as te,vt as M,xt as N}from"./index-pE9wnfTb.js";import{t as ne}from"./clipboard-D_9N0yai.js";import{t as P}from"./IconButton-CsCZOqWo.js";import{n as F,t as I}from"./time-D8OmbYzY.js";var L={class:`w-full max-w-2xl bg-background border border-border rounded-lg shadow-lg flex flex-col max-h-[80vh]`},R={class:`px-5 py-4 border-b border-border flex items-start justify-between gap-3`},z={class:`px-5 py-3 border-b border-border flex items-center gap-2`},B={class:`flex-1 overflow-y-auto`},V={key:0,class:`px-5 py-10 text-center text-xs text-foreground-muted italic`},H={key:1,class:`px-5 py-10 text-center`},U={class:`text-xs text-foreground-muted`},W={key:2,class:`divide-y divide-border`},G=[`onClick`],K=[`checked`,`onClick`],q={class:`flex-1 min-w-0`},J={class:`text-sm font-medium text-white truncate`},Y={key:0,class:`text-xs text-foreground-muted mt-0.5 line-clamp-1`},X={class:`text-[11px] text-foreground-muted font-mono shrink-0`},Z={class:`px-5 py-3 border-t border-border flex items-center justify-between gap-3`},Q={class:`text-xs text-foreground-muted tabular-nums`},re={class:`flex gap-2`},ie={__name:`FunctionPickerModal`,props:{selected:{type:Array,default:()=>[]}},emits:[`close`,`apply`],setup(d,{emit:_}){let v=d,y=_,b=n([]),x=n(!0),w=n(``),T=n(new Set(v.selected)),E=e=>{let t=new Set(T.value);t.has(e)?t.delete(e):t.add(e),T.value=t},k=m(()=>{let e=w.value.trim().toLowerCase();return e?b.value.filter(t=>t.name.toLowerCase().includes(e)||(t.description||``).toLowerCase().includes(e)||(t.runtime||``).toLowerCase().includes(e)):b.value}),A=()=>{y(`apply`,Array.from(T.value))};return i(async()=>{try{let e=await S({limit:200});b.value=e.data.functions||[]}finally{x.value=!1}}),(n,i)=>(e(),s(`div`,{class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm`,onClick:i[3]||=C(e=>n.$emit(`close`),[`self`])},[o(`div`,L,[o(`div`,R,[i[4]||=o(`div`,null,[o(`div`,{class:`text-sm font-semibold text-white`},` Pick functions `),o(`div`,{class:`text-xs text-foreground-muted mt-0.5 max-w-prose leading-relaxed`},` Each selection becomes an MCP tool. Dashes become underscores. `)],-1),o(`button`,{class:`text-foreground-muted hover:text-white transition-colors`,title:`Dismiss`,"aria-label":`Close function picker`,onClick:i[0]||=e=>n.$emit(`close`)},[l(a(M),{class:`w-4 h-4`})])]),o(`div`,z,[l(a(N),{class:`w-4 h-4 text-foreground-muted shrink-0`}),r(o(`input`,{"onUpdate:modelValue":i[1]||=e=>w.value=e,"aria-label":`Search functions`,type:`text`,placeholder:`Filter by name, description, or runtime`,class:`flex-1 bg-transparent text-sm text-foreground placeholder-foreground-muted focus:outline-none`},null,512),[[D,w.value]])]),o(`div`,B,[x.value?(e(),s(`div`,V,` Loading functions… `)):k.value.length===0?(e(),s(`div`,H,[l(a(N),{class:`w-8 h-8 text-foreground-muted mx-auto mb-2 opacity-30`}),o(`p`,U,[b.value.length===0?(e(),s(p,{key:0},[f(` No functions deployed yet. `)],64)):(e(),s(p,{key:1},[f(` No functions match "`+g(w.value)+`". `,1)],64))])])):(e(),s(`ul`,W,[(e(!0),s(p,null,u(k.value,t=>(e(),s(`li`,{key:t.id,class:c([`px-5 py-3 flex items-center gap-3 cursor-pointer transition-colors`,T.value.has(t.id)?`bg-surface/30 hover:bg-surface/50`:`hover:bg-surface/40`]),onClick:e=>E(t.id)},[o(`input`,{type:`checkbox`,checked:T.value.has(t.id),class:`accent-primary cursor-pointer`,onClick:C(e=>E(t.id),[`stop`])},null,8,K),o(`div`,q,[o(`div`,J,g(t.name),1),t.description?(e(),s(`div`,Y,g(t.description),1)):h(``,!0)]),o(`code`,X,g(t.runtime),1)],10,G))),128))]))]),o(`div`,Z,[o(`div`,Q,g(T.value.size)+` of `+g(b.value.length)+` selected `,1),o(`div`,re,[l(O,{variant:`secondary`,onClick:i[2]||=e=>n.$emit(`close`)},{default:t(()=>[...i[5]||=[f(` Cancel `,-1)]]),_:1}),l(O,{disabled:T.value.size===0,onClick:A},{default:t(()=>[...i[6]||=[f(` Apply `,-1)]]),_:1},8,[`disabled`])])])])]))}},ae={class:`space-y-6`},oe={class:`flex items-center justify-between gap-4`},se={key:0,class:`bg-background border border-warning-ring rounded-lg p-4 space-y-3`},ce={class:`flex items-start justify-between gap-3`},le={class:`flex items-center gap-2`},ue={class:`flex-1 font-mono text-sm text-white break-all bg-surface px-3 py-2 rounded border border-border`},de={class:`text-xs text-foreground-muted flex flex-wrap items-center gap-x-3 gap-y-1`},fe={class:`text-foreground bg-surface px-1.5 py-0.5 rounded`},pe={key:1,class:`bg-background border border-border rounded-lg p-5 space-y-4`},me={class:`grid grid-cols-1 md:grid-cols-2 gap-3`},he={class:`flex items-center justify-between mb-1.5`},ge={key:0,class:`text-[11px] text-foreground-muted`},_e={key:0,class:`rounded-md border border-red-700/40 bg-red-950/30 p-3 text-xs text-red-200 flex items-start gap-2`},ve={class:`flex gap-2 pt-1`},ye={class:`bg-background border border-border rounded-lg overflow-x-auto`},be={class:`sm:hidden divide-y divide-border`},xe={class:`flex items-start justify-between gap-2`},Se={class:`min-w-0 flex-1`},Ce={class:`flex items-center gap-2 flex-wrap`},we={class:`font-medium text-white truncate`},Te={class:`inline-flex items-center gap-1 text-[11px] text-foreground-muted`},Ee={key:0,class:`mt-1 text-xs text-foreground-muted line-clamp-2`},De={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},Oe={class:`font-mono`},ke={key:0},Ae={key:1,class:`text-amber-400/80`},je={key:2,class:`text-red-400`},Me={key:3},Ne={class:`flex items-center gap-1 shrink-0`},Pe={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},Fe={class:`hidden sm:table w-full text-sm text-left`},Ie={class:`divide-y divide-border`},Le={class:`px-6 py-4`},Re={class:`font-medium text-white`},ze={key:0,class:`text-xs text-foreground-muted mt-0.5 line-clamp-1 max-w-md`},Be={class:`px-6 py-4`},Ve={class:`inline-flex items-center gap-1.5 text-foreground-muted`},$={class:`tabular-nums`},He={class:`px-6 py-4 hidden sm:table-cell`},Ue={class:`text-foreground-muted font-mono text-xs`},We={class:`px-6 py-4 hidden md:table-cell`},Ge={key:0,class:`text-foreground-muted`},Ke={key:1,class:`text-amber-400/70 text-xs`},qe={class:`px-6 py-4 hidden lg:table-cell`},Je={key:0,class:`text-foreground-muted`},Ye={key:1,class:`text-red-400 text-xs`},Xe={key:2,class:`text-foreground-muted`},Ze={class:`px-6 py-4 text-right`},Qe={class:`inline-flex justify-end gap-1`},$e={key:0},et=Object.assign({name:`ChannelsView`},{__name:`Channels`,setup(c){let S=A(),C=n([]),N=n(``),L=n(!1),R=n(!1),z=n(!1),B=n(``),V=n(!1),H=n({name:``,description:``,expiresInDays:0,functionIds:[]}),U=m(()=>`${window.location.origin}/mcp`),W=m(()=>H.value.name.trim()&&H.value.functionIds.length>0),G=async()=>{let e=await T();C.value=e.data.channels||[]},K=()=>{H.value={name:``,description:``,expiresInDays:0,functionIds:[]},B.value=``,R.value=!0},q=()=>{R.value=!1},J=e=>{H.value.functionIds=e,V.value=!1},Y=async()=>{z.value=!0,B.value=``;try{let e={name:H.value.name.trim(),description:H.value.description.trim(),function_ids:H.value.functionIds};H.value.expiresInDays>0&&(e.expires_in_days=H.value.expiresInDays);let t=await ee(e);N.value=t.data.token,R.value=!1,await G()}catch(e){B.value=e?.response?.data?.error?.message||`Failed to create channel.`}finally{z.value=!1}},X=async()=>{N.value&&await ne(N.value)&&(L.value=!0,setTimeout(()=>{L.value=!1},1500))},Z=async e=>{if(!await S.ask({title:`Rotate ${e.name}?`,message:`A new token will be issued. The previous token stops working immediately. Agents using it will need the new value.`,confirmLabel:`Rotate`,danger:!0}))return;let t=await te(e.id);N.value=t.data.token,await G()},Q=async e=>{await S.ask({title:`Delete ${e.name}?`,message:`${e.name} will lose MCP access immediately. Functions inside are not affected. Re-create the channel if you need it again.`,confirmLabel:`Delete`,danger:!0})&&(await k(e.id),await G())};return i(G),(n,i)=>(e(),s(`div`,ae,[o(`div`,oe,[i[7]||=o(`div`,null,[o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Channels `),o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Expose selected functions as scoped MCP tools. `)],-1),l(O,{onClick:K},{default:t(()=>[l(a(w),{class:`w-4 h-4`}),i[6]||=f(` New channel `,-1)]),_:1})]),N.value?(e(),s(`div`,se,[o(`div`,ce,[i[8]||=o(`div`,null,[o(`h2`,{class:`text-xs font-bold text-warning-fg uppercase tracking-wider`},` Copy this token now `),o(`div`,{class:`text-xs text-foreground-muted mt-0.5`},` Store it securely, then add it to your MCP client. `)],-1),o(`button`,{class:`text-foreground-muted hover:text-white transition-colors`,title:`Dismiss`,"aria-label":`Dismiss channel token`,onClick:i[0]||=e=>N.value=``},[l(a(M),{class:`w-4 h-4`})])]),o(`div`,le,[o(`code`,ue,g(N.value),1),o(`button`,{class:`px-3 py-2 rounded-md border border-border bg-surface-hover hover:bg-surface text-foreground-muted hover:text-white transition-colors flex items-center gap-1.5 text-xs`,onClick:X},[L.value?(e(),d(a(_),{key:0,class:`w-3.5 h-3.5 text-success`})):(e(),d(a(y),{key:1,class:`w-3.5 h-3.5`})),f(` `+g(L.value?`Copied`:`Copy`),1)])]),o(`div`,de,[o(`span`,null,[i[9]||=f(`URL `,-1),o(`code`,fe,g(U.value),1)]),i[10]||=o(`span`,null,[f(`Header `),o(`code`,{class:`text-foreground bg-surface px-1.5 py-0.5 rounded`},`Authorization: Bearer `)],-1)])])):h(``,!0),R.value?(e(),s(`div`,pe,[i[18]||=o(`div`,{class:`text-sm font-semibold text-white`},` New channel `,-1),o(`div`,me,[o(`div`,null,[i[11]||=o(`label`,{for:`channel-name`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Name`,-1),r(o(`input`,{id:`channel-name`,"onUpdate:modelValue":i[1]||=e=>H.value.name=e,placeholder:`e.g. support-bot`,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},null,512),[[D,H.value.name]])]),o(`div`,null,[i[13]||=o(`label`,{for:`channel-expiry`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Expires in`,-1),r(o(`select`,{id:`channel-expiry`,"onUpdate:modelValue":i[2]||=e=>H.value.expiresInDays=e,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},[...i[12]||=[o(`option`,{value:0},` Never `,-1),o(`option`,{value:7},` 7 days `,-1),o(`option`,{value:30},` 30 days `,-1),o(`option`,{value:90},` 90 days `,-1)]],512),[[E,H.value.expiresInDays]])])]),o(`div`,null,[i[14]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Description (optional)`,-1),r(o(`input`,{"onUpdate:modelValue":i[3]||=e=>H.value.description=e,placeholder:`What this channel is for`,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary transition-colors`},null,512),[[D,H.value.description]])]),o(`div`,null,[o(`div`,he,[i[15]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Functions`,-1),H.value.functionIds.length>0?(e(),s(`span`,ge,g(H.value.functionIds.length)+` selected`,1)):h(``,!0)]),l(O,{variant:`secondary`,onClick:i[4]||=e=>V.value=!0},{default:t(()=>[l(a(j),{class:`w-4 h-4`}),f(` `+g(H.value.functionIds.length===0?`Pick functions`:`Edit selection`),1)]),_:1})]),B.value?(e(),s(`div`,_e,[l(a(v),{class:`w-4 h-4 text-red-400 shrink-0 mt-0.5`}),o(`span`,null,g(B.value),1)])):h(``,!0),o(`div`,ve,[l(O,{disabled:!W.value||z.value,loading:z.value,onClick:Y},{default:t(()=>[...i[16]||=[f(` Generate token `,-1)]]),_:1},8,[`disabled`,`loading`]),l(O,{variant:`secondary`,onClick:q},{default:t(()=>[...i[17]||=[f(` Cancel `,-1)]]),_:1})])])):h(``,!0),o(`div`,ye,[o(`ul`,be,[(e(!0),s(p,null,u(C.value,t=>(e(),s(`li`,{key:t.id,class:`px-4 py-3`},[o(`div`,xe,[o(`div`,Se,[o(`div`,Ce,[o(`span`,we,g(t.name),1),o(`span`,Te,[l(a(j),{class:`w-3 h-3`}),f(` `+g(t.function_count),1)])]),t.description?(e(),s(`div`,Ee,g(t.description),1)):h(``,!0),o(`div`,De,[o(`code`,Oe,g(t.prefix)+`…`,1),t.last_used_at?(e(),s(`span`,ke,`used `+g(a(I)(t.last_used_at)),1)):(e(),s(`span`,Ae,`never used`)),t.expires_at&&a(F)(t.expires_at)?(e(),s(`span`,je,`expired`)):t.expires_at?(e(),s(`span`,Me,`expires `+g(a(I)(t.expires_at)),1)):h(``,!0)])]),o(`div`,Ne,[l(P,{icon:a(b),title:`Rotate token`,onClick:e=>Z(t)},null,8,[`icon`,`onClick`]),l(P,{icon:a(x),variant:`danger`,title:`Delete channel`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),C.value.length===0?(e(),s(`li`,Pe,` No channels yet. `)):h(``,!0)]),o(`table`,Fe,[i[20]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-6 py-3 font-medium`},` Name `),o(`th`,{class:`px-6 py-3 font-medium`},` Functions `),o(`th`,{class:`px-6 py-3 font-medium hidden sm:table-cell`},` Prefix `),o(`th`,{class:`px-6 py-3 font-medium hidden md:table-cell`},` Last used `),o(`th`,{class:`px-6 py-3 font-medium hidden lg:table-cell`},` Expires `),o(`th`,{class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,Ie,[(e(!0),s(p,null,u(C.value,t=>(e(),s(`tr`,{key:t.id,class:`hover:bg-surface/50 transition-colors`},[o(`td`,Le,[o(`div`,Re,g(t.name),1),t.description?(e(),s(`div`,ze,g(t.description),1)):h(``,!0)]),o(`td`,Be,[o(`span`,Ve,[l(a(j),{class:`w-3.5 h-3.5`}),o(`span`,$,g(t.function_count),1)])]),o(`td`,He,[o(`code`,Ue,g(t.prefix)+`…`,1)]),o(`td`,We,[t.last_used_at?(e(),s(`span`,Ge,g(a(I)(t.last_used_at)),1)):(e(),s(`span`,Ke,`Never used`))]),o(`td`,qe,[t.expires_at?a(F)(t.expires_at)?(e(),s(`span`,Ye,`Expired `+g(a(I)(t.expires_at)),1)):(e(),s(`span`,Xe,g(a(I)(t.expires_at)),1)):(e(),s(`span`,Je,`Never`))]),o(`td`,Ze,[o(`div`,Qe,[l(P,{icon:a(b),title:`Rotate token`,onClick:e=>Z(t)},null,8,[`icon`,`onClick`]),l(P,{icon:a(x),variant:`danger`,title:`Delete channel`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),C.value.length===0?(e(),s(`tr`,$e,[...i[19]||=[o(`td`,{colspan:`6`,class:`px-6 py-8 text-center text-foreground-muted`},[f(` No channels yet. Click `),o(`span`,{class:`text-white`},`New channel`),f(` to bundle functions for an agent. `)],-1)]])):h(``,!0)])])]),V.value?(e(),d(ie,{key:2,selected:H.value.functionIds,onClose:i[5]||=e=>V.value=!1,onApply:J},null,8,[`selected`])):h(``,!0)]))}});export{et as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/CodeEditor-CiRqvRcK.js b/backend/internal/server/ui_dist/assets/CodeEditor-Y2EEC-Gt.js similarity index 90% rename from backend/internal/server/ui_dist/assets/CodeEditor-CiRqvRcK.js rename to backend/internal/server/ui_dist/assets/CodeEditor-Y2EEC-Gt.js index d857bb14..cbe40c5b 100644 --- a/backend/internal/server/ui_dist/assets/CodeEditor-CiRqvRcK.js +++ b/backend/internal/server/ui_dist/assets/CodeEditor-Y2EEC-Gt.js @@ -1 +1 @@ -import{D as e,E as t,G as n,P as r,T as i,d as a}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{ut as o}from"./index-DTqMKlE1.js";import{E as s,T as c,a as l,n as u,r as d,t as f,v as p}from"./dist-CR15Grce.js";var m=o({__name:`CodeEditor`,props:{modelValue:{type:String,default:``},language:{type:String,default:`javascript`},readOnly:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(o,{emit:m}){let h=o,g=m,_=n(null),v=null,y=new c,b=e=>e?.startsWith(`python`)?u():(e?.startsWith(`node`),d());return i(()=>{let e=s.create({doc:h.modelValue,extensions:[l,y.of(b(h.language)),f,p.updateListener.of(e=>{e.docChanged&&g(`update:modelValue`,e.state.doc.toString())}),p.theme({"&":{fontSize:`16px`,height:`100%`},"@media (min-width: 640px)":{"&":{fontSize:`14px`}},".cm-scroller":{fontFamily:`JetBrains Mono, monospace`,lineHeight:`1.6`},".cm-content":{padding:`16px 0`},".cm-line":{padding:`0 16px`}}),s.readOnly.of(h.readOnly)]});v=new p({state:e,parent:_.value})}),t(()=>{v&&v.destroy()}),r(()=>h.modelValue,e=>{v&&e!==v.state.doc.toString()&&v.dispatch({changes:{from:0,to:v.state.doc.length,insert:e}})}),r(()=>h.language,e=>{v&&v.dispatch({effects:y.reconfigure(b(e))})}),(t,n)=>(e(),a(`div`,{ref_key:`editorRef`,ref:_,class:`h-full w-full`},null,512))}},[[`__scopeId`,`data-v-ccca551c`]]);export{m as default}; \ No newline at end of file +import{D as e,E as t,G as n,P as r,T as i,d as a}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{ut as o}from"./index-pE9wnfTb.js";import{E as s,T as c,a as l,n as u,r as d,t as f,v as p}from"./dist-CR15Grce.js";var m=o({__name:`CodeEditor`,props:{modelValue:{type:String,default:``},language:{type:String,default:`javascript`},readOnly:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(o,{emit:m}){let h=o,g=m,_=n(null),v=null,y=new c,b=e=>e?.startsWith(`python`)?u():(e?.startsWith(`node`),d());return i(()=>{let e=s.create({doc:h.modelValue,extensions:[l,y.of(b(h.language)),f,p.updateListener.of(e=>{e.docChanged&&g(`update:modelValue`,e.state.doc.toString())}),p.theme({"&":{fontSize:`16px`,height:`100%`},"@media (min-width: 640px)":{"&":{fontSize:`14px`}},".cm-scroller":{fontFamily:`JetBrains Mono, monospace`,lineHeight:`1.6`},".cm-content":{padding:`16px 0`},".cm-line":{padding:`0 16px`}}),s.readOnly.of(h.readOnly)]});v=new p({state:e,parent:_.value})}),t(()=>{v&&v.destroy()}),r(()=>h.modelValue,e=>{v&&e!==v.state.doc.toString()&&v.dispatch({changes:{from:0,to:v.state.doc.length,insert:e}})}),r(()=>h.language,e=>{v&&v.dispatch({effects:y.reconfigure(b(e))})}),(t,n)=>(e(),a(`div`,{ref_key:`editorRef`,ref:_,class:`h-full w-full`},null,512))}},[[`__scopeId`,`data-v-ccca551c`]]);export{m as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/CronJobs-CDFaee6D.js b/backend/internal/server/ui_dist/assets/CronJobs-Ches-sRR.js similarity index 98% rename from backend/internal/server/ui_dist/assets/CronJobs-CDFaee6D.js rename to backend/internal/server/ui_dist/assets/CronJobs-Ches-sRR.js index 011f3f52..8b813a68 100644 --- a/backend/internal/server/ui_dist/assets/CronJobs-CDFaee6D.js +++ b/backend/internal/server/ui_dist/assets/CronJobs-Ches-sRR.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,M as i,T as a,Z as o,c as s,d as c,gt as l,h as u,k as d,l as f,m as p,r as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as _,t as v}from"./clock-CiH8bQVI.js";import{t as y}from"./play-CmQifd74.js";import{t as b}from"./square-pen-DCrjAsLy.js";import{t as x}from"./trash-2-DaeYqnW_.js";import{B as ee,It as S,L as te,Lt as C,Nt as ne,_t as w,at as T,c as re,gt as ie,i as ae,jt as E,p as oe}from"./index-DTqMKlE1.js";import{t as D}from"./IconButton-CsCZOqWo.js";import{t as se}from"./Modal-BAoZams6.js";var ce=E(`circle-plus`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M8 12h8`,key:`1wcyev`}],[`path`,{d:`M12 8v8`,key:`napkw2`}]]),O=E(`pause`,[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`kaeet6`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`1wsw3u`}]]),le={class:`space-y-6`},ue={class:`flex items-center justify-between`},de={class:`bg-background border border-border rounded-lg overflow-x-auto`},fe={class:`sm:hidden divide-y divide-border`},pe={class:`flex items-start justify-between gap-2`},me={class:`min-w-0 flex-1`},he={class:`flex items-center gap-2 flex-wrap`},ge={class:`font-medium text-foreground truncate`},_e={class:`mt-1 text-[11px] text-foreground font-mono break-all`},ve={class:`mt-0.5 text-[11px] text-foreground-muted`},k={class:`text-foreground-muted/70`},A={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},j={class:`flex items-center gap-1 shrink-0`},M={key:0,class:`px-6 py-12 text-center`},N={class:`hidden sm:table w-full text-sm text-left`},P={class:`divide-y divide-border`},F={class:`px-6 py-4 font-medium text-foreground max-w-[16rem] truncate`},ye={class:`px-6 py-4`},be={class:`flex flex-col gap-1`},xe={class:`text-foreground font-mono text-xs break-all`},Se={class:`text-foreground-muted text-[10px]`},Ce={class:`text-foreground-muted/70`},we={class:`px-6 py-4 hidden sm:table-cell`},Te={class:`px-6 py-4 text-foreground-muted text-xs hidden md:table-cell`},Ee={class:`px-6 py-4 text-foreground-muted text-xs hidden lg:table-cell`},De={class:`px-6 py-4 text-right`},Oe={class:`inline-flex items-center gap-1`},ke={key:0},Ae={class:`space-y-5`},je=[`disabled`],Me=[`value`],Ne={class:`flex gap-2 bg-background rounded-lg p-1 border border-border`},Pe=[`onClick`],Fe={key:0,class:`space-y-4`},Ie={class:`grid grid-cols-3 gap-3`},I={key:0},Le={key:1},Re={key:2},ze={key:3},Be={class:`bg-background border border-border rounded-lg p-4`},Ve={class:`font-mono text-sm text-foreground`},He={class:`text-xs text-foreground-muted mt-1`},Ue={key:1,class:`space-y-3`},We={class:`bg-background border border-border rounded-lg p-4`},Ge={class:`text-xs text-foreground`},Ke=[`value`],qe={class:`text-xs text-foreground-muted mt-1.5`},Je={class:`bg-surface px-1 rounded`},Ye={class:`flex items-center gap-3`},L={__name:`CronJobs`,setup(E){let L=ae(),Xe=[...new Set([L,`UTC`,`America/Los_Angeles`,`America/New_York`,`America/Chicago`,`America/Denver`,`America/Sao_Paulo`,`Europe/London`,`Europe/Berlin`,`Europe/Paris`,`Europe/Moscow`,`Africa/Lagos`,`Africa/Cairo`,`Africa/Johannesburg`,`Asia/Dubai`,`Asia/Kolkata`,`Asia/Singapore`,`Asia/Shanghai`,`Asia/Tokyo`,`Australia/Sydney`,`Pacific/Auckland`])],R=ie(),z=n([]),B=n([]),V=n(!1),H=n(null),U=n(`simple`),W=n({function_name:``,cron:`0 0 * * *`,timezone:L,enabled:!0}),G=n({frequency:`day`,minute:0,hour:0,dayOfWeek:1,dayOfMonth:1}),K=async()=>{try{let e=await te();z.value=e.data.schedules||[]}catch(e){console.error(`Failed to load cron jobs`,e)}},Ze=async()=>{try{let e=await ee();B.value=e.data.functions||[]}catch(e){console.error(`Failed to load functions`,e)}},q=()=>{let{frequency:e,minute:t,hour:n,dayOfWeek:r,dayOfMonth:i}=G.value;switch(e){case`minute`:W.value.cron=`* * * * *`;break;case`hour`:W.value.cron=`${t} * * * *`;break;case`day`:W.value.cron=`${t} ${n} * * *`;break;case`week`:W.value.cron=`${t} ${n} * * ${r}`;break;case`month`:W.value.cron=`${t} ${n} ${i} * *`}},J=e=>{if(!e)return`Invalid expression`;let t=e.trim().split(/\s+/);if(t.length!==5)return`Invalid format (use 5 fields)`;let[n,r,i,a,o]=t;return e===`* * * * *`?`Every minute`:n!==`*`&&r===`*`&&i===`*`&&a===`*`&&o===`*`?`Every hour at minute ${n}`:n!==`*`&&r!==`*`&&i===`*`&&a===`*`&&o===`*`?`Every day at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:n!==`*`&&r!==`*`&&i===`*`&&a===`*`&&o!==`*`?`Every ${[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`][o]} at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:n!==`*`&&r!==`*`&&i!==`*`&&a===`*`&&o===`*`?`On day ${i} of every month at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:`Custom: ${e}`},Y=e=>new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}),Qe=async()=>{try{H.value?await T(H.value.id,{function_id:H.value.function_id,cron:W.value.cron,timezone:W.value.timezone,enabled:W.value.enabled}):await re(W.value.function_name,{cron:W.value.cron,timezone:W.value.timezone,enabled:W.value.enabled}),await K(),$()}catch(e){console.error(`Failed to save schedule`,e),R.notify({title:`Failed to save schedule`,danger:!0})}},X=e=>{H.value=e,W.value={function_name:e.function_name,cron:e.cron_expression,timezone:e.timezone||`UTC`,enabled:e.enabled},V.value=!0},Z=async e=>{try{await T(e.id,{function_id:e.function_id,enabled:!e.enabled}),await K()}catch(e){console.error(`Failed to toggle schedule`,e)}},Q=async e=>{if(await R.ask({title:`Delete schedule?`,message:`Cron schedule for "${e.function_name}" will be removed.`,confirmLabel:`Delete`,danger:!0}))try{await oe(e.id,e.function_id),await K()}catch(e){console.error(`Failed to delete schedule`,e)}},$=()=>{V.value=!1,H.value=null,W.value={function_name:``,cron:`0 0 * * *`,timezone:L,enabled:!0},G.value={frequency:`day`,minute:0,hour:0,dayOfWeek:1,dayOfMonth:1},U.value=`simple`};return a(()=>{K(),Ze(),q()}),(n,a)=>(e(),c(`div`,le,[s(`div`,ue,[a[12]||=s(`div`,null,[s(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Scheduled Jobs `),s(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Run functions on a cron schedule. `)],-1),u(w,{onClick:a[0]||=e=>V.value=!0},{default:t(()=>[u(o(ce),{class:`w-4 h-4`}),a[11]||=p(` New Schedule `,-1)]),_:1})]),s(`div`,de,[s(`ul`,fe,[(e(!0),c(m,null,d(z.value,t=>(e(),c(`li`,{key:t.id,class:`px-4 py-3`},[s(`div`,pe,[s(`div`,me,[s(`div`,he,[s(`span`,ge,g(t.function_name),1),s(`span`,{class:l([`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium border`,t.enabled?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`])},[(e(),f(i(t.enabled?o(_):o(v)),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),p(` `+g(t.enabled?`Active`:`Paused`),1)],2)]),s(`div`,_e,g(t.cron_expression),1),s(`div`,ve,[p(g(J(t.cron_expression))+` `,1),s(`span`,k,`· `+g(t.timezone||`UTC`),1)]),s(`div`,A,[s(`span`,null,`last `+g(t.last_run_at?Y(t.last_run_at):o(`—`)),1),s(`span`,null,`next `+g(t.next_run_at?Y(t.next_run_at):o(`—`)),1)])]),s(`div`,j,[u(D,{icon:t.enabled?o(O):o(y),title:t.enabled?`Pause`:`Resume`,onClick:e=>Z(t)},null,8,[`icon`,`title`,`onClick`]),u(D,{icon:o(b),title:`Edit`,onClick:e=>X(t)},null,8,[`icon`,`onClick`]),u(D,{icon:o(x),variant:`danger`,title:`Delete`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),z.value.length===0?(e(),c(`li`,M,[...a[13]||=[s(`p`,{class:`text-foreground-muted`},` No scheduled jobs yet. `,-1),s(`p`,{class:`text-foreground-muted text-xs mt-1`},` Create a schedule to run a function automatically. `,-1)]])):h(``,!0)]),s(`table`,N,[a[15]||=s(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[s(`tr`,null,[s(`th`,{class:`px-6 py-3 font-medium`},` Function `),s(`th`,{class:`px-6 py-3 font-medium`},` Schedule `),s(`th`,{class:`px-6 py-3 font-medium hidden sm:table-cell`},` Status `),s(`th`,{class:`px-6 py-3 font-medium hidden md:table-cell`},` Last Run `),s(`th`,{class:`px-6 py-3 font-medium hidden lg:table-cell`},` Next Run `),s(`th`,{class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),s(`tbody`,P,[(e(!0),c(m,null,d(z.value,t=>(e(),c(`tr`,{key:t.id,class:`hover:bg-surface-hover transition-colors`},[s(`td`,F,g(t.function_name),1),s(`td`,ye,[s(`div`,be,[s(`span`,xe,g(t.cron_expression),1),s(`span`,Se,[p(g(J(t.cron_expression))+` `,1),s(`span`,Ce,`· `+g(t.timezone||`UTC`),1)])])]),s(`td`,we,[s(`span`,{class:l([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border`,t.enabled?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`])},[(e(),f(i(t.enabled?o(_):o(v)),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),p(` `+g(t.enabled?`Active`:`Paused`),1)],2)]),s(`td`,Te,g(t.last_run_at?Y(t.last_run_at):o(`—`)),1),s(`td`,Ee,g(t.next_run_at?Y(t.next_run_at):o(`—`)),1),s(`td`,De,[s(`div`,Oe,[u(D,{icon:t.enabled?o(O):o(y),title:t.enabled?`Pause`:`Resume`,onClick:e=>Z(t)},null,8,[`icon`,`title`,`onClick`]),u(D,{icon:o(b),title:`Edit`,onClick:e=>X(t)},null,8,[`icon`,`onClick`]),u(D,{icon:o(x),variant:`danger`,title:`Delete`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),z.value.length===0?(e(),c(`tr`,ke,[...a[14]||=[s(`td`,{colspan:`6`,class:`px-6 py-12 text-center`},[s(`p`,{class:`text-foreground-muted`},` No scheduled jobs yet. `),s(`p`,{class:`text-foreground-muted text-xs mt-1`},` Create a schedule to run a function automatically. `)],-1)]])):h(``,!0)])])]),u(se,{"model-value":V.value,title:H.value?`Edit Schedule`:`Create Schedule`,size:`lg`,"onUpdate:modelValue":a[10]||=e=>{e||$()}},{footer:t(()=>[u(w,{variant:`ghost`,onClick:$},{default:t(()=>[...a[36]||=[p(` Cancel `,-1)]]),_:1}),u(w,{disabled:!W.value.function_name||!W.value.cron,onClick:Qe},{default:t(()=>[p(g(H.value?`Update`:`Create`)+` Schedule `,1)]),_:1},8,[`disabled`])]),default:t(()=>[s(`div`,Ae,[s(`div`,null,[a[17]||=s(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},`Function`,-1),r(s(`select`,{"onUpdate:modelValue":a[1]||=e=>W.value.function_name=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,disabled:!!H.value},[a[16]||=s(`option`,{value:``},` Select a function `,-1),(e(!0),c(m,null,d(B.value,t=>(e(),c(`option`,{key:t.name,value:t.name},g(t.name)+` (`+g(t.runtime)+`) `,9,Me))),128))],8,je),[[S,W.value.function_name]])]),s(`div`,null,[a[18]||=s(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},`Schedule Type`,-1),s(`div`,Ne,[(e(),c(m,null,d([`simple`,`advanced`],e=>s(`button`,{key:e,class:l([`flex-1 py-2 px-3 text-sm font-medium rounded transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,U.value===e?`bg-primary text-primary-foreground shadow-sm`:`text-foreground-muted hover:text-foreground`]),onClick:t=>U.value=e},g(e===`simple`?`Natural Language`:`Cron Expression`),11,Pe)),64))])]),U.value===`simple`?(e(),c(`div`,Fe,[s(`div`,Ie,[s(`div`,null,[a[20]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Frequency`,-1),r(s(`select`,{"onUpdate:modelValue":a[2]||=e=>G.value.frequency=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:q},[...a[19]||=[s(`option`,{value:`minute`},` Every Minute `,-1),s(`option`,{value:`hour`},` Hourly `,-1),s(`option`,{value:`day`},` Daily `,-1),s(`option`,{value:`week`},` Weekly `,-1),s(`option`,{value:`month`},` Monthly `,-1)]],544),[[S,G.value.frequency]])]),[`hour`,`day`,`week`,`month`].includes(G.value.frequency)?(e(),c(`div`,I,[a[21]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`At Minute`,-1),r(s(`input`,{"onUpdate:modelValue":a[3]||=e=>G.value.minute=e,type:`number`,min:`0`,max:`59`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.minute,void 0,{number:!0}]])])):h(``,!0),[`day`,`week`,`month`].includes(G.value.frequency)?(e(),c(`div`,Le,[a[22]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`At Hour`,-1),r(s(`input`,{"onUpdate:modelValue":a[4]||=e=>G.value.hour=e,type:`number`,min:`0`,max:`23`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.hour,void 0,{number:!0}]])])):h(``,!0),G.value.frequency===`week`?(e(),c(`div`,Re,[a[24]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Day of Week`,-1),r(s(`select`,{"onUpdate:modelValue":a[5]||=e=>G.value.dayOfWeek=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:q},[...a[23]||=[s(`option`,{value:`0`},` Sunday `,-1),s(`option`,{value:`1`},` Monday `,-1),s(`option`,{value:`2`},` Tuesday `,-1),s(`option`,{value:`3`},` Wednesday `,-1),s(`option`,{value:`4`},` Thursday `,-1),s(`option`,{value:`5`},` Friday `,-1),s(`option`,{value:`6`},` Saturday `,-1)]],544),[[S,G.value.dayOfWeek]])])):h(``,!0),G.value.frequency===`month`?(e(),c(`div`,ze,[a[25]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Day of Month`,-1),r(s(`input`,{"onUpdate:modelValue":a[6]||=e=>G.value.dayOfMonth=e,type:`number`,min:`1`,max:`31`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.dayOfMonth,void 0,{number:!0}]])])):h(``,!0)]),s(`div`,Be,[a[26]||=s(`div`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide mb-2`},` Generated Expression `,-1),s(`div`,Ve,g(W.value.cron),1),s(`div`,He,g(J(W.value.cron)),1)])])):h(``,!0),U.value===`advanced`?(e(),c(`div`,Ue,[s(`div`,null,[a[27]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Cron Expression`,-1),r(s(`input`,{"onUpdate:modelValue":a[7]||=e=>W.value.cron=e,placeholder:`* * * * *`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[C,W.value.cron]]),a[28]||=s(`p`,{class:`text-xs text-foreground-muted mt-1.5`},` Format: minute hour day month weekday `,-1)]),s(`div`,We,[a[29]||=s(`div`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide mb-2`},` Preview `,-1),s(`div`,Ge,g(J(W.value.cron)),1)])])):h(``,!0),s(`div`,null,[a[34]||=s(`label`,{class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},` Timezone `,-1),r(s(`select`,{"onUpdate:modelValue":a[8]||=e=>W.value.timezone=e,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:border-white`},[(e(!0),c(m,null,d(o(Xe),t=>(e(),c(`option`,{key:t,value:t},g(t)+g(t===o(L)?` (your browser)`:``),9,Ke))),128))],512),[[S,W.value.timezone]]),s(`div`,qe,[a[30]||=p(` The cron expression is interpreted in this zone (e.g. `,-1),a[31]||=s(`code`,{class:`bg-surface px-1 rounded`},`0 9 * * *`,-1),a[32]||=p(` with timezone `,-1),s(`code`,Je,g(W.value.timezone),1),a[33]||=p(` fires at 9 AM local time every day. `,-1)])]),s(`div`,Ye,[r(s(`input`,{id:`enabled-toggle`,"onUpdate:modelValue":a[9]||=e=>W.value.enabled=e,type:`checkbox`,class:`w-4 h-4 text-primary bg-background border-border rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`},null,512),[[ne,W.value.enabled]]),a[35]||=s(`label`,{for:`enabled-toggle`,class:`text-sm font-medium text-foreground cursor-pointer`},` Enable schedule immediately `,-1)])])]),_:1},8,[`model-value`,`title`])]))}};export{L as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,M as i,T as a,Z as o,c as s,d as c,gt as l,h as u,k as d,l as f,m as p,r as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as _,t as v}from"./clock-CIjbNepe.js";import{t as y}from"./play-CnkMURxf.js";import{t as b}from"./square-pen-Ctkj2Y_N.js";import{t as x}from"./trash-2-Cz9PSE2q.js";import{B as ee,It as S,L as te,Lt as C,Nt as ne,_t as w,at as T,c as re,gt as ie,i as ae,jt as E,p as oe}from"./index-pE9wnfTb.js";import{t as D}from"./IconButton-CsCZOqWo.js";import{t as se}from"./Modal-C1IBLm0r.js";var ce=E(`circle-plus`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M8 12h8`,key:`1wcyev`}],[`path`,{d:`M12 8v8`,key:`napkw2`}]]),O=E(`pause`,[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`kaeet6`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`1wsw3u`}]]),le={class:`space-y-6`},ue={class:`flex items-center justify-between`},de={class:`bg-background border border-border rounded-lg overflow-x-auto`},fe={class:`sm:hidden divide-y divide-border`},pe={class:`flex items-start justify-between gap-2`},me={class:`min-w-0 flex-1`},he={class:`flex items-center gap-2 flex-wrap`},ge={class:`font-medium text-foreground truncate`},_e={class:`mt-1 text-[11px] text-foreground font-mono break-all`},ve={class:`mt-0.5 text-[11px] text-foreground-muted`},k={class:`text-foreground-muted/70`},A={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},j={class:`flex items-center gap-1 shrink-0`},M={key:0,class:`px-6 py-12 text-center`},N={class:`hidden sm:table w-full text-sm text-left`},P={class:`divide-y divide-border`},F={class:`px-6 py-4 font-medium text-foreground max-w-[16rem] truncate`},ye={class:`px-6 py-4`},be={class:`flex flex-col gap-1`},xe={class:`text-foreground font-mono text-xs break-all`},Se={class:`text-foreground-muted text-[10px]`},Ce={class:`text-foreground-muted/70`},we={class:`px-6 py-4 hidden sm:table-cell`},Te={class:`px-6 py-4 text-foreground-muted text-xs hidden md:table-cell`},Ee={class:`px-6 py-4 text-foreground-muted text-xs hidden lg:table-cell`},De={class:`px-6 py-4 text-right`},Oe={class:`inline-flex items-center gap-1`},ke={key:0},Ae={class:`space-y-5`},je=[`disabled`],Me=[`value`],Ne={class:`flex gap-2 bg-background rounded-lg p-1 border border-border`},Pe=[`onClick`],Fe={key:0,class:`space-y-4`},Ie={class:`grid grid-cols-3 gap-3`},I={key:0},Le={key:1},Re={key:2},ze={key:3},Be={class:`bg-background border border-border rounded-lg p-4`},Ve={class:`font-mono text-sm text-foreground`},He={class:`text-xs text-foreground-muted mt-1`},Ue={key:1,class:`space-y-3`},We={class:`bg-background border border-border rounded-lg p-4`},Ge={class:`text-xs text-foreground`},Ke=[`value`],qe={class:`text-xs text-foreground-muted mt-1.5`},Je={class:`bg-surface px-1 rounded`},Ye={class:`flex items-center gap-3`},L={__name:`CronJobs`,setup(E){let L=ae(),Xe=[...new Set([L,`UTC`,`America/Los_Angeles`,`America/New_York`,`America/Chicago`,`America/Denver`,`America/Sao_Paulo`,`Europe/London`,`Europe/Berlin`,`Europe/Paris`,`Europe/Moscow`,`Africa/Lagos`,`Africa/Cairo`,`Africa/Johannesburg`,`Asia/Dubai`,`Asia/Kolkata`,`Asia/Singapore`,`Asia/Shanghai`,`Asia/Tokyo`,`Australia/Sydney`,`Pacific/Auckland`])],R=ie(),z=n([]),B=n([]),V=n(!1),H=n(null),U=n(`simple`),W=n({function_name:``,cron:`0 0 * * *`,timezone:L,enabled:!0}),G=n({frequency:`day`,minute:0,hour:0,dayOfWeek:1,dayOfMonth:1}),K=async()=>{try{let e=await te();z.value=e.data.schedules||[]}catch(e){console.error(`Failed to load cron jobs`,e)}},Ze=async()=>{try{let e=await ee();B.value=e.data.functions||[]}catch(e){console.error(`Failed to load functions`,e)}},q=()=>{let{frequency:e,minute:t,hour:n,dayOfWeek:r,dayOfMonth:i}=G.value;switch(e){case`minute`:W.value.cron=`* * * * *`;break;case`hour`:W.value.cron=`${t} * * * *`;break;case`day`:W.value.cron=`${t} ${n} * * *`;break;case`week`:W.value.cron=`${t} ${n} * * ${r}`;break;case`month`:W.value.cron=`${t} ${n} ${i} * *`}},J=e=>{if(!e)return`Invalid expression`;let t=e.trim().split(/\s+/);if(t.length!==5)return`Invalid format (use 5 fields)`;let[n,r,i,a,o]=t;return e===`* * * * *`?`Every minute`:n!==`*`&&r===`*`&&i===`*`&&a===`*`&&o===`*`?`Every hour at minute ${n}`:n!==`*`&&r!==`*`&&i===`*`&&a===`*`&&o===`*`?`Every day at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:n!==`*`&&r!==`*`&&i===`*`&&a===`*`&&o!==`*`?`Every ${[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`][o]} at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:n!==`*`&&r!==`*`&&i!==`*`&&a===`*`&&o===`*`?`On day ${i} of every month at ${r.padStart(2,`0`)}:${n.padStart(2,`0`)}`:`Custom: ${e}`},Y=e=>new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}),Qe=async()=>{try{H.value?await T(H.value.id,{function_id:H.value.function_id,cron:W.value.cron,timezone:W.value.timezone,enabled:W.value.enabled}):await re(W.value.function_name,{cron:W.value.cron,timezone:W.value.timezone,enabled:W.value.enabled}),await K(),$()}catch(e){console.error(`Failed to save schedule`,e),R.notify({title:`Failed to save schedule`,danger:!0})}},X=e=>{H.value=e,W.value={function_name:e.function_name,cron:e.cron_expression,timezone:e.timezone||`UTC`,enabled:e.enabled},V.value=!0},Z=async e=>{try{await T(e.id,{function_id:e.function_id,enabled:!e.enabled}),await K()}catch(e){console.error(`Failed to toggle schedule`,e)}},Q=async e=>{if(await R.ask({title:`Delete schedule?`,message:`Cron schedule for "${e.function_name}" will be removed.`,confirmLabel:`Delete`,danger:!0}))try{await oe(e.id,e.function_id),await K()}catch(e){console.error(`Failed to delete schedule`,e)}},$=()=>{V.value=!1,H.value=null,W.value={function_name:``,cron:`0 0 * * *`,timezone:L,enabled:!0},G.value={frequency:`day`,minute:0,hour:0,dayOfWeek:1,dayOfMonth:1},U.value=`simple`};return a(()=>{K(),Ze(),q()}),(n,a)=>(e(),c(`div`,le,[s(`div`,ue,[a[12]||=s(`div`,null,[s(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Scheduled Jobs `),s(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Run functions on a cron schedule. `)],-1),u(w,{onClick:a[0]||=e=>V.value=!0},{default:t(()=>[u(o(ce),{class:`w-4 h-4`}),a[11]||=p(` New Schedule `,-1)]),_:1})]),s(`div`,de,[s(`ul`,fe,[(e(!0),c(m,null,d(z.value,t=>(e(),c(`li`,{key:t.id,class:`px-4 py-3`},[s(`div`,pe,[s(`div`,me,[s(`div`,he,[s(`span`,ge,g(t.function_name),1),s(`span`,{class:l([`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium border`,t.enabled?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`])},[(e(),f(i(t.enabled?o(_):o(v)),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),p(` `+g(t.enabled?`Active`:`Paused`),1)],2)]),s(`div`,_e,g(t.cron_expression),1),s(`div`,ve,[p(g(J(t.cron_expression))+` `,1),s(`span`,k,`· `+g(t.timezone||`UTC`),1)]),s(`div`,A,[s(`span`,null,`last `+g(t.last_run_at?Y(t.last_run_at):o(`—`)),1),s(`span`,null,`next `+g(t.next_run_at?Y(t.next_run_at):o(`—`)),1)])]),s(`div`,j,[u(D,{icon:t.enabled?o(O):o(y),title:t.enabled?`Pause`:`Resume`,onClick:e=>Z(t)},null,8,[`icon`,`title`,`onClick`]),u(D,{icon:o(b),title:`Edit`,onClick:e=>X(t)},null,8,[`icon`,`onClick`]),u(D,{icon:o(x),variant:`danger`,title:`Delete`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),z.value.length===0?(e(),c(`li`,M,[...a[13]||=[s(`p`,{class:`text-foreground-muted`},` No scheduled jobs yet. `,-1),s(`p`,{class:`text-foreground-muted text-xs mt-1`},` Create a schedule to run a function automatically. `,-1)]])):h(``,!0)]),s(`table`,N,[a[15]||=s(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[s(`tr`,null,[s(`th`,{class:`px-6 py-3 font-medium`},` Function `),s(`th`,{class:`px-6 py-3 font-medium`},` Schedule `),s(`th`,{class:`px-6 py-3 font-medium hidden sm:table-cell`},` Status `),s(`th`,{class:`px-6 py-3 font-medium hidden md:table-cell`},` Last Run `),s(`th`,{class:`px-6 py-3 font-medium hidden lg:table-cell`},` Next Run `),s(`th`,{class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),s(`tbody`,P,[(e(!0),c(m,null,d(z.value,t=>(e(),c(`tr`,{key:t.id,class:`hover:bg-surface-hover transition-colors`},[s(`td`,F,g(t.function_name),1),s(`td`,ye,[s(`div`,be,[s(`span`,xe,g(t.cron_expression),1),s(`span`,Se,[p(g(J(t.cron_expression))+` `,1),s(`span`,Ce,`· `+g(t.timezone||`UTC`),1)])])]),s(`td`,we,[s(`span`,{class:l([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border`,t.enabled?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`])},[(e(),f(i(t.enabled?o(_):o(v)),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),p(` `+g(t.enabled?`Active`:`Paused`),1)],2)]),s(`td`,Te,g(t.last_run_at?Y(t.last_run_at):o(`—`)),1),s(`td`,Ee,g(t.next_run_at?Y(t.next_run_at):o(`—`)),1),s(`td`,De,[s(`div`,Oe,[u(D,{icon:t.enabled?o(O):o(y),title:t.enabled?`Pause`:`Resume`,onClick:e=>Z(t)},null,8,[`icon`,`title`,`onClick`]),u(D,{icon:o(b),title:`Edit`,onClick:e=>X(t)},null,8,[`icon`,`onClick`]),u(D,{icon:o(x),variant:`danger`,title:`Delete`,onClick:e=>Q(t)},null,8,[`icon`,`onClick`])])])]))),128)),z.value.length===0?(e(),c(`tr`,ke,[...a[14]||=[s(`td`,{colspan:`6`,class:`px-6 py-12 text-center`},[s(`p`,{class:`text-foreground-muted`},` No scheduled jobs yet. `),s(`p`,{class:`text-foreground-muted text-xs mt-1`},` Create a schedule to run a function automatically. `)],-1)]])):h(``,!0)])])]),u(se,{"model-value":V.value,title:H.value?`Edit Schedule`:`Create Schedule`,size:`lg`,"onUpdate:modelValue":a[10]||=e=>{e||$()}},{footer:t(()=>[u(w,{variant:`ghost`,onClick:$},{default:t(()=>[...a[36]||=[p(` Cancel `,-1)]]),_:1}),u(w,{disabled:!W.value.function_name||!W.value.cron,onClick:Qe},{default:t(()=>[p(g(H.value?`Update`:`Create`)+` Schedule `,1)]),_:1},8,[`disabled`])]),default:t(()=>[s(`div`,Ae,[s(`div`,null,[a[17]||=s(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},`Function`,-1),r(s(`select`,{"onUpdate:modelValue":a[1]||=e=>W.value.function_name=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,disabled:!!H.value},[a[16]||=s(`option`,{value:``},` Select a function `,-1),(e(!0),c(m,null,d(B.value,t=>(e(),c(`option`,{key:t.name,value:t.name},g(t.name)+` (`+g(t.runtime)+`) `,9,Me))),128))],8,je),[[S,W.value.function_name]])]),s(`div`,null,[a[18]||=s(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},`Schedule Type`,-1),s(`div`,Ne,[(e(),c(m,null,d([`simple`,`advanced`],e=>s(`button`,{key:e,class:l([`flex-1 py-2 px-3 text-sm font-medium rounded transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`,U.value===e?`bg-primary text-primary-foreground shadow-sm`:`text-foreground-muted hover:text-foreground`]),onClick:t=>U.value=e},g(e===`simple`?`Natural Language`:`Cron Expression`),11,Pe)),64))])]),U.value===`simple`?(e(),c(`div`,Fe,[s(`div`,Ie,[s(`div`,null,[a[20]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Frequency`,-1),r(s(`select`,{"onUpdate:modelValue":a[2]||=e=>G.value.frequency=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:q},[...a[19]||=[s(`option`,{value:`minute`},` Every Minute `,-1),s(`option`,{value:`hour`},` Hourly `,-1),s(`option`,{value:`day`},` Daily `,-1),s(`option`,{value:`week`},` Weekly `,-1),s(`option`,{value:`month`},` Monthly `,-1)]],544),[[S,G.value.frequency]])]),[`hour`,`day`,`week`,`month`].includes(G.value.frequency)?(e(),c(`div`,I,[a[21]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`At Minute`,-1),r(s(`input`,{"onUpdate:modelValue":a[3]||=e=>G.value.minute=e,type:`number`,min:`0`,max:`59`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.minute,void 0,{number:!0}]])])):h(``,!0),[`day`,`week`,`month`].includes(G.value.frequency)?(e(),c(`div`,Le,[a[22]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`At Hour`,-1),r(s(`input`,{"onUpdate:modelValue":a[4]||=e=>G.value.hour=e,type:`number`,min:`0`,max:`23`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.hour,void 0,{number:!0}]])])):h(``,!0),G.value.frequency===`week`?(e(),c(`div`,Re,[a[24]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Day of Week`,-1),r(s(`select`,{"onUpdate:modelValue":a[5]||=e=>G.value.dayOfWeek=e,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:q},[...a[23]||=[s(`option`,{value:`0`},` Sunday `,-1),s(`option`,{value:`1`},` Monday `,-1),s(`option`,{value:`2`},` Tuesday `,-1),s(`option`,{value:`3`},` Wednesday `,-1),s(`option`,{value:`4`},` Thursday `,-1),s(`option`,{value:`5`},` Friday `,-1),s(`option`,{value:`6`},` Saturday `,-1)]],544),[[S,G.value.dayOfWeek]])])):h(``,!0),G.value.frequency===`month`?(e(),c(`div`,ze,[a[25]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Day of Month`,-1),r(s(`input`,{"onUpdate:modelValue":a[6]||=e=>G.value.dayOfMonth=e,type:`number`,min:`1`,max:`31`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:q},null,544),[[C,G.value.dayOfMonth,void 0,{number:!0}]])])):h(``,!0)]),s(`div`,Be,[a[26]||=s(`div`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide mb-2`},` Generated Expression `,-1),s(`div`,Ve,g(W.value.cron),1),s(`div`,He,g(J(W.value.cron)),1)])])):h(``,!0),U.value===`advanced`?(e(),c(`div`,Ue,[s(`div`,null,[a[27]||=s(`label`,{class:`text-xs font-medium text-foreground-muted block mb-1.5`},`Cron Expression`,-1),r(s(`input`,{"onUpdate:modelValue":a[7]||=e=>W.value.cron=e,placeholder:`* * * * *`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[C,W.value.cron]]),a[28]||=s(`p`,{class:`text-xs text-foreground-muted mt-1.5`},` Format: minute hour day month weekday `,-1)]),s(`div`,We,[a[29]||=s(`div`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide mb-2`},` Preview `,-1),s(`div`,Ge,g(J(W.value.cron)),1)])])):h(``,!0),s(`div`,null,[a[34]||=s(`label`,{class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},` Timezone `,-1),r(s(`select`,{"onUpdate:modelValue":a[8]||=e=>W.value.timezone=e,class:`w-full bg-surface-hover border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:border-white`},[(e(!0),c(m,null,d(o(Xe),t=>(e(),c(`option`,{key:t,value:t},g(t)+g(t===o(L)?` (your browser)`:``),9,Ke))),128))],512),[[S,W.value.timezone]]),s(`div`,qe,[a[30]||=p(` The cron expression is interpreted in this zone (e.g. `,-1),a[31]||=s(`code`,{class:`bg-surface px-1 rounded`},`0 9 * * *`,-1),a[32]||=p(` with timezone `,-1),s(`code`,Je,g(W.value.timezone),1),a[33]||=p(` fires at 9 AM local time every day. `,-1)])]),s(`div`,Ye,[r(s(`input`,{id:`enabled-toggle`,"onUpdate:modelValue":a[9]||=e=>W.value.enabled=e,type:`checkbox`,class:`w-4 h-4 text-primary bg-background border-border rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`},null,512),[[ne,W.value.enabled]]),a[35]||=s(`label`,{for:`enabled-toggle`,class:`text-sm font-medium text-foreground cursor-pointer`},` Enable schedule immediately `,-1)])])]),_:1},8,[`model-value`,`title`])]))}};export{L as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Dashboard-DdzpeDBo.js b/backend/internal/server/ui_dist/assets/Dashboard-DdzpeDBo.js new file mode 100644 index 00000000..25a6eca8 --- /dev/null +++ b/backend/internal/server/ui_dist/assets/Dashboard-DdzpeDBo.js @@ -0,0 +1 @@ +import{D as e,E as t,F as n,T as r,Z as i,c as a,d as o,h as s,j as ee,k as te,l as ne,m as c,r as re,s as l,u as ie,v as u,vt as d}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{At as ae,St as oe,_t as se,jt as f,kt as ce,n as le}from"./index-pE9wnfTb.js";var ue=f(`snowflake`,[[`path`,{d:`m10 20-1.25-2.5L6 18`,key:`18frcb`}],[`path`,{d:`M10 4 8.75 6.5 6 6`,key:`7mghy3`}],[`path`,{d:`m14 20 1.25-2.5L18 18`,key:`1chtki`}],[`path`,{d:`m14 4 1.25 2.5L18 6`,key:`1b4wsy`}],[`path`,{d:`m17 21-3-6h-4`,key:`15hhxa`}],[`path`,{d:`m17 3-3 6 1.5 3`,key:`11697g`}],[`path`,{d:`M2 12h6.5L10 9`,key:`kv9z4n`}],[`path`,{d:`m20 10-1.5 2 1.5 2`,key:`1swlpi`}],[`path`,{d:`M22 12h-6.5L14 15`,key:`1mxi28`}],[`path`,{d:`m4 10 1.5 2L4 14`,key:`k9enpj`}],[`path`,{d:`m7 21 3-6-1.5-3`,key:`j8hb9u`}],[`path`,{d:`m7 3 3 6h4`,key:`1otusx`}]]),p=f(`trending-up`,[[`path`,{d:`M16 7h6v6`,key:`box55l`}],[`path`,{d:`m22 7-8.5 8.5-5-5L2 17`,key:`1t1m79`}]]),m={class:`space-y-6`},h={class:`grid grid-cols-2 md:grid-cols-4 gap-4`},g={class:`grid grid-cols-1 lg:grid-cols-3 gap-4`},_={class:`bg-background border border-border rounded-lg p-5 lg:col-span-1`},v={class:`bg-background border border-border rounded-lg p-5 lg:col-span-2 space-y-5`},y={class:`grid grid-cols-2 gap-4 text-sm`},b={class:`text-lg font-mono text-white mt-0.5`},x={class:`text-lg font-mono text-white mt-0.5`},S={class:`text-foreground-muted text-sm`},C={class:`text-xs text-foreground-muted mt-0.5`},w={class:`space-y-2`},T={class:`flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-foreground-muted`},E={class:`flex items-center gap-1.5`},D={class:`flex items-center gap-1.5`},O={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},k={class:`bg-background border border-border rounded-lg p-5 space-y-3`},A={class:`grid grid-cols-3 gap-3`},j={key:0,class:`text-xs text-danger-fg flex items-center gap-1.5 pt-1`},M={class:`bg-background border border-border rounded-lg p-5 space-y-3`},N={class:`grid grid-cols-3 gap-3`},P={key:0},F={class:`flex items-baseline justify-between mb-3`},I={class:`text-sm font-semibold text-white`},L={class:`grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4`},R={class:`flex items-start justify-between gap-2`},z={class:`min-w-0`},B={key:1,class:`truncate font-mono text-sm font-medium text-white`},de={class:`text-right shrink-0`},V={class:`text-xs font-mono text-white`},H={class:`text-[11px] text-foreground-muted`},fe={class:`grid grid-cols-3 gap-2`},pe={class:`grid grid-cols-2 gap-3 border-t border-border pt-3 text-xs`},me={class:`mt-0.5 font-mono text-white`},he={class:`mt-0.5 font-mono text-white`},ge={class:`text-foreground-muted`},_e={key:1,class:`bg-background border border-border rounded-lg p-8 text-center space-y-4`},U={__name:`Dashboard`,setup(f){let U=le(),W=l(()=>U.metrics||{}),ve=e=>U.poolHistory[e]||[],ye=e=>e==null?`—`:`${e.toFixed(1)}%`,be=e=>e==null?`0`:e.toFixed(1),xe=e=>e?e.replaceAll(`_`,` `):`calculating`,G=e=>{let t=e||0;return t>=1024?`${(t/1024).toFixed(1)} GB`:`${Math.round(t)} MB`},K=e=>{let t=Number(e)||0;return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)},q=l(()=>W.value.host?.mem_total_mb??0),Se=l(()=>W.value.host?.mem_reserved_mb??0),Ce=l(()=>W.value.host?.mem_available_mb??0),we=l(()=>W.value.host?.effective_memory_capacity_mb??0),J=l(()=>Math.max(0,q.value-Ce.value)),Y=l(()=>Math.max(0,q.value-J.value)),Te=l(()=>q.value>0?J.value/q.value*100:0);r(()=>U.connect()),t(()=>U.disconnect());let X={props:{label:String,value:[String,Number],icon:Object},setup(e){return()=>u(`div`,{class:`bg-background border border-border rounded-lg p-5 flex flex-col h-full hover:border-primary/50 transition-colors group`},[u(`div`,{class:`flex items-center justify-between mb-3`},[u(`span`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},e.label),e.icon?u(e.icon,{class:`w-4 h-4 text-foreground-muted group-hover:text-primary`}):null]),u(`div`,{class:`text-2xl font-mono text-foreground leading-none`},String(e.value))])}},Z={props:{p50:Number,p95:Number,p99:Number},setup(e){return()=>{let t=[{label:`p50`,ms:e.p50,color:`bg-success/70`},{label:`p95`,ms:e.p95,color:`bg-warning/70`},{label:`p99`,ms:e.p99,color:`bg-danger/70`}],n=Math.max(e.p50||0,e.p95||0,e.p99||0,1);return u(`div`,{class:`space-y-2.5`},t.map(e=>{let t=e.ms==null?0:e.ms/n*100;return u(`div`,{class:`space-y-1`},[u(`div`,{class:`flex items-baseline justify-between text-xs`},[u(`span`,{class:`font-mono uppercase text-foreground-muted tracking-wider`},e.label),u(`span`,{class:`font-mono text-white`},e.ms==null?`—`:`${e.ms}ms`)]),u(`div`,{class:`h-1.5 bg-surface rounded overflow-hidden`},[u(`div`,{class:`h-full ${e.color} transition-[width] duration-500 ease-out`,style:{width:`${t.toFixed(1)}%`}})])])}))}}},Q={props:{label:String,value:[String,Number]},setup(e){return()=>u(`div`,{class:`bg-surface border border-border rounded p-3 flex flex-col h-full`},[u(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},e.label),u(`div`,{class:`text-lg font-mono text-white mt-0.5`},String(e.value??0))])}},$={props:{label:String,value:[String,Number]},setup(e){return()=>u(`div`,{class:`bg-surface border border-border rounded p-2.5 flex flex-col h-full`},[u(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},e.label),u(`div`,{class:`text-base font-mono text-white mt-0.5 leading-none`},String(e.value??0))])}},Ee={props:{total:{type:Number,required:!0},segments:{type:Array,required:!0}},setup(e){return()=>{let t=e.total>0?e.total:1;return u(`div`,{class:`h-2.5 bg-surface rounded overflow-hidden flex`,role:`img`,"aria-label":e.segments.map(t=>`${t.label}: ${t.value} of ${e.total}`).join(`; `)},e.segments.map(e=>u(`div`,{class:`h-full ${e.color}`,style:{width:`${(e.value/t*100).toFixed(2)}%`},title:`${e.label}: ${e.value}`})))}}},De={props:{points:{type:Array,default:()=>[]}},setup(e){return()=>{let t=e.points||[];if(t.length<2)return u(`div`,{class:`h-8 flex items-center text-xs text-foreground-muted`},`Collecting samples…`);let n=Math.max(...t,1),r=100/(t.length-1),i=t.map((e,t)=>{let i=(t*r).toFixed(2),a=(32-e/n*32).toFixed(2);return`${t===0?`M`:`L`}${i},${a}`}).join(` `);return u(`svg`,{viewBox:`0 0 100 32`,class:`w-full h-8 text-primary`,preserveAspectRatio:`none`},[u(`path`,{d:i,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`})])}}};return(t,r)=>{let l=ee(`router-link`);return e(),o(`div`,m,[r[17]||=a(`div`,null,[a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` System Overview `),a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Live platform health and activity. `)],-1),a(`div`,h,[s(X,{label:`Functions`,value:i(U).functionsCount,icon:i(ce)},null,8,[`value`,`icon`]),s(X,{label:`In flight`,value:W.value.active_requests??0,icon:i(ae)},null,8,[`value`,`icon`]),s(X,{label:`Invocations`,value:K(W.value.totals?.invocations??0),icon:i(p)},null,8,[`value`,`icon`]),s(X,{label:`Cold starts`,value:ye(W.value.rates?.cold_start_pct),icon:i(ue)},null,8,[`value`,`icon`])]),a(`div`,g,[a(`div`,_,[r[1]||=a(`div`,{class:`mb-3`},[a(`h2`,{class:`text-sm font-semibold text-white`},` Response time `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Invocation latency by percentile. `)],-1),s(Z,{p50:W.value.latency_ms?.p50,p95:W.value.latency_ms?.p95,p99:W.value.latency_ms?.p99},null,8,[`p50`,`p95`,`p99`])]),a(`div`,v,[r[6]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Host machine `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Capacity and current memory use. `)],-1),a(`div`,y,[a(`div`,null,[r[2]||=a(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` CPU / worker slots `,-1),a(`div`,b,d(W.value.host?.num_cpu??`?`)+` / `+d(W.value.host?.effective_cpu_workers??`?`),1)]),a(`div`,null,[r[3]||=a(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` Memory in use `,-1),a(`div`,x,[c(d(G(J.value))+` `,1),a(`span`,S,`/ `+d(G(q.value)),1)]),a(`div`,C,d(Te.value.toFixed(1))+`% used · `+d(G(we.value))+` allocatable `,1)])]),a(`div`,w,[s(Ee,{total:q.value,segments:[{label:`In use`,value:J.value,color:`bg-info/70`},{label:`Free`,value:Y.value,color:`bg-success/40`}]},null,8,[`total`,`segments`]),a(`div`,T,[a(`span`,E,[r[4]||=a(`span`,{class:`w-2 h-2 rounded-full bg-info/70`},null,-1),c(` `+d(G(J.value))+` in use `,1)]),a(`span`,D,[r[5]||=a(`span`,{class:`w-2 h-2 rounded-full bg-success/40`},null,-1),c(` `+d(G(Y.value))+` free `,1)]),a(`span`,null,d(G(Se.value))+` reserved for warm pools `,1)])])])]),a(`div`,O,[a(`div`,k,[r[8]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Builds `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Deployment work in progress. `)],-1),a(`div`,A,[s(Q,{label:`In queue`,value:W.value.build_queue?.pending??0},null,8,[`value`]),s(Q,{label:`Build workers`,value:W.value.build_queue?.workers??0},null,8,[`value`]),s(Q,{label:`Built so far`,value:K(W.value.totals?.builds??0)},null,8,[`value`])]),(W.value.totals?.build_errors??0)>0?(e(),o(`div`,j,[r[7]||=a(`span`,{class:`w-1.5 h-1.5 rounded-full bg-danger`},null,-1),c(` `+d(W.value.totals.build_errors)+` build`+d(W.value.totals.build_errors===1?` has`:`s have`)+` failed since start `,1)])):ie(``,!0)]),a(`div`,M,[r[9]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Sandbox activity `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Current sandbox reuse and startup activity. `)],-1),a(`div`,N,[s(Q,{label:`Running now`,value:W.value.sandbox?.active??0},null,8,[`value`]),s(Q,{label:`Reused`,value:K(W.value.totals?.warm_hits??0)},null,8,[`value`]),s(Q,{label:`Spawned fresh`,value:K(W.value.totals?.cold_starts??0)},null,8,[`value`])])])]),(W.value.pools||[]).length?(e(),o(`div`,P,[a(`div`,F,[a(`div`,null,[a(`h2`,I,` Warm pools (`+d(W.value.pools.length)+`) `,1),r[10]||=a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Ready sandboxes by function. `,-1)])]),a(`div`,L,[(e(!0),o(re,null,te(W.value.pools,t=>(e(),o(`div`,{key:t.function_id,class:`bg-background border border-border rounded-lg p-4 space-y-3`},[a(`div`,R,[a(`div`,z,[t.function_name?(e(),ne(l,{key:0,to:{name:`function-detail`,params:{name:t.function_name}},class:`block truncate text-sm font-medium text-white hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},{default:n(()=>[c(d(t.function_name),1)]),_:2},1032,[`to`])):(e(),o(`div`,B,d(t.function_id),1))]),a(`div`,de,[r[11]||=a(`div`,{class:`text-xs text-foreground-muted`},` Capacity `,-1),a(`div`,V,d(t.effective_max)+` max `,1),a(`div`,H,d(xe(t.limiting_reason)),1)])]),a(`div`,fe,[s($,{label:`Ready / desired`,value:`${t.idle} / ${t.desired_workers}`},null,8,[`value`]),s($,{label:`Busy / queued`,value:`${t.busy} / ${t.queued}`},null,8,[`value`]),s($,{label:`Calls / sec`,value:be(t.stable_rate)},null,8,[`value`])]),a(`div`,null,[s(De,{points:ve(t.function_id)},null,8,[`points`]),r[12]||=a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Traffic, last 5 minutes `,-1)]),a(`div`,pe,[a(`div`,null,[r[13]||=a(`div`,{class:`text-foreground-muted`},` Service p95 `,-1),a(`div`,me,d(t.service_p95_ms?.toFixed?.(1)??0)+` ms `,1)]),a(`div`,null,[r[14]||=a(`div`,{class:`text-foreground-muted`},` Queue / cold p95 `,-1),a(`div`,he,[c(d(t.queue_wait_p95_ms?.toFixed?.(1)??0)+` `,1),a(`span`,ge,`/ `+d(t.cold_start_p95_ms?.toFixed?.(1)??0)+` ms`,1)])])])]))),128))])])):(e(),o(`div`,_e,[r[16]||=a(`div`,null,[a(`div`,{class:`text-sm text-white`},` No warm pools yet `),a(`div`,{class:`text-xs text-foreground-muted mt-1 max-w-prose mx-auto leading-body`},` Deploy a function to start collecting runtime metrics. `)],-1),a(`div`,null,[s(se,{onClick:r[0]||=e=>t.$router.push(`/functions/new`)},{default:n(()=>[s(i(oe),{class:`w-4 h-4`}),r[15]||=c(` Deploy your first function `,-1)]),_:1})])]))])}}};export{U as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Dashboard-rKNyCP0W.js b/backend/internal/server/ui_dist/assets/Dashboard-rKNyCP0W.js deleted file mode 100644 index 37bc99ef..00000000 --- a/backend/internal/server/ui_dist/assets/Dashboard-rKNyCP0W.js +++ /dev/null @@ -1 +0,0 @@ -import{D as e,E as t,F as n,T as r,Z as i,c as a,d as o,h as s,j as ee,k as te,l as ne,m as c,r as re,s as l,u as ie,v as u,vt as d}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{At as f,St as p,_t as ae,jt as m,kt as oe,n as se}from"./index-DTqMKlE1.js";var ce=m(`snowflake`,[[`path`,{d:`m10 20-1.25-2.5L6 18`,key:`18frcb`}],[`path`,{d:`M10 4 8.75 6.5 6 6`,key:`7mghy3`}],[`path`,{d:`m14 20 1.25-2.5L18 18`,key:`1chtki`}],[`path`,{d:`m14 4 1.25 2.5L18 6`,key:`1b4wsy`}],[`path`,{d:`m17 21-3-6h-4`,key:`15hhxa`}],[`path`,{d:`m17 3-3 6 1.5 3`,key:`11697g`}],[`path`,{d:`M2 12h6.5L10 9`,key:`kv9z4n`}],[`path`,{d:`m20 10-1.5 2 1.5 2`,key:`1swlpi`}],[`path`,{d:`M22 12h-6.5L14 15`,key:`1mxi28`}],[`path`,{d:`m4 10 1.5 2L4 14`,key:`k9enpj`}],[`path`,{d:`m7 21 3-6-1.5-3`,key:`j8hb9u`}],[`path`,{d:`m7 3 3 6h4`,key:`1otusx`}]]),le=m(`trending-up`,[[`path`,{d:`M16 7h6v6`,key:`box55l`}],[`path`,{d:`m22 7-8.5 8.5-5-5L2 17`,key:`1t1m79`}]]),ue={class:`space-y-6`},h={class:`grid grid-cols-2 md:grid-cols-4 gap-4`},g={class:`grid grid-cols-1 lg:grid-cols-3 gap-4`},_={class:`bg-background border border-border rounded-lg p-5 lg:col-span-1`},v={class:`bg-background border border-border rounded-lg p-5 lg:col-span-2 space-y-5`},y={class:`grid grid-cols-2 gap-4 text-sm`},b={class:`text-lg font-mono text-white mt-0.5`},x={class:`text-lg font-mono text-white mt-0.5`},S={class:`text-foreground-muted text-sm`},C={class:`text-xs text-foreground-muted mt-0.5`},w={class:`space-y-2`},T={class:`flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-foreground-muted`},E={class:`flex items-center gap-1.5`},D={class:`flex items-center gap-1.5`},O={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},k={class:`bg-background border border-border rounded-lg p-5 space-y-3`},A={class:`grid grid-cols-3 gap-3`},j={key:0,class:`text-xs text-danger-fg flex items-center gap-1.5 pt-1`},M={class:`bg-background border border-border rounded-lg p-5 space-y-3`},N={class:`grid grid-cols-3 gap-3`},P={key:0},F={class:`flex items-baseline justify-between mb-3`},I={class:`text-sm font-semibold text-white`},L={class:`grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4`},de={class:`flex items-start justify-between gap-2`},R={class:`min-w-0`},z={key:1,class:`truncate font-mono text-sm font-medium text-white`},B={class:`text-right shrink-0`},V={class:`text-xs font-mono text-white`},H={class:`grid grid-cols-3 gap-2`},fe={class:`grid grid-cols-2 gap-3 border-t border-border pt-3 text-xs`},pe={class:`mt-0.5 font-mono text-white`},me={class:`mt-0.5 font-mono text-white`},he={class:`text-foreground-muted`},ge={key:1,class:`bg-background border border-border rounded-lg p-8 text-center space-y-4`},U={__name:`Dashboard`,setup(m){let U=se(),W=l(()=>U.metrics||{}),_e=e=>U.poolHistory[e]||[],ve=e=>e==null?`—`:`${e.toFixed(1)}%`,ye=e=>e==null?`0`:e.toFixed(1),G=e=>{let t=e||0;return t>=1024?`${(t/1024).toFixed(1)} GB`:`${Math.round(t)} MB`},K=e=>{let t=Number(e)||0;return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)},q=l(()=>W.value.host?.mem_total_mb??0),J=l(()=>W.value.host?.mem_reserved_mb??0),be=l(()=>W.value.host?.mem_available_mb??0),Y=l(()=>Math.max(0,q.value-be.value)),X=l(()=>Math.max(0,q.value-Y.value)),xe=l(()=>q.value>0?Y.value/q.value*100:0);r(()=>U.connect()),t(()=>U.disconnect());let Z={props:{label:String,value:[String,Number],icon:Object},setup(e){return()=>u(`div`,{class:`bg-background border border-border rounded-lg p-5 flex flex-col h-full hover:border-primary/50 transition-colors group`},[u(`div`,{class:`flex items-center justify-between mb-3`},[u(`span`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},e.label),e.icon?u(e.icon,{class:`w-4 h-4 text-foreground-muted group-hover:text-primary`}):null]),u(`div`,{class:`text-2xl font-mono text-foreground leading-none`},String(e.value))])}},Se={props:{p50:Number,p95:Number,p99:Number},setup(e){return()=>{let t=[{label:`p50`,ms:e.p50,color:`bg-success/70`},{label:`p95`,ms:e.p95,color:`bg-warning/70`},{label:`p99`,ms:e.p99,color:`bg-danger/70`}],n=Math.max(e.p50||0,e.p95||0,e.p99||0,1);return u(`div`,{class:`space-y-2.5`},t.map(e=>{let t=e.ms==null?0:e.ms/n*100;return u(`div`,{class:`space-y-1`},[u(`div`,{class:`flex items-baseline justify-between text-xs`},[u(`span`,{class:`font-mono uppercase text-foreground-muted tracking-wider`},e.label),u(`span`,{class:`font-mono text-white`},e.ms==null?`—`:`${e.ms}ms`)]),u(`div`,{class:`h-1.5 bg-surface rounded overflow-hidden`},[u(`div`,{class:`h-full ${e.color} transition-[width] duration-500 ease-out`,style:{width:`${t.toFixed(1)}%`}})])])}))}}},Q={props:{label:String,value:[String,Number]},setup(e){return()=>u(`div`,{class:`bg-surface border border-border rounded p-3 flex flex-col h-full`},[u(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},e.label),u(`div`,{class:`text-lg font-mono text-white mt-0.5`},String(e.value??0))])}},$={props:{label:String,value:[String,Number]},setup(e){return()=>u(`div`,{class:`bg-surface border border-border rounded p-2.5 flex flex-col h-full`},[u(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},e.label),u(`div`,{class:`text-base font-mono text-white mt-0.5 leading-none`},String(e.value??0))])}},Ce={props:{total:{type:Number,required:!0},segments:{type:Array,required:!0}},setup(e){return()=>{let t=e.total>0?e.total:1;return u(`div`,{class:`h-2.5 bg-surface rounded overflow-hidden flex`,role:`img`,"aria-label":e.segments.map(t=>`${t.label}: ${t.value} of ${e.total}`).join(`; `)},e.segments.map(e=>u(`div`,{class:`h-full ${e.color}`,style:{width:`${(e.value/t*100).toFixed(2)}%`},title:`${e.label}: ${e.value}`})))}}},we={props:{points:{type:Array,default:()=>[]}},setup(e){return()=>{let t=e.points||[];if(t.length<2)return u(`div`,{class:`h-8 flex items-center text-xs text-foreground-muted`},`Collecting samples…`);let n=Math.max(...t,1),r=100/(t.length-1),i=t.map((e,t)=>{let i=(t*r).toFixed(2),a=(32-e/n*32).toFixed(2);return`${t===0?`M`:`L`}${i},${a}`}).join(` `);return u(`svg`,{viewBox:`0 0 100 32`,class:`w-full h-8 text-primary`,preserveAspectRatio:`none`},[u(`path`,{d:i,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`})])}}};return(t,r)=>{let l=ee(`router-link`);return e(),o(`div`,ue,[r[17]||=a(`div`,null,[a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` System Overview `),a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Live platform health and activity. `)],-1),a(`div`,h,[s(Z,{label:`Functions`,value:i(U).functionsCount,icon:i(oe)},null,8,[`value`,`icon`]),s(Z,{label:`In flight`,value:W.value.active_requests??0,icon:i(f)},null,8,[`value`,`icon`]),s(Z,{label:`Invocations`,value:K(W.value.totals?.invocations??0),icon:i(le)},null,8,[`value`,`icon`]),s(Z,{label:`Cold starts`,value:ve(W.value.rates?.cold_start_pct),icon:i(ce)},null,8,[`value`,`icon`])]),a(`div`,g,[a(`div`,_,[r[1]||=a(`div`,{class:`mb-3`},[a(`h2`,{class:`text-sm font-semibold text-white`},` Response time `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Invocation latency by percentile. `)],-1),s(Se,{p50:W.value.latency_ms?.p50,p95:W.value.latency_ms?.p95,p99:W.value.latency_ms?.p99},null,8,[`p50`,`p95`,`p99`])]),a(`div`,v,[r[6]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Host machine `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Capacity and current memory use. `)],-1),a(`div`,y,[a(`div`,null,[r[2]||=a(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` CPU cores `,-1),a(`div`,b,d(W.value.host?.num_cpu??`?`),1)]),a(`div`,null,[r[3]||=a(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` Memory in use `,-1),a(`div`,x,[c(d(G(Y.value))+` `,1),a(`span`,S,`/ `+d(G(q.value)),1)]),a(`div`,C,d(xe.value.toFixed(1))+`% used · `+d(G(J.value))+` reserved by warm pools `,1)])]),a(`div`,w,[s(Ce,{total:q.value,segments:[{label:`In use`,value:Y.value,color:`bg-info/70`},{label:`Free`,value:X.value,color:`bg-success/40`}]},null,8,[`total`,`segments`]),a(`div`,T,[a(`span`,E,[r[4]||=a(`span`,{class:`w-2 h-2 rounded-full bg-info/70`},null,-1),c(` `+d(G(Y.value))+` in use `,1)]),a(`span`,D,[r[5]||=a(`span`,{class:`w-2 h-2 rounded-full bg-success/40`},null,-1),c(` `+d(G(X.value))+` free `,1)]),a(`span`,null,d(G(J.value))+` reserved for warm pools `,1)])])])]),a(`div`,O,[a(`div`,k,[r[8]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Builds `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Deployment work in progress. `)],-1),a(`div`,A,[s(Q,{label:`In queue`,value:W.value.build_queue?.pending??0},null,8,[`value`]),s(Q,{label:`Build workers`,value:W.value.build_queue?.workers??0},null,8,[`value`]),s(Q,{label:`Built so far`,value:K(W.value.totals?.builds??0)},null,8,[`value`])]),(W.value.totals?.build_errors??0)>0?(e(),o(`div`,j,[r[7]||=a(`span`,{class:`w-1.5 h-1.5 rounded-full bg-danger`},null,-1),c(` `+d(W.value.totals.build_errors)+` build`+d(W.value.totals.build_errors===1?` has`:`s have`)+` failed since start `,1)])):ie(``,!0)]),a(`div`,M,[r[9]||=a(`div`,null,[a(`h2`,{class:`text-sm font-semibold text-white`},` Sandbox activity `),a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Current sandbox reuse and startup activity. `)],-1),a(`div`,N,[s(Q,{label:`Running now`,value:W.value.sandbox?.active??0},null,8,[`value`]),s(Q,{label:`Reused`,value:K(W.value.totals?.warm_hits??0)},null,8,[`value`]),s(Q,{label:`Spawned fresh`,value:K(W.value.totals?.cold_starts??0)},null,8,[`value`])])])]),(W.value.pools||[]).length?(e(),o(`div`,P,[a(`div`,F,[a(`div`,null,[a(`h2`,I,` Warm pools (`+d(W.value.pools.length)+`) `,1),r[10]||=a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Ready sandboxes by function. `,-1)])]),a(`div`,L,[(e(!0),o(re,null,te(W.value.pools,t=>(e(),o(`div`,{key:t.function_id,class:`bg-background border border-border rounded-lg p-4 space-y-3`},[a(`div`,de,[a(`div`,R,[t.function_name?(e(),ne(l,{key:0,to:{name:`function-detail`,params:{name:t.function_name}},class:`block truncate text-sm font-medium text-white hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},{default:n(()=>[c(d(t.function_name),1)]),_:2},1032,[`to`])):(e(),o(`div`,z,d(t.function_id),1))]),a(`div`,B,[r[11]||=a(`div`,{class:`text-xs text-foreground-muted`},` Capacity `,-1),a(`div`,V,d(t.dynamic_max)+` max `,1)])]),a(`div`,H,[s($,{label:`Ready / target`,value:`${t.idle} / ${t.target}`},null,8,[`value`]),s($,{label:`Busy`,value:t.busy},null,8,[`value`]),s($,{label:`Calls / sec`,value:ye(t.rate_ewma)},null,8,[`value`])]),a(`div`,null,[s(we,{points:_e(t.function_id)},null,8,[`points`]),r[12]||=a(`div`,{class:`text-xs text-foreground-muted mt-1`},` Traffic, last 5 minutes `,-1)]),a(`div`,fe,[a(`div`,null,[r[13]||=a(`div`,{class:`text-foreground-muted`},` Avg latency `,-1),a(`div`,pe,d(t.latency_ewma_ms?.toFixed?.(1)??0)+` ms `,1)]),a(`div`,null,[r[14]||=a(`div`,{class:`text-foreground-muted`},` Avg memory / limit `,-1),a(`div`,me,[c(d(t.mem_used_avg_mb>0?`~`+Math.round(t.mem_used_avg_mb):i(`—`))+` `,1),a(`span`,he,`/ `+d(t.mem_limit_mb)+` MB`,1)])])])]))),128))])])):(e(),o(`div`,ge,[r[16]||=a(`div`,null,[a(`div`,{class:`text-sm text-white`},` No warm pools yet `),a(`div`,{class:`text-xs text-foreground-muted mt-1 max-w-prose mx-auto leading-body`},` Deploy a function to start collecting runtime metrics. `)],-1),a(`div`,null,[s(ae,{onClick:r[0]||=e=>t.$router.push(`/functions/new`)},{default:n(()=>[s(i(p),{class:`w-4 h-4`}),r[15]||=c(` Deploy your first function `,-1)]),_:1})])]))])}}};export{U as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Deployments-CRPgafhC.js b/backend/internal/server/ui_dist/assets/Deployments-BvLjnxyG.js similarity index 96% rename from backend/internal/server/ui_dist/assets/Deployments-CRPgafhC.js rename to backend/internal/server/ui_dist/assets/Deployments-BvLjnxyG.js index 7d7515ea..02fafeff 100644 --- a/backend/internal/server/ui_dist/assets/Deployments-CRPgafhC.js +++ b/backend/internal/server/ui_dist/assets/Deployments-BvLjnxyG.js @@ -1,3 +1,3 @@ -import{C as e,D as t,F as n,G as r,P as i,T as ee,Z as a,c as o,d as s,gt as c,h as l,j as te,k as u,l as d,m as f,r as p,s as m,u as h,v as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as ne}from"./clock-CiH8bQVI.js";import{n as re,t as v}from"./git-compare-Co883xFS.js";import{t as ie}from"./refresh-cw-Cn8qkf-v.js";import{t as y}from"./rotate-ccw-DWwjKCqh.js";import{B as ae,Bt as b,R as oe,_t as x,b as S,et as se,gt as ce,pt as le,r as ue,x as de}from"./index-DTqMKlE1.js";import{t as fe}from"./Drawer-B98TBytl.js";import{t as C}from"./StatusBadge-Baoe7YAb.js";import{t as pe}from"./rollbackDiff-DsaWcdbl.js";var me={class:`space-y-6`},he={class:`flex items-center justify-between`},ge={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},_e={class:`flex items-center gap-2`},ve={key:0,class:`border-y border-border py-3 flex items-center gap-3`},ye={class:`flex-1 min-w-0`},be={class:`flex items-center gap-2 flex-wrap`},xe={class:`text-xs px-2 py-0.5 rounded bg-success/15 text-success border border-success/30 font-mono`},Se={key:0,class:`text-xs px-2 py-0.5 rounded bg-warning-tint text-warning-fg border border-warning-ring`},Ce={class:`text-xs text-foreground-muted mt-1 font-mono truncate`},we={key:1,class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg`,role:`alert`},Te={class:`bg-background border border-border rounded-lg overflow-x-auto`},Ee={class:`sm:hidden divide-y divide-border`},De=[`onClick`],Oe={class:`flex items-start justify-between gap-2`},ke={class:`min-w-0 flex-1`},Ae={class:`flex items-center gap-2 flex-wrap`},je={key:0,class:`px-1.5 py-0.5 rounded text-xs bg-success-tint text-success-fg border border-success-ring`},Me={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-foreground-muted`},Ne={key:0,class:`font-mono`},Pe={key:1},Fe={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},Ie={class:`hidden sm:table w-full text-sm text-left`},Le={class:`divide-y divide-border`},Re=[`onClick`],ze={class:`px-6 py-4 font-mono text-xs`},Be={class:`flex items-center gap-2`},Ve={key:0,class:`px-1.5 py-0.5 rounded text-xs bg-success-tint text-success-fg border border-success-ring normal-case`},He={class:`px-6 py-4 text-foreground`},Ue={class:`px-6 py-4`},We={class:`px-6 py-4 text-foreground-muted text-xs hidden md:table-cell`},Ge={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden sm:table-cell`},Ke={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden xl:table-cell`},qe={class:`inline-flex items-center gap-2 justify-end`},Je={key:2,class:`text-foreground-muted/50`},Ye={key:3,class:`text-foreground-muted/30`},Xe={key:0},Ze={key:0,class:`p-6 text-sm text-foreground-muted`},Qe={key:1,class:`p-5 space-y-4`},$e={class:`flex items-center gap-2 flex-wrap`},et={key:0,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-foreground-muted`},tt={class:`grid grid-cols-2 gap-3 text-sm`},nt={key:0},rt={class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg font-mono whitespace-pre-wrap break-words`},it={class:`flex items-center justify-between mb-2`},at={key:0,class:`text-xs text-success-fg`},ot={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-96 whitespace-pre-wrap break-words`},st=Object.assign({name:`DeploymentsView`},{__name:`Deployments`,setup(st){let w=ce(),ct=le(),T=m(()=>ct.params.name),E=r(null),D=r(null),O=r([]),k=r(!1),A=r(``),j=r(!1),M=e=>e&&e.status===`succeeded`&&e.code_hash&&!I(e),N=m(()=>O.value.find(e=>I(e))?.id||null),P=e=>e&&e.status===`succeeded`&&e.code_hash&&!I(e)&&N.value,F=async e=>{if(!E.value||!e?.id||j.value)return;let t=(e.code_hash||``).slice(0,12),n=`Code hash ${t}. Current ${D.value?`v`+D.value.version:`version`} stays in history.`;try{let r=(await S(e.id))?.data?.snapshot;if(r&&D.value){let i=pe(D.value,r);n=i.length?`Rolling back to v${e.version} (code ${t}) will also change:\n\n${i.join(` +import{C as e,D as t,F as n,G as r,P as i,T as ee,Z as a,c as o,d as s,gt as c,h as l,j as te,k as u,l as d,m as f,r as p,s as m,u as h,v as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as ne}from"./clock-CIjbNepe.js";import{n as re,t as v}from"./git-compare-BnvFSVmQ.js";import{t as ie}from"./refresh-cw-CEfUzOcv.js";import{t as y}from"./rotate-ccw-DgujV-4F.js";import{B as ae,Bt as b,R as oe,_t as x,b as S,et as se,gt as ce,pt as le,r as ue,x as de}from"./index-pE9wnfTb.js";import{t as fe}from"./Drawer-CSwYBfhJ.js";import{t as C}from"./StatusBadge-BpEw6z9Z.js";import{t as pe}from"./rollbackDiff-DsaWcdbl.js";var me={class:`space-y-6`},he={class:`flex items-center justify-between`},ge={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},_e={class:`flex items-center gap-2`},ve={key:0,class:`border-y border-border py-3 flex items-center gap-3`},ye={class:`flex-1 min-w-0`},be={class:`flex items-center gap-2 flex-wrap`},xe={class:`text-xs px-2 py-0.5 rounded bg-success/15 text-success border border-success/30 font-mono`},Se={key:0,class:`text-xs px-2 py-0.5 rounded bg-warning-tint text-warning-fg border border-warning-ring`},Ce={class:`text-xs text-foreground-muted mt-1 font-mono truncate`},we={key:1,class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg`,role:`alert`},Te={class:`bg-background border border-border rounded-lg overflow-x-auto`},Ee={class:`sm:hidden divide-y divide-border`},De=[`onClick`],Oe={class:`flex items-start justify-between gap-2`},ke={class:`min-w-0 flex-1`},Ae={class:`flex items-center gap-2 flex-wrap`},je={key:0,class:`px-1.5 py-0.5 rounded text-xs bg-success-tint text-success-fg border border-success-ring`},Me={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-foreground-muted`},Ne={key:0,class:`font-mono`},Pe={key:1},Fe={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted`},Ie={class:`hidden sm:table w-full text-sm text-left`},Le={class:`divide-y divide-border`},Re=[`onClick`],ze={class:`px-6 py-4 font-mono text-xs`},Be={class:`flex items-center gap-2`},Ve={key:0,class:`px-1.5 py-0.5 rounded text-xs bg-success-tint text-success-fg border border-success-ring normal-case`},He={class:`px-6 py-4 text-foreground`},Ue={class:`px-6 py-4`},We={class:`px-6 py-4 text-foreground-muted text-xs hidden md:table-cell`},Ge={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden sm:table-cell`},Ke={class:`px-6 py-4 text-foreground-muted font-mono text-xs hidden xl:table-cell`},qe={class:`inline-flex items-center gap-2 justify-end`},Je={key:2,class:`text-foreground-muted/50`},Ye={key:3,class:`text-foreground-muted/30`},Xe={key:0},Ze={key:0,class:`p-6 text-sm text-foreground-muted`},Qe={key:1,class:`p-5 space-y-4`},$e={class:`flex items-center gap-2 flex-wrap`},et={key:0,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-foreground-muted`},tt={class:`grid grid-cols-2 gap-3 text-sm`},nt={key:0},rt={class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg font-mono whitespace-pre-wrap break-words`},it={class:`flex items-center justify-between mb-2`},at={key:0,class:`text-xs text-success-fg`},ot={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-96 whitespace-pre-wrap break-words`},st=Object.assign({name:`DeploymentsView`},{__name:`Deployments`,setup(st){let w=ce(),ct=le(),T=m(()=>ct.params.name),E=r(null),D=r(null),O=r([]),k=r(!1),A=r(``),j=r(!1),M=e=>e&&e.status===`succeeded`&&e.code_hash&&!I(e),N=m(()=>O.value.find(e=>I(e))?.id||null),P=e=>e&&e.status===`succeeded`&&e.code_hash&&!I(e)&&N.value,F=async e=>{if(!E.value||!e?.id||j.value)return;let t=(e.code_hash||``).slice(0,12),n=`Code hash ${t}. Current ${D.value?`v`+D.value.version:`version`} stays in history.`;try{let r=(await S(e.id))?.data?.snapshot;if(r&&D.value){let i=pe(D.value,r);n=i.length?`Rolling back to v${e.version} (code ${t}) will also change:\n\n${i.join(` `)}\n\nSecrets keep their current values; they aren't part of the rollback.`:`Rolling back to v${e.version} (code ${t}). Settings and env are already identical, so only the code changes.`}}catch{}if(N.value&&N.value!==e.id&&(n+=`\n\nFull source diff: ${window.location.origin}/web/functions/${T.value}/diff?from=${e.id}&to=${N.value}`),await w.ask({title:`Restore v${e.version}?`,message:n,confirmLabel:`Rollback`})){j.value=!0;try{await se(E.value,{deployment_id:e.id}),await G()}catch(e){let t=e.response?.data?.error?.code||``,n=e.response?.data?.error?.message||e.message||`Rollback failed`;t===`VERSION_GCD`?w.notify({title:`Version unavailable`,message:`This version has been garbage-collected and can no longer be restored.\n\n${n}`,danger:!0}):w.notify({title:`Rollback failed`,message:n,danger:!0})}finally{j.value=!1}}},I=e=>D.value&&e.version===D.value.version&&e.status===`succeeded`,L=r(!1),R=r(null),z=r([]),B=r(!1),V=null,lt=m(()=>R.value?`Deployment · ${R.value.id?.substring(0,14)}`:`Deployment`),ut=m(()=>z.value.join(` `)),H=e=>e?new Date(e).toLocaleString():`—`,U={props:{label:String,value:[String,Number],mono:Boolean},setup(e){return()=>g(`div`,{class:`bg-surface border border-border rounded p-3`},[g(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},e.label),g(`div`,{class:[`text-sm text-white`,e.mono&&`font-mono text-xs`].filter(Boolean)},String(e.value))])}},W=async()=>{let e=((await ae()).data.functions||[]).find(e=>e.name===T.value);if(!e)throw Error(`Function "${T.value}" not found`);return e},G=async()=>{k.value=!0,A.value=``;try{let e=await W();E.value=e.id,D.value=e;let t=await oe(E.value,100);O.value=t.data.deployments||[]}catch(e){A.value=e.message||`Failed to load deployments`}finally{k.value=!1}},K=async e=>{R.value=e,L.value=!0,z.value=[],B.value=!1;try{let t=await S(e.id);R.value={...e,...t.data}}catch{}try{let t=await de(e.id,0,1e3);z.value=(t.data.logs||[]).map(q)}catch{}(e.status===`queued`||e.status===`building`)&&dt(e.id)},q=e=>`[${e.stream||`log`}] ${e.line}`,dt=e=>{J();let t=new EventSource(`/api/v1/deployments/${e}/stream`);V=t,B.value=!0,t.addEventListener(`log`,e=>{try{let t=JSON.parse(e.data);z.value.push(q(t))}catch{}}),t.addEventListener(`succeeded`,()=>J(!0)),t.addEventListener(`failed`,()=>J(!0)),t.onerror=()=>{t.readyState===EventSource.CLOSED&&J()}},J=(e=!1)=>{if(V){try{V.close()}catch{}V=null}B.value=!1,e&&R.value&&(S(R.value.id).then(e=>{R.value={...R.value,...e.data}}).catch(()=>{}),G())};i(L,e=>{e||J()});let Y=ue(),X=null,Z=()=>{X||=setTimeout(()=>{X=null,G()},300)},Q=null,$=null;return ee(()=>{G(),Q=Y.subscribe(`deployment`,Z),$=Y.subscribe(`function`,Z)}),e(()=>{J(),Q&&=(Q(),null),$&&=($(),null),X&&=(clearTimeout(X),null)}),(e,r)=>{let i=te(`router-link`);return t(),s(`div`,me,[o(`div`,he,[o(`div`,null,[r[5]||=o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Deployments `,-1),o(`p`,ge,[r[4]||=f(` History for `,-1),l(i,{to:`/functions/${T.value}`,class:`text-white underline`},{default:n(()=>[f(_(T.value),1)]),_:1},8,[`to`])])]),o(`div`,_e,[l(x,{variant:`secondary`,onClick:r[0]||=t=>e.$router.push(`/functions/${T.value}`)},{default:n(()=>[l(a(re),{class:`w-4 h-4 mr-2`}),r[6]||=f(` New version `,-1)]),_:1}),l(x,{variant:`secondary`,onClick:G},{default:n(()=>[l(a(ie),{class:c([`w-4 h-4 mr-2`,{"animate-spin":k.value}])},null,8,[`class`]),r[7]||=f(` Refresh `,-1)]),_:1})])]),D.value?(t(),s(`div`,ve,[l(a(ne),{class:`w-4 h-4 text-success-fg shrink-0`}),o(`div`,ye,[o(`div`,be,[r[8]||=o(`span`,{class:`text-sm text-white font-medium`},`Currently serving`,-1),o(`span`,xe,` v`+_(D.value.version),1),D.value.status===`active`?h(``,!0):(t(),s(`span`,Se,` status: `+_(D.value.status),1))]),o(`div`,Ce,` hash: `+_(D.value.code_hash||a(`—`))+` · runtime: `+_(D.value.runtime)+` · updated `+_(H(D.value.updated_at)),1)])])):h(``,!0),A.value?(t(),s(`div`,we,_(A.value),1)):h(``,!0),o(`div`,Te,[o(`ul`,Ee,[(t(!0),s(p,null,u(O.value,e=>(t(),s(`li`,{key:e.id,class:c([`px-4 py-3 cursor-pointer active:bg-surface-hover/50 transition-colors`,I(e)?`bg-success/5`:``]),onClick:t=>K(e)},[o(`div`,Oe,[o(`div`,ke,[o(`div`,Ae,[o(`span`,{class:c([`font-mono text-xs`,I(e)?`text-white font-semibold`:`text-foreground-muted`])},`v`+_(e.version),3),l(C,{status:e.status},null,8,[`status`]),I(e)?(t(),s(`span`,je,`Active`)):h(``,!0)]),o(`div`,Me,[o(`span`,null,_(H(e.submitted_at)),1),e.duration_ms==null?h(``,!0):(t(),s(`span`,Ne,_(e.duration_ms)+` ms`,1)),e.phase?(t(),s(`span`,Pe,_(e.phase),1)):h(``,!0)])]),o(`div`,{class:`shrink-0 flex items-center gap-1`,onClick:r[1]||=b(()=>{},[`stop`])},[P(e)?(t(),d(i,{key:0,to:{name:`function-diff`,params:{name:T.value},query:{from:e.id,to:N.value}},class:`text-foreground-muted hover:text-white text-xs flex items-center gap-1 px-2 py-1`,title:`Compare with active version`},{default:n(()=>[l(a(v),{class:`w-3 h-3`}),r[9]||=f(` Compare `,-1)]),_:1},8,[`to`])):h(``,!0),M(e)?(t(),d(x,{key:1,size:`xs`,variant:`ghost`,disabled:j.value,onClick:t=>F(e)},{default:n(()=>[l(a(y),{class:`w-3 h-3`}),r[10]||=f(` Rollback `,-1)]),_:1},8,[`disabled`,`onClick`])):h(``,!0)])])],10,De))),128)),!k.value&&O.value.length===0?(t(),s(`li`,Fe,` No deployments yet. `)):h(``,!0)]),o(`table`,Ie,[r[14]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-6 py-3 font-medium`},` Version `),o(`th`,{class:`px-6 py-3 font-medium`},` Submitted `),o(`th`,{class:`px-6 py-3 font-medium`},` Status `),o(`th`,{class:`px-6 py-3 font-medium hidden md:table-cell`},` Phase `),o(`th`,{class:`px-6 py-3 font-medium hidden sm:table-cell`},` Duration `),o(`th`,{class:`px-6 py-3 font-medium hidden xl:table-cell`},` Deployment ID `),o(`th`,{class:`px-6 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,Le,[(t(!0),s(p,null,u(O.value,e=>(t(),s(`tr`,{key:e.id,class:c([`hover:bg-surface/50 transition-colors cursor-pointer`,I(e)?`bg-success/5`:``]),onClick:t=>K(e)},[o(`td`,ze,[o(`div`,Be,[o(`span`,{class:c([`text-white`,I(e)?`font-semibold`:`text-foreground-muted`])},`v`+_(e.version),3),I(e)?(t(),s(`span`,Ve,`Active`)):h(``,!0)])]),o(`td`,He,_(H(e.submitted_at)),1),o(`td`,Ue,[l(C,{status:e.status},null,8,[`status`])]),o(`td`,We,_(e.phase||a(`—`)),1),o(`td`,Ge,_(e.duration_ms==null?a(`—`):e.duration_ms+`ms`),1),o(`td`,Ke,_(e.id?.substring(0,14)),1),o(`td`,{class:`px-6 py-4 text-right text-xs`,onClick:r[2]||=b(()=>{},[`stop`])},[o(`div`,qe,[P(e)?(t(),d(i,{key:0,to:{name:`function-diff`,params:{name:T.value},query:{from:e.id,to:N.value}},class:`text-foreground-muted hover:text-white flex items-center gap-1`,title:`Compare with active version`},{default:n(()=>[l(a(v),{class:`w-3 h-3`}),r[11]||=f(` Compare `,-1)]),_:1},8,[`to`])):h(``,!0),M(e)?(t(),d(x,{key:1,size:`xs`,variant:`ghost`,disabled:j.value,onClick:t=>F(e)},{default:n(()=>[l(a(y),{class:`w-3 h-3`}),r[12]||=f(` Rollback `,-1)]),_:1},8,[`disabled`,`onClick`])):h(``,!0),!M(e)&&e.source===`rollback`?(t(),s(`span`,Je,`via rollback`)):!P(e)&&!M(e)?(t(),s(`span`,Ye,_(a(`—`)),1)):h(``,!0)])])],10,Re))),128)),!k.value&&O.value.length===0?(t(),s(`tr`,Xe,[...r[13]||=[o(`td`,{colspan:`7`,class:`px-6 py-8 text-center text-foreground-muted`},` No deployments yet. `,-1)]])):h(``,!0)])])]),l(fe,{modelValue:L.value,"onUpdate:modelValue":r[3]||=e=>L.value=e,title:lt.value,width:`640px`},{default:n(()=>[R.value?(t(),s(`div`,Qe,[o(`div`,$e,[l(C,{status:R.value.status},null,8,[`status`]),R.value.phase?(t(),s(`span`,et,_(R.value.phase),1)):h(``,!0)]),o(`div`,tt,[l(U,{label:`Version`,value:`v${R.value.version}`,mono:``},null,8,[`value`]),l(U,{label:`Duration`,value:R.value.duration_ms==null?a(`—`):R.value.duration_ms+` ms`},null,8,[`value`]),l(U,{label:`Submitted`,value:H(R.value.submitted_at)},null,8,[`value`]),l(U,{label:`Finished`,value:R.value.finished_at?H(R.value.finished_at):a(`—`)},null,8,[`value`])]),R.value.error_message?(t(),s(`div`,nt,[r[15]||=o(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},` Error `,-1),o(`pre`,rt,_(R.value.error_message),1)])):h(``,!0),o(`div`,null,[o(`div`,it,[r[16]||=o(`h3`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` Build log `,-1),B.value?(t(),s(`span`,at,`live`)):h(``,!0)]),o(`pre`,ot,_(ut.value||`(no logs available)`),1)])])):(t(),s(`div`,Ze,` Nothing selected. `))]),_:1},8,[`modelValue`,`title`])])}}});export{st as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Docs-BssSTQCS.js b/backend/internal/server/ui_dist/assets/Docs-CMWnQ8Ew.js similarity index 99% rename from backend/internal/server/ui_dist/assets/Docs-BssSTQCS.js rename to backend/internal/server/ui_dist/assets/Docs-CMWnQ8Ew.js index e20168d6..cde8b458 100644 --- a/backend/internal/server/ui_dist/assets/Docs-BssSTQCS.js +++ b/backend/internal/server/ui_dist/assets/Docs-CMWnQ8Ew.js @@ -1,4 +1,4 @@ -import{C as e,D as t,F as n,G as r,M as i,T as a,Z as o,_ as s,c,d as l,gt as u,h as d,j as ee,k as f,l as p,m,p as h,r as g,s as _,u as te,v,vt as y}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as b}from"./check-BNre7JFR.js";import{t as x}from"./chevron-right-CRxFsA9Y.js";import{t as S}from"./copy-BqdwwcxC.js";import{t as C}from"./globe-BnBar2lO.js";import{t as w}from"./key-round-BKXtbC85.js";import{t as T}from"./lock-CttMBTH5.js";import{t as ne}from"./variable-DrK2KZuk.js";import{t as re}from"./client-BF51V3uE.js";import{Dt as ie,Et as ae,Ot as oe,gt as se}from"./index-DTqMKlE1.js";import{a as E,i as D,n as ce,r as le,t as O}from"./github-dark-D7LxIVih.js";import{t as k}from"./clipboard-D_9N0yai.js";import{r as ue,t as de}from"./aiPrompts-XrsFCpj_.js";function fe(e){let t=e.regex,n=`HTTP/([32]|1\\.[01])`,r={className:`attribute`,begin:t.concat(`^`,/[A-Za-z][A-Za-z0-9-]*/,`(?=\\:\\s)`),starts:{contains:[{className:`punctuation`,begin:/: /,relevance:0,starts:{end:`$`,relevance:0}}]}},i=[r,{begin:`\\n\\n`,starts:{subLanguage:[],endsWithParent:!0}}];return{name:`HTTP`,aliases:[`https`],illegal:/\S/,contains:[{begin:`^(?=HTTP/([32]|1\\.[01]) \\d{3})`,end:/$/,contains:[{className:`meta`,begin:n},{className:`number`,begin:`\\b\\d{3}\\b`}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},{begin:`(?=^[A-Z]+ (.*?) HTTP/([32]|1\\.[01])$)`,end:/$/,contains:[{className:`string`,begin:` `,end:` `,excludeBegin:!0,excludeEnd:!0},{className:`meta`,begin:n},{className:`keyword`,begin:`[A-Z]+`}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},e.inherit(r,{relevance:0})]}}var pe={class:`space-y-12 pb-16`},me={class:`docs-hero`},he={class:`docs-hero-content`},ge={class:`docs-hero-row`},_e={class:`docs-hero-actions`},ve=[`title`,`aria-label`],A={class:`docs-hero-toc`,"aria-label":`Jump to docs section`},j=[`href`],M={class:`docs-hero-toc-num`},N={id:`handler`,class:`space-y-5 scroll-mt-6`},P={class:`doc-table-wrap`},F={class:`doc-table`},ye={class:`doc-cell-key`},be={class:`doc-cell-mono`},xe={class:`doc-cell-mono hidden sm:table-cell`},Se={class:`doc-cell-mono hidden md:table-cell`},Ce={id:`deploy`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},we={class:`grid grid-cols-1 lg:grid-cols-2 gap-3`},Te={class:`space-y-2`},Ee={class:`space-y-2`},De={class:`space-y-2`},Oe={id:`config`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},ke={class:`doc-table-wrap`},Ae={class:`doc-table`},je={class:`doc-cell-key whitespace-nowrap`},Me={class:`doc-cell-mono hidden sm:table-cell whitespace-nowrap`},Ne={class:`doc-cell-body`},Pe={class:`space-y-2`},Fe={class:`doc-details group`},Ie={class:`doc-details-summary`},Le={class:`doc-details-body`},Re={id:`sdk`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},ze={class:`space-y-2`},Be={class:`space-y-2`},Ve={class:`space-y-2`},He={id:`schedules`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ue={class:`doc-section-head`},We={class:`doc-lede`},Ge={id:`webhooks`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ke={class:`doc-section-head`},qe={class:`doc-lede`},Je={class:`doc-table-wrap`},Ye={class:`doc-table`},Xe={class:`doc-cell-key whitespace-nowrap`},Ze={class:`doc-cell-body`},Qe={class:`space-y-2`},$e={id:`mcp`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},et={class:`grid grid-cols-1 md:grid-cols-3 gap-3`},tt={class:`doc-card`},nt={class:`doc-card-body`},rt={class:`doc-chip break-all`},it={class:`doc-token-bar`},at={class:`flex items-center gap-2 min-w-0 flex-1`},ot={key:0,class:`text-sm text-foreground-muted truncate`},st={key:1,class:`text-sm text-success truncate`},ct={class:`doc-chip`},lt=[`disabled`],ut={class:`doc-details group`},dt={class:`doc-details-summary`},ft={class:`doc-details-body space-y-4`},pt={id:`generate`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},mt={class:`ai-prompt-actions`},ht={key:0,class:`prompt-collapse-fade`,"aria-hidden":`true`},gt=[`aria-expanded`],_t={id:`tracing`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},vt={class:`doc-table-wrap`},yt={class:`doc-table`},bt={class:`doc-cell-key whitespace-nowrap`},xt={class:`doc-cell-body`},St={id:`errors`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ct={class:`doc-table-wrap`},wt={class:`doc-table`},Tt={class:`doc-cell-key whitespace-nowrap`},Et={class:`doc-cell-body`},Dt={id:`cli`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ot={class:`doc-prose`},kt={class:`doc-table-wrap`},At={class:`doc-table`},jt={class:`doc-cell-key whitespace-nowrap`},Mt={class:`doc-cell-mono`},Nt={class:`doc-cell-body hidden md:table-cell`},Pt={class:`space-y-2`},Ft={class:`space-y-2`},It={class:`space-y-2`},Lt={class:`space-y-2`},Rt={class:`space-y-2`},zt=`# Available inside every running function — refresh per-invocation: +import{C as e,D as t,F as n,G as r,M as i,T as a,Z as o,_ as s,c,d as l,gt as u,h as d,j as ee,k as f,l as p,m,p as h,r as g,s as _,u as te,v,vt as y}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as b}from"./check-CZmR72iA.js";import{t as x}from"./chevron-right-D5C5fM5p.js";import{t as S}from"./copy-3UAsea5P.js";import{t as C}from"./globe-DJC2u-h_.js";import{t as w}from"./key-round-D9wVuhgl.js";import{t as T}from"./lock-n1lM5kKa.js";import{t as ne}from"./variable-DFVSR15i.js";import{t as re}from"./client-BF51V3uE.js";import{Dt as ie,Et as ae,Ot as oe,gt as se}from"./index-pE9wnfTb.js";import{a as E,i as D,n as ce,r as le,t as O}from"./github-dark-D7LxIVih.js";import{t as k}from"./clipboard-D_9N0yai.js";import{r as ue,t as de}from"./aiPrompts-XrsFCpj_.js";function fe(e){let t=e.regex,n=`HTTP/([32]|1\\.[01])`,r={className:`attribute`,begin:t.concat(`^`,/[A-Za-z][A-Za-z0-9-]*/,`(?=\\:\\s)`),starts:{contains:[{className:`punctuation`,begin:/: /,relevance:0,starts:{end:`$`,relevance:0}}]}},i=[r,{begin:`\\n\\n`,starts:{subLanguage:[],endsWithParent:!0}}];return{name:`HTTP`,aliases:[`https`],illegal:/\S/,contains:[{begin:`^(?=HTTP/([32]|1\\.[01]) \\d{3})`,end:/$/,contains:[{className:`meta`,begin:n},{className:`number`,begin:`\\b\\d{3}\\b`}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},{begin:`(?=^[A-Z]+ (.*?) HTTP/([32]|1\\.[01])$)`,end:/$/,contains:[{className:`string`,begin:` `,end:` `,excludeBegin:!0,excludeEnd:!0},{className:`meta`,begin:n},{className:`keyword`,begin:`[A-Z]+`}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},e.inherit(r,{relevance:0})]}}var pe={class:`space-y-12 pb-16`},me={class:`docs-hero`},he={class:`docs-hero-content`},ge={class:`docs-hero-row`},_e={class:`docs-hero-actions`},ve=[`title`,`aria-label`],A={class:`docs-hero-toc`,"aria-label":`Jump to docs section`},j=[`href`],M={class:`docs-hero-toc-num`},N={id:`handler`,class:`space-y-5 scroll-mt-6`},P={class:`doc-table-wrap`},F={class:`doc-table`},ye={class:`doc-cell-key`},be={class:`doc-cell-mono`},xe={class:`doc-cell-mono hidden sm:table-cell`},Se={class:`doc-cell-mono hidden md:table-cell`},Ce={id:`deploy`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},we={class:`grid grid-cols-1 lg:grid-cols-2 gap-3`},Te={class:`space-y-2`},Ee={class:`space-y-2`},De={class:`space-y-2`},Oe={id:`config`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},ke={class:`doc-table-wrap`},Ae={class:`doc-table`},je={class:`doc-cell-key whitespace-nowrap`},Me={class:`doc-cell-mono hidden sm:table-cell whitespace-nowrap`},Ne={class:`doc-cell-body`},Pe={class:`space-y-2`},Fe={class:`doc-details group`},Ie={class:`doc-details-summary`},Le={class:`doc-details-body`},Re={id:`sdk`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},ze={class:`space-y-2`},Be={class:`space-y-2`},Ve={class:`space-y-2`},He={id:`schedules`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ue={class:`doc-section-head`},We={class:`doc-lede`},Ge={id:`webhooks`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ke={class:`doc-section-head`},qe={class:`doc-lede`},Je={class:`doc-table-wrap`},Ye={class:`doc-table`},Xe={class:`doc-cell-key whitespace-nowrap`},Ze={class:`doc-cell-body`},Qe={class:`space-y-2`},$e={id:`mcp`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},et={class:`grid grid-cols-1 md:grid-cols-3 gap-3`},tt={class:`doc-card`},nt={class:`doc-card-body`},rt={class:`doc-chip break-all`},it={class:`doc-token-bar`},at={class:`flex items-center gap-2 min-w-0 flex-1`},ot={key:0,class:`text-sm text-foreground-muted truncate`},st={key:1,class:`text-sm text-success truncate`},ct={class:`doc-chip`},lt=[`disabled`],ut={class:`doc-details group`},dt={class:`doc-details-summary`},ft={class:`doc-details-body space-y-4`},pt={id:`generate`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},mt={class:`ai-prompt-actions`},ht={key:0,class:`prompt-collapse-fade`,"aria-hidden":`true`},gt=[`aria-expanded`],_t={id:`tracing`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},vt={class:`doc-table-wrap`},yt={class:`doc-table`},bt={class:`doc-cell-key whitespace-nowrap`},xt={class:`doc-cell-body`},St={id:`errors`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ct={class:`doc-table-wrap`},wt={class:`doc-table`},Tt={class:`doc-cell-key whitespace-nowrap`},Et={class:`doc-cell-body`},Dt={id:`cli`,class:`space-y-5 scroll-mt-6 border-t border-border pt-12`},Ot={class:`doc-prose`},kt={class:`doc-table-wrap`},At={class:`doc-table`},jt={class:`doc-cell-key whitespace-nowrap`},Mt={class:`doc-cell-mono`},Nt={class:`doc-cell-body hidden md:table-cell`},Pt={class:`space-y-2`},Ft={class:`space-y-2`},It={class:`space-y-2`},Lt={class:`space-y-2`},Rt={class:`space-y-2`},zt=`# Available inside every running function — refresh per-invocation: ORVA_TRACE_ID=tr_3e39f6991c66f140577c6021da7dd13b # one per causal chain ORVA_SPAN_ID=sp_4ceba57f6b1c982e # this execution diff --git a/backend/internal/server/ui_dist/assets/Drawer-B98TBytl.js b/backend/internal/server/ui_dist/assets/Drawer-CSwYBfhJ.js similarity index 96% rename from backend/internal/server/ui_dist/assets/Drawer-B98TBytl.js rename to backend/internal/server/ui_dist/assets/Drawer-CSwYBfhJ.js index d544765a..df19b9d3 100644 --- a/backend/internal/server/ui_dist/assets/Drawer-B98TBytl.js +++ b/backend/internal/server/ui_dist/assets/Drawer-CSwYBfhJ.js @@ -1 +1 @@ -import{A as e,D as t,E as n,F as r,G as i,P as a,T as o,Z as s,_t as c,a as l,c as u,d,h as f,l as p,m,u as h,vt as g,x as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{Mt as v,ut as y,vt as b,zt as x}from"./index-DTqMKlE1.js";var S={key:0,class:`fixed inset-0 z-50 pointer-events-none`},C={class:`px-5 py-3 border-b border-border flex items-center justify-between shrink-0`},w={class:`text-sm font-medium text-white truncate`},T={class:`flex-1 overflow-y-auto scrollable`},E={key:0,class:`px-5 py-3 border-t border-border shrink-0`},D=y(Object.assign({name:`CommonDrawer`},{__name:`Drawer`,props:{modelValue:{type:Boolean,default:!1},title:{type:String,default:``},width:{type:String,default:`560px`}},emits:[`update:modelValue`],setup(y,{emit:D}){let O=y,k=D,A=i(null),j=()=>k(`update:modelValue`,!1);a(()=>O.modelValue,async e=>{e&&(await _(),A.value?.focus?.())});let M=e=>{e.key===`Escape`&&O.modelValue&&j()};return o(()=>window.addEventListener(`keydown`,M)),n(()=>window.removeEventListener(`keydown`,M)),(n,i)=>(t(),p(l,{to:`body`},[f(v,{name:`drawer-fade`},{default:r(()=>[y.modelValue?(t(),d(`div`,S,[u(`div`,{class:`absolute inset-0 pointer-events-auto`,onClick:j}),f(v,{name:`drawer-slide`},{default:r(()=>[y.modelValue?(t(),d(`div`,{key:0,ref_key:`root`,ref:A,class:`absolute pointer-events-auto bg-background flex flex-col inset-x-0 bottom-0 max-h-[85dvh] border-t border-border rounded-t-lg pb-safe sm:inset-x-auto sm:right-0 sm:top-0 sm:bottom-0 sm:max-h-none sm:border-t-0 sm:border-l sm:rounded-none sm:pb-0 sm:w-[var(--drawer-w,560px)]`,style:c({"--drawer-w":y.width}),tabindex:`-1`,onKeydown:x(j,[`esc`])},[u(`header`,C,[u(`div`,w,[e(n.$slots,`title`,{},()=>[m(g(y.title),1)],!0)]),u(`button`,{class:`text-foreground-muted hover:text-white transition-colors touch-expand-iconbtn -mr-1`,"aria-label":`Close`,onClick:j},[f(s(b),{class:`w-4 h-4`})])]),u(`div`,T,[e(n.$slots,`default`,{},void 0,!0)]),n.$slots.footer?(t(),d(`footer`,E,[e(n.$slots,`footer`,{},void 0,!0)])):h(``,!0)],36)):h(``,!0)]),_:3})])):h(``,!0)]),_:3})]))}}),[[`__scopeId`,`data-v-42911a7f`]]);export{D as t}; \ No newline at end of file +import{A as e,D as t,E as n,F as r,G as i,P as a,T as o,Z as s,_t as c,a as l,c as u,d,h as f,l as p,m,u as h,vt as g,x as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{Mt as v,ut as y,vt as b,zt as x}from"./index-pE9wnfTb.js";var S={key:0,class:`fixed inset-0 z-50 pointer-events-none`},C={class:`px-5 py-3 border-b border-border flex items-center justify-between shrink-0`},w={class:`text-sm font-medium text-white truncate`},T={class:`flex-1 overflow-y-auto scrollable`},E={key:0,class:`px-5 py-3 border-t border-border shrink-0`},D=y(Object.assign({name:`CommonDrawer`},{__name:`Drawer`,props:{modelValue:{type:Boolean,default:!1},title:{type:String,default:``},width:{type:String,default:`560px`}},emits:[`update:modelValue`],setup(y,{emit:D}){let O=y,k=D,A=i(null),j=()=>k(`update:modelValue`,!1);a(()=>O.modelValue,async e=>{e&&(await _(),A.value?.focus?.())});let M=e=>{e.key===`Escape`&&O.modelValue&&j()};return o(()=>window.addEventListener(`keydown`,M)),n(()=>window.removeEventListener(`keydown`,M)),(n,i)=>(t(),p(l,{to:`body`},[f(v,{name:`drawer-fade`},{default:r(()=>[y.modelValue?(t(),d(`div`,S,[u(`div`,{class:`absolute inset-0 pointer-events-auto`,onClick:j}),f(v,{name:`drawer-slide`},{default:r(()=>[y.modelValue?(t(),d(`div`,{key:0,ref_key:`root`,ref:A,class:`absolute pointer-events-auto bg-background flex flex-col inset-x-0 bottom-0 max-h-[85dvh] border-t border-border rounded-t-lg pb-safe sm:inset-x-auto sm:right-0 sm:top-0 sm:bottom-0 sm:max-h-none sm:border-t-0 sm:border-l sm:rounded-none sm:pb-0 sm:w-[var(--drawer-w,560px)]`,style:c({"--drawer-w":y.width}),tabindex:`-1`,onKeydown:x(j,[`esc`])},[u(`header`,C,[u(`div`,w,[e(n.$slots,`title`,{},()=>[m(g(y.title),1)],!0)]),u(`button`,{class:`text-foreground-muted hover:text-white transition-colors touch-expand-iconbtn -mr-1`,"aria-label":`Close`,onClick:j},[f(s(b),{class:`w-4 h-4`})])]),u(`div`,T,[e(n.$slots,`default`,{},void 0,!0)]),n.$slots.footer?(t(),d(`footer`,E,[e(n.$slots,`footer`,{},void 0,!0)])):h(``,!0)],36)):h(``,!0)]),_:3})])):h(``,!0)]),_:3})]))}}),[[`__scopeId`,`data-v-42911a7f`]]);export{D as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Editor-C_JYWteY.js b/backend/internal/server/ui_dist/assets/Editor--ZYS7LkE.js similarity index 99% rename from backend/internal/server/ui_dist/assets/Editor-C_JYWteY.js rename to backend/internal/server/ui_dist/assets/Editor--ZYS7LkE.js index 1190b2b0..802229d8 100644 --- a/backend/internal/server/ui_dist/assets/Editor-C_JYWteY.js +++ b/backend/internal/server/ui_dist/assets/Editor--ZYS7LkE.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/CodeEditor-CiRqvRcK.js","assets/runtime-core.esm-bundler-BMQPyJ_W.js","assets/index-DTqMKlE1.js","assets/axios-DVDuIpRy.js","assets/pinia-B41TZNUX.js","assets/client-BF51V3uE.js","assets/index-C9cn_46N.css","assets/dist-CR15Grce.js","assets/CodeEditor-x1XGuNl0.css"])))=>i.map(i=>d[i]); -import{C as e,D as t,F as n,G as r,I as i,M as ee,P as a,T as te,Z as o,c as s,d as c,g as ne,gt as l,h as u,j as re,k as d,l as ie,m as f,r as p,s as m,u as h,v as ae,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as oe}from"./book-open-B7-cMpW6.js";import{t as se}from"./check-BNre7JFR.js";import{n as ce,t as le}from"./git-compare-Co883xFS.js";import{t as ue}from"./copy-BqdwwcxC.js";import{n as de,r as fe,t as pe}from"./settings-2-D5QtFfdZ.js";import{t as me}from"./globe-BnBar2lO.js";import{t as he}from"./key-round-BKXtbC85.js";import{t as ge}from"./lock-CttMBTH5.js";import{t as _e}from"./play-CmQifd74.js";import{t as ve}from"./rotate-ccw-DWwjKCqh.js";import{t as ye}from"./shield-check-piXkOtNv.js";import{t as be}from"./sparkles-DTHEIS5T.js";import{t as xe}from"./terminal-BQdlNiyt.js";import{t as Se}from"./trash-2-DaeYqnW_.js";import{t as Ce}from"./variable-DrK2KZuk.js";import{r as we,t as _}from"./client-BF51V3uE.js";import{Bt as Te,Ct as Ee,Dt as De,It as Oe,Lt as v,Nt as ke,Rt as Ae,W as je,_ as Me,_t as y,et as Ne,gt as Pe,jt as Fe,k as Ie,m as Le,mt as Re,ot as ze,pt as Be,rt as Ve,t as He,ut as Ue,vt as We,yt as Ge,z as Ke,zt as qe}from"./index-DTqMKlE1.js";import{t as Je}from"./clipboard-D_9N0yai.js";import{t as Ye}from"./Modal-BAoZams6.js";import{t as Xe}from"./rollbackDiff-DsaWcdbl.js";import{n as Ze}from"./aiPrompts-XrsFCpj_.js";import{t as Qe}from"./Input-DQ-tWGkn.js";var $e=Fe(`database`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]),et=Fe(`layers`,[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]]),tt=Fe(`shuffle`,[[`path`,{d:`m18 14 4 4-4 4`,key:`10pe0f`}],[`path`,{d:`m18 2 4 4-4 4`,key:`pucp1d`}],[`path`,{d:`M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22`,key:`1ailkh`}],[`path`,{d:`M2 6h1.972a4 4 0 0 1 3.6 2.2`,key:`km57vx`}],[`path`,{d:`M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45`,key:`os18l9`}]]),b=`amber.arctic.aurora.bold.brave.breezy.bright.brisk.calm.celestial.cobalt.cosmic.crimson.crisp.crystal.dapper.dazzling.deep.eager.ember.fearless.feisty.fierce.flaming.fluent.fluorescent.frosty.gentle.glacial.golden.graceful.happy.hazy.icy.indigo.jade.jolly.jovial.keen.kindred.lavender.lively.lucent.lunar.magenta.magnetic.merry.midnight.mighty.mellow.mossy.mystic.neon.nimble.noble.obsidian.opal.pearl.peppy.pixel.plucky.plush.polar.prime.quartz.quick.quiet.radiant.rapid.rare.roaming.rosy.royal.rugged.runic.rustic.sapphire.scarlet.sharp.silent.silken.silver.sleek.smooth.snowy.snug.solar.sonic.spry.starlit.stellar.sturdy.sublime.sunny.svelte.swift.tame.tender.thunder.tidal.topaz.tropic.turquoise.twilight.urban.velvet.verdant.vibrant.violet.vivid.warm.whisper.wild.wise.witty.woven.zesty.zen`.split(`.`),nt=`albatross.amber.antler.apricot.archer.arrow.atlas.aurora.badger.bayou.beacon.bison.blossom.bramble.breeze.cactus.canyon.caravan.cedar.cliff.comet.compass.coral.cosmos.cypress.dawn.delta.dolphin.drift.dune.eagle.ember.fable.falcon.fern.fjord.flame.flint.forest.galaxy.garnet.geyser.glacier.glade.glint.gorge.gull.harbor.haven.horizon.iceberg.iris.jaguar.jetty.jungle.kelp.kestrel.kettle.kraken.lagoon.lantern.lark.ledge.lily.lighthouse.lupine.lynx.maple.meadow.meridian.meteor.mirage.mistral.monsoon.moon.moss.mountain.nebula.oak.oasis.ocean.orchid.osprey.otter.panda.panther.parrot.pebble.phoenix.pine.pinion.pixel.planet.plume.pond.poppy.prairie.puffin.puma.quartz.quasar.quill.rapids.raven.reef.ridge.river.robin.rune.sage.satellite.savanna.sequoia.shadow.signal.silo.sky.sloth.snow.sparrow.spire.star.stream.summit.swan.tempest.thicket.thistle.thunder.tide.tiger.totem.tower.tundra.twilight.twister.valley.vortex.walnut.wave.whale.whisper.wildflower.willow.wolf.wren.zenith.zephyr`.split(`.`),x=e=>e[Math.floor(Math.random()*e.length)];function rt(){return`${x(b)}-${x(nt)}`}var S=`import json +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/CodeEditor-Y2EEC-Gt.js","assets/runtime-core.esm-bundler-BMQPyJ_W.js","assets/index-pE9wnfTb.js","assets/axios-DVDuIpRy.js","assets/pinia-B41TZNUX.js","assets/client-BF51V3uE.js","assets/index-C9cn_46N.css","assets/dist-CR15Grce.js","assets/CodeEditor-x1XGuNl0.css"])))=>i.map(i=>d[i]); +import{C as e,D as t,F as n,G as r,I as i,M as ee,P as a,T as te,Z as o,c as s,d as c,g as ne,gt as l,h as u,j as re,k as d,l as ie,m as f,r as p,s as m,u as h,v as ae,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as oe}from"./book-open-DQ3Rz8Ui.js";import{t as se}from"./check-CZmR72iA.js";import{n as ce,t as le}from"./git-compare-BnvFSVmQ.js";import{t as ue}from"./copy-3UAsea5P.js";import{n as de,r as fe,t as pe}from"./settings-2-C0pnmjU4.js";import{t as me}from"./globe-DJC2u-h_.js";import{t as he}from"./key-round-D9wVuhgl.js";import{t as ge}from"./lock-n1lM5kKa.js";import{t as _e}from"./play-CnkMURxf.js";import{t as ve}from"./rotate-ccw-DgujV-4F.js";import{t as ye}from"./shield-check-CowI6J3x.js";import{t as be}from"./sparkles-BZcVxan3.js";import{t as xe}from"./terminal-Czs3Hy-Y.js";import{t as Se}from"./trash-2-Cz9PSE2q.js";import{t as Ce}from"./variable-DFVSR15i.js";import{r as we,t as _}from"./client-BF51V3uE.js";import{Bt as Te,Ct as Ee,Dt as De,It as Oe,Lt as v,Nt as ke,Rt as Ae,W as je,_ as Me,_t as y,et as Ne,gt as Pe,jt as Fe,k as Ie,m as Le,mt as Re,ot as ze,pt as Be,rt as Ve,t as He,ut as Ue,vt as We,yt as Ge,z as Ke,zt as qe}from"./index-pE9wnfTb.js";import{t as Je}from"./clipboard-D_9N0yai.js";import{t as Ye}from"./Modal-C1IBLm0r.js";import{t as Xe}from"./rollbackDiff-DsaWcdbl.js";import{n as Ze}from"./aiPrompts-XrsFCpj_.js";import{t as Qe}from"./Input-DQ-tWGkn.js";var $e=Fe(`database`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]),et=Fe(`layers`,[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]]),tt=Fe(`shuffle`,[[`path`,{d:`m18 14 4 4-4 4`,key:`10pe0f`}],[`path`,{d:`m18 2 4 4-4 4`,key:`pucp1d`}],[`path`,{d:`M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22`,key:`1ailkh`}],[`path`,{d:`M2 6h1.972a4 4 0 0 1 3.6 2.2`,key:`km57vx`}],[`path`,{d:`M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45`,key:`os18l9`}]]),b=`amber.arctic.aurora.bold.brave.breezy.bright.brisk.calm.celestial.cobalt.cosmic.crimson.crisp.crystal.dapper.dazzling.deep.eager.ember.fearless.feisty.fierce.flaming.fluent.fluorescent.frosty.gentle.glacial.golden.graceful.happy.hazy.icy.indigo.jade.jolly.jovial.keen.kindred.lavender.lively.lucent.lunar.magenta.magnetic.merry.midnight.mighty.mellow.mossy.mystic.neon.nimble.noble.obsidian.opal.pearl.peppy.pixel.plucky.plush.polar.prime.quartz.quick.quiet.radiant.rapid.rare.roaming.rosy.royal.rugged.runic.rustic.sapphire.scarlet.sharp.silent.silken.silver.sleek.smooth.snowy.snug.solar.sonic.spry.starlit.stellar.sturdy.sublime.sunny.svelte.swift.tame.tender.thunder.tidal.topaz.tropic.turquoise.twilight.urban.velvet.verdant.vibrant.violet.vivid.warm.whisper.wild.wise.witty.woven.zesty.zen`.split(`.`),nt=`albatross.amber.antler.apricot.archer.arrow.atlas.aurora.badger.bayou.beacon.bison.blossom.bramble.breeze.cactus.canyon.caravan.cedar.cliff.comet.compass.coral.cosmos.cypress.dawn.delta.dolphin.drift.dune.eagle.ember.fable.falcon.fern.fjord.flame.flint.forest.galaxy.garnet.geyser.glacier.glade.glint.gorge.gull.harbor.haven.horizon.iceberg.iris.jaguar.jetty.jungle.kelp.kestrel.kettle.kraken.lagoon.lantern.lark.ledge.lily.lighthouse.lupine.lynx.maple.meadow.meridian.meteor.mirage.mistral.monsoon.moon.moss.mountain.nebula.oak.oasis.ocean.orchid.osprey.otter.panda.panther.parrot.pebble.phoenix.pine.pinion.pixel.planet.plume.pond.poppy.prairie.puffin.puma.quartz.quasar.quill.rapids.raven.reef.ridge.river.robin.rune.sage.satellite.savanna.sequoia.shadow.signal.silo.sky.sloth.snow.sparrow.spire.star.stream.summit.swan.tempest.thicket.thistle.thunder.tide.tiger.totem.tower.tundra.twilight.twister.valley.vortex.walnut.wave.whale.whisper.wildflower.willow.wolf.wren.zenith.zephyr`.split(`.`),x=e=>e[Math.floor(Math.random()*e.length)];function rt(){return`${x(b)}-${x(nt)}`}var S=`import json def handler(event): @@ -1274,7 +1274,7 @@ export = handler "include": ["handler.ts"], "exclude": ["node_modules", "dist"] } -`},entrypoint:`handler.ts`}]},pt={python:S,node:T},mt=[`Starter`,`Webhooks`,`Auth`,`Utility`,`Scheduled`,`Showcase`],ht={class:`flex flex-col h-full`},gt={class:`sr-only`},_t={class:`flex flex-col sm:flex-row sm:flex-wrap sm:items-center gap-2 pb-3 border-b border-border`},vt={class:`flex items-center gap-2 sm:mr-auto min-w-0 w-full sm:w-auto`},yt=[`disabled`],bt={class:`text-[11px] text-foreground-muted font-medium tracking-tight shrink-0`},xt={class:`flex flex-wrap items-center gap-2 sm:contents`},St=[`aria-expanded`],Ct={key:0,class:`absolute right-0 mt-1 z-30 min-w-[210px] bg-background border border-border rounded-md shadow-xl overflow-hidden`,role:`menu`},wt={key:0,class:`text-[10px] text-foreground-muted tabular-nums`},Tt={key:0,class:`text-[10px] text-foreground-muted tabular-nums`},Et={class:`text-[10px] text-foreground-muted tabular-nums`},Dt=[`aria-expanded`],Ot={key:0,class:`absolute right-0 mt-1 z-30 min-w-[210px] bg-background border border-border rounded-md shadow-xl overflow-hidden`,role:`menu`},kt={key:0,class:`flex items-center gap-2 px-2 py-1.5 mt-2 border border-border bg-surface rounded text-xs`},At={class:`font-mono text-white truncate flex-1 min-w-0`},jt={class:`flex-1 flex flex-col min-h-0 mt-3 bg-background border border-border rounded-lg overflow-hidden shadow-sm`},Mt={class:`h-9 border-b border-border flex items-center justify-between px-4 bg-surface shrink-0`},Nt={class:`text-xs font-mono text-foreground-muted flex items-center gap-2`},Pt={class:`text-white`},Ft={key:0,class:`text-foreground-muted`},It={class:`text-[10px] text-foreground-muted font-mono`},Lt={class:`mt-3 bg-background border border-border rounded-lg overflow-hidden shrink-0`},Rt={class:`h-9 border-b border-border flex items-center px-2 bg-surface`},zt=[`onClick`],Bt={key:0,class:`ml-1 text-[10px] px-1.5 rounded bg-surface-hover text-foreground-muted`},Vt={class:`ml-auto flex items-center gap-1`},Ht=[`disabled`,`title`],Ut={key:1,class:`run-spinner`},Wt=[`title`,`aria-label`],Gt={class:`h-48 overflow-y-auto bg-background`},Kt={key:0,class:`p-3 font-mono text-xs space-y-0.5`},qt={key:0,class:`text-foreground-muted`},Jt={key:1,class:`grid grid-cols-1 md:grid-cols-[minmax(0,1fr)_minmax(0,1.3fr)] h-full`},Yt={class:`flex flex-col min-h-0 border-b md:border-b-0 md:border-r border-border`},Xt={class:`h-7 px-2 flex items-center gap-1.5 bg-surface/60 border-b border-border shrink-0`},Zt=[`disabled`],Qt=[`value`],$t=[`disabled`],en={class:`relative shrink-0`},tn=[`disabled`,`title`],nn={key:0,class:`text-[10px] text-foreground-muted`},rn={key:0,class:`px-3 py-3 text-[11px] text-foreground-muted italic`},an={key:1,class:`max-h-56 overflow-y-auto`},on=[`onClick`],sn={class:`font-mono text-[10px] text-foreground-muted shrink-0`},cn={class:`truncate flex-1 text-foreground`},ln=[`title`,`aria-label`,`onClick`],un={class:`border-t border-border px-2 py-1.5 bg-surface/50`},dn=[`disabled`],fn={class:`border-b border-border shrink-0`},pn={key:0,class:`ml-1 text-foreground-muted/80 normal-case tracking-normal`},mn={key:0,class:`px-2 py-2 space-y-1`},hn=[`onUpdate:modelValue`,`disabled`],gn=[`onUpdate:modelValue`,`disabled`],_n=[`onClick`],vn=[`disabled`],yn={class:`h-6 px-3 flex items-center justify-between bg-surface/30 border-b border-border shrink-0`},bn={key:0,class:`text-[10px] text-amber-400/80`},xn={key:1,class:`text-[10px] text-foreground-muted/70 font-mono`},Sn=[`disabled`],Cn={class:`flex flex-col min-h-0`},wn={class:`h-7 px-3 flex items-center justify-between bg-surface/60 border-b border-border shrink-0`},Tn={class:`flex items-center gap-2`},En=[`disabled`],Dn={key:1,class:`text-[10px] text-foreground-muted/80 font-mono`},On={class:`flex-1 min-h-0 overflow-y-auto`},kn={key:1,class:`px-3 py-3 text-xs text-foreground-muted italic`},An={key:2,class:`border-t border-border`},jn={class:`h-6 px-3 flex items-center text-[10px] uppercase tracking-[0.14em] text-foreground-muted/80 bg-surface/30`},Mn={class:`px-3 py-2 font-mono text-xs space-y-0.5`},Nn={class:`space-y-4`},Pn={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5 flex items-center justify-between`},Fn={key:0,class:`text-[10px] normal-case tracking-normal text-success/80`},In={class:`grid grid-cols-2 gap-2`},Ln=[`onClick`],Rn=[`label`],zn=[`value`],Bn={key:0,class:`text-[11px] text-foreground-muted mt-1.5`},Vn={class:`grid grid-cols-2 gap-3`},Hn={class:`border-t border-border pt-4 space-y-2`},Un={class:`grid grid-cols-2 gap-3`},Wn=[`disabled`],Gn={class:`border-t border-border pt-4`},Kn={class:`flex items-start gap-3 cursor-pointer select-none`},qn={class:`min-w-0`},Jn={class:`text-sm font-medium text-white flex items-center gap-2`},Yn={class:`border-t border-border pt-4 space-y-2`},Xn={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide flex items-center gap-2`},Zn={class:`border-t border-border pt-4 space-y-2`},Qn={class:`border-t border-border pt-4 space-y-3`},$n={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide flex items-center gap-2`},er={key:0,class:`text-[10px] normal-case tracking-normal text-foreground-muted`},tr={key:0,class:`text-[11px] text-foreground-muted leading-snug`},nr={key:1,class:`text-[11px] text-foreground-muted leading-snug`},rr={class:`font-mono`},ir={key:2,class:`space-y-1.5`},ar={class:`flex-1 min-w-0 font-mono text-xs text-foreground truncate`},or={key:0,class:`text-[10px] font-mono text-foreground-muted`},sr=[`aria-label`,`onClick`],cr={key:3,class:`space-y-2 pt-1`},lr={class:`flex items-center gap-2`},ur={key:0,class:`text-[11px] text-amber-400 leading-snug`},dr={class:`font-mono`},fr={class:`font-mono`},pr={key:1,class:`text-[11px] text-red-400 leading-snug`},mr={class:`space-y-2`},hr=[`onUpdate:modelValue`],gr=[`onUpdate:modelValue`],_r=[`aria-label`,`onClick`],vr={class:`space-y-2`},yr={class:`text-[10px] text-foreground-muted font-mono`},br={class:`space-y-3`},xr={key:0,class:`text-xs text-foreground-muted`},Sr={key:0},Cr={class:`text-foreground-muted font-mono`},wr=[`aria-label`,`onClick`],Tr={class:`flex items-center gap-2 min-w-0`},Er={class:`text-foreground-muted font-mono`},Dr=[`aria-label`,`onClick`],Or={class:`border-t border-border pt-3 space-y-2`},kr={class:`space-y-2`},Ar={class:`flex items-center gap-2 min-w-0`},jr={class:`font-mono text-foreground-muted shrink-0`},Mr={key:0,class:`px-1.5 py-0.5 rounded text-[10px] bg-success/15 text-success border border-success/30 shrink-0`},Nr=[`title`],Pr={class:`text-foreground-muted shrink-0`},Fr={key:0,class:`shrink-0 flex items-center gap-2`},Ir=[`disabled`,`onClick`],Lr={class:`space-y-3 text-xs text-foreground-muted`},Rr={class:`bg-surface border border-border rounded p-3 font-mono text-[12px] text-white overflow-x-auto whitespace-pre`},zr={class:`space-y-4`},Br={class:`relative`},Vr={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5 flex items-center justify-between`},Hr={key:0,class:`text-[10px] normal-case tracking-normal text-success/80`},Ur={class:`grid grid-cols-2 gap-2`},Wr=[`onClick`],Gr={class:`grid grid-cols-2 gap-3`},E=Ue({__name:`Editor`,setup(Fe){let Ue=ne({loader:()=>He(()=>import(`./CodeEditor-CiRqvRcK.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8])),loadingComponent:{render(){return ae(`div`,{class:`flex-1 min-h-0 w-full bg-background flex items-start`,"aria-busy":`true`,"aria-label":`Loading code editor`},[ae(`div`,{class:`p-4 space-y-2 w-full font-mono text-xs text-foreground-muted/40`},[ae(`div`,{class:`h-3 w-1/3 bg-surface-hover rounded animate-pulse`}),ae(`div`,{class:`h-3 w-2/3 bg-surface-hover rounded animate-pulse`}),ae(`div`,{class:`h-3 w-1/2 bg-surface-hover rounded animate-pulse`})])])}},delay:0}),b=Be(),nt=Re(),x=Pe(),S=r({settings:!1,envVars:!1,deps:!1,secrets:!1,versions:!1,docs:!1,firstDeploy:!1}),it=r(null),C=r({config:!1,bindings:!1}),at=r(null),ot=r(null),st=()=>{C.value.config=!1,C.value.bindings=!1},ct=e=>{let t=!C.value[e];st(),C.value[e]=t},w=e=>{st(),S.value[e]=!0},lt=e=>{st(),nt.push(e)},ut=e=>{if(!C.value.config&&!C.value.bindings)return;let t=at.value?.contains(e.target),n=ot.value?.contains(e.target);!t&&!n&&st()},dt=e=>{e.key===`Escape`&&(C.value.config||C.value.bindings)&&st()},T=r(!0),E=r(`build`),Kr=m(()=>[{id:`build`,label:`Build`,icon:xe,badge:V.value.length||null},{id:`test`,label:`Test`,icon:_e,badge:H.value.length||null}]),qr=e=>e?e===`node`?`Node.js 24`:e===`python`?`Python 3.14`:e:``,Jr=m(()=>U.value.filter(e=>e.key.trim()).length),D=r(``),O=r({name:``,description:``,runtime:`python`,memory_mb:64,cpus:.5,network_mode:`none`,max_concurrency:0,concurrency_policy:`queue`,auth_mode:`none`,rate_limit_per_min:0}),k=r(``),A=r(`{"name": "World"}`),j=r(`POST`),M=r(`/`),N=r([]),P=r(!1),Yr=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],F=r([]),I=r(!1),Xr=m(()=>N.value.filter(e=>e.name&&e.name.trim()).length),L=r(!1),Zr=r(!1),Qr=r(!1),R=r(null),z=r(null),$r=r(0),B=r(``),V=r([]),H=r([]),ei=r(!1),ti=r(!1),ni=r(!1),ri=m(()=>k.value?`${window.location.origin}/fn/${k.value}`:``),ii=async()=>{ri.value&&(await Je(ri.value)?(ei.value=!0,setTimeout(()=>{ei.value=!1},1500)):x.notify({title:`Copy failed`,message:`Could not copy to clipboard. Select the URL manually: +`},entrypoint:`handler.ts`}]},pt={python:S,node:T},mt=[`Starter`,`Webhooks`,`Auth`,`Utility`,`Scheduled`,`Showcase`],ht={class:`flex flex-col h-full`},gt={class:`sr-only`},_t={class:`flex flex-col sm:flex-row sm:flex-wrap sm:items-center gap-2 pb-3 border-b border-border`},vt={class:`flex items-center gap-2 sm:mr-auto min-w-0 w-full sm:w-auto`},yt=[`disabled`],bt={class:`text-[11px] text-foreground-muted font-medium tracking-tight shrink-0`},xt={class:`flex flex-wrap items-center gap-2 sm:contents`},St=[`aria-expanded`],Ct={key:0,class:`absolute right-0 mt-1 z-30 min-w-[210px] bg-background border border-border rounded-md shadow-xl overflow-hidden`,role:`menu`},wt={key:0,class:`text-[10px] text-foreground-muted tabular-nums`},Tt={key:0,class:`text-[10px] text-foreground-muted tabular-nums`},Et={class:`text-[10px] text-foreground-muted tabular-nums`},Dt=[`aria-expanded`],Ot={key:0,class:`absolute right-0 mt-1 z-30 min-w-[210px] bg-background border border-border rounded-md shadow-xl overflow-hidden`,role:`menu`},kt={key:0,class:`flex items-center gap-2 px-2 py-1.5 mt-2 border border-border bg-surface rounded text-xs`},At={class:`font-mono text-white truncate flex-1 min-w-0`},jt={class:`flex-1 flex flex-col min-h-0 mt-3 bg-background border border-border rounded-lg overflow-hidden shadow-sm`},Mt={class:`h-9 border-b border-border flex items-center justify-between px-4 bg-surface shrink-0`},Nt={class:`text-xs font-mono text-foreground-muted flex items-center gap-2`},Pt={class:`text-white`},Ft={key:0,class:`text-foreground-muted`},It={class:`text-[10px] text-foreground-muted font-mono`},Lt={class:`mt-3 bg-background border border-border rounded-lg overflow-hidden shrink-0`},Rt={class:`h-9 border-b border-border flex items-center px-2 bg-surface`},zt=[`onClick`],Bt={key:0,class:`ml-1 text-[10px] px-1.5 rounded bg-surface-hover text-foreground-muted`},Vt={class:`ml-auto flex items-center gap-1`},Ht=[`disabled`,`title`],Ut={key:1,class:`run-spinner`},Wt=[`title`,`aria-label`],Gt={class:`h-48 overflow-y-auto bg-background`},Kt={key:0,class:`p-3 font-mono text-xs space-y-0.5`},qt={key:0,class:`text-foreground-muted`},Jt={key:1,class:`grid grid-cols-1 md:grid-cols-[minmax(0,1fr)_minmax(0,1.3fr)] h-full`},Yt={class:`flex flex-col min-h-0 border-b md:border-b-0 md:border-r border-border`},Xt={class:`h-7 px-2 flex items-center gap-1.5 bg-surface/60 border-b border-border shrink-0`},Zt=[`disabled`],Qt=[`value`],$t=[`disabled`],en={class:`relative shrink-0`},tn=[`disabled`,`title`],nn={key:0,class:`text-[10px] text-foreground-muted`},rn={key:0,class:`px-3 py-3 text-[11px] text-foreground-muted italic`},an={key:1,class:`max-h-56 overflow-y-auto`},on=[`onClick`],sn={class:`font-mono text-[10px] text-foreground-muted shrink-0`},cn={class:`truncate flex-1 text-foreground`},ln=[`title`,`aria-label`,`onClick`],un={class:`border-t border-border px-2 py-1.5 bg-surface/50`},dn=[`disabled`],fn={class:`border-b border-border shrink-0`},pn={key:0,class:`ml-1 text-foreground-muted/80 normal-case tracking-normal`},mn={key:0,class:`px-2 py-2 space-y-1`},hn=[`onUpdate:modelValue`,`disabled`],gn=[`onUpdate:modelValue`,`disabled`],_n=[`onClick`],vn=[`disabled`],yn={class:`h-6 px-3 flex items-center justify-between bg-surface/30 border-b border-border shrink-0`},bn={key:0,class:`text-[10px] text-amber-400/80`},xn={key:1,class:`text-[10px] text-foreground-muted/70 font-mono`},Sn=[`disabled`],Cn={class:`flex flex-col min-h-0`},wn={class:`h-7 px-3 flex items-center justify-between bg-surface/60 border-b border-border shrink-0`},Tn={class:`flex items-center gap-2`},En=[`disabled`],Dn={key:1,class:`text-[10px] text-foreground-muted/80 font-mono`},On={class:`flex-1 min-h-0 overflow-y-auto`},kn={key:1,class:`px-3 py-3 text-xs text-foreground-muted italic`},An={key:2,class:`border-t border-border`},jn={class:`h-6 px-3 flex items-center text-[10px] uppercase tracking-[0.14em] text-foreground-muted/80 bg-surface/30`},Mn={class:`px-3 py-2 font-mono text-xs space-y-0.5`},Nn={class:`space-y-4`},Pn={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5 flex items-center justify-between`},Fn={key:0,class:`text-[10px] normal-case tracking-normal text-success/80`},In={class:`grid grid-cols-2 gap-2`},Ln=[`onClick`],Rn=[`label`],zn=[`value`],Bn={key:0,class:`text-[11px] text-foreground-muted mt-1.5`},Vn={class:`grid grid-cols-2 gap-3`},Hn={class:`border-t border-border pt-4 space-y-2`},Un={class:`grid grid-cols-2 gap-3`},Wn=[`disabled`],Gn={class:`border-t border-border pt-4`},Kn={class:`flex items-start gap-3 cursor-pointer select-none`},qn={class:`min-w-0`},Jn={class:`text-sm font-medium text-white flex items-center gap-2`},Yn={class:`border-t border-border pt-4 space-y-2`},Xn={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide flex items-center gap-2`},Zn={class:`border-t border-border pt-4 space-y-2`},Qn={class:`border-t border-border pt-4 space-y-3`},$n={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide flex items-center gap-2`},er={key:0,class:`text-[10px] normal-case tracking-normal text-foreground-muted`},tr={key:0,class:`text-[11px] text-foreground-muted leading-snug`},nr={key:1,class:`text-[11px] text-foreground-muted leading-snug`},rr={class:`font-mono`},ir={key:2,class:`space-y-1.5`},ar={class:`flex-1 min-w-0 font-mono text-xs text-foreground truncate`},or={key:0,class:`text-[10px] font-mono text-foreground-muted`},sr=[`aria-label`,`onClick`],cr={key:3,class:`space-y-2 pt-1`},lr={class:`flex items-center gap-2`},ur={key:0,class:`text-[11px] text-amber-400 leading-snug`},dr={class:`font-mono`},fr={class:`font-mono`},pr={key:1,class:`text-[11px] text-red-400 leading-snug`},mr={class:`space-y-2`},hr=[`onUpdate:modelValue`],gr=[`onUpdate:modelValue`],_r=[`aria-label`,`onClick`],vr={class:`space-y-2`},yr={class:`text-[10px] text-foreground-muted font-mono`},br={class:`space-y-3`},xr={key:0,class:`text-xs text-foreground-muted`},Sr={key:0},Cr={class:`text-foreground-muted font-mono`},wr=[`aria-label`,`onClick`],Tr={class:`flex items-center gap-2 min-w-0`},Er={class:`text-foreground-muted font-mono`},Dr=[`aria-label`,`onClick`],Or={class:`border-t border-border pt-3 space-y-2`},kr={class:`space-y-2`},Ar={class:`flex items-center gap-2 min-w-0`},jr={class:`font-mono text-foreground-muted shrink-0`},Mr={key:0,class:`px-1.5 py-0.5 rounded text-[10px] bg-success/15 text-success border border-success/30 shrink-0`},Nr=[`title`],Pr={class:`text-foreground-muted shrink-0`},Fr={key:0,class:`shrink-0 flex items-center gap-2`},Ir=[`disabled`,`onClick`],Lr={class:`space-y-3 text-xs text-foreground-muted`},Rr={class:`bg-surface border border-border rounded p-3 font-mono text-[12px] text-white overflow-x-auto whitespace-pre`},zr={class:`space-y-4`},Br={class:`relative`},Vr={class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5 flex items-center justify-between`},Hr={key:0,class:`text-[10px] normal-case tracking-normal text-success/80`},Ur={class:`grid grid-cols-2 gap-2`},Wr=[`onClick`],Gr={class:`grid grid-cols-2 gap-3`},E=Ue({__name:`Editor`,setup(Fe){let Ue=ne({loader:()=>He(()=>import(`./CodeEditor-Y2EEC-Gt.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8])),loadingComponent:{render(){return ae(`div`,{class:`flex-1 min-h-0 w-full bg-background flex items-start`,"aria-busy":`true`,"aria-label":`Loading code editor`},[ae(`div`,{class:`p-4 space-y-2 w-full font-mono text-xs text-foreground-muted/40`},[ae(`div`,{class:`h-3 w-1/3 bg-surface-hover rounded animate-pulse`}),ae(`div`,{class:`h-3 w-2/3 bg-surface-hover rounded animate-pulse`}),ae(`div`,{class:`h-3 w-1/2 bg-surface-hover rounded animate-pulse`})])])}},delay:0}),b=Be(),nt=Re(),x=Pe(),S=r({settings:!1,envVars:!1,deps:!1,secrets:!1,versions:!1,docs:!1,firstDeploy:!1}),it=r(null),C=r({config:!1,bindings:!1}),at=r(null),ot=r(null),st=()=>{C.value.config=!1,C.value.bindings=!1},ct=e=>{let t=!C.value[e];st(),C.value[e]=t},w=e=>{st(),S.value[e]=!0},lt=e=>{st(),nt.push(e)},ut=e=>{if(!C.value.config&&!C.value.bindings)return;let t=at.value?.contains(e.target),n=ot.value?.contains(e.target);!t&&!n&&st()},dt=e=>{e.key===`Escape`&&(C.value.config||C.value.bindings)&&st()},T=r(!0),E=r(`build`),Kr=m(()=>[{id:`build`,label:`Build`,icon:xe,badge:V.value.length||null},{id:`test`,label:`Test`,icon:_e,badge:H.value.length||null}]),qr=e=>e?e===`node`?`Node.js 24`:e===`python`?`Python 3.14`:e:``,Jr=m(()=>U.value.filter(e=>e.key.trim()).length),D=r(``),O=r({name:``,description:``,runtime:`python`,memory_mb:64,cpus:.5,network_mode:`none`,max_concurrency:0,concurrency_policy:`queue`,auth_mode:`none`,rate_limit_per_min:0}),k=r(``),A=r(`{"name": "World"}`),j=r(`POST`),M=r(`/`),N=r([]),P=r(!1),Yr=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],F=r([]),I=r(!1),Xr=m(()=>N.value.filter(e=>e.name&&e.name.trim()).length),L=r(!1),Zr=r(!1),Qr=r(!1),R=r(null),z=r(null),$r=r(0),B=r(``),V=r([]),H=r([]),ei=r(!1),ti=r(!1),ni=r(!1),ri=m(()=>k.value?`${window.location.origin}/fn/${k.value}`:``),ii=async()=>{ri.value&&(await Je(ri.value)?(ei.value=!0,setTimeout(()=>{ei.value=!1},1500)):x.notify({title:`Copy failed`,message:`Could not copy to clipboard. Select the URL manually: `+ri.value}))},U=r([{key:``,value:``}]),W=r(``),G=r(``),ai=r([]),oi=r([]),K=r({name:``,value:``}),si=r([]),ci=r(!1),q=r(``),J=r({path:``,methods:`*`}),Y=r(null),li=m(()=>k.value?si.value.filter(e=>e.function_id===k.value):[]),X=r([]),ui=m(()=>oi.value.length+X.value.length),Z=m(()=>!!b.params.name),di=m(()=>Z.value||Qr.value),Q=m(()=>di.value&&!L.value),fi=[{id:`python`,label:`Python 3.14`},{id:`node`,label:`Node.js 24`}],pi=e=>e===`python`,mi=e=>e===`node`,hi=m(()=>pi(O.value.runtime)?`handler.py`:(O.value.runtime,`handler.js`)),gi=m(()=>pi(O.value.runtime)?`def handler(event): return { diff --git a/backend/internal/server/ui_dist/assets/Firewall-Bpe5shll.js b/backend/internal/server/ui_dist/assets/Firewall-qk4ey7XG.js similarity index 98% rename from backend/internal/server/ui_dist/assets/Firewall-Bpe5shll.js rename to backend/internal/server/ui_dist/assets/Firewall-qk4ey7XG.js index 4aa72eb9..d61911e3 100644 --- a/backend/internal/server/ui_dist/assets/Firewall-Bpe5shll.js +++ b/backend/internal/server/ui_dist/assets/Firewall-qk4ey7XG.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,M as i,S as a,T as o,Z as s,_ as c,c as l,d as u,gt as d,h as f,k as p,l as m,m as h,r as g,s as _,u as v,v as y,vt as b}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ee}from"./globe-BnBar2lO.js";import{t as te}from"./refresh-cw-Cn8qkf-v.js";import{t as ne}from"./shield-check-piXkOtNv.js";import{t as re}from"./trash-2-DaeYqnW_.js";import{t as x}from"./client-BF51V3uE.js";import{Lt as S,St as C,_t as w,bt as ie,gt as ae,jt as T,zt as E}from"./index-DTqMKlE1.js";import{t as oe}from"./Modal-BAoZams6.js";import{t as se}from"./Input-DQ-tWGkn.js";var ce=T(`asterisk`,[[`path`,{d:`M12 6v12`,key:`1vza4d`}],[`path`,{d:`M17.196 9 6.804 15`,key:`1ah31z`}],[`path`,{d:`m6.804 9 10.392 6`,key:`1b6pxd`}]]),D=T(`earth`,[[`path`,{d:`M21.54 15H17a2 2 0 0 0-2 2v4.54`,key:`1djwo0`}],[`path`,{d:`M7 3.34V5a3 3 0 0 0 3 3a2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17`,key:`1tzkfa`}],[`path`,{d:`M11 21.95V18a2 2 0 0 0-2-2a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05`,key:`14pb5j`}],[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),le=T(`hash`,[[`line`,{x1:`4`,x2:`20`,y1:`9`,y2:`9`,key:`4lhtct`}],[`line`,{x1:`4`,x2:`20`,y1:`15`,y2:`15`,key:`vyu0kd`}],[`line`,{x1:`10`,x2:`8`,y1:`3`,y2:`21`,key:`1ggp8o`}],[`line`,{x1:`16`,x2:`14`,y1:`3`,y2:`21`,key:`weycgp`}]]),ue=T(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]),de=T(`shield-off`,[[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71`,key:`1jlk70`}],[`path`,{d:`M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264`,key:`18rp1v`}]]),fe={class:`space-y-8`},pe={class:`space-y-3`},me={class:`flex items-start justify-between gap-4 flex-wrap`},he={class:`flex items-center gap-2`},ge={class:`flex-1 min-w-0 space-y-1`},_e={class:`leading-snug`},ve={key:0,class:`font-mono text-xs leading-snug break-words opacity-90`},ye={key:1,class:`leading-snug opacity-80`},be={key:0,class:`text-foreground-muted hidden sm:inline shrink-0`},xe={class:`group`},Se={class:`policy-meta mt-2`},Ce={class:`policy-chip`},we={class:`policy-chip-v`},Te={class:`policy-chip`},Ee={class:`policy-chip-v`},De={class:`policy-chip`},Oe={class:`policy-chip-v`},ke={key:0,class:`policy-chip policy-chip-pending`},Ae={key:1,class:`policy-chip`},je={class:`policy-chip-v`},Me={key:2,class:`policy-chip`},Ne={class:`policy-chip-v`},Pe={class:`dns-card`},Fe={class:`dns-row`},Ie={class:`dns-current`},Le={key:0,class:`dns-chips`},Re={class:`font-mono`},ze=[`aria-label`,`onClick`],Be={key:1,class:`dns-defaults`},Ve={class:`font-mono`},He={class:`dns-form`},Ue={class:`dns-row`},We={class:`dns-row-label`},Ge={class:`dns-row-meta`},Ke={key:0,class:`dns-records`},qe={class:`font-mono text-white text-xs flex-1 truncate`},Je={class:`font-mono text-foreground text-xs flex-1 truncate`},Ye=[`aria-label`,`onClick`],Xe={key:1,class:`text-xs text-foreground-muted italic px-1`},Ze={class:`dns-form`},Qe={class:`dns-savebar`},$e={key:0,class:`unenforced-note`},et={class:`min-w-0`},tt={class:`rule-filterbar`},nt=[`onClick`],rt={class:`rule-filter-count`},it={key:1,class:`empty-card`},at={class:`text-sm text-white`},ot={class:`text-xs text-foreground-muted mt-1 max-w-sm`},st={key:2,class:`rule-grid`},ct={class:`space-y-4`},lt={class:`grid grid-cols-2 gap-2`},ut=[`onClick`],dt={class:`text-xs text-foreground-muted mt-1.5 leading-snug`},ft={key:0,class:`text-xs text-danger-fg leading-snug`},O=`Wildcard patterns are not enforceable: the egress policy matches IPs and CIDRs, not DNS names. Block a CIDR or an exact hostname instead.`,k={__name:`Firewall`,setup(T){let k=ae(),A=n([]),pt=()=>({ipv4:[],ipv6:[],hostname_map:{},last_error:``,backend:`nstun`,enforced:!1,policy_generation:``,policy_rule_counts:{v4:0,v6:0,allow:0,reject:0},policy_stale:!1,pending_recycle:!1,last_compile_error:``,last_success_at:``,control_plane_allow:{addrs:[],port:0},unenforced_rules:[]}),j=n(pt()),M=n(null),N=n(!1),P=n(!1),F=n(!1),I=n({rule_type:`cidr`,value:``,label:``}),L=n({servers:[],search:``,records:[],defaults:[]}),R=n({servers:[],search:``,records:[]}),z=n(``),B=n(``),V=n(``),H=n(!1),mt=_(()=>JSON.stringify({s:L.value.servers||[],q:L.value.search||``,r:(L.value.records||[]).map(e=>`${e.host}=${e.ip}`).sort()})!==JSON.stringify({s:R.value.servers||[],q:R.value.search||``,r:(R.value.records||[]).map(e=>`${e.host}=${e.ip}`).sort()})),ht=_(()=>{let e=[];return e.push(L.value.servers.length?`${L.value.servers.length} resolver${L.value.servers.length===1?``:`s`}`:`defaults (${(L.value.defaults||[]).join(`, `)||`none`})`),L.value.records.length&&e.push(`${L.value.records.length} override${L.value.records.length===1?``:`s`}`),e.join(` · `)}),gt=async()=>{try{let e=await x.get(`/firewall/dns`);L.value={servers:e.data.servers||[],search:e.data.search||``,records:e.data.records||[],defaults:e.data.defaults||[]},R.value={servers:[...L.value.servers],search:L.value.search,records:L.value.records.map(e=>({...e}))}}catch(e){console.error(`loadDNS failed`,e)}},U=()=>{let e=z.value.trim();if(e){if(!(/^[0-9.]+$/.test(e)||e.includes(`:`))){k.notify({title:`Invalid IP`,message:`"${e}" doesn't look like an IPv4 or IPv6 address.`});return}if(L.value.servers.includes(e)){z.value=``;return}L.value.servers=[...L.value.servers,e],z.value=``}},_t=e=>{L.value.servers=L.value.servers.filter((t,n)=>n!==e)},W=()=>{let e=B.value.trim(),t=V.value.trim();if(!e||!t)return;let n=/^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$/.test(e),r=/^[0-9.]+$/.test(t)||t.includes(`:`);if(!n){k.notify({title:`Invalid hostname`,message:`"${e}" is not a valid hostname.`});return}if(!r){k.notify({title:`Invalid IP`,message:`"${t}" is not a literal IPv4 or IPv6 address.`});return}if((L.value.records||[]).some(t=>t.host===e)){k.notify({title:`Duplicate host`,message:`"${e}" already has an override.`});return}L.value.records=[...L.value.records||[],{host:e,ip:t}],B.value=``,V.value=``},vt=e=>{L.value.records=L.value.records.filter((t,n)=>n!==e)},yt=()=>{L.value.servers=[],L.value.search=``,L.value.records=[]},bt=async()=>{H.value=!0;try{let e=await x.put(`/firewall/dns`,{servers:L.value.servers,search:L.value.search||``,records:L.value.records||[]});L.value={servers:e.data.servers||[],search:e.data.search||``,records:e.data.records||[],defaults:e.data.defaults||L.value.defaults},R.value={servers:[...L.value.servers],search:L.value.search,records:L.value.records.map(e=>({...e}))}}catch(e){k.notify({title:`Save failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{H.value=!1}},xt=_(()=>A.value.filter(e=>e.kind===`custom`)),St=_(()=>{let e=new Map;for(let t of j.value.unenforced_rules||[])e.set(t.id,t.reason);return e}),Ct=e=>St.value.get(e.id)||(e.rule_type===`wildcard`?O:``),G=e=>Ct(e)!==``,K=_(()=>{let e=new Map;for(let t of j.value.unenforced_rules||[])e.set(t.id,{id:t.id,value:t.value,reason:t.reason});for(let t of A.value)t.rule_type===`wildcard`&&!e.has(t.id)&&e.set(t.id,{id:t.id,value:t.value,reason:O});return[...e.values()]}),wt={"169.254.0.0/16":{name:`Cloud metadata service`,why:`Blocks the special address AWS, Azure, and GCP use to expose VM credentials and instance settings. Leaving this open is a common credential-leak path.`},"fd00:ec2::254/128":{name:`Cloud metadata (IPv6)`,why:`Same as above, but the IPv6 path GCP uses. Recommended on.`},"10.0.0.0/8":{name:`Private network, 10.x`,why:`Standard internal-network range. Turn on if your functions should not reach internal services on your LAN.`},"172.16.0.0/12":{name:`Private network, 172.16.x`,why:`Another internal-network range (often used by Docker default bridge). Turn on for stricter isolation.`},"192.168.0.0/16":{name:`Private network, 192.168.x`,why:`Common home/office network range. Turn on if functions should not reach your local LAN.`},"100.64.0.0/10":{name:`CGNAT / Tailscale`,why:`Used by Tailscale and large ISPs. Turn on to keep functions out of your tailnet.`}},q=e=>e.kind===`custom`?e.label||e.value:wt[e.value]?.name||e.label||e.value,Tt=e=>e.kind===`custom`?``:wt[e.value]?.why||``,J=n(`enforced`),Et=_(()=>{let e=[{id:`all`,label:`All`,count:A.value.length},{id:`enforced`,label:`Enforced`,count:Y.value},{id:`off`,label:`Off`,count:X.value}];return Z.value.length&&e.push({id:`unenforced`,label:`Not enforced`,count:Z.value.length}),e.push({id:`yours`,label:`Yours`,count:xt.value.length}),e}),Dt=_(()=>{let e={default:0,suggested:1,custom:2};return[...A.value.filter(e=>J.value===`enforced`?e.enabled&&!G(e):J.value===`off`?!e.enabled:J.value===`unenforced`?G(e):J.value!==`yours`||e.kind===`custom`)].sort((t,n)=>{let r=G(t);return r===G(n)?t.enabled===n.enabled?e[t.kind]===e[n.kind]?q(t).localeCompare(q(n)):e[t.kind]-e[n.kind]:t.enabled?-1:1:r?1:-1})}),Y=_(()=>A.value.filter(e=>e.enabled&&!G(e)).length),X=_(()=>A.value.filter(e=>!e.enabled).length),Z=_(()=>A.value.filter(e=>G(e))),Ot=_(()=>{if(!A.value.length)return`Nothing in the blocklist yet.`;let e=Y.value,t=X.value,n=[j.value.enforced?`${e} block${e===1?``:`s`} enforced`:`${e} block${e===1?``:`s`} staged, none enforced`,`${t} available to turn on`,`${xt.value.length} you added`];return Z.value.length&&n.push(`${Z.value.length} not enforceable`),n.join(` · `)}),kt=[{value:`cidr`,label:`IP / Range`,icon:le},{value:`hostname`,label:`Hostname`,icon:ee}],At=_(()=>I.value.rule_type===`hostname`?`api.internal.corp`:`192.168.1.0/24`),jt=_(()=>I.value.rule_type===`hostname`?`A specific website or service name. We resolve it to IPs and block those, re-resolving on every refresh.`:`A single IP (e.g. 1.2.3.4) or a CIDR range (e.g. 10.0.0.0/8) to block all addresses inside it.`),Mt=_(()=>I.value.value.includes(`*`)),Q=_(()=>j.value.enforced&&j.value.policy_stale?`stale`:j.value.enforced?j.value.last_error?`degraded`:`ok`:`unenforced`),Nt=_(()=>{switch(Q.value){case`unenforced`:return`border-danger-ring bg-danger-tint text-danger-fg`;case`stale`:case`degraded`:return`border-warning-ring bg-warning-tint text-warning-fg`;default:return`border-success-ring bg-success-tint text-foreground-muted`}}),Pt=_(()=>Q.value===`ok`?ne:ie),Ft=_(()=>{switch(Q.value){case`unenforced`:return`No egress policy is compiled, so nothing below is in force. Orva fails closed: functions with outbound network enabled cannot start until a policy compiles.`;case`stale`:return`Enforcing the last known-good policy (generation ${j.value.policy_generation}). The newest recompile failed, so recent changes are not live yet.`;case`degraded`:return`The policy is in force, but the last refresh reported a problem.`;default:return`Enforced per sandbox by nsjail NSTUN, generation ${j.value.policy_generation}. Applies to every function with outbound network enabled.`}}),It=_(()=>{switch(Q.value){case`unenforced`:return`Hit Apply now to recompile. There is nothing to install: if invocations fail with a sandbox error instead, nsjail needs /dev/net/tun (Docker: --device /dev/net/tun).`;case`stale`:case`degraded`:return`Fix the reported rule or resolver, then hit Apply now to recompile.`;default:return``}}),Lt=_(()=>{let e=j.value.policy_rule_counts||{};return`${e.v4??0} v4 · ${e.v6??0} v6 · ${e.reject??0} reject · ${e.allow??0} allow`}),Rt=_(()=>{let e=j.value.control_plane_allow||{},t=e.addrs||[];return t.length?`${t.join(`, `)}${e.port?`:${e.port}`:``}`:``}),zt=_(()=>{let e=j.value.last_success_at;if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString()}),$=async()=>{let e=await x.get(`/firewall/rules`);A.value=e.data.rules||[],j.value={...pt(),...e.data.status||{}}},Bt=async e=>{M.value=e.id;try{await x.put(`/firewall/rules/${e.id}`,{enabled:!e.enabled}),await $()}catch(e){k.notify({title:`Toggle failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{M.value=null}},Vt=async e=>{if(await k.ask({title:`Delete custom rule?`,message:`"${e.value}" will be removed from the blocklist.`,confirmLabel:`Delete`,danger:!0}))try{await x.delete(`/firewall/rules/${e.id}`),await $()}catch(e){k.notify({title:`Delete failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}},Ht=async()=>{if(I.value.value.trim()){P.value=!0;try{await x.post(`/firewall/rules`,{rule_type:I.value.rule_type,value:I.value.value.trim(),label:I.value.label.trim()}),N.value=!1,I.value={rule_type:`cidr`,value:``,label:``},await $()}catch(e){k.notify({title:`Failed to add rule`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{P.value=!1}}},Ut=async()=>{F.value=!0;try{let e=await x.post(`/firewall/resolve`);e.data.error&&k.notify({title:`Resolve had errors`,message:e.data.error,danger:!0}),await $()}catch(e){k.notify({title:`Resolve failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{F.value=!1}},Wt=async()=>{await Promise.all([$(),gt()])};o(Wt),a(Wt);let Gt=c({name:`PanelSection`,props:{title:{type:String,default:``},subtitle:{type:String,default:``}},setup(e,{slots:t}){return()=>y(`section`,{class:`space-y-3`},[y(`div`,null,[y(`h2`,{class:`text-sm font-semibold text-white tracking-tight`},e.title),e.subtitle?y(`p`,{class:`text-xs text-foreground-muted mt-0.5`},e.subtitle):null]),y(`div`,null,t.default?.())])}}),Kt={default:{label:`Recommended`,cls:`kind-recommended`},suggested:{label:`Optional`,cls:`kind-optional`},custom:{label:`Yours`,cls:`kind-yours`}},qt=c({name:`RuleCard`,props:{rule:{type:Object,required:!0},status:{type:Object,required:!0},unenforcedReason:{type:String,default:``},busy:{type:Boolean,default:!1},readonlyEdit:{type:Boolean,default:!1}},emits:[`toggle`,`delete`],setup(e,{emit:t}){let n=_(()=>{switch(e.rule.rule_type){case`hostname`:return ee;case`wildcard`:return ce;default:return le}}),r=_(()=>e.rule.rule_type===`cidr`?[e.rule.value]:e.status.hostname_map?.[e.rule.value]||[]),i=_(()=>q(e.rule)),a=_(()=>Tt(e.rule)),o=_(()=>Kt[e.rule.kind]||Kt.custom),s=_(()=>e.unenforcedReason?`unenforced`:e.rule.enabled?e.status.enforced?`on`:`pending`:`off`),c=_(()=>s.value===`unenforced`&&!e.rule.enabled),l=_(()=>c.value?`Cannot be enforced. See the reason on this card.`:e.rule.enabled?`Click to allow`:`Click to block`);return()=>y(`div`,{class:[`rule-card`,`is-${s.value}`]},[y(`div`,{class:`rule-card-row`},[y(`div`,{class:`rule-card-titlewrap`},[y(`div`,{class:`rule-card-title`},i.value),y(`div`,{class:`rule-card-pills`},[y(`span`,{class:[`rule-kind-pill`,o.value.cls]},o.value.label),s.value===`unenforced`?y(`span`,{class:`rule-kind-pill kind-inert`},`Not enforced`):null,s.value===`pending`?y(`span`,{class:`rule-kind-pill kind-inert`},`Not in force`):null])]),y(`button`,{class:[`rule-toggle`,s.value===`on`?`on`:s.value===`off`?`off`:[`inert`,e.rule.enabled?`is-set`:``],e.busy?`busy`:``,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`],disabled:e.busy||c.value,title:l.value,onClick:()=>t(`toggle`)},[y(`span`,{class:`rule-toggle-knob`})])]),e.unenforcedReason?y(`p`,{class:`rule-card-warn`},e.unenforcedReason):null,a.value?y(`p`,{class:`rule-card-why`},a.value):null,y(`div`,{class:`rule-card-foot`},[y(n.value,{class:`rule-card-type-icon`}),y(`code`,{class:`rule-card-value`},e.rule.value),r.value.length&&e.rule.rule_type!==`cidr`?y(`span`,{class:`rule-card-resolved`},`→ ${r.value.slice(0,2).join(`, `)}${r.value.length>2?` +${r.value.length-2}`:``}`):null]),e.readonlyEdit?null:y(`button`,{class:`rule-card-delete`,title:`Remove this block`,onClick:()=>t(`delete`)},[y(re,{class:`w-3.5 h-3.5`})])])}});return(n,a)=>(e(),u(`div`,fe,[l(`header`,pe,[l(`div`,me,[a[12]||=l(`div`,{class:`max-w-2xl`},[l(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Egress `),l(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Control outbound destinations and DNS for function sandboxes. `)],-1),l(`div`,he,[f(w,{variant:`secondary`,size:`sm`,loading:F.value,onClick:Ut},{default:t(()=>[f(s(te),{class:`w-4 h-4`}),a[10]||=h(` Apply now `,-1)]),_:1},8,[`loading`]),f(w,{size:`sm`,onClick:a[0]||=e=>N.value=!0},{default:t(()=>[f(s(C),{class:`w-4 h-4`}),a[11]||=h(` Add block `,-1)]),_:1})])]),l(`div`,{class:d([`flex items-start gap-3 text-xs px-3 py-2 rounded-md border`,Nt.value])},[(e(),m(i(Pt.value),{class:`w-4 h-4 shrink-0 mt-0.5`})),l(`div`,ge,[l(`p`,_e,b(Ft.value),1),j.value.last_error?(e(),u(`p`,ve,b(j.value.last_error),1)):v(``,!0),It.value?(e(),u(`p`,ye,b(It.value),1)):v(``,!0)]),j.value.enforced?(e(),u(`span`,be,b(Y.value)+` enforced · `+b(X.value)+` off `,1)):v(``,!0)],2),l(`details`,xe,[a[19]||=l(`summary`,{class:`cursor-pointer text-xs text-foreground-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},` Policy details `,-1),l(`div`,Se,[l(`span`,Ce,[a[13]||=l(`span`,{class:`policy-chip-k`},`Backend`,-1),l(`span`,we,b(j.value.backend||`nstun`),1)]),l(`span`,Te,[a[14]||=l(`span`,{class:`policy-chip-k`},`Generation`,-1),l(`span`,Ee,b(j.value.policy_generation||`none`),1)]),l(`span`,De,[a[15]||=l(`span`,{class:`policy-chip-k`},`Compiled rules`,-1),l(`span`,Oe,b(Lt.value),1)]),j.value.pending_recycle?(e(),u(`span`,ke,[...a[16]||=[l(`span`,{class:`policy-chip-k`},`Rollout`,-1),l(`span`,{class:`policy-chip-v`},`warm workers still on the previous generation`,-1)]])):v(``,!0),Rt.value?(e(),u(`span`,Ae,[a[17]||=l(`span`,{class:`policy-chip-k`},`SDK carve-out`,-1),l(`span`,je,b(Rt.value),1)])):v(``,!0),zt.value?(e(),u(`span`,Me,[a[18]||=l(`span`,{class:`policy-chip-k`},`Applied`,-1),l(`span`,Ne,b(zt.value),1)])):v(``,!0)])])]),f(s(Gt),{title:`DNS`,subtitle:ht.value},{default:t(()=>[l(`div`,Pe,[l(`div`,Fe,[a[22]||=l(`div`,{class:`dns-row-label`},` Upstream resolvers `,-1),l(`div`,Ie,[L.value.servers.length?(e(),u(`div`,Le,[(e(!0),u(g,null,p(L.value.servers,(t,n)=>(e(),u(`span`,{key:t+n,class:`dns-chip`},[f(s(D),{class:`w-3 h-3 opacity-60`}),l(`span`,Re,b(t),1),l(`button`,{class:`dns-chip-x`,title:`Remove`,"aria-label":`Remove resolver ${t}`,onClick:e=>_t(n)},` × `,8,ze)]))),128))])):(e(),u(`div`,Be,[a[20]||=l(`span`,{class:`text-foreground-muted text-xs`},`Defaults:`,-1),(e(!0),u(g,null,p(L.value.defaults,t=>(e(),u(`span`,{key:t,class:`dns-chip muted`},[f(s(D),{class:`w-3 h-3 opacity-60`}),l(`span`,Ve,b(t),1)]))),128))]))]),l(`div`,He,[r(l(`input`,{"onUpdate:modelValue":a[1]||=e=>z.value=e,"aria-label":`Resolver address`,placeholder:`1.1.1.1`,class:`dns-input`,onKeydown:E(U,[`enter`])},null,544),[[S,z.value]]),f(w,{variant:`secondary`,size:`sm`,disabled:!z.value.trim(),onClick:U},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[21]||=h(` Add resolver `,-1)]),_:1},8,[`disabled`]),r(l(`input`,{"onUpdate:modelValue":a[2]||=e=>L.value.search=e,"aria-label":`DNS search domain`,placeholder:`search domain`,class:`dns-input narrow`},null,512),[[S,L.value.search]])])]),l(`div`,Ue,[l(`div`,We,[a[23]||=h(` Host overrides `,-1),l(`span`,Ge,b(L.value.records.length)+` record`+b(L.value.records.length===1?``:`s`),1)]),L.value.records.length?(e(),u(`div`,Ke,[(e(!0),u(g,null,p(L.value.records,(t,n)=>(e(),u(`div`,{key:t.host+n,class:`dns-record`},[l(`span`,qe,b(t.host),1),a[24]||=l(`span`,{class:`text-foreground-muted text-xs`},`→`,-1),l(`span`,Je,b(t.ip),1),l(`button`,{class:`dns-chip-x`,title:`Remove`,"aria-label":`Remove host override ${t.host}`,onClick:e=>vt(n)},` × `,8,Ye)]))),128))])):(e(),u(`div`,Xe,` No overrides. Anything resolves through the upstream resolvers above. `)),l(`div`,Ze,[r(l(`input`,{"onUpdate:modelValue":a[3]||=e=>B.value=e,"aria-label":`Override hostname`,placeholder:`api.internal`,class:`dns-input host`,onKeydown:E(W,[`enter`])},null,544),[[S,B.value]]),a[26]||=l(`span`,{class:`text-foreground-muted text-xs`},`→`,-1),r(l(`input`,{"onUpdate:modelValue":a[4]||=e=>V.value=e,"aria-label":`Override IP address`,placeholder:`10.0.5.10`,class:`dns-input`,onKeydown:E(W,[`enter`])},null,544),[[S,V.value]]),f(w,{variant:`secondary`,size:`sm`,disabled:!(B.value.trim()&&V.value.trim()),onClick:W},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[25]||=h(` Add record `,-1)]),_:1},8,[`disabled`])])]),l(`div`,Qe,[a[28]||=l(`span`,{class:`dns-hint`},` Overrides bypass upstream DNS. Existing warm workers update after recycle. `,-1),L.value.servers.length||L.value.search||L.value.records.length?(e(),u(`button`,{key:0,class:`text-xs text-foreground-muted hover:text-white px-2 py-1 transition-colors`,onClick:yt},` Reset `)):v(``,!0),f(w,{size:`sm`,loading:H.value,disabled:!mt.value,onClick:bt},{default:t(()=>[...a[27]||=[h(` Save `,-1)]]),_:1},8,[`loading`,`disabled`])])])]),_:1},8,[`subtitle`]),f(s(Gt),{title:`Blocklist`,subtitle:Ot.value},{default:t(()=>[K.value.length?(e(),u(`div`,$e,[f(s(ie),{class:`w-3.5 h-3.5 shrink-0 mt-0.5`}),l(`div`,et,[l(`p`,null,b(K.value.length===1?`One stored rule is not part of the compiled policy and blocks nothing:`:`${K.value.length} stored rules are not part of the compiled policy and block nothing:`),1),l(`ul`,null,[(e(!0),u(g,null,p(K.value,t=>(e(),u(`li`,{key:t.id},[l(`code`,null,b(t.value),1),h(`: `+b(t.reason),1)]))),128))])])])):v(``,!0),l(`div`,tt,[(e(!0),u(g,null,p(Et.value,t=>(e(),u(`button`,{key:t.id,class:d([`rule-filter`,{active:J.value===t.id}]),onClick:e=>J.value=t.id},[h(b(t.label)+` `,1),l(`span`,rt,b(t.count),1)],10,nt))),128))]),Dt.value.length?(e(),u(`div`,st,[(e(!0),u(g,null,p(Dt.value,t=>(e(),m(s(qt),{key:t.id,rule:t,status:j.value,"unenforced-reason":Ct(t),busy:M.value===t.id,"readonly-edit":t.kind!==`custom`,onToggle:e=>Bt(t),onDelete:e=>Vt(t)},null,8,[`rule`,`status`,`unenforced-reason`,`busy`,`readonly-edit`,`onToggle`,`onDelete`]))),128))])):(e(),u(`div`,it,[f(s(de),{class:`w-5 h-5 mb-2 text-foreground-muted/60`}),l(`p`,at,b(J.value===`yours`?`No custom blocks yet`:`Nothing matches this filter`),1),l(`p`,ot,b(J.value===`yours`?`Add an IP, network, or hostname.`:`Try another filter.`),1),J.value===`yours`?(e(),m(w,{key:0,class:`mt-4`,size:`sm`,variant:`secondary`,onClick:a[5]||=e=>N.value=!0},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[29]||=h(` Add block `,-1)]),_:1})):v(``,!0)]))]),_:1},8,[`subtitle`]),f(oe,{modelValue:N.value,"onUpdate:modelValue":a[9]||=e=>N.value=e,title:`Add block`,icon:s(ue),size:`md`},{footer:t(()=>[f(w,{variant:`secondary`,onClick:a[8]||=e=>N.value=!1},{default:t(()=>[...a[33]||=[h(` Cancel `,-1)]]),_:1}),f(w,{loading:P.value,disabled:!I.value.value.trim()||Mt.value,onClick:Ht},{default:t(()=>[f(s(C),{class:`w-4 h-4`}),a[34]||=h(` Block it `,-1)]),_:1},8,[`loading`,`disabled`])]),default:t(()=>[l(`div`,ct,[a[31]||=l(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Block an IP, network, or hostname. Wildcards are not supported. `,-1),l(`div`,null,[a[30]||=l(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` What is it? `,-1),l(`div`,lt,[(e(),u(g,null,p(kt,t=>l(`button`,{key:t.value,class:d([`px-2 py-2 rounded border text-xs font-medium transition-colors flex flex-col items-center gap-1`,I.value.rule_type===t.value?`bg-white text-black border-white`:`bg-surface-hover text-foreground-muted border-border hover:border-foreground-muted`]),onClick:e=>I.value.rule_type=t.value},[(e(),m(i(t.icon),{class:`w-3.5 h-3.5`})),h(` `+b(t.label),1)],10,ut)),64))]),l(`p`,dt,b(jt.value),1)]),f(se,{modelValue:I.value.value,"onUpdate:modelValue":a[6]||=e=>I.value.value=e,label:I.value.rule_type===`hostname`?`Hostname`:`IP or network`,placeholder:At.value},null,8,[`modelValue`,`label`,`placeholder`]),Mt.value?(e(),u(`p`,ft,b(O))):v(``,!0),f(se,{modelValue:I.value.label,"onUpdate:modelValue":a[7]||=e=>I.value.label=e,label:`Why? (optional)`,placeholder:`e.g. our staging Postgres`},null,8,[`modelValue`]),a[32]||=l(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Applies within seconds and recycles warm functions. `,-1)])]),_:1},8,[`modelValue`,`icon`])]))}};export{k as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,M as i,S as a,T as o,Z as s,_ as c,c as l,d as u,gt as d,h as f,k as p,l as m,m as h,r as g,s as _,u as v,v as y,vt as b}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ee}from"./globe-DJC2u-h_.js";import{t as te}from"./refresh-cw-CEfUzOcv.js";import{t as ne}from"./shield-check-CowI6J3x.js";import{t as re}from"./trash-2-Cz9PSE2q.js";import{t as x}from"./client-BF51V3uE.js";import{Lt as S,St as C,_t as w,bt as ie,gt as ae,jt as T,zt as E}from"./index-pE9wnfTb.js";import{t as oe}from"./Modal-C1IBLm0r.js";import{t as se}from"./Input-DQ-tWGkn.js";var ce=T(`asterisk`,[[`path`,{d:`M12 6v12`,key:`1vza4d`}],[`path`,{d:`M17.196 9 6.804 15`,key:`1ah31z`}],[`path`,{d:`m6.804 9 10.392 6`,key:`1b6pxd`}]]),D=T(`earth`,[[`path`,{d:`M21.54 15H17a2 2 0 0 0-2 2v4.54`,key:`1djwo0`}],[`path`,{d:`M7 3.34V5a3 3 0 0 0 3 3a2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17`,key:`1tzkfa`}],[`path`,{d:`M11 21.95V18a2 2 0 0 0-2-2a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05`,key:`14pb5j`}],[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),le=T(`hash`,[[`line`,{x1:`4`,x2:`20`,y1:`9`,y2:`9`,key:`4lhtct`}],[`line`,{x1:`4`,x2:`20`,y1:`15`,y2:`15`,key:`vyu0kd`}],[`line`,{x1:`10`,x2:`8`,y1:`3`,y2:`21`,key:`1ggp8o`}],[`line`,{x1:`16`,x2:`14`,y1:`3`,y2:`21`,key:`weycgp`}]]),ue=T(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]),de=T(`shield-off`,[[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71`,key:`1jlk70`}],[`path`,{d:`M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264`,key:`18rp1v`}]]),fe={class:`space-y-8`},pe={class:`space-y-3`},me={class:`flex items-start justify-between gap-4 flex-wrap`},he={class:`flex items-center gap-2`},ge={class:`flex-1 min-w-0 space-y-1`},_e={class:`leading-snug`},ve={key:0,class:`font-mono text-xs leading-snug break-words opacity-90`},ye={key:1,class:`leading-snug opacity-80`},be={key:0,class:`text-foreground-muted hidden sm:inline shrink-0`},xe={class:`group`},Se={class:`policy-meta mt-2`},Ce={class:`policy-chip`},we={class:`policy-chip-v`},Te={class:`policy-chip`},Ee={class:`policy-chip-v`},De={class:`policy-chip`},Oe={class:`policy-chip-v`},ke={key:0,class:`policy-chip policy-chip-pending`},Ae={key:1,class:`policy-chip`},je={class:`policy-chip-v`},Me={key:2,class:`policy-chip`},Ne={class:`policy-chip-v`},Pe={class:`dns-card`},Fe={class:`dns-row`},Ie={class:`dns-current`},Le={key:0,class:`dns-chips`},Re={class:`font-mono`},ze=[`aria-label`,`onClick`],Be={key:1,class:`dns-defaults`},Ve={class:`font-mono`},He={class:`dns-form`},Ue={class:`dns-row`},We={class:`dns-row-label`},Ge={class:`dns-row-meta`},Ke={key:0,class:`dns-records`},qe={class:`font-mono text-white text-xs flex-1 truncate`},Je={class:`font-mono text-foreground text-xs flex-1 truncate`},Ye=[`aria-label`,`onClick`],Xe={key:1,class:`text-xs text-foreground-muted italic px-1`},Ze={class:`dns-form`},Qe={class:`dns-savebar`},$e={key:0,class:`unenforced-note`},et={class:`min-w-0`},tt={class:`rule-filterbar`},nt=[`onClick`],rt={class:`rule-filter-count`},it={key:1,class:`empty-card`},at={class:`text-sm text-white`},ot={class:`text-xs text-foreground-muted mt-1 max-w-sm`},st={key:2,class:`rule-grid`},ct={class:`space-y-4`},lt={class:`grid grid-cols-2 gap-2`},ut=[`onClick`],dt={class:`text-xs text-foreground-muted mt-1.5 leading-snug`},ft={key:0,class:`text-xs text-danger-fg leading-snug`},O=`Wildcard patterns are not enforceable: the egress policy matches IPs and CIDRs, not DNS names. Block a CIDR or an exact hostname instead.`,k={__name:`Firewall`,setup(T){let k=ae(),A=n([]),pt=()=>({ipv4:[],ipv6:[],hostname_map:{},last_error:``,backend:`nstun`,enforced:!1,policy_generation:``,policy_rule_counts:{v4:0,v6:0,allow:0,reject:0},policy_stale:!1,pending_recycle:!1,last_compile_error:``,last_success_at:``,control_plane_allow:{addrs:[],port:0},unenforced_rules:[]}),j=n(pt()),M=n(null),N=n(!1),P=n(!1),F=n(!1),I=n({rule_type:`cidr`,value:``,label:``}),L=n({servers:[],search:``,records:[],defaults:[]}),R=n({servers:[],search:``,records:[]}),z=n(``),B=n(``),V=n(``),H=n(!1),mt=_(()=>JSON.stringify({s:L.value.servers||[],q:L.value.search||``,r:(L.value.records||[]).map(e=>`${e.host}=${e.ip}`).sort()})!==JSON.stringify({s:R.value.servers||[],q:R.value.search||``,r:(R.value.records||[]).map(e=>`${e.host}=${e.ip}`).sort()})),ht=_(()=>{let e=[];return e.push(L.value.servers.length?`${L.value.servers.length} resolver${L.value.servers.length===1?``:`s`}`:`defaults (${(L.value.defaults||[]).join(`, `)||`none`})`),L.value.records.length&&e.push(`${L.value.records.length} override${L.value.records.length===1?``:`s`}`),e.join(` · `)}),gt=async()=>{try{let e=await x.get(`/firewall/dns`);L.value={servers:e.data.servers||[],search:e.data.search||``,records:e.data.records||[],defaults:e.data.defaults||[]},R.value={servers:[...L.value.servers],search:L.value.search,records:L.value.records.map(e=>({...e}))}}catch(e){console.error(`loadDNS failed`,e)}},U=()=>{let e=z.value.trim();if(e){if(!(/^[0-9.]+$/.test(e)||e.includes(`:`))){k.notify({title:`Invalid IP`,message:`"${e}" doesn't look like an IPv4 or IPv6 address.`});return}if(L.value.servers.includes(e)){z.value=``;return}L.value.servers=[...L.value.servers,e],z.value=``}},_t=e=>{L.value.servers=L.value.servers.filter((t,n)=>n!==e)},W=()=>{let e=B.value.trim(),t=V.value.trim();if(!e||!t)return;let n=/^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$/.test(e),r=/^[0-9.]+$/.test(t)||t.includes(`:`);if(!n){k.notify({title:`Invalid hostname`,message:`"${e}" is not a valid hostname.`});return}if(!r){k.notify({title:`Invalid IP`,message:`"${t}" is not a literal IPv4 or IPv6 address.`});return}if((L.value.records||[]).some(t=>t.host===e)){k.notify({title:`Duplicate host`,message:`"${e}" already has an override.`});return}L.value.records=[...L.value.records||[],{host:e,ip:t}],B.value=``,V.value=``},vt=e=>{L.value.records=L.value.records.filter((t,n)=>n!==e)},yt=()=>{L.value.servers=[],L.value.search=``,L.value.records=[]},bt=async()=>{H.value=!0;try{let e=await x.put(`/firewall/dns`,{servers:L.value.servers,search:L.value.search||``,records:L.value.records||[]});L.value={servers:e.data.servers||[],search:e.data.search||``,records:e.data.records||[],defaults:e.data.defaults||L.value.defaults},R.value={servers:[...L.value.servers],search:L.value.search,records:L.value.records.map(e=>({...e}))}}catch(e){k.notify({title:`Save failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{H.value=!1}},xt=_(()=>A.value.filter(e=>e.kind===`custom`)),St=_(()=>{let e=new Map;for(let t of j.value.unenforced_rules||[])e.set(t.id,t.reason);return e}),Ct=e=>St.value.get(e.id)||(e.rule_type===`wildcard`?O:``),G=e=>Ct(e)!==``,K=_(()=>{let e=new Map;for(let t of j.value.unenforced_rules||[])e.set(t.id,{id:t.id,value:t.value,reason:t.reason});for(let t of A.value)t.rule_type===`wildcard`&&!e.has(t.id)&&e.set(t.id,{id:t.id,value:t.value,reason:O});return[...e.values()]}),wt={"169.254.0.0/16":{name:`Cloud metadata service`,why:`Blocks the special address AWS, Azure, and GCP use to expose VM credentials and instance settings. Leaving this open is a common credential-leak path.`},"fd00:ec2::254/128":{name:`Cloud metadata (IPv6)`,why:`Same as above, but the IPv6 path GCP uses. Recommended on.`},"10.0.0.0/8":{name:`Private network, 10.x`,why:`Standard internal-network range. Turn on if your functions should not reach internal services on your LAN.`},"172.16.0.0/12":{name:`Private network, 172.16.x`,why:`Another internal-network range (often used by Docker default bridge). Turn on for stricter isolation.`},"192.168.0.0/16":{name:`Private network, 192.168.x`,why:`Common home/office network range. Turn on if functions should not reach your local LAN.`},"100.64.0.0/10":{name:`CGNAT / Tailscale`,why:`Used by Tailscale and large ISPs. Turn on to keep functions out of your tailnet.`}},q=e=>e.kind===`custom`?e.label||e.value:wt[e.value]?.name||e.label||e.value,Tt=e=>e.kind===`custom`?``:wt[e.value]?.why||``,J=n(`enforced`),Et=_(()=>{let e=[{id:`all`,label:`All`,count:A.value.length},{id:`enforced`,label:`Enforced`,count:Y.value},{id:`off`,label:`Off`,count:X.value}];return Z.value.length&&e.push({id:`unenforced`,label:`Not enforced`,count:Z.value.length}),e.push({id:`yours`,label:`Yours`,count:xt.value.length}),e}),Dt=_(()=>{let e={default:0,suggested:1,custom:2};return[...A.value.filter(e=>J.value===`enforced`?e.enabled&&!G(e):J.value===`off`?!e.enabled:J.value===`unenforced`?G(e):J.value!==`yours`||e.kind===`custom`)].sort((t,n)=>{let r=G(t);return r===G(n)?t.enabled===n.enabled?e[t.kind]===e[n.kind]?q(t).localeCompare(q(n)):e[t.kind]-e[n.kind]:t.enabled?-1:1:r?1:-1})}),Y=_(()=>A.value.filter(e=>e.enabled&&!G(e)).length),X=_(()=>A.value.filter(e=>!e.enabled).length),Z=_(()=>A.value.filter(e=>G(e))),Ot=_(()=>{if(!A.value.length)return`Nothing in the blocklist yet.`;let e=Y.value,t=X.value,n=[j.value.enforced?`${e} block${e===1?``:`s`} enforced`:`${e} block${e===1?``:`s`} staged, none enforced`,`${t} available to turn on`,`${xt.value.length} you added`];return Z.value.length&&n.push(`${Z.value.length} not enforceable`),n.join(` · `)}),kt=[{value:`cidr`,label:`IP / Range`,icon:le},{value:`hostname`,label:`Hostname`,icon:ee}],At=_(()=>I.value.rule_type===`hostname`?`api.internal.corp`:`192.168.1.0/24`),jt=_(()=>I.value.rule_type===`hostname`?`A specific website or service name. We resolve it to IPs and block those, re-resolving on every refresh.`:`A single IP (e.g. 1.2.3.4) or a CIDR range (e.g. 10.0.0.0/8) to block all addresses inside it.`),Mt=_(()=>I.value.value.includes(`*`)),Q=_(()=>j.value.enforced&&j.value.policy_stale?`stale`:j.value.enforced?j.value.last_error?`degraded`:`ok`:`unenforced`),Nt=_(()=>{switch(Q.value){case`unenforced`:return`border-danger-ring bg-danger-tint text-danger-fg`;case`stale`:case`degraded`:return`border-warning-ring bg-warning-tint text-warning-fg`;default:return`border-success-ring bg-success-tint text-foreground-muted`}}),Pt=_(()=>Q.value===`ok`?ne:ie),Ft=_(()=>{switch(Q.value){case`unenforced`:return`No egress policy is compiled, so nothing below is in force. Orva fails closed: functions with outbound network enabled cannot start until a policy compiles.`;case`stale`:return`Enforcing the last known-good policy (generation ${j.value.policy_generation}). The newest recompile failed, so recent changes are not live yet.`;case`degraded`:return`The policy is in force, but the last refresh reported a problem.`;default:return`Enforced per sandbox by nsjail NSTUN, generation ${j.value.policy_generation}. Applies to every function with outbound network enabled.`}}),It=_(()=>{switch(Q.value){case`unenforced`:return`Hit Apply now to recompile. There is nothing to install: if invocations fail with a sandbox error instead, nsjail needs /dev/net/tun (Docker: --device /dev/net/tun).`;case`stale`:case`degraded`:return`Fix the reported rule or resolver, then hit Apply now to recompile.`;default:return``}}),Lt=_(()=>{let e=j.value.policy_rule_counts||{};return`${e.v4??0} v4 · ${e.v6??0} v6 · ${e.reject??0} reject · ${e.allow??0} allow`}),Rt=_(()=>{let e=j.value.control_plane_allow||{},t=e.addrs||[];return t.length?`${t.join(`, `)}${e.port?`:${e.port}`:``}`:``}),zt=_(()=>{let e=j.value.last_success_at;if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString()}),$=async()=>{let e=await x.get(`/firewall/rules`);A.value=e.data.rules||[],j.value={...pt(),...e.data.status||{}}},Bt=async e=>{M.value=e.id;try{await x.put(`/firewall/rules/${e.id}`,{enabled:!e.enabled}),await $()}catch(e){k.notify({title:`Toggle failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{M.value=null}},Vt=async e=>{if(await k.ask({title:`Delete custom rule?`,message:`"${e.value}" will be removed from the blocklist.`,confirmLabel:`Delete`,danger:!0}))try{await x.delete(`/firewall/rules/${e.id}`),await $()}catch(e){k.notify({title:`Delete failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}},Ht=async()=>{if(I.value.value.trim()){P.value=!0;try{await x.post(`/firewall/rules`,{rule_type:I.value.rule_type,value:I.value.value.trim(),label:I.value.label.trim()}),N.value=!1,I.value={rule_type:`cidr`,value:``,label:``},await $()}catch(e){k.notify({title:`Failed to add rule`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{P.value=!1}}},Ut=async()=>{F.value=!0;try{let e=await x.post(`/firewall/resolve`);e.data.error&&k.notify({title:`Resolve had errors`,message:e.data.error,danger:!0}),await $()}catch(e){k.notify({title:`Resolve failed`,message:e.response?.data?.error?.message||e.message,danger:!0})}finally{F.value=!1}},Wt=async()=>{await Promise.all([$(),gt()])};o(Wt),a(Wt);let Gt=c({name:`PanelSection`,props:{title:{type:String,default:``},subtitle:{type:String,default:``}},setup(e,{slots:t}){return()=>y(`section`,{class:`space-y-3`},[y(`div`,null,[y(`h2`,{class:`text-sm font-semibold text-white tracking-tight`},e.title),e.subtitle?y(`p`,{class:`text-xs text-foreground-muted mt-0.5`},e.subtitle):null]),y(`div`,null,t.default?.())])}}),Kt={default:{label:`Recommended`,cls:`kind-recommended`},suggested:{label:`Optional`,cls:`kind-optional`},custom:{label:`Yours`,cls:`kind-yours`}},qt=c({name:`RuleCard`,props:{rule:{type:Object,required:!0},status:{type:Object,required:!0},unenforcedReason:{type:String,default:``},busy:{type:Boolean,default:!1},readonlyEdit:{type:Boolean,default:!1}},emits:[`toggle`,`delete`],setup(e,{emit:t}){let n=_(()=>{switch(e.rule.rule_type){case`hostname`:return ee;case`wildcard`:return ce;default:return le}}),r=_(()=>e.rule.rule_type===`cidr`?[e.rule.value]:e.status.hostname_map?.[e.rule.value]||[]),i=_(()=>q(e.rule)),a=_(()=>Tt(e.rule)),o=_(()=>Kt[e.rule.kind]||Kt.custom),s=_(()=>e.unenforcedReason?`unenforced`:e.rule.enabled?e.status.enforced?`on`:`pending`:`off`),c=_(()=>s.value===`unenforced`&&!e.rule.enabled),l=_(()=>c.value?`Cannot be enforced. See the reason on this card.`:e.rule.enabled?`Click to allow`:`Click to block`);return()=>y(`div`,{class:[`rule-card`,`is-${s.value}`]},[y(`div`,{class:`rule-card-row`},[y(`div`,{class:`rule-card-titlewrap`},[y(`div`,{class:`rule-card-title`},i.value),y(`div`,{class:`rule-card-pills`},[y(`span`,{class:[`rule-kind-pill`,o.value.cls]},o.value.label),s.value===`unenforced`?y(`span`,{class:`rule-kind-pill kind-inert`},`Not enforced`):null,s.value===`pending`?y(`span`,{class:`rule-kind-pill kind-inert`},`Not in force`):null])]),y(`button`,{class:[`rule-toggle`,s.value===`on`?`on`:s.value===`off`?`off`:[`inert`,e.rule.enabled?`is-set`:``],e.busy?`busy`:``,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`],disabled:e.busy||c.value,title:l.value,onClick:()=>t(`toggle`)},[y(`span`,{class:`rule-toggle-knob`})])]),e.unenforcedReason?y(`p`,{class:`rule-card-warn`},e.unenforcedReason):null,a.value?y(`p`,{class:`rule-card-why`},a.value):null,y(`div`,{class:`rule-card-foot`},[y(n.value,{class:`rule-card-type-icon`}),y(`code`,{class:`rule-card-value`},e.rule.value),r.value.length&&e.rule.rule_type!==`cidr`?y(`span`,{class:`rule-card-resolved`},`→ ${r.value.slice(0,2).join(`, `)}${r.value.length>2?` +${r.value.length-2}`:``}`):null]),e.readonlyEdit?null:y(`button`,{class:`rule-card-delete`,title:`Remove this block`,onClick:()=>t(`delete`)},[y(re,{class:`w-3.5 h-3.5`})])])}});return(n,a)=>(e(),u(`div`,fe,[l(`header`,pe,[l(`div`,me,[a[12]||=l(`div`,{class:`max-w-2xl`},[l(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Egress `),l(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Control outbound destinations and DNS for function sandboxes. `)],-1),l(`div`,he,[f(w,{variant:`secondary`,size:`sm`,loading:F.value,onClick:Ut},{default:t(()=>[f(s(te),{class:`w-4 h-4`}),a[10]||=h(` Apply now `,-1)]),_:1},8,[`loading`]),f(w,{size:`sm`,onClick:a[0]||=e=>N.value=!0},{default:t(()=>[f(s(C),{class:`w-4 h-4`}),a[11]||=h(` Add block `,-1)]),_:1})])]),l(`div`,{class:d([`flex items-start gap-3 text-xs px-3 py-2 rounded-md border`,Nt.value])},[(e(),m(i(Pt.value),{class:`w-4 h-4 shrink-0 mt-0.5`})),l(`div`,ge,[l(`p`,_e,b(Ft.value),1),j.value.last_error?(e(),u(`p`,ve,b(j.value.last_error),1)):v(``,!0),It.value?(e(),u(`p`,ye,b(It.value),1)):v(``,!0)]),j.value.enforced?(e(),u(`span`,be,b(Y.value)+` enforced · `+b(X.value)+` off `,1)):v(``,!0)],2),l(`details`,xe,[a[19]||=l(`summary`,{class:`cursor-pointer text-xs text-foreground-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},` Policy details `,-1),l(`div`,Se,[l(`span`,Ce,[a[13]||=l(`span`,{class:`policy-chip-k`},`Backend`,-1),l(`span`,we,b(j.value.backend||`nstun`),1)]),l(`span`,Te,[a[14]||=l(`span`,{class:`policy-chip-k`},`Generation`,-1),l(`span`,Ee,b(j.value.policy_generation||`none`),1)]),l(`span`,De,[a[15]||=l(`span`,{class:`policy-chip-k`},`Compiled rules`,-1),l(`span`,Oe,b(Lt.value),1)]),j.value.pending_recycle?(e(),u(`span`,ke,[...a[16]||=[l(`span`,{class:`policy-chip-k`},`Rollout`,-1),l(`span`,{class:`policy-chip-v`},`warm workers still on the previous generation`,-1)]])):v(``,!0),Rt.value?(e(),u(`span`,Ae,[a[17]||=l(`span`,{class:`policy-chip-k`},`SDK carve-out`,-1),l(`span`,je,b(Rt.value),1)])):v(``,!0),zt.value?(e(),u(`span`,Me,[a[18]||=l(`span`,{class:`policy-chip-k`},`Applied`,-1),l(`span`,Ne,b(zt.value),1)])):v(``,!0)])])]),f(s(Gt),{title:`DNS`,subtitle:ht.value},{default:t(()=>[l(`div`,Pe,[l(`div`,Fe,[a[22]||=l(`div`,{class:`dns-row-label`},` Upstream resolvers `,-1),l(`div`,Ie,[L.value.servers.length?(e(),u(`div`,Le,[(e(!0),u(g,null,p(L.value.servers,(t,n)=>(e(),u(`span`,{key:t+n,class:`dns-chip`},[f(s(D),{class:`w-3 h-3 opacity-60`}),l(`span`,Re,b(t),1),l(`button`,{class:`dns-chip-x`,title:`Remove`,"aria-label":`Remove resolver ${t}`,onClick:e=>_t(n)},` × `,8,ze)]))),128))])):(e(),u(`div`,Be,[a[20]||=l(`span`,{class:`text-foreground-muted text-xs`},`Defaults:`,-1),(e(!0),u(g,null,p(L.value.defaults,t=>(e(),u(`span`,{key:t,class:`dns-chip muted`},[f(s(D),{class:`w-3 h-3 opacity-60`}),l(`span`,Ve,b(t),1)]))),128))]))]),l(`div`,He,[r(l(`input`,{"onUpdate:modelValue":a[1]||=e=>z.value=e,"aria-label":`Resolver address`,placeholder:`1.1.1.1`,class:`dns-input`,onKeydown:E(U,[`enter`])},null,544),[[S,z.value]]),f(w,{variant:`secondary`,size:`sm`,disabled:!z.value.trim(),onClick:U},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[21]||=h(` Add resolver `,-1)]),_:1},8,[`disabled`]),r(l(`input`,{"onUpdate:modelValue":a[2]||=e=>L.value.search=e,"aria-label":`DNS search domain`,placeholder:`search domain`,class:`dns-input narrow`},null,512),[[S,L.value.search]])])]),l(`div`,Ue,[l(`div`,We,[a[23]||=h(` Host overrides `,-1),l(`span`,Ge,b(L.value.records.length)+` record`+b(L.value.records.length===1?``:`s`),1)]),L.value.records.length?(e(),u(`div`,Ke,[(e(!0),u(g,null,p(L.value.records,(t,n)=>(e(),u(`div`,{key:t.host+n,class:`dns-record`},[l(`span`,qe,b(t.host),1),a[24]||=l(`span`,{class:`text-foreground-muted text-xs`},`→`,-1),l(`span`,Je,b(t.ip),1),l(`button`,{class:`dns-chip-x`,title:`Remove`,"aria-label":`Remove host override ${t.host}`,onClick:e=>vt(n)},` × `,8,Ye)]))),128))])):(e(),u(`div`,Xe,` No overrides. Anything resolves through the upstream resolvers above. `)),l(`div`,Ze,[r(l(`input`,{"onUpdate:modelValue":a[3]||=e=>B.value=e,"aria-label":`Override hostname`,placeholder:`api.internal`,class:`dns-input host`,onKeydown:E(W,[`enter`])},null,544),[[S,B.value]]),a[26]||=l(`span`,{class:`text-foreground-muted text-xs`},`→`,-1),r(l(`input`,{"onUpdate:modelValue":a[4]||=e=>V.value=e,"aria-label":`Override IP address`,placeholder:`10.0.5.10`,class:`dns-input`,onKeydown:E(W,[`enter`])},null,544),[[S,V.value]]),f(w,{variant:`secondary`,size:`sm`,disabled:!(B.value.trim()&&V.value.trim()),onClick:W},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[25]||=h(` Add record `,-1)]),_:1},8,[`disabled`])])]),l(`div`,Qe,[a[28]||=l(`span`,{class:`dns-hint`},` Overrides bypass upstream DNS. Existing warm workers update after recycle. `,-1),L.value.servers.length||L.value.search||L.value.records.length?(e(),u(`button`,{key:0,class:`text-xs text-foreground-muted hover:text-white px-2 py-1 transition-colors`,onClick:yt},` Reset `)):v(``,!0),f(w,{size:`sm`,loading:H.value,disabled:!mt.value,onClick:bt},{default:t(()=>[...a[27]||=[h(` Save `,-1)]]),_:1},8,[`loading`,`disabled`])])])]),_:1},8,[`subtitle`]),f(s(Gt),{title:`Blocklist`,subtitle:Ot.value},{default:t(()=>[K.value.length?(e(),u(`div`,$e,[f(s(ie),{class:`w-3.5 h-3.5 shrink-0 mt-0.5`}),l(`div`,et,[l(`p`,null,b(K.value.length===1?`One stored rule is not part of the compiled policy and blocks nothing:`:`${K.value.length} stored rules are not part of the compiled policy and block nothing:`),1),l(`ul`,null,[(e(!0),u(g,null,p(K.value,t=>(e(),u(`li`,{key:t.id},[l(`code`,null,b(t.value),1),h(`: `+b(t.reason),1)]))),128))])])])):v(``,!0),l(`div`,tt,[(e(!0),u(g,null,p(Et.value,t=>(e(),u(`button`,{key:t.id,class:d([`rule-filter`,{active:J.value===t.id}]),onClick:e=>J.value=t.id},[h(b(t.label)+` `,1),l(`span`,rt,b(t.count),1)],10,nt))),128))]),Dt.value.length?(e(),u(`div`,st,[(e(!0),u(g,null,p(Dt.value,t=>(e(),m(s(qt),{key:t.id,rule:t,status:j.value,"unenforced-reason":Ct(t),busy:M.value===t.id,"readonly-edit":t.kind!==`custom`,onToggle:e=>Bt(t),onDelete:e=>Vt(t)},null,8,[`rule`,`status`,`unenforced-reason`,`busy`,`readonly-edit`,`onToggle`,`onDelete`]))),128))])):(e(),u(`div`,it,[f(s(de),{class:`w-5 h-5 mb-2 text-foreground-muted/60`}),l(`p`,at,b(J.value===`yours`?`No custom blocks yet`:`Nothing matches this filter`),1),l(`p`,ot,b(J.value===`yours`?`Add an IP, network, or hostname.`:`Try another filter.`),1),J.value===`yours`?(e(),m(w,{key:0,class:`mt-4`,size:`sm`,variant:`secondary`,onClick:a[5]||=e=>N.value=!0},{default:t(()=>[f(s(C),{class:`w-3.5 h-3.5`}),a[29]||=h(` Add block `,-1)]),_:1})):v(``,!0)]))]),_:1},8,[`subtitle`]),f(oe,{modelValue:N.value,"onUpdate:modelValue":a[9]||=e=>N.value=e,title:`Add block`,icon:s(ue),size:`md`},{footer:t(()=>[f(w,{variant:`secondary`,onClick:a[8]||=e=>N.value=!1},{default:t(()=>[...a[33]||=[h(` Cancel `,-1)]]),_:1}),f(w,{loading:P.value,disabled:!I.value.value.trim()||Mt.value,onClick:Ht},{default:t(()=>[f(s(C),{class:`w-4 h-4`}),a[34]||=h(` Block it `,-1)]),_:1},8,[`loading`,`disabled`])]),default:t(()=>[l(`div`,ct,[a[31]||=l(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Block an IP, network, or hostname. Wildcards are not supported. `,-1),l(`div`,null,[a[30]||=l(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` What is it? `,-1),l(`div`,lt,[(e(),u(g,null,p(kt,t=>l(`button`,{key:t.value,class:d([`px-2 py-2 rounded border text-xs font-medium transition-colors flex flex-col items-center gap-1`,I.value.rule_type===t.value?`bg-white text-black border-white`:`bg-surface-hover text-foreground-muted border-border hover:border-foreground-muted`]),onClick:e=>I.value.rule_type=t.value},[(e(),m(i(t.icon),{class:`w-3.5 h-3.5`})),h(` `+b(t.label),1)],10,ut)),64))]),l(`p`,dt,b(jt.value),1)]),f(se,{modelValue:I.value.value,"onUpdate:modelValue":a[6]||=e=>I.value.value=e,label:I.value.rule_type===`hostname`?`Hostname`:`IP or network`,placeholder:At.value},null,8,[`modelValue`,`label`,`placeholder`]),Mt.value?(e(),u(`p`,ft,b(O))):v(``,!0),f(se,{modelValue:I.value.label,"onUpdate:modelValue":a[7]||=e=>I.value.label=e,label:`Why? (optional)`,placeholder:`e.g. our staging Postgres`},null,8,[`modelValue`]),a[32]||=l(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Applies within seconds and recycles warm functions. `,-1)])]),_:1},8,[`modelValue`,`icon`])]))}};export{k as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/FunctionDiff-DtVzmfsl.js b/backend/internal/server/ui_dist/assets/FunctionDiff-CpSHReET.js similarity index 99% rename from backend/internal/server/ui_dist/assets/FunctionDiff-DtVzmfsl.js rename to backend/internal/server/ui_dist/assets/FunctionDiff-CpSHReET.js index 5e940db6..d89fbc0b 100644 --- a/backend/internal/server/ui_dist/assets/FunctionDiff-DtVzmfsl.js +++ b/backend/internal/server/ui_dist/assets/FunctionDiff-CpSHReET.js @@ -1,4 +1,4 @@ -import{D as e,E as t,F as n,G as r,P as i,T as a,Z as o,c as s,d as c,gt as l,h as u,j as d,k as f,l as p,m,r as h,s as g,u as _,vt as v,x as ee}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./copy-BqdwwcxC.js";import{n as ne,r as re,t as ie}from"./settings-2-D5QtFfdZ.js";import{t as ae}from"./rotate-ccw-DWwjKCqh.js";import{t as oe}from"./zap-BXGoxm_a.js";import{B as se,Dt as ce,R as le,_t as ue,a as de,b as fe,et as pe,gt as me,jt as he,mt as ge,pt as _e}from"./index-DTqMKlE1.js";import{A as y,C as ve,D as b,E as ye,M as x,N as S,O as C,S as w,T,_ as E,a as be,b as xe,c as D,d as Se,f as O,g as k,h as A,i as Ce,j,k as M,l as N,m as we,n as Te,o as Ee,p as De,r as Oe,s as ke,t as Ae,u as je,v as P,w as Me,x as Ne,y as F}from"./dist-CR15Grce.js";import{t as Pe}from"./clipboard-D_9N0yai.js";import{t as Fe}from"./rollbackDiff-DsaWcdbl.js";var Ie=he(`arrow-left-right`,[[`path`,{d:`M8 3 4 7l4 4`,key:`9rb6wj`}],[`path`,{d:`M4 7h16`,key:`6tx8e3`}],[`path`,{d:`m16 21 4-4-4-4`,key:`siv7j2`}],[`path`,{d:`M20 17H4`,key:`h6l3hr`}]]),Le=he(`list`,[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]),I=class e{constructor(e,t,n,r){this.fromA=e,this.toA=t,this.fromB=n,this.toB=r}offset(t,n=t){return new e(this.fromA+t,this.toA+t,this.fromB+n,this.toB+n)}};function L(e,t,n,r,i,a){if(e==r)return[];let o=Be(e,t,n,r,i,a),s=Ve(e,t+o,n,r,i+o,a);t+=o,n-=s,i+=o,a-=s;let c=n-t,l=a-i;if(!c||!l)return[new I(t,n,i,a)];if(c>l){let o=e.slice(t,n).indexOf(r.slice(i,a));if(o>-1)return[new I(t,t+o,i,i),new I(t+o+l,n,a,a)]}else if(l>c){let o=r.slice(i,a).indexOf(e.slice(t,n));if(o>-1)return[new I(t,t,i,i+o),new I(n,n,i+o+c,a)]}if(c==1||l==1)return[new I(t,n,i,a)];let u=Ue(e,t,n,r,i,a);if(u){let[o,s,c]=u;return L(e,t,o,r,i,s).concat(L(e,o+c,n,r,s+c,a))}return Re(e,t,n,r,i,a)}var R=1e9,z=0,B=!1;function Re(e,t,n,r,i,a){let o=n-t,s=a-i;if(R<1e9&&Math.min(o,s)>R*16||z>0&&Date.now()>z)return Math.min(o,s)>R*64?[new I(t,n,i,a)]:G(e,t,n,r,i,a);let c=Math.ceil((o+s)/2);ze.reset(c),H.reset(c);let l=(n,a)=>e.charCodeAt(t+n)==r.charCodeAt(i+a),u=(t,i)=>e.charCodeAt(n-t-1)==r.charCodeAt(a-i-1),d=(o-s)%2==0?null:H,f=d?null:ze;for(let p=0;pR||z>0&&!(p&63)&&Date.now()>z)return G(e,t,n,r,i,a);let m=ze.advance(p,o,s,c,d,!1,l)||H.advance(p,o,s,c,f,!0,u);if(m)return U(e,t,n,t+m[0],r,i,a,i+m[1])}return[new I(t,n,i,a)]}var V=class{constructor(){this.vec=[]}reset(e){this.len=e<<1;for(let e=0;et)this.end+=2;else if(u>n)this.start+=2;else if(i){let e=r+(t-n)-s;if(e>=0&&e=t-l)return[n,r+n-e]}else{let n=t-i.vec[e];if(l>=n)return[l,u]}}}return null}},ze=new V,H=new V;function U(e,t,n,r,i,a,o,s){let c=!1;return!Y(e,r)&&++r==n&&(c=!0),!Y(i,s)&&++s==o&&(c=!0),c?[new I(t,n,a,o)]:L(e,t,r,i,a,s).concat(L(e,r,n,i,s,o))}function W(e,t){let n=1,r=Math.min(e,t);for(;nn||l>a||e.slice(s,i)!=r.slice(c,l)){if(o==1)return s-t-+!Y(e,s);o>>=1}else if(i==n||l==a)return i-t;else s=i,c=l}}function Ve(e,t,n,r,i,a){if(t==n||i==a||e.charCodeAt(n-1)!=r.charCodeAt(a-1))return 0;let o=W(n-t,a-i);for(let s=n,c=a;;){let a=s-o,l=c-o;if(a>=1}else if(a==t||l==i)return n-a;else s=a,c=l}}function He(e,t,n,r,i,a,o,s){let c=r.slice(i,a),l=null;for(;;){if(l||o=n)break;let d=e.slice(s,u),f=-1;for(;(f=c.indexOf(d,f+1))!=-1;){let o=Be(e,u,n,r,i+f+d.length,a),c=Ve(e,t,s,r,i,i+f),p=d.length+o+c;(!l||l[2]>=1}}function Ue(e,t,n,r,i,a){let o=n-t,s=a-i;if(oi.fromA-t&&r.toB>i.fromB-t&&(e[n-1]=new I(r.fromA,i.toA,r.fromB,i.toB),e.splice(n--,1))}}function Ge(e,t,n){for(;;){We(n,1);let r=!1;for(let i=0;i3||s>3){let c=i==e.length-1?t.length:e[i+1].fromA,l=a.fromA-r,u=c-a.toA,d=Xe(t,a.fromA,l),f=Ye(t,a.toA,u),p=a.fromA-d,m=f-a.toA;if((!o||!s)&&p&&m){let l=Math.max(o,s),[u,h,g]=o?[t,a.fromA,a.toA]:[n,a.fromB,a.toB];l>p&&t.slice(d,a.fromA)==u.slice(g-p,g)?(a=e[i]=new I(d,d+o,a.fromB-p,a.toB-p),d=a.fromA,f=Ye(t,a.toA,c-a.toA)):l>m&&t.slice(a.toA,f)==u.slice(h,h+m)&&(a=e[i]=new I(f-o,f,a.fromB+m,a.toB+m),f=a.toA,d=Xe(t,a.fromA,a.fromA-r)),p=a.fromA-d,m=f-a.toA}if(p||m)a=e[i]=new I(a.fromA-p,a.toA+m,a.fromB-p,a.toB+m);else if(!o){let t=Qe(n,a.fromB,a.toB),r,o=t<0?-1:Ze(n,a.toB,a.fromB);t>-1&&(r=t-a.fromB)<=u&&n.slice(a.fromB,t)==n.slice(a.toB,a.toB+r)?a=e[i]=a.offset(r):o>-1&&(r=a.toB-o)<=l&&n.slice(a.fromB-r,a.fromB)==n.slice(o,a.toB)&&(a=e[i]=a.offset(-r))}else if(!s){let n=Qe(t,a.fromA,a.toA),r,o=n<0?-1:Ze(t,a.toA,a.fromA);n>-1&&(r=n-a.fromA)<=u&&t.slice(a.fromA,n)==t.slice(a.toA,a.toA+r)?a=e[i]=a.offset(r):o>-1&&(r=a.toA-o)<=l&&t.slice(a.fromA-r,a.fromA)==t.slice(o,a.toA)&&(a=e[i]=a.offset(-r))}}r=a.toA}return We(e,3),e}var q;try{q=RegExp(`[\\p{Alphabetic}\\p{Number}]`,`u`)}catch{}function Ke(e){return e>48&&e<58||e>64&&e<91||e>96&&e<123}function qe(e,t){if(t==e.length)return 0;let n=e.charCodeAt(t);return n<192?+!!Ke(n):q?!$e(n)||t==e.length-1?+!!q.test(String.fromCharCode(n)):q.test(e.slice(t,t+2))?2:0:0}function J(e,t){if(!t)return 0;let n=e.charCodeAt(t-1);return n<192?+!!Ke(n):q?!et(n)||t==1?+!!q.test(String.fromCharCode(n)):q.test(e.slice(t-2,t))?2:0:0}var Je=8;function Ye(e,t,n){if(t==e.length||!J(e,t))return t;for(let r=t,i=t+n,a=0;ai)return r;r+=t}return t}function Xe(e,t,n){if(!t||!qe(e,t))return t;for(let r=t,i=t-n,a=0;ae>=55296&&e<=56319,et=e=>e>=56320&&e<=57343;function Y(e,t){return!t||t==e.length||!$e(e.charCodeAt(t-1))||!et(e.charCodeAt(t))}function tt(e,t,n){let r=n?.override;return r?r(e,t):(R=(n?.scanLimit??1e9)>>1,z=n?.timeout?Date.now()+n.timeout:0,B=!1,Ge(e,t,L(e,0,e.length,t,0,t.length)))}function nt(){return!B}function rt(e,t,n){return K(tt(e,t,n),e,t)}var X=b.define({combine:e=>e[0]}),it=j.define(),at=b.define(),Z=x.define({create(e){return null},update(e,t){for(let n of t.effects)n.is(it)&&(e=n.value);for(let n of t.state.facet(at))e=n(e,t);return e}}),Q=class e{constructor(e,t,n,r,i,a=!0){this.changes=e,this.fromA=t,this.toA=n,this.fromB=r,this.toB=i,this.precise=a}offset(t,n){return t||n?new e(this.changes,this.fromA+t,this.toA+t,this.fromB+n,this.toB+n,this.precise):this}get endA(){return Math.max(this.fromA,this.toA-1)}get endB(){return Math.max(this.fromB,this.toB-1)}static build(e,t,n){return ct(rt(e.toString(),t.toString(),n),e,t,0,0,nt())}static updateA(e,t,n,r,i){return ft(dt(e,r,!0,n.length),e,t,n,i)}static updateB(e,t,n,r,i){return ft(dt(e,r,!1,t.length),e,t,n,i)}};function ot(e,t,n,r){let i=n.lineAt(e),a=r.lineAt(t);return i.to==e&&a.to==t&&ed+1&&c>f+1)break;p.push(a.offset(-l+r,-u+i)),[d,f]=st(a.toA+r,a.toB+i,t,n),s++}o.push(new Q(p,l,Math.max(l,d),u,Math.max(u,f),a))}return o}var lt=1e3;function ut(e,t,n,r){let i=0,a=e.length;for(;;){if(i==a){let r=0,a=0;i&&({toA:r,toB:a}=e[i-1]);let o=t-(n?r:a);return[r+o,a+o]}let o=i+a>>1,s=e[o],[c,l]=n?[s.fromA,s.toA]:[s.fromB,s.toB];if(c>t)a=o;else if(l<=t)i=o+1;else return r?[s.fromA,s.fromB]:[s.toA,s.toB]}}function dt(e,t,n,r){let i=[];return t.iterChangedRanges((a,o,s,c)=>{let l=0,u=n?t.length:r,d=0,f=n?r:t.length;a>lt&&([l,d]=ut(e,a-lt,n,!0)),o=l?i[i.length-1]={fromA:m.fromA,fromB:m.fromB,toA:u,toB:f,diffA:m.diffA+h,diffB:m.diffB+g}:i.push({fromA:l,toA:u,fromB:d,toB:f,diffA:h,diffB:g})}),i}function ft(e,t,n,r,i){if(!e.length)return t;let a=[];for(let o=0,s=0,c=0,l=0;;o++){let u=o==e.length?null:e[o],d=u?u.fromA+s:n.length,f=u?u.fromB+c:r.length;for(;ld||e.toB+c>f))break;a.push(e.offset(s,c)),l++}if(!u)break;let p=u.toA+s+u.diffA,m=u.toB+c+u.diffB,h=rt(n.sliceString(d,p),r.sliceString(f,m),i);for(let e of ct(h,n,r,d,f,nt()))a.push(e);for(s+=u.diffA,c+=u.diffB;lp&&e.fromB+c>m)break;l++}}return a}var pt={scanLimit:500},mt=xe.fromClass(class{constructor(e){({deco:this.deco,gutter:this.gutter}=wt(e))}update(e){(e.docChanged||e.viewportChanged||gt(e.startState,e.state)||_t(e.startState,e.state))&&({deco:this.deco,gutter:this.gutter}=wt(e.view))}},{decorations:e=>e.deco}),ht=C.low(w({class:`cm-changeGutter`,markers:e=>e.plugin(mt)?.gutter||M.empty}));function gt(e,t){return e.field(Z,!1)!=t.field(Z,!1)}function _t(e,t){return e.facet(X)!=t.facet(X)}var vt=E.line({class:`cm-changedLine`}),yt=E.mark({class:`cm-changedText`}),bt=E.mark({tagName:`ins`,class:`cm-insertedLine`}),xt=E.mark({tagName:`del`,class:`cm-deletedLine`}),St=new class extends F{constructor(){super(...arguments),this.elementClass=`cm-changedLineGutter`}};function Ct(e,t,n,r,i,a){let o=n?e.fromA:e.fromB,s=n?e.toA:e.toB,c=0;if(o!=s){i.add(o,o,vt),i.add(o,s,n?xt:bt),a&&a.add(o,o,St);for(let l=t.iterRange(o,s-1),u=o;!l.next().done;){if(l.lineBreak){u++,i.add(u,u,vt),a&&a.add(u,u,St);continue}let t=u+l.value.length;if(r)for(;c=u)break;(o?n.toA:n.toB)>l&&(!a||!a(e.state,n,s,c))&&Ct(n,e.state.doc,o,r,s,c)}return{deco:s.finish(),gutter:c&&c.finish()}}var Tt=class extends Ne{constructor(e){super(),this.height=e}eq(e){return this.height==e.height}toDOM(){let e=document.createElement(`div`);return e.className=`cm-mergeSpacer`,e.style.height=this.height+`px`,e}updateDOM(e){return e.style.height=this.height+`px`,!0}get estimatedHeight(){return this.height}ignoreEvent(){return!1}},Et=j.define({map:(e,t)=>e.map(t)}),Dt=x.define({create:()=>E.none,update:(e,t)=>{for(let e of t.effects)if(e.is(Et))return e.value;return e.map(t.changes)},provide:e=>P.decorations.from(e)}),Ot=.01;function kt(e,t){if(e.size!=t.size)return!1;let n=e.iter(),r=t.iter();for(;n.value;){if(n.from!=r.from||Math.abs(n.value.spec.widget.height-r.value.spec.widget.height)>1)return!1;n.next(),r.next()}return!0}function At(e,t,n){let r=new y,i=new y,a=e.state.field(Dt).iter(),o=t.state.field(Dt).iter(),s=0,c=0,l=0,u=0,d=e.viewport,f=t.viewport;for(let p=0;;p++){let m=pOt&&(u+=n,i.add(c,c,E.widget({widget:new Tt(n),block:!0,side:-1})))}if(h>s+1e3&&sd.from&&cf.from){let e=Math.min(d.from-s,f.from-c);s+=e,c+=e,p--}else if(m)s=m.toA,c=m.toB;else break;for(;a.value&&a.fromOt&&i.add(t.state.doc.length,t.state.doc.length,E.widget({widget:new Tt(p),block:!0,side:1}));let m=r.finish(),h=i.finish();kt(m,e.state.field(Dt))||e.dispatch({effects:Et.of(m)}),kt(h,t.state.field(Dt))||t.dispatch({effects:Et.of(h)})}var jt=j.define({map:(e,t)=>t.mapPos(e)}),Mt=class extends Ne{constructor(e){super(),this.lines=e}eq(e){return this.lines==e.lines}toDOM(e){let t=document.createElement(`div`);return t.className=`cm-collapsedLines`,t.textContent=e.state.phrase(`$ unchanged lines`,this.lines),t.addEventListener(`click`,t=>{let n=e.posAtDOM(t.target);e.dispatch({effects:jt.of(n)});let{side:r,sibling:i}=e.state.facet(X);i&&i().dispatch({effects:jt.of(Nt(n,e.state.field(Z),r==`a`))})}),t}ignoreEvent(e){return e instanceof MouseEvent}get estimatedHeight(){return 27}get type(){return`collapsed-unchanged-code`}};function Nt(e,t,n){let r=0,i=0;for(let a=0;;a++){let o=a=e)return i+(e-r);[r,i]=n?[o.toA,o.toB]:[o.toB,o.toA]}}var Pt=x.define({create(e){return E.none},update(e,t){e=e.map(t.changes);for(let n of t.effects)n.is(jt)&&(e=e.update({filter:e=>e!=n.value}));if(e.size&&t.state.field(Z)!=t.startState.field(Z,!1)){let n=t.state.facet(X).side==`a`,r=[];for(let i of t.state.field(Z))e.between(n?i.fromA:i.fromB,n?i.toA:i.toB,e=>{r.push(e)});r.length&&(e=e.update({filter:e=>r.indexOf(e)<0}))}return e},provide:e=>P.decorations.from(e)});function Ft({margin:e=3,minSize:t=4}){return Pt.init(n=>It(n,e,t))}function It(e,t,n){let r=new y,i=e.facet(X).side==`a`,a=e.field(Z),o=1;for(let s=0;;s++){let c=s=n&&r.add(e.doc.line(l).from,e.doc.line(u).to,E.replace({widget:new Mt(d),block:!0})),!c)break;o=e.doc.lineAt(Math.min(e.doc.length,i?c.toA:c.toB)).number}return r.finish()}var Lt=P.styleModule.of(new ve({".cm-mergeView":{overflowY:`auto`},".cm-mergeViewEditors":{display:`flex`,alignItems:`stretch`},".cm-mergeViewEditor":{flexGrow:1,flexBasis:0,overflow:`hidden`},".cm-merge-revert":{width:`1.6em`,flexGrow:0,flexShrink:0,position:`relative`},".cm-merge-revert button":{position:`absolute`,display:`block`,width:`100%`,boxSizing:`border-box`,textAlign:`center`,background:`none`,border:`none`,font:`inherit`,cursor:`pointer`}})),Rt=P.baseTheme({".cm-mergeView & .cm-scroller, .cm-mergeView &":{height:`auto !important`,overflowY:`visible !important`},"&.cm-merge-a .cm-changedLine, .cm-deletedChunk":{backgroundColor:`rgba(160, 128, 100, .08)`},"&.cm-merge-b .cm-changedLine, .cm-inlineChangedLine":{backgroundColor:`rgba(100, 160, 128, .08)`},"&light.cm-merge-a .cm-changedText, &light .cm-deletedChunk .cm-deletedText":{background:`linear-gradient(#ee443366, #ee443366) bottom/100% 2px no-repeat`},"&dark.cm-merge-a .cm-changedText, &dark .cm-deletedChunk .cm-deletedText":{background:`linear-gradient(#ffaa9966, #ffaa9966) bottom/100% 2px no-repeat`},"&light.cm-merge-b .cm-changedText":{background:`linear-gradient(#22bb22aa, #22bb22aa) bottom/100% 2px no-repeat`},"&dark.cm-merge-b .cm-changedText":{background:`linear-gradient(#88ff88aa, #88ff88aa) bottom/100% 2px no-repeat`},"&.cm-merge-b .cm-deletedText":{background:`#ff000033`},".cm-insertedLine, .cm-deletedLine, .cm-deletedLine del":{textDecoration:`none`},".cm-deletedChunk":{paddingLeft:`6px`,"& .cm-chunkButtons":{position:`absolute`,insetInlineEnd:`5px`},"& button":{border:`none`,cursor:`pointer`,color:`white`,margin:`0 2px`,borderRadius:`3px`,"&[name=accept]":{background:`#2a2`},"&[name=reject]":{background:`#d43`}}},".cm-collapsedLines":{padding:`5px 5px 5px 10px`,cursor:`pointer`,"&:before":{content:`"⦚"`,marginInlineEnd:`7px`},"&:after":{content:`"⦚"`,marginInlineStart:`7px`}},"&light .cm-collapsedLines":{color:`#444`,background:`linear-gradient(to bottom, transparent 0, #f3f3f3 30%, #f3f3f3 70%, transparent 100%)`},"&dark .cm-collapsedLines":{color:`#ddd`,background:`linear-gradient(to bottom, transparent 0, #222 30%, #222 70%, transparent 100%)`},".cm-changeGutter":{width:`3px`,paddingLeft:`1px`},"&light.cm-merge-a .cm-changedLineGutter, &light .cm-deletedLineGutter":{background:`#e43`},"&dark.cm-merge-a .cm-changedLineGutter, &dark .cm-deletedLineGutter":{background:`#fa9`},"&light.cm-merge-b .cm-changedLineGutter":{background:`#2b2`},"&dark.cm-merge-b .cm-changedLineGutter":{background:`#8f8`},".cm-inlineChangedLineGutter":{background:`#75d`}}),zt=new T,Bt=new T,Vt=class{constructor(e){this.revertDOM=null,this.revertToA=!1,this.revertToLeft=!1,this.measuring=-1,this.diffConf=e.diffConfig||pt;let t=[C.low(mt),Rt,Lt,Dt,P.updateListener.of(e=>{this.measuring<0&&(e.heightChanged||e.viewportChanged)&&!e.transactions.some(e=>e.effects.some(e=>e.is(Et)))&&this.measure()})],n=[X.of({side:`a`,sibling:()=>this.b,highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1})];e.gutter!==!1&&n.push(ht);let r=ye.create({doc:e.a.doc,selection:e.a.selection,extensions:[e.a.extensions||[],P.editorAttributes.of({class:`cm-merge-a`}),Bt.of(n),t]}),i=[X.of({side:`b`,sibling:()=>this.a,highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1})];e.gutter!==!1&&i.push(ht);let a=ye.create({doc:e.b.doc,selection:e.b.selection,extensions:[e.b.extensions||[],P.editorAttributes.of({class:`cm-merge-b`}),Bt.of(i),t]});this.chunks=Q.build(r.doc,a.doc,this.diffConf);let o=[Z.init(()=>this.chunks),zt.of(e.collapseUnchanged?Ft(e.collapseUnchanged):[])];r=r.update({effects:j.appendConfig.of(o)}).state,a=a.update({effects:j.appendConfig.of(o)}).state,this.dom=document.createElement(`div`),this.dom.className=`cm-mergeView`,this.editorDOM=this.dom.appendChild(document.createElement(`div`)),this.editorDOM.className=`cm-mergeViewEditors`;let s=e.orientation||`a-b`,c=document.createElement(`div`);c.className=`cm-mergeViewEditor`;let l=document.createElement(`div`);l.className=`cm-mergeViewEditor`,this.editorDOM.appendChild(s==`a-b`?c:l),this.editorDOM.appendChild(s==`a-b`?l:c),this.a=new P({state:r,parent:c,root:e.root,dispatchTransactions:e=>this.dispatch(e,this.a)}),this.b=new P({state:a,parent:l,root:e.root,dispatchTransactions:e=>this.dispatch(e,this.b)}),this.setupRevertControls(!!e.revertControls,e.revertControls==`b-to-a`,e.renderRevertControl),e.parent&&e.parent.appendChild(this.dom),this.scheduleMeasure()}dispatch(e,t){if(e.some(e=>e.docChanged)){let n=e[e.length-1],r=e.reduce((e,t)=>e.compose(t.changes),Me.empty(e[0].startState.doc.length));this.chunks=t==this.a?Q.updateA(this.chunks,n.newDoc,this.b.state.doc,r,this.diffConf):Q.updateB(this.chunks,this.a.state.doc,n.newDoc,r,this.diffConf),t.update([...e,n.state.update({effects:it.of(this.chunks)})]);let i=t==this.a?this.b:this.a;i.update([i.state.update({effects:it.of(this.chunks)})]),this.scheduleMeasure()}else t.update(e)}reconfigure(e){if(`diffConfig`in e&&(this.diffConf=e.diffConfig),`orientation`in e){let t=e.orientation!=`b-a`;if(t!=(this.editorDOM.firstChild==this.a.dom.parentNode)){let e=this.a.dom.parentNode,n=this.b.dom.parentNode;e.remove(),n.remove(),this.editorDOM.insertBefore(t?e:n,this.editorDOM.firstChild),this.editorDOM.appendChild(t?n:e),this.revertToLeft=!this.revertToLeft,this.revertDOM&&(this.revertDOM.textContent=``)}}if(`revertControls`in e||`renderRevertControl`in e){let t=!!this.revertDOM,n=this.revertToA,r=this.renderRevert;`revertControls`in e&&(t=!!e.revertControls,n=e.revertControls==`b-to-a`),`renderRevertControl`in e&&(r=e.renderRevertControl),this.setupRevertControls(t,n,r)}let t=`highlightChanges`in e,n=`gutter`in e,r=`collapseUnchanged`in e;if(t||n||r){let i=[],a=[];if(t||n){let r=this.a.state.facet(X),o=n?e.gutter!==!1:r.markGutter,s=t?e.highlightChanges!==!1:r.highlightChanges;i.push(Bt.reconfigure([X.of({side:`a`,sibling:()=>this.b,highlightChanges:s,markGutter:o}),o?ht:[]])),a.push(Bt.reconfigure([X.of({side:`b`,sibling:()=>this.a,highlightChanges:s,markGutter:o}),o?ht:[]]))}if(r){let t=zt.reconfigure(e.collapseUnchanged?Ft(e.collapseUnchanged):[]);i.push(t),a.push(t)}this.a.dispatch({effects:i}),this.b.dispatch({effects:a})}this.scheduleMeasure()}setupRevertControls(e,t,n){this.revertToA=t,this.revertToLeft=this.revertToA==(this.editorDOM.firstChild==this.a.dom.parentNode),this.renderRevert=n,!e&&this.revertDOM?(this.revertDOM.remove(),this.revertDOM=null):e&&!this.revertDOM?(this.revertDOM=this.editorDOM.insertBefore(document.createElement(`div`),this.editorDOM.firstChild.nextSibling),this.revertDOM.addEventListener(`mousedown`,e=>this.revertClicked(e)),this.revertDOM.className=`cm-merge-revert`):this.revertDOM&&(this.revertDOM.textContent=``)}scheduleMeasure(){if(this.measuring<0){let e=this.dom.ownerDocument.defaultView||window;this.measuring=e.requestAnimationFrame(()=>{this.measuring=-1,this.measure()})}}measure(){At(this.a,this.b,this.chunks),this.revertDOM&&this.updateRevertButtons()}updateRevertButtons(){let e=this.revertDOM,t=e.firstChild,n=this.a.viewport,r=this.b.viewport;for(let i=0;in.to||a.fromB>r.to)break;if(a.fromA-1&&(this.dom.ownerDocument.defaultView||window).cancelAnimationFrame(this.measuring),this.dom.remove()}};function Ht(e){let t=e.nextSibling;return e.remove(),t}var Ut=new class extends F{constructor(){super(...arguments),this.elementClass=`cm-deletedLineGutter`}},Wt=C.low(w({class:`cm-changeGutter`,markers:e=>e.plugin(mt)?.gutter||M.empty,widgetMarker:(e,t)=>t instanceof Jt?Ut:null}));function Gt(e){let t=typeof e.original==`string`?S.of(e.original.split(/\r?\n/)):e.original,n=e.diffConfig||pt;return[C.low(mt),$t,Rt,P.editorAttributes.of({class:`cm-merge-b`}),at.of((e,t)=>{let r=t.effects.find(e=>e.is(Kt));return r&&(e=Q.updateA(e,r.value.doc,t.startState.doc,r.value.changes,n)),t.docChanged&&(e=Q.updateB(e,t.state.field($),t.newDoc,t.changes,n)),e}),X.of({highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1,syntaxHighlightDeletions:e.syntaxHighlightDeletions!==!1,syntaxHighlightDeletionsMaxLength:3e3,mergeControls:e.mergeControls??!0,overrideChunk:e.allowInlineDiffs?on:void 0,side:`b`}),$.init(()=>t),e.gutter===!1?[]:Wt,e.collapseUnchanged?Ft(e.collapseUnchanged):[],Z.init(e=>Q.build(t,e.doc,n))]}var Kt=j.define(),$=x.define({create:()=>S.empty,update(e,t){for(let n of t.effects)n.is(Kt)&&(e=n.value.doc);return e}}),qt=new WeakMap,Jt=class extends Ne{constructor(e){super(),this.buildDOM=e,this.dom=null}eq(e){return this.dom==e.dom}toDOM(e){return this.dom||=this.buildDOM(e)}};function Yt(e,t,n){let r=qt.get(t.changes);if(r)return r;let i=E.widget({block:!0,side:-1,widget:new Jt(r=>{let{highlightChanges:i,syntaxHighlightDeletions:a,syntaxHighlightDeletionsMaxLength:o,mergeControls:s}=e.facet(X),c=document.createElement(`div`);if(c.className=`cm-deletedChunk`,s){let t=c.appendChild(document.createElement(`div`));t.className=`cm-chunkButtons`;let n=e=>{e.preventDefault(),Xt(r,r.posAtDOM(c))},i=e=>{e.preventDefault(),Zt(r,r.posAtDOM(c))};if(typeof s==`function`)t.appendChild(s(`accept`,n)),t.appendChild(s(`reject`,i));else{let r=t.appendChild(document.createElement(`button`));r.name=`accept`,r.textContent=e.phrase(`Accept`),r.onmousedown=n;let a=t.appendChild(document.createElement(`button`));a.name=`reject`,a.textContent=e.phrase(`Reject`),a.onmousedown=i}}if(n||t.fromA>=t.toA)return c;let l=r.state.field($).sliceString(t.fromA,t.endA),u=a&&e.facet(De),d=h(),f=t.changes,p=0,m=!1;function h(){let e=c.appendChild(document.createElement(`div`));return e.className=`cm-deletedLine`,e.appendChild(document.createElement(`del`))}function g(e,t,n){for(let r=e;rl){let o=e.slice(t,n).indexOf(r.slice(i,a));if(o>-1)return[new I(t,t+o,i,i),new I(t+o+l,n,a,a)]}else if(l>c){let o=r.slice(i,a).indexOf(e.slice(t,n));if(o>-1)return[new I(t,t,i,i+o),new I(n,n,i+o+c,a)]}if(c==1||l==1)return[new I(t,n,i,a)];let u=Ue(e,t,n,r,i,a);if(u){let[o,s,c]=u;return L(e,t,o,r,i,s).concat(L(e,o+c,n,r,s+c,a))}return Re(e,t,n,r,i,a)}var R=1e9,z=0,B=!1;function Re(e,t,n,r,i,a){let o=n-t,s=a-i;if(R<1e9&&Math.min(o,s)>R*16||z>0&&Date.now()>z)return Math.min(o,s)>R*64?[new I(t,n,i,a)]:G(e,t,n,r,i,a);let c=Math.ceil((o+s)/2);ze.reset(c),H.reset(c);let l=(n,a)=>e.charCodeAt(t+n)==r.charCodeAt(i+a),u=(t,i)=>e.charCodeAt(n-t-1)==r.charCodeAt(a-i-1),d=(o-s)%2==0?null:H,f=d?null:ze;for(let p=0;pR||z>0&&!(p&63)&&Date.now()>z)return G(e,t,n,r,i,a);let m=ze.advance(p,o,s,c,d,!1,l)||H.advance(p,o,s,c,f,!0,u);if(m)return U(e,t,n,t+m[0],r,i,a,i+m[1])}return[new I(t,n,i,a)]}var V=class{constructor(){this.vec=[]}reset(e){this.len=e<<1;for(let e=0;et)this.end+=2;else if(u>n)this.start+=2;else if(i){let e=r+(t-n)-s;if(e>=0&&e=t-l)return[n,r+n-e]}else{let n=t-i.vec[e];if(l>=n)return[l,u]}}}return null}},ze=new V,H=new V;function U(e,t,n,r,i,a,o,s){let c=!1;return!Y(e,r)&&++r==n&&(c=!0),!Y(i,s)&&++s==o&&(c=!0),c?[new I(t,n,a,o)]:L(e,t,r,i,a,s).concat(L(e,r,n,i,s,o))}function W(e,t){let n=1,r=Math.min(e,t);for(;nn||l>a||e.slice(s,i)!=r.slice(c,l)){if(o==1)return s-t-+!Y(e,s);o>>=1}else if(i==n||l==a)return i-t;else s=i,c=l}}function Ve(e,t,n,r,i,a){if(t==n||i==a||e.charCodeAt(n-1)!=r.charCodeAt(a-1))return 0;let o=W(n-t,a-i);for(let s=n,c=a;;){let a=s-o,l=c-o;if(a>=1}else if(a==t||l==i)return n-a;else s=a,c=l}}function He(e,t,n,r,i,a,o,s){let c=r.slice(i,a),l=null;for(;;){if(l||o=n)break;let d=e.slice(s,u),f=-1;for(;(f=c.indexOf(d,f+1))!=-1;){let o=Be(e,u,n,r,i+f+d.length,a),c=Ve(e,t,s,r,i,i+f),p=d.length+o+c;(!l||l[2]>=1}}function Ue(e,t,n,r,i,a){let o=n-t,s=a-i;if(oi.fromA-t&&r.toB>i.fromB-t&&(e[n-1]=new I(r.fromA,i.toA,r.fromB,i.toB),e.splice(n--,1))}}function Ge(e,t,n){for(;;){We(n,1);let r=!1;for(let i=0;i3||s>3){let c=i==e.length-1?t.length:e[i+1].fromA,l=a.fromA-r,u=c-a.toA,d=Xe(t,a.fromA,l),f=Ye(t,a.toA,u),p=a.fromA-d,m=f-a.toA;if((!o||!s)&&p&&m){let l=Math.max(o,s),[u,h,g]=o?[t,a.fromA,a.toA]:[n,a.fromB,a.toB];l>p&&t.slice(d,a.fromA)==u.slice(g-p,g)?(a=e[i]=new I(d,d+o,a.fromB-p,a.toB-p),d=a.fromA,f=Ye(t,a.toA,c-a.toA)):l>m&&t.slice(a.toA,f)==u.slice(h,h+m)&&(a=e[i]=new I(f-o,f,a.fromB+m,a.toB+m),f=a.toA,d=Xe(t,a.fromA,a.fromA-r)),p=a.fromA-d,m=f-a.toA}if(p||m)a=e[i]=new I(a.fromA-p,a.toA+m,a.fromB-p,a.toB+m);else if(!o){let t=Qe(n,a.fromB,a.toB),r,o=t<0?-1:Ze(n,a.toB,a.fromB);t>-1&&(r=t-a.fromB)<=u&&n.slice(a.fromB,t)==n.slice(a.toB,a.toB+r)?a=e[i]=a.offset(r):o>-1&&(r=a.toB-o)<=l&&n.slice(a.fromB-r,a.fromB)==n.slice(o,a.toB)&&(a=e[i]=a.offset(-r))}else if(!s){let n=Qe(t,a.fromA,a.toA),r,o=n<0?-1:Ze(t,a.toA,a.fromA);n>-1&&(r=n-a.fromA)<=u&&t.slice(a.fromA,n)==t.slice(a.toA,a.toA+r)?a=e[i]=a.offset(r):o>-1&&(r=a.toA-o)<=l&&t.slice(a.fromA-r,a.fromA)==t.slice(o,a.toA)&&(a=e[i]=a.offset(-r))}}r=a.toA}return We(e,3),e}var q;try{q=RegExp(`[\\p{Alphabetic}\\p{Number}]`,`u`)}catch{}function Ke(e){return e>48&&e<58||e>64&&e<91||e>96&&e<123}function qe(e,t){if(t==e.length)return 0;let n=e.charCodeAt(t);return n<192?+!!Ke(n):q?!$e(n)||t==e.length-1?+!!q.test(String.fromCharCode(n)):q.test(e.slice(t,t+2))?2:0:0}function J(e,t){if(!t)return 0;let n=e.charCodeAt(t-1);return n<192?+!!Ke(n):q?!et(n)||t==1?+!!q.test(String.fromCharCode(n)):q.test(e.slice(t-2,t))?2:0:0}var Je=8;function Ye(e,t,n){if(t==e.length||!J(e,t))return t;for(let r=t,i=t+n,a=0;ai)return r;r+=t}return t}function Xe(e,t,n){if(!t||!qe(e,t))return t;for(let r=t,i=t-n,a=0;ae>=55296&&e<=56319,et=e=>e>=56320&&e<=57343;function Y(e,t){return!t||t==e.length||!$e(e.charCodeAt(t-1))||!et(e.charCodeAt(t))}function tt(e,t,n){let r=n?.override;return r?r(e,t):(R=(n?.scanLimit??1e9)>>1,z=n?.timeout?Date.now()+n.timeout:0,B=!1,Ge(e,t,L(e,0,e.length,t,0,t.length)))}function nt(){return!B}function rt(e,t,n){return K(tt(e,t,n),e,t)}var X=b.define({combine:e=>e[0]}),it=j.define(),at=b.define(),Z=x.define({create(e){return null},update(e,t){for(let n of t.effects)n.is(it)&&(e=n.value);for(let n of t.state.facet(at))e=n(e,t);return e}}),Q=class e{constructor(e,t,n,r,i,a=!0){this.changes=e,this.fromA=t,this.toA=n,this.fromB=r,this.toB=i,this.precise=a}offset(t,n){return t||n?new e(this.changes,this.fromA+t,this.toA+t,this.fromB+n,this.toB+n,this.precise):this}get endA(){return Math.max(this.fromA,this.toA-1)}get endB(){return Math.max(this.fromB,this.toB-1)}static build(e,t,n){return ct(rt(e.toString(),t.toString(),n),e,t,0,0,nt())}static updateA(e,t,n,r,i){return ft(dt(e,r,!0,n.length),e,t,n,i)}static updateB(e,t,n,r,i){return ft(dt(e,r,!1,t.length),e,t,n,i)}};function ot(e,t,n,r){let i=n.lineAt(e),a=r.lineAt(t);return i.to==e&&a.to==t&&ed+1&&c>f+1)break;p.push(a.offset(-l+r,-u+i)),[d,f]=st(a.toA+r,a.toB+i,t,n),s++}o.push(new Q(p,l,Math.max(l,d),u,Math.max(u,f),a))}return o}var lt=1e3;function ut(e,t,n,r){let i=0,a=e.length;for(;;){if(i==a){let r=0,a=0;i&&({toA:r,toB:a}=e[i-1]);let o=t-(n?r:a);return[r+o,a+o]}let o=i+a>>1,s=e[o],[c,l]=n?[s.fromA,s.toA]:[s.fromB,s.toB];if(c>t)a=o;else if(l<=t)i=o+1;else return r?[s.fromA,s.fromB]:[s.toA,s.toB]}}function dt(e,t,n,r){let i=[];return t.iterChangedRanges((a,o,s,c)=>{let l=0,u=n?t.length:r,d=0,f=n?r:t.length;a>lt&&([l,d]=ut(e,a-lt,n,!0)),o=l?i[i.length-1]={fromA:m.fromA,fromB:m.fromB,toA:u,toB:f,diffA:m.diffA+h,diffB:m.diffB+g}:i.push({fromA:l,toA:u,fromB:d,toB:f,diffA:h,diffB:g})}),i}function ft(e,t,n,r,i){if(!e.length)return t;let a=[];for(let o=0,s=0,c=0,l=0;;o++){let u=o==e.length?null:e[o],d=u?u.fromA+s:n.length,f=u?u.fromB+c:r.length;for(;ld||e.toB+c>f))break;a.push(e.offset(s,c)),l++}if(!u)break;let p=u.toA+s+u.diffA,m=u.toB+c+u.diffB,h=rt(n.sliceString(d,p),r.sliceString(f,m),i);for(let e of ct(h,n,r,d,f,nt()))a.push(e);for(s+=u.diffA,c+=u.diffB;lp&&e.fromB+c>m)break;l++}}return a}var pt={scanLimit:500},mt=xe.fromClass(class{constructor(e){({deco:this.deco,gutter:this.gutter}=wt(e))}update(e){(e.docChanged||e.viewportChanged||gt(e.startState,e.state)||_t(e.startState,e.state))&&({deco:this.deco,gutter:this.gutter}=wt(e.view))}},{decorations:e=>e.deco}),ht=C.low(w({class:`cm-changeGutter`,markers:e=>e.plugin(mt)?.gutter||M.empty}));function gt(e,t){return e.field(Z,!1)!=t.field(Z,!1)}function _t(e,t){return e.facet(X)!=t.facet(X)}var vt=E.line({class:`cm-changedLine`}),yt=E.mark({class:`cm-changedText`}),bt=E.mark({tagName:`ins`,class:`cm-insertedLine`}),xt=E.mark({tagName:`del`,class:`cm-deletedLine`}),St=new class extends F{constructor(){super(...arguments),this.elementClass=`cm-changedLineGutter`}};function Ct(e,t,n,r,i,a){let o=n?e.fromA:e.fromB,s=n?e.toA:e.toB,c=0;if(o!=s){i.add(o,o,vt),i.add(o,s,n?xt:bt),a&&a.add(o,o,St);for(let l=t.iterRange(o,s-1),u=o;!l.next().done;){if(l.lineBreak){u++,i.add(u,u,vt),a&&a.add(u,u,St);continue}let t=u+l.value.length;if(r)for(;c=u)break;(o?n.toA:n.toB)>l&&(!a||!a(e.state,n,s,c))&&Ct(n,e.state.doc,o,r,s,c)}return{deco:s.finish(),gutter:c&&c.finish()}}var Tt=class extends Ne{constructor(e){super(),this.height=e}eq(e){return this.height==e.height}toDOM(){let e=document.createElement(`div`);return e.className=`cm-mergeSpacer`,e.style.height=this.height+`px`,e}updateDOM(e){return e.style.height=this.height+`px`,!0}get estimatedHeight(){return this.height}ignoreEvent(){return!1}},Et=j.define({map:(e,t)=>e.map(t)}),Dt=x.define({create:()=>E.none,update:(e,t)=>{for(let e of t.effects)if(e.is(Et))return e.value;return e.map(t.changes)},provide:e=>P.decorations.from(e)}),Ot=.01;function kt(e,t){if(e.size!=t.size)return!1;let n=e.iter(),r=t.iter();for(;n.value;){if(n.from!=r.from||Math.abs(n.value.spec.widget.height-r.value.spec.widget.height)>1)return!1;n.next(),r.next()}return!0}function At(e,t,n){let r=new y,i=new y,a=e.state.field(Dt).iter(),o=t.state.field(Dt).iter(),s=0,c=0,l=0,u=0,d=e.viewport,f=t.viewport;for(let p=0;;p++){let m=pOt&&(u+=n,i.add(c,c,E.widget({widget:new Tt(n),block:!0,side:-1})))}if(h>s+1e3&&sd.from&&cf.from){let e=Math.min(d.from-s,f.from-c);s+=e,c+=e,p--}else if(m)s=m.toA,c=m.toB;else break;for(;a.value&&a.fromOt&&i.add(t.state.doc.length,t.state.doc.length,E.widget({widget:new Tt(p),block:!0,side:1}));let m=r.finish(),h=i.finish();kt(m,e.state.field(Dt))||e.dispatch({effects:Et.of(m)}),kt(h,t.state.field(Dt))||t.dispatch({effects:Et.of(h)})}var jt=j.define({map:(e,t)=>t.mapPos(e)}),Mt=class extends Ne{constructor(e){super(),this.lines=e}eq(e){return this.lines==e.lines}toDOM(e){let t=document.createElement(`div`);return t.className=`cm-collapsedLines`,t.textContent=e.state.phrase(`$ unchanged lines`,this.lines),t.addEventListener(`click`,t=>{let n=e.posAtDOM(t.target);e.dispatch({effects:jt.of(n)});let{side:r,sibling:i}=e.state.facet(X);i&&i().dispatch({effects:jt.of(Nt(n,e.state.field(Z),r==`a`))})}),t}ignoreEvent(e){return e instanceof MouseEvent}get estimatedHeight(){return 27}get type(){return`collapsed-unchanged-code`}};function Nt(e,t,n){let r=0,i=0;for(let a=0;;a++){let o=a=e)return i+(e-r);[r,i]=n?[o.toA,o.toB]:[o.toB,o.toA]}}var Pt=x.define({create(e){return E.none},update(e,t){e=e.map(t.changes);for(let n of t.effects)n.is(jt)&&(e=e.update({filter:e=>e!=n.value}));if(e.size&&t.state.field(Z)!=t.startState.field(Z,!1)){let n=t.state.facet(X).side==`a`,r=[];for(let i of t.state.field(Z))e.between(n?i.fromA:i.fromB,n?i.toA:i.toB,e=>{r.push(e)});r.length&&(e=e.update({filter:e=>r.indexOf(e)<0}))}return e},provide:e=>P.decorations.from(e)});function Ft({margin:e=3,minSize:t=4}){return Pt.init(n=>It(n,e,t))}function It(e,t,n){let r=new y,i=e.facet(X).side==`a`,a=e.field(Z),o=1;for(let s=0;;s++){let c=s=n&&r.add(e.doc.line(l).from,e.doc.line(u).to,E.replace({widget:new Mt(d),block:!0})),!c)break;o=e.doc.lineAt(Math.min(e.doc.length,i?c.toA:c.toB)).number}return r.finish()}var Lt=P.styleModule.of(new ve({".cm-mergeView":{overflowY:`auto`},".cm-mergeViewEditors":{display:`flex`,alignItems:`stretch`},".cm-mergeViewEditor":{flexGrow:1,flexBasis:0,overflow:`hidden`},".cm-merge-revert":{width:`1.6em`,flexGrow:0,flexShrink:0,position:`relative`},".cm-merge-revert button":{position:`absolute`,display:`block`,width:`100%`,boxSizing:`border-box`,textAlign:`center`,background:`none`,border:`none`,font:`inherit`,cursor:`pointer`}})),Rt=P.baseTheme({".cm-mergeView & .cm-scroller, .cm-mergeView &":{height:`auto !important`,overflowY:`visible !important`},"&.cm-merge-a .cm-changedLine, .cm-deletedChunk":{backgroundColor:`rgba(160, 128, 100, .08)`},"&.cm-merge-b .cm-changedLine, .cm-inlineChangedLine":{backgroundColor:`rgba(100, 160, 128, .08)`},"&light.cm-merge-a .cm-changedText, &light .cm-deletedChunk .cm-deletedText":{background:`linear-gradient(#ee443366, #ee443366) bottom/100% 2px no-repeat`},"&dark.cm-merge-a .cm-changedText, &dark .cm-deletedChunk .cm-deletedText":{background:`linear-gradient(#ffaa9966, #ffaa9966) bottom/100% 2px no-repeat`},"&light.cm-merge-b .cm-changedText":{background:`linear-gradient(#22bb22aa, #22bb22aa) bottom/100% 2px no-repeat`},"&dark.cm-merge-b .cm-changedText":{background:`linear-gradient(#88ff88aa, #88ff88aa) bottom/100% 2px no-repeat`},"&.cm-merge-b .cm-deletedText":{background:`#ff000033`},".cm-insertedLine, .cm-deletedLine, .cm-deletedLine del":{textDecoration:`none`},".cm-deletedChunk":{paddingLeft:`6px`,"& .cm-chunkButtons":{position:`absolute`,insetInlineEnd:`5px`},"& button":{border:`none`,cursor:`pointer`,color:`white`,margin:`0 2px`,borderRadius:`3px`,"&[name=accept]":{background:`#2a2`},"&[name=reject]":{background:`#d43`}}},".cm-collapsedLines":{padding:`5px 5px 5px 10px`,cursor:`pointer`,"&:before":{content:`"⦚"`,marginInlineEnd:`7px`},"&:after":{content:`"⦚"`,marginInlineStart:`7px`}},"&light .cm-collapsedLines":{color:`#444`,background:`linear-gradient(to bottom, transparent 0, #f3f3f3 30%, #f3f3f3 70%, transparent 100%)`},"&dark .cm-collapsedLines":{color:`#ddd`,background:`linear-gradient(to bottom, transparent 0, #222 30%, #222 70%, transparent 100%)`},".cm-changeGutter":{width:`3px`,paddingLeft:`1px`},"&light.cm-merge-a .cm-changedLineGutter, &light .cm-deletedLineGutter":{background:`#e43`},"&dark.cm-merge-a .cm-changedLineGutter, &dark .cm-deletedLineGutter":{background:`#fa9`},"&light.cm-merge-b .cm-changedLineGutter":{background:`#2b2`},"&dark.cm-merge-b .cm-changedLineGutter":{background:`#8f8`},".cm-inlineChangedLineGutter":{background:`#75d`}}),zt=new T,Bt=new T,Vt=class{constructor(e){this.revertDOM=null,this.revertToA=!1,this.revertToLeft=!1,this.measuring=-1,this.diffConf=e.diffConfig||pt;let t=[C.low(mt),Rt,Lt,Dt,P.updateListener.of(e=>{this.measuring<0&&(e.heightChanged||e.viewportChanged)&&!e.transactions.some(e=>e.effects.some(e=>e.is(Et)))&&this.measure()})],n=[X.of({side:`a`,sibling:()=>this.b,highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1})];e.gutter!==!1&&n.push(ht);let r=ye.create({doc:e.a.doc,selection:e.a.selection,extensions:[e.a.extensions||[],P.editorAttributes.of({class:`cm-merge-a`}),Bt.of(n),t]}),i=[X.of({side:`b`,sibling:()=>this.a,highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1})];e.gutter!==!1&&i.push(ht);let a=ye.create({doc:e.b.doc,selection:e.b.selection,extensions:[e.b.extensions||[],P.editorAttributes.of({class:`cm-merge-b`}),Bt.of(i),t]});this.chunks=Q.build(r.doc,a.doc,this.diffConf);let o=[Z.init(()=>this.chunks),zt.of(e.collapseUnchanged?Ft(e.collapseUnchanged):[])];r=r.update({effects:j.appendConfig.of(o)}).state,a=a.update({effects:j.appendConfig.of(o)}).state,this.dom=document.createElement(`div`),this.dom.className=`cm-mergeView`,this.editorDOM=this.dom.appendChild(document.createElement(`div`)),this.editorDOM.className=`cm-mergeViewEditors`;let s=e.orientation||`a-b`,c=document.createElement(`div`);c.className=`cm-mergeViewEditor`;let l=document.createElement(`div`);l.className=`cm-mergeViewEditor`,this.editorDOM.appendChild(s==`a-b`?c:l),this.editorDOM.appendChild(s==`a-b`?l:c),this.a=new P({state:r,parent:c,root:e.root,dispatchTransactions:e=>this.dispatch(e,this.a)}),this.b=new P({state:a,parent:l,root:e.root,dispatchTransactions:e=>this.dispatch(e,this.b)}),this.setupRevertControls(!!e.revertControls,e.revertControls==`b-to-a`,e.renderRevertControl),e.parent&&e.parent.appendChild(this.dom),this.scheduleMeasure()}dispatch(e,t){if(e.some(e=>e.docChanged)){let n=e[e.length-1],r=e.reduce((e,t)=>e.compose(t.changes),Me.empty(e[0].startState.doc.length));this.chunks=t==this.a?Q.updateA(this.chunks,n.newDoc,this.b.state.doc,r,this.diffConf):Q.updateB(this.chunks,this.a.state.doc,n.newDoc,r,this.diffConf),t.update([...e,n.state.update({effects:it.of(this.chunks)})]);let i=t==this.a?this.b:this.a;i.update([i.state.update({effects:it.of(this.chunks)})]),this.scheduleMeasure()}else t.update(e)}reconfigure(e){if(`diffConfig`in e&&(this.diffConf=e.diffConfig),`orientation`in e){let t=e.orientation!=`b-a`;if(t!=(this.editorDOM.firstChild==this.a.dom.parentNode)){let e=this.a.dom.parentNode,n=this.b.dom.parentNode;e.remove(),n.remove(),this.editorDOM.insertBefore(t?e:n,this.editorDOM.firstChild),this.editorDOM.appendChild(t?n:e),this.revertToLeft=!this.revertToLeft,this.revertDOM&&(this.revertDOM.textContent=``)}}if(`revertControls`in e||`renderRevertControl`in e){let t=!!this.revertDOM,n=this.revertToA,r=this.renderRevert;`revertControls`in e&&(t=!!e.revertControls,n=e.revertControls==`b-to-a`),`renderRevertControl`in e&&(r=e.renderRevertControl),this.setupRevertControls(t,n,r)}let t=`highlightChanges`in e,n=`gutter`in e,r=`collapseUnchanged`in e;if(t||n||r){let i=[],a=[];if(t||n){let r=this.a.state.facet(X),o=n?e.gutter!==!1:r.markGutter,s=t?e.highlightChanges!==!1:r.highlightChanges;i.push(Bt.reconfigure([X.of({side:`a`,sibling:()=>this.b,highlightChanges:s,markGutter:o}),o?ht:[]])),a.push(Bt.reconfigure([X.of({side:`b`,sibling:()=>this.a,highlightChanges:s,markGutter:o}),o?ht:[]]))}if(r){let t=zt.reconfigure(e.collapseUnchanged?Ft(e.collapseUnchanged):[]);i.push(t),a.push(t)}this.a.dispatch({effects:i}),this.b.dispatch({effects:a})}this.scheduleMeasure()}setupRevertControls(e,t,n){this.revertToA=t,this.revertToLeft=this.revertToA==(this.editorDOM.firstChild==this.a.dom.parentNode),this.renderRevert=n,!e&&this.revertDOM?(this.revertDOM.remove(),this.revertDOM=null):e&&!this.revertDOM?(this.revertDOM=this.editorDOM.insertBefore(document.createElement(`div`),this.editorDOM.firstChild.nextSibling),this.revertDOM.addEventListener(`mousedown`,e=>this.revertClicked(e)),this.revertDOM.className=`cm-merge-revert`):this.revertDOM&&(this.revertDOM.textContent=``)}scheduleMeasure(){if(this.measuring<0){let e=this.dom.ownerDocument.defaultView||window;this.measuring=e.requestAnimationFrame(()=>{this.measuring=-1,this.measure()})}}measure(){At(this.a,this.b,this.chunks),this.revertDOM&&this.updateRevertButtons()}updateRevertButtons(){let e=this.revertDOM,t=e.firstChild,n=this.a.viewport,r=this.b.viewport;for(let i=0;in.to||a.fromB>r.to)break;if(a.fromA-1&&(this.dom.ownerDocument.defaultView||window).cancelAnimationFrame(this.measuring),this.dom.remove()}};function Ht(e){let t=e.nextSibling;return e.remove(),t}var Ut=new class extends F{constructor(){super(...arguments),this.elementClass=`cm-deletedLineGutter`}},Wt=C.low(w({class:`cm-changeGutter`,markers:e=>e.plugin(mt)?.gutter||M.empty,widgetMarker:(e,t)=>t instanceof Jt?Ut:null}));function Gt(e){let t=typeof e.original==`string`?S.of(e.original.split(/\r?\n/)):e.original,n=e.diffConfig||pt;return[C.low(mt),$t,Rt,P.editorAttributes.of({class:`cm-merge-b`}),at.of((e,t)=>{let r=t.effects.find(e=>e.is(Kt));return r&&(e=Q.updateA(e,r.value.doc,t.startState.doc,r.value.changes,n)),t.docChanged&&(e=Q.updateB(e,t.state.field($),t.newDoc,t.changes,n)),e}),X.of({highlightChanges:e.highlightChanges!==!1,markGutter:e.gutter!==!1,syntaxHighlightDeletions:e.syntaxHighlightDeletions!==!1,syntaxHighlightDeletionsMaxLength:3e3,mergeControls:e.mergeControls??!0,overrideChunk:e.allowInlineDiffs?on:void 0,side:`b`}),$.init(()=>t),e.gutter===!1?[]:Wt,e.collapseUnchanged?Ft(e.collapseUnchanged):[],Z.init(e=>Q.build(t,e.doc,n))]}var Kt=j.define(),$=x.define({create:()=>S.empty,update(e,t){for(let n of t.effects)n.is(Kt)&&(e=n.value.doc);return e}}),qt=new WeakMap,Jt=class extends Ne{constructor(e){super(),this.buildDOM=e,this.dom=null}eq(e){return this.dom==e.dom}toDOM(e){return this.dom||=this.buildDOM(e)}};function Yt(e,t,n){let r=qt.get(t.changes);if(r)return r;let i=E.widget({block:!0,side:-1,widget:new Jt(r=>{let{highlightChanges:i,syntaxHighlightDeletions:a,syntaxHighlightDeletionsMaxLength:o,mergeControls:s}=e.facet(X),c=document.createElement(`div`);if(c.className=`cm-deletedChunk`,s){let t=c.appendChild(document.createElement(`div`));t.className=`cm-chunkButtons`;let n=e=>{e.preventDefault(),Xt(r,r.posAtDOM(c))},i=e=>{e.preventDefault(),Zt(r,r.posAtDOM(c))};if(typeof s==`function`)t.appendChild(s(`accept`,n)),t.appendChild(s(`reject`,i));else{let r=t.appendChild(document.createElement(`button`));r.name=`accept`,r.textContent=e.phrase(`Accept`),r.onmousedown=n;let a=t.appendChild(document.createElement(`button`));a.name=`reject`,a.textContent=e.phrase(`Reject`),a.onmousedown=i}}if(n||t.fromA>=t.toA)return c;let l=r.state.field($).sliceString(t.fromA,t.endA),u=a&&e.facet(De),d=h(),f=t.changes,p=0,m=!1;function h(){let e=c.appendChild(document.createElement(`div`));return e.className=`cm-deletedLine`,e.appendChild(document.createElement(`del`))}function g(e,t,n){for(let r=e;r-1&&sr){let t=document.createTextNode(l.slice(r,e));if(a){let e=d.appendChild(document.createElement(`span`));e.className=a,e.appendChild(t)}else d.appendChild(t);r=e}o&&(m=!m)}}if(u&&t.toA-t.fromA<=o){let t=u.parser.parse(l),n=0;we(t,{style:t=>Se(e,t)},(e,t,r)=>{e>n&&g(n,e,``),g(e,t,r),n=t}),g(n,l.length,``)}else g(0,l.length,``);return d.firstChild||d.appendChild(document.createElement(`br`)),c})});return qt.set(t.changes,i),i}function Xt(e,t){let{state:n}=e,r=t??n.selection.main.head,i=e.state.field(Z).find(e=>e.fromB<=r&&e.endB>=r);if(!i)return!1;let a=e.state.sliceDoc(i.fromB,Math.max(i.fromB,i.toB-1)),o=e.state.field($);i.fromB!=i.toB&&i.toA<=o.length&&(a+=e.state.lineBreak);let s=Me.of({from:i.fromA,to:Math.min(o.length,i.toA),insert:a},o.length);return e.dispatch({effects:Kt.of({doc:s.apply(o),changes:s}),userEvent:`accept`}),!0}function Zt(e,t){let{state:n}=e,r=t??n.selection.main.head,i=n.field(Z).find(e=>e.fromB<=r&&e.endB>=r);if(!i)return!1;let a=n.field($).sliceString(i.fromA,Math.max(i.fromA,i.toA-1));return i.fromA!=i.toA&&i.toB<=n.doc.length&&(a+=n.lineBreak),e.dispatch({changes:{from:i.fromB,to:Math.min(n.doc.length,i.toB),insert:a},userEvent:`revert`}),!0}function Qt(e){let t=new y;for(let n of e.field(Z)){let r=e.facet(X).overrideChunk&&tn(e,n);t.add(n.fromB,n.fromB,Yt(e,n,!!r))}return t.finish()}var $t=x.define({create:e=>Qt(e),update(e,t){return t.state.field(Z,!1)==t.startState.field(Z,!1)?e:Qt(t.state)},provide:e=>P.decorations.from(e)}),en=new WeakMap;function tn(e,t){let n=en.get(t);if(n!==void 0)return n;n=null;let r=e.field($),i=e.doc,a=r.lineAt(t.endA).number-r.lineAt(t.fromA).number+1,o=i.lineAt(t.endB).number-i.lineAt(t.fromB).number+1;abort:if(a==o&&a<10){let e=[],i=0,o=t.fromA,s=t.fromB;for(let n of t.changes){if(n.fromA=t.endB)break;o=e.doc.lineAt(o.to+1)}return!0}var sn=A({String:k.string,Number:k.number,"True False":k.bool,PropertyName:k.propertyName,Null:k.null,", :":k.separator,"[ ]":k.squareBracket,"{ }":k.brace}),cn=Ce.deserialize({version:14,states:"$bOVQPOOOOQO'#Cb'#CbOnQPO'#CeOvQPO'#ClOOQO'#Cr'#CrQOQPOOOOQO'#Cg'#CgO}QPO'#CfO!SQPO'#CtOOQO,59P,59PO![QPO,59PO!aQPO'#CuOOQO,59W,59WO!iQPO,59WOVQPO,59QOqQPO'#CmO!nQPO,59`OOQO1G.k1G.kOVQPO'#CnO!vQPO,59aOOQO1G.r1G.rOOQO1G.l1G.lOOQO,59X,59XOOQO-E6k-E6kOOQO,59Y,59YOOQO-E6l-E6l",stateData:`#O~OeOS~OQSORSOSSOTSOWQO_ROgPO~OVXOgUO~O^[O~PVO[^O~O]_OVhX~OVaO~O]bO^iX~O^dO~O]_OVha~O]bO^ia~O`,goto:"!kjPPPPPPkPPkqwPPPPk{!RPPP!XP!e!hXSOR^bQWQRf_TVQ_Q`WRg`QcZRicQTOQZRQe^RhbRYQR]R",nodeNames:`⚠ JsonText True False Null Number String } { Object Property PropertyName : , ] [ Array`,maxTerm:25,nodeProps:[[`isolate`,-2,6,11,``],[`openedBy`,7,`{`,14,`[`],[`closedBy`,8,`}`,15,`]`]],propSources:[sn],skippedNodes:[0],repeatNodeCount:2,tokenData:"(|~RaXY!WYZ!W]^!Wpq!Wrs!]|}$u}!O$z!Q!R%T!R![&c![!]&t!}#O&y#P#Q'O#Y#Z'T#b#c'r#h#i(Z#o#p(r#q#r(w~!]Oe~~!`Wpq!]qr!]rs!xs#O!]#O#P!}#P;'S!];'S;=`$o<%lO!]~!}Og~~#QXrs!]!P!Q!]#O#P!]#U#V!]#Y#Z!]#b#c!]#f#g!]#h#i!]#i#j#m~#pR!Q![#y!c!i#y#T#Z#y~#|R!Q![$V!c!i$V#T#Z$V~$YR!Q![$c!c!i$c#T#Z$c~$fR!Q![!]!c!i!]#T#Z!]~$rP;=`<%l!]~$zO]~~$}Q!Q!R%T!R![&c~%YRT~!O!P%c!g!h%w#X#Y%w~%fP!Q![%i~%nRT~!Q![%i!g!h%w#X#Y%w~%zR{|&T}!O&T!Q![&Z~&WP!Q![&Z~&`PT~!Q![&Z~&hST~!O!P%c!Q![&c!g!h%w#X#Y%w~&yO[~~'OO_~~'TO^~~'WP#T#U'Z~'^P#`#a'a~'dP#g#h'g~'jP#X#Y'm~'rOR~~'uP#i#j'x~'{P#`#a(O~(RP#`#a(U~(ZOS~~(^P#f#g(a~(dP#i#j(g~(jP#X#Y(m~(rOQ~~(wOW~~(|OV~",tokenizers:[0],topRules:{JsonText:[0,1]},tokenPrec:0}),ln=Ee.define({name:`json`,parser:cn.configure({props:[O.add({Object:D({except:/^\s*\}/}),Array:D({except:/^\s*\]/})}),je.add({"Object Array":N})]}),languageData:{closeBrackets:{brackets:[`[`,`{`,`"`]},indentOnInput:/^\s*[\}\]]$/}});function un(){return new ke(ln)}var dn={class:`space-y-6`},fn={class:`flex items-end justify-between gap-4 flex-wrap`},pn={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},mn={class:`flex items-center gap-2`},hn={class:`pb-5 border-b border-border`},gn={class:`grid gap-3 sm:gap-4 sm:grid-cols-[1fr_auto_1fr] items-end`},_n={class:`space-y-1.5`},vn=[`value`],yn=[`value`,`disabled`],bn=[`disabled`],xn={class:`space-y-1.5`},Sn=[`value`],Cn=[`value`,`disabled`],wn={key:0,class:`mt-4 flex flex-wrap items-center gap-2 justify-end`},Tn={key:0,class:`text-sm text-foreground-muted py-12 text-center`},En={key:1,class:`text-sm text-foreground-muted py-12 text-center`},Dn={key:2,class:`bg-warning/10 border border-warning/30 rounded-lg p-5 space-y-3 text-sm`},On={key:0,class:`font-mono text-xs space-y-1`},kn=[`title`,`onClick`],An={key:1,class:`text-warning/90`},jn={key:1,class:`text-warning/70 italic text-xs`},Mn={key:3,class:`bg-danger/10 border border-danger/30 rounded-lg p-5 text-sm text-danger`},Nn={key:4,class:`bg-danger/10 border border-danger/30 rounded-lg p-5 text-sm text-danger`},Pn={key:0,class:`text-xs text-foreground-muted -mt-2`},Fn={key:1,class:`bg-background border border-border rounded-lg`},In={class:`px-4 py-3 flex items-center justify-between gap-3`},Ln={class:`text-xs font-bold uppercase tracking-wider text-foreground-muted flex items-center gap-2`},Rn={class:`text-[10px] px-1.5 py-0.5 rounded bg-warning/15 text-warning border border-warning/30 font-medium tracking-normal normal-case`},zn=[`aria-label`],Bn={key:0,class:`px-4 pb-4 pt-3 border-t border-border/60`},Vn={class:`font-mono text-xs space-y-1`},Hn={key:2,class:`bg-background border border-border rounded-lg overflow-hidden`},Un={class:`px-4 py-2.5 flex items-center justify-between gap-3 bg-surface border-b border-border`},Wn={class:`text-xs font-bold uppercase tracking-wider text-white flex items-center gap-2`},Gn={class:`font-mono normal-case tracking-normal text-sm font-medium`},Kn={key:0,class:`text-[10px] px-1.5 py-0.5 rounded bg-success/15 text-success border border-success/30 font-medium tracking-normal normal-case`},qn={key:1,class:`text-[10px] px-1.5 py-0.5 rounded bg-danger/15 text-danger border border-danger/30 font-medium tracking-normal normal-case`},Jn=[`title`,`aria-pressed`],Yn={key:3,class:`bg-background border border-border rounded-lg overflow-hidden`},Xn={class:`px-4 py-2.5 flex items-center justify-between gap-3 bg-surface border-b border-border`},Zn={class:`text-xs font-bold uppercase tracking-wider text-foreground-muted flex items-center gap-2`},Qn={class:`font-mono normal-case tracking-normal text-white text-sm font-medium`},$n=[`aria-label`],er={key:4,class:`text-sm text-foreground-muted py-12 text-center`},tr=`orva:diff:sideBySide`,nr={__name:`FunctionDiff`,setup(he){let y=_e(),ve=ge(),b=g(()=>y.params.name),x=g(()=>y.query.from||``),S=g(()=>y.query.to||``),C=r(null),w=r([]),T=r(null),E=r(``),xe=r(``),D=r([]),Se=r(`Copy link`),O=r(!0),k=r(!0),A=r(!1),Ce=me(),j=r(!0),M=r(null),N=g(()=>M.value===null?j.value:M.value);try{let e=typeof window<`u`&&window.localStorage?.getItem?.(tr);e===`true`?M.value=!0:e===`false`&&(M.value=!1)}catch{}let we=()=>{let e=!N.value;M.value=e;try{window.localStorage?.setItem?.(tr,String(e))}catch{}V()},Ee=r(null),De=r(null),ke=null,je=null,Me=g(()=>C.value?.runtime?.startsWith(`python`)?[Te()]:[Oe()]),Ne=P.theme({"&.cm-merge-a .cm-changedLine":{backgroundColor:`rgba(248, 81, 73, 0.15)`},"&.cm-merge-b .cm-changedLine":{backgroundColor:`rgba(63, 185, 80, 0.15)`},"&.cm-merge-a .cm-changedText":{background:`none`,backgroundColor:`rgba(248, 81, 73, 0.35)`,borderRadius:`2px`},"&.cm-merge-b .cm-changedText":{background:`none`,backgroundColor:`rgba(63, 185, 80, 0.30)`,borderRadius:`2px`},"&.cm-merge-a .cm-changedLineGutter":{color:`#f85149`},"&.cm-merge-b .cm-changedLineGutter":{color:`#3fb950`},".cm-deletedChunk":{backgroundColor:`rgba(248, 81, 73, 0.15)`},".cm-deletedChunk .cm-deletedText":{background:`none`,backgroundColor:`rgba(248, 81, 73, 0.35)`,borderRadius:`2px`},".cm-deletedChunk .cm-changedLineGutter, .cm-deletedChunk .cm-deletedLineGutter":{color:`#f85149`},".cm-insertedLine, .cm-changedLine, .cm-inlineChangedLine":{backgroundColor:`rgba(63, 185, 80, 0.15)`},".cm-changedLine .cm-changedText, .cm-inlineChangedLine .cm-changedText":{background:`none`,backgroundColor:`rgba(63, 185, 80, 0.30)`,borderRadius:`2px`},".cm-changedLineGutter, .cm-inlineChangedLineGutter":{color:`#3fb950`}}),F=e=>[be,...e,Ae,Ne,ye.readOnly.of(!0),P.lineWrapping],I=null,L=()=>{if(typeof window>`u`||!window.matchMedia)return;let e=window.matchMedia(`(min-width: 768px)`),t=e=>{let t=!!e.matches;t!==j.value&&(j.value=t,M.value===null&&V())};t(e),e.addEventListener?(e.addEventListener(`change`,t),I=()=>e.removeEventListener(`change`,t)):(e.addListener(t),I=()=>e.removeListener(t))},R=(e,t,n,r)=>e?N.value?new Vt({a:{doc:t,extensions:F(r)},b:{doc:n,extensions:F(r)},parent:e,orientation:`a-b`,revertControls:!1,highlightChanges:!0,gutter:!0}):new P({parent:e,state:ye.create({doc:n,extensions:[...F(r),Gt({original:t,mergeControls:!1})]})}):null,z=()=>{je?.destroy?.(),je=null},B=()=>{ke?.destroy?.(),z(),ke=null},Re=()=>{let e=U.value;!e||!k.value||e.before===e.after&&!e.added&&!e.removed||(je=R(De.value,e.before||``,e.after||``,[un()]))},V=async()=>{if(await ee(),B(),!T.value)return;let e=H.value;e&&(ke=R(Ee.value,e.before||``,e.after||``,Me.value)),Re()},ze=async()=>{if(E.value=``,xe.value=``,T.value=null,B(),!(!C.value||!x.value||!S.value||x.value===S.value))try{let e=await de(C.value.id,x.value,S.value,`json`);T.value=e.data,await V()}catch(e){let t=e.response?.data?.error;E.value=t?.code||`INTERNAL`,xe.value=t?.message||e.message||`Failed to load diff.`,E.value===`VERSION_GCD`&&(D.value=t?.details?.available_hashes||[])}},H=g(()=>T.value?.files?.find(e=>e.kind===`handler`)),U=g(()=>T.value?.files?.find(e=>e.kind===`manifest`)),W=g(()=>{let e=T.value?.from?.snapshot,t=T.value?.to?.snapshot;return!e||!t?[]:Fe(e,t)}),Be=e=>e.startsWith(`+`)?`text-success`:e.startsWith(`-`)?`text-danger`:`text-warning`,Ve=g(()=>{let e=C.value?.code_hash||``;return w.value.filter(e=>e.status===`succeeded`&&e.code_hash).map(t=>({id:t.id,version:t.version,shortHash:(t.code_hash||``).slice(0,12),submittedAt:t.submitted_at,isActive:!!e&&t.code_hash===e}))}),He=e=>{if(!e)return``;let t=new Date(e);return`${t.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} ${t.toLocaleTimeString(void 0,{hour:`numeric`,minute:`2-digit`})}`},Ue=e=>`v${e.version} · ${e.shortHash} · ${He(e.submittedAt)}${e.isActive?` · active`:``}`,G=({from:e,to:t})=>{ve.replace({query:{from:e??x.value,to:t??S.value}})},We=()=>{!x.value||!S.value||ve.replace({query:{from:S.value,to:x.value}})},Ge=async()=>{let e=await Pe(window.location.href);Se.value=e?`Copied!`:`Copy failed`,setTimeout(()=>{Se.value=`Copy link`},1500)},K=g(()=>{let e=C.value?.code_hash;return e&&w.value.find(t=>t.status===`succeeded`&&t.code_hash===e)?.id||null}),q=g(()=>w.value.find(e=>e.id===x.value)||null),Ke=g(()=>!!(q.value&&C.value?.code_hash&&q.value.code_hash===C.value.code_hash)),qe=()=>{if(!K.value||!C.value)return;let e=C.value.code_hash,t=w.value.filter(t=>t.status===`succeeded`&&t.code_hash&&t.code_hash!==e)[0];G({from:t?.id||x.value,to:K.value})},J=e=>w.value.find(t=>t.code_hash===e)||null,Je=e=>{let t=J(e);if(!t)return;let n=w.value.find(e=>e.id===S.value);n&&D.value.length&&!D.value.includes(n.code_hash)?G({from:t.id,to:K.value||S.value}):G({from:t.id,to:S.value})},Ye=async()=>{try{let e=((await se()).data?.functions||[]).find(e=>e.name===b.value);e&&(C.value=e);let t=await le(C.value.id,100);w.value=t.data.deployments||t.data||[]}catch{}},Xe=async()=>{if(A.value||!C.value||!q.value||Ke.value)return;let e=q.value,t=(e.code_hash||``).slice(0,12),n=`Code hash ${t}. The current version stays in history.`;try{let r=(await fe(e.id))?.data?.snapshot;if(r){let i=Fe(C.value,r);n=i.length?`Rolling back to v${e.version} (code ${t}) will also change:\n\n${i.join(` `)}\n\nSecrets keep their current values; they aren't part of the rollback.`:`Rolling back to v${e.version} (code ${t}). Settings and env are already identical, so only the code changes.`}}catch{}if(await Ce.ask({title:`Restore v${e.version}?`,message:n,confirmLabel:`Rollback`})){A.value=!0;try{let n=await pe(C.value.id,{deployment_id:e.id}),r=n?.data?.id||n?.data?.deployment_id;await Ye(),r&&G({from:x.value,to:r}),Ce.notify({title:`Rollback complete`,message:`v${e.version} (code ${t}) is now serving.`})}catch(e){let t=e.response?.data?.error?.code||``,n=e.response?.data?.error?.message||e.message||`Rollback failed`;t===`VERSION_GCD`?Ce.notify({title:`Version unavailable`,message:`This version has been garbage-collected and can no longer be restored.\n\n${n}`,danger:!0}):Ce.notify({title:`Rollback failed`,message:n,danger:!0})}finally{A.value=!1}}};return a(async()=>{L();try{let e=((await se()).data?.functions||[]).find(e=>e.name===b.value);if(!e)throw Error(`not found`);C.value=e}catch(e){E.value=e.response?.data?.error?.code||`FUNCTION_NOT_FOUND`,xe.value=e.response?.data?.error?.message||`Function not found.`;return}try{let e=await le(C.value.id,100);w.value=e.data.deployments||e.data||[]}catch{w.value=[]}await ze()}),i(k,async e=>{await ee(),z(),e&&Re()}),i([x,S],ze),i(()=>C.value?.runtime,()=>{V()}),t(()=>{B(),I?.()}),(t,r)=>{let i=d(`router-link`);return e(),c(`div`,dn,[s(`div`,fn,[s(`div`,null,[r[7]||=s(`h1`,{class:`text-xl font-semibold text-white tracking-tight text-balance`},` Compare versions `,-1),s(`p`,pn,[r[5]||=m(` Compare source and configuration for `,-1),u(i,{to:`/functions/${b.value}`,class:`text-white underline`},{default:n(()=>[m(v(b.value),1)]),_:1},8,[`to`]),r[6]||=m(`. `,-1)])]),s(`div`,mn,[s(`button`,{class:`text-xs text-foreground-muted hover:text-white hover:bg-surface-hover rounded-md flex items-center justify-center gap-1.5 px-2 py-1.5 transition-colors min-w-[6rem] focus:outline-none focus-visible:ring-1 focus-visible:ring-white`,title:`Copy share link`,"aria-label":`Copy share link`,onClick:Ge},[u(o(te),{class:`w-3.5 h-3.5`}),m(` `+v(Se.value),1)]),u(ue,{variant:`secondary`,onClick:r[0]||=e=>t.$router.push(`/functions/${b.value}/deployments`)},{default:n(()=>[u(o(Le),{class:`w-4 h-4 mr-2`}),r[8]||=m(` All deployments `,-1)]),_:1})])]),s(`div`,hn,[s(`div`,gn,[s(`div`,_n,[r[10]||=s(`label`,{for:`diff-from`,class:`block text-xs font-medium uppercase tracking-label text-foreground-muted`},[m(` From `),s(`span`,{class:`ml-1 text-foreground-muted/60 normal-case font-medium tracking-normal`},`(older)`)],-1),s(`select`,{id:`diff-from`,value:x.value,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:r[1]||=e=>G({from:e.target.value})},[r[9]||=s(`option`,{value:``,disabled:``},` Pick a version `,-1),(e(!0),c(h,null,f(Ve.value,t=>(e(),c(`option`,{key:t.id,value:t.id,disabled:t.id===S.value},v(Ue(t)),9,yn))),128))],40,vn)]),s(`button`,{disabled:!x.value||!S.value,class:`justify-self-center sm:self-end mb-1 h-9 w-9 flex items-center justify-center rounded-md text-foreground-muted hover:text-white hover:bg-surface-hover transition-colors disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-foreground-muted`,title:`Swap from / to`,"aria-label":`Swap from and to versions`,onClick:We},[u(o(Ie),{class:`w-4 h-4 rotate-90 sm:rotate-0 motion-reduce:transition-none transition-transform`})],8,bn),s(`div`,xn,[r[12]||=s(`label`,{for:`diff-to`,class:`block text-xs font-medium uppercase tracking-label text-foreground-muted`},[m(` To `),s(`span`,{class:`ml-1 text-foreground-muted/60 normal-case font-medium tracking-normal`},`(newer)`)],-1),s(`select`,{id:`diff-to`,value:S.value,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:r[2]||=e=>G({to:e.target.value})},[r[11]||=s(`option`,{value:``,disabled:``},` Pick a version `,-1),(e(!0),c(h,null,f(Ve.value,t=>(e(),c(`option`,{key:t.id,value:t.id,disabled:t.id===x.value},v(Ue(t)),9,Cn))),128))],40,Sn)])]),C.value?(e(),c(`div`,wn,[K.value&&S.value!==K.value?(e(),c(`button`,{key:0,class:`inline-flex items-center gap-1.5 text-xs text-foreground-muted hover:text-white hover:bg-surface-hover rounded-md px-2.5 py-1.5 transition-colors`,title:`Compare previous version with currently active`,onClick:qe},[u(o(oe),{class:`w-3.5 h-3.5`}),r[13]||=m(` vs active `,-1)])):_(``,!0),q.value&&!Ke.value?(e(),p(ue,{key:1,variant:`primary`,size:`sm`,loading:A.value,disabled:A.value,onClick:Xe},{default:n(()=>[u(o(ae),{class:`w-3.5 h-3.5 mr-1.5`}),m(` Roll back to v`+v(q.value.version),1)]),_:1},8,[`loading`,`disabled`])):_(``,!0)])):_(``,!0)]),!x.value||!S.value?(e(),c(`p`,Tn,` Pick two different deployments above to compare. `)):x.value===S.value?(e(),c(`p`,En,` Same version on both sides. Pick a different deployment to see a diff. `)):E.value===`VERSION_GCD`?(e(),c(`div`,Dn,[r[14]||=s(`div`,{class:`text-warning font-medium`},` Source data for one or both versions has been garbage-collected. `,-1),r[15]||=s(`p`,{class:`text-warning/80 leading-body`},` The deployment row still exists, but the on-disk code tree was pruned by the version GC. Pick a version whose source is still archived: `,-1),D.value.length?(e(),c(`ul`,On,[(e(!0),c(h,null,f(D.value,t=>(e(),c(`li`,{key:t},[J(t)?(e(),c(`button`,{key:0,class:`text-left text-warning hover:text-white hover:bg-warning/15 rounded px-1.5 py-0.5 -mx-1.5 transition-colors`,title:`Use v${J(t).version} as the From side`,onClick:e=>Je(t)},` v`+v(J(t).version)+` · `+v(t.slice(0,12))+`… · `+v(He(J(t).submitted_at)),9,kn)):(e(),c(`span`,An,v(t.slice(0,12))+`…`,1))]))),128))])):(e(),c(`p`,jn,` No surviving on-disk versions for this function. Redeploy the original source to compare against the current code. `))])):E.value===`VERSION_NOT_FOUND`?(e(),c(`div`,Mn,[r[17]||=m(` One of the supplied deployment IDs doesn't exist. Pick from the dropdowns above, or go back to the `,-1),u(i,{to:`/functions/${b.value}/deployments`,class:`underline`},{default:n(()=>[...r[16]||=[m(` deployment history `,-1)]]),_:1},8,[`to`]),r[18]||=m(`. `,-1)])):E.value&&E.value!==`OK`?(e(),c(`div`,Nn,v(xe.value||`Failed to load diff.`),1)):T.value?(e(),c(h,{key:5},[W.value.length?(e(),c(`section`,Fn,[s(`header`,In,[s(`h2`,Ln,[u(o(ie),{class:`w-3.5 h-3.5`}),r[19]||=m(` Settings & env `,-1),s(`span`,Rn,v(W.value.length)+` change`+v(W.value.length===1?``:`s`),1)]),s(`button`,{class:`text-foreground-muted hover:text-white`,"aria-label":O.value?`Collapse settings diff`:`Expand settings diff`,onClick:r[3]||=e=>O.value=!O.value},[u(o(ce),{class:l([`w-4 h-4 transition-transform motion-reduce:transition-none`,{"rotate-180":O.value}])},null,8,[`class`])],8,zn)]),O.value?(e(),c(`div`,Bn,[s(`ul`,Vn,[(e(!0),c(h,null,f(W.value,(t,n)=>(e(),c(`li`,{key:n,class:l(Be(t))},v(t),3))),128))]),r[20]||=s(`p`,{class:`text-[11px] text-foreground-muted/70 mt-3`},` Secrets aren't tracked per-version; they always reflect the current values. `,-1)])):_(``,!0)])):(e(),c(`p`,Pn,` Settings and env are identical between these versions. Secrets aren't tracked per-version. `)),H.value?(e(),c(`section`,Hn,[s(`header`,Un,[s(`h2`,Wn,[u(o(re),{class:`w-3.5 h-3.5 text-foreground-muted`}),s(`span`,Gn,v(H.value.path),1),H.value.added?(e(),c(`span`,Kn,`added`)):H.value.removed?(e(),c(`span`,qn,`removed`)):_(``,!0)]),s(`button`,{class:`text-[10px] font-medium uppercase tracking-label text-foreground-muted hover:text-white hover:bg-surface-hover rounded px-2 py-1 transition-colors`,title:N.value?`Switch to unified inline view`:`Switch to side-by-side view`,"aria-pressed":N.value,onClick:we},v(N.value?`side-by-side`:`unified`),9,Jn)]),s(`div`,{ref_key:`codeMountRef`,ref:Ee,class:`orva-merge`},null,512)])):_(``,!0),U.value&&(U.value.before!==U.value.after||U.value.added||U.value.removed)?(e(),c(`section`,Yn,[s(`header`,Xn,[s(`h2`,Zn,[u(o(ne),{class:`w-3.5 h-3.5`}),s(`span`,Qn,v(U.value.path),1),r[21]||=s(`span`,{class:`text-[10px] px-1.5 py-0.5 rounded bg-warning/15 text-warning border border-warning/30 font-medium tracking-normal normal-case`},` changed `,-1)]),s(`button`,{class:`text-foreground-muted hover:text-white`,"aria-label":k.value?`Collapse manifest diff`:`Expand manifest diff`,onClick:r[4]||=e=>k.value=!k.value},[u(o(ce),{class:l([`w-4 h-4 transition-transform motion-reduce:transition-none`,{"rotate-180":k.value}])},null,8,[`class`])],8,$n)]),k.value?(e(),c(`div`,{key:0,ref_key:`manifestMountRef`,ref:De,class:`orva-merge`},null,512)):_(``,!0)])):_(``,!0),!H.value&&!U.value?(e(),c(`p`,er,` No code changes between these versions. `)):_(``,!0)],64)):_(``,!0)])}}};export{nr as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/FunctionsList-CPOzZCfJ.js b/backend/internal/server/ui_dist/assets/FunctionsList-CqkUOCmN.js similarity index 96% rename from backend/internal/server/ui_dist/assets/FunctionsList-CPOzZCfJ.js rename to backend/internal/server/ui_dist/assets/FunctionsList-CqkUOCmN.js index d5df68c5..574aba46 100644 --- a/backend/internal/server/ui_dist/assets/FunctionsList-CPOzZCfJ.js +++ b/backend/internal/server/ui_dist/assets/FunctionsList-CqkUOCmN.js @@ -1,3 +1,3 @@ -import{D as e,E as t,F as n,G as r,I as ee,S as te,T as ne,Z as i,c as a,d as o,gt as re,h as s,k as c,l as ie,m as l,r as u,s as d,u as f,vt as p,w as ae}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as oe}from"./check-BNre7JFR.js";import{t as se}from"./copy-BqdwwcxC.js";import{t as m}from"./globe-BnBar2lO.js";import{t as h}from"./lock-CttMBTH5.js";import{t as g}from"./pencil-Do2I7soU.js";import{t as ce}from"./refresh-cw-Cn8qkf-v.js";import{t as _}from"./trash-2-DaeYqnW_.js";import{t as v}from"./client-BF51V3uE.js";import{B as le,Et as ue,Lt as de,Mt as fe,St as y,_t as b,gt as pe,mt as me,r as he,xt as ge}from"./index-DTqMKlE1.js";import{t as _e}from"./clipboard-D_9N0yai.js";import{t as x}from"./IconButton-CsCZOqWo.js";var ve={class:`space-y-6`},ye={class:`flex items-start justify-between gap-4 flex-wrap`},be={key:0,class:`space-y-3`},xe={class:`flex items-center gap-2 flex-wrap`},Se={class:`relative flex-1 min-w-0 sm:min-w-[280px] max-w-full sm:max-w-[440px]`},S={class:`text-[11px] text-foreground-muted shrink-0 tabular-nums`},C={class:`bg-background border border-border rounded-lg overflow-x-auto`},w={class:`sm:hidden divide-y divide-border`},T={class:`flex items-start justify-between gap-2`},E={class:`min-w-0 flex-1`},D={class:`flex items-center gap-1.5 flex-wrap`},O={class:`font-medium text-white truncate`},k={key:0,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-warning-tint text-warning-fg border border-warning-ring`},A={key:1,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-info-tint text-info-fg border border-info-ring`},j={key:0,class:`mt-1 text-xs text-foreground-muted line-clamp-2`},Ce={class:`mt-1.5 flex items-center gap-3 text-[11px] text-foreground-muted font-mono`},we={class:`flex items-center gap-1 shrink-0`},Te={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted space-y-3`},Ee={class:`hidden sm:table w-full text-sm text-left`},De={class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},Oe={class:`px-4 py-3 w-8`},ke=[`checked`,`.indeterminate`],Ae={class:`divide-y divide-border`},je={class:`px-4 py-3 align-middle`},Me=[`checked`,`onChange`],Ne={class:`px-4 py-3 font-medium text-white`},Pe={class:`flex items-center gap-2 flex-wrap`},Fe={key:0,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-warning-tint text-warning-fg border border-warning-ring`,title:`Outbound network enabled`},Ie=[`title`],Le=[`title`],Re=[`title`],ze={class:`px-4 py-3 text-foreground hidden sm:table-cell`},Be={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border border-border bg-background text-foreground-muted font-mono`},M={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden lg:table-cell`},Ve={class:`px-4 py-3 hidden md:table-cell align-middle`},He={class:`flex items-center gap-2 min-w-0`},Ue=[`title`],We={class:`px-4 py-3 text-foreground-muted hidden xl:table-cell`},Ge={class:`px-4 py-3 text-right`},Ke={class:`inline-flex items-center gap-1`},qe={key:0},Je={colspan:`7`,class:`px-6 py-8 text-center text-foreground-muted`},Ye={class:`space-y-3`},Xe={key:0,class:`flex justify-center border-t border-border py-3 bg-surface/30`},Ze=[`disabled`],Qe={key:1,class:`bg-background border border-border rounded-lg p-8 text-center space-y-4`},$e={key:0,class:`fixed bottom-[calc(1rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 z-30 flex items-center gap-3 bg-background border border-border shadow-lg rounded-full pl-4 pr-2 py-2`},et={class:`text-xs text-white`},tt=25,nt={__name:`FunctionsList`,setup(nt){let N=pe(),P=me(),F=r([]),I=r(0),L=r(!1),R=r(``),z=r(``),B=r(``),V=r(!1),H=r(new Set),U=d(()=>{let e=R.value.trim().toLowerCase();return e?F.value.filter(t=>t.name?.toLowerCase().includes(e)||t.description?.toLowerCase().includes(e)||t.runtime?.toLowerCase().includes(e)||t.id?.toLowerCase().includes(e)):F.value}),rt=d(()=>F.value.lengthU.value.length>0&&U.value.every(e=>H.value.has(e.id))),it=d(()=>U.value.some(e=>H.value.has(e.id))),at=e=>{let t=new Set(H.value);t.has(e)?t.delete(e):t.add(e),H.value=t},ot=()=>{if(W.value)H.value=new Set;else{let e=new Set(H.value);U.value.forEach(t=>e.add(t.id)),H.value=e}},G=e=>`${window.location.origin}/fn/${e.id}`,st=async e=>{await _e(G(e))?(z.value=e.id,setTimeout(()=>{z.value===e.id&&(z.value=``)},1500)):N.notify({title:`Copy failed`,message:`Could not copy to clipboard. URL: +import{D as e,E as t,F as n,G as r,I as ee,S as te,T as ne,Z as i,c as a,d as o,gt as re,h as s,k as c,l as ie,m as l,r as u,s as d,u as f,vt as p,w as ae}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as oe}from"./check-CZmR72iA.js";import{t as se}from"./copy-3UAsea5P.js";import{t as m}from"./globe-DJC2u-h_.js";import{t as h}from"./lock-n1lM5kKa.js";import{t as g}from"./pencil-BmuCVcyO.js";import{t as ce}from"./refresh-cw-CEfUzOcv.js";import{t as _}from"./trash-2-Cz9PSE2q.js";import{t as v}from"./client-BF51V3uE.js";import{B as le,Et as ue,Lt as de,Mt as fe,St as y,_t as b,gt as pe,mt as me,r as he,xt as ge}from"./index-pE9wnfTb.js";import{t as _e}from"./clipboard-D_9N0yai.js";import{t as x}from"./IconButton-CsCZOqWo.js";var ve={class:`space-y-6`},ye={class:`flex items-start justify-between gap-4 flex-wrap`},be={key:0,class:`space-y-3`},xe={class:`flex items-center gap-2 flex-wrap`},Se={class:`relative flex-1 min-w-0 sm:min-w-[280px] max-w-full sm:max-w-[440px]`},S={class:`text-[11px] text-foreground-muted shrink-0 tabular-nums`},C={class:`bg-background border border-border rounded-lg overflow-x-auto`},w={class:`sm:hidden divide-y divide-border`},T={class:`flex items-start justify-between gap-2`},E={class:`min-w-0 flex-1`},D={class:`flex items-center gap-1.5 flex-wrap`},O={class:`font-medium text-white truncate`},k={key:0,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-warning-tint text-warning-fg border border-warning-ring`},A={key:1,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-info-tint text-info-fg border border-info-ring`},j={key:0,class:`mt-1 text-xs text-foreground-muted line-clamp-2`},Ce={class:`mt-1.5 flex items-center gap-3 text-[11px] text-foreground-muted font-mono`},we={class:`flex items-center gap-1 shrink-0`},Te={key:0,class:`px-6 py-8 text-center text-sm text-foreground-muted space-y-3`},Ee={class:`hidden sm:table w-full text-sm text-left`},De={class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},Oe={class:`px-4 py-3 w-8`},ke=[`checked`,`.indeterminate`],Ae={class:`divide-y divide-border`},je={class:`px-4 py-3 align-middle`},Me=[`checked`,`onChange`],Ne={class:`px-4 py-3 font-medium text-white`},Pe={class:`flex items-center gap-2 flex-wrap`},Fe={key:0,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-warning-tint text-warning-fg border border-warning-ring`,title:`Outbound network enabled`},Ie=[`title`],Le=[`title`],Re=[`title`],ze={class:`px-4 py-3 text-foreground hidden sm:table-cell`},Be={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border border-border bg-background text-foreground-muted font-mono`},M={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden lg:table-cell`},Ve={class:`px-4 py-3 hidden md:table-cell align-middle`},He={class:`flex items-center gap-2 min-w-0`},Ue=[`title`],We={class:`px-4 py-3 text-foreground-muted hidden xl:table-cell`},Ge={class:`px-4 py-3 text-right`},Ke={class:`inline-flex items-center gap-1`},qe={key:0},Je={colspan:`7`,class:`px-6 py-8 text-center text-foreground-muted`},Ye={class:`space-y-3`},Xe={key:0,class:`flex justify-center border-t border-border py-3 bg-surface/30`},Ze=[`disabled`],Qe={key:1,class:`bg-background border border-border rounded-lg p-8 text-center space-y-4`},$e={key:0,class:`fixed bottom-[calc(1rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 z-30 flex items-center gap-3 bg-background border border-border shadow-lg rounded-full pl-4 pr-2 py-2`},et={class:`text-xs text-white`},tt=25,nt={__name:`FunctionsList`,setup(nt){let N=pe(),P=me(),F=r([]),I=r(0),L=r(!1),R=r(``),z=r(``),B=r(``),V=r(!1),H=r(new Set),U=d(()=>{let e=R.value.trim().toLowerCase();return e?F.value.filter(t=>t.name?.toLowerCase().includes(e)||t.description?.toLowerCase().includes(e)||t.runtime?.toLowerCase().includes(e)||t.id?.toLowerCase().includes(e)):F.value}),rt=d(()=>F.value.lengthU.value.length>0&&U.value.every(e=>H.value.has(e.id))),it=d(()=>U.value.some(e=>H.value.has(e.id))),at=e=>{let t=new Set(H.value);t.has(e)?t.delete(e):t.add(e),H.value=t},ot=()=>{if(W.value)H.value=new Set;else{let e=new Set(H.value);U.value.forEach(t=>e.add(t.id)),H.value=e}},G=e=>`${window.location.origin}/fn/${e.id}`,st=async e=>{await _e(G(e))?(z.value=e.id,setTimeout(()=>{z.value===e.id&&(z.value=``)},1500)):N.notify({title:`Copy failed`,message:`Could not copy to clipboard. URL: `+G(e)})},K=async e=>{L.value=!0;try{let t=await le({limit:tt,offset:e}),n=t.data.functions||[];I.value=t.data.total??n.length,e===0?F.value=n:F.value=[...F.value,...n]}catch(e){console.error(e)}finally{L.value=!1}},ct=()=>K(F.value.length),q=()=>K(0),J=async e=>{if(await N.ask({title:`Delete "${e.name}"?`,message:`This is irreversible. Code, deployments, secrets, and routes for this function are removed.`,confirmLabel:`Delete`,danger:!0})){B.value=e.id;try{await v.delete(`/functions/${e.id}`),await q(),H.value.delete(e.id),H.value=new Set(H.value)}catch(e){let t=e.response?.data?.error?.message||e.message||`Delete failed`;N.notify({title:`Delete failed`,message:t,danger:!0})}finally{B.value=``}}},lt=async()=>{let e=H.value.size;if(!await N.ask({title:`Delete ${e} ${e===1?`function`:`functions`}?`,message:`Each one is irreversible. Code, deployments, secrets, and routes are removed.`,confirmLabel:`Delete ${e}`,danger:!0}))return;V.value=!0;let t=[...H.value],n=0;try{for(let e of t)try{await v.delete(`/functions/${e}`)}catch{n++}H.value=new Set,await q(),n&&N.notify({title:`Some deletes failed`,message:`${n} of ${t.length} could not be deleted.`,danger:!0})}finally{V.value=!1}},Y=he(),X=null,Z=()=>{X||=setTimeout(()=>{X=null,K(0)},300)},Q=null,$=null;return ne(()=>{K(0),Q=Y.subscribe(`function`,Z),$=Y.subscribe(`deployment`,Z)}),t(()=>{Q&&=(Q(),null),$&&=($(),null),X&&=(clearTimeout(X),null)}),te(()=>K(0)),ae(()=>{X&&=(clearTimeout(X),null)}),(t,r)=>(e(),o(`div`,ve,[a(`div`,ye,[r[7]||=a(`div`,null,[a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Functions `),a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Deployed functions and invoke endpoints. `)],-1),s(b,{onClick:r[0]||=e=>i(P).push(`/functions/new`)},{default:n(()=>[s(i(y),{class:`w-4 h-4`}),r[6]||=l(` New Function `,-1)]),_:1})]),F.value.length>0||L.value?(e(),o(`div`,be,[a(`div`,xe,[a(`div`,Se,[s(i(ge),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),ee(a(`input`,{"onUpdate:modelValue":r[1]||=e=>R.value=e,placeholder:`Search by name, runtime, or function id…`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-base sm:text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[de,R.value]])]),a(`span`,S,p(U.value.length)+` of `+p(F.value.length),1)]),a(`div`,C,[a(`ul`,w,[(e(!0),o(u,null,c(U.value,t=>(e(),o(`li`,{key:t.id,class:`px-4 py-3 active:bg-surface-hover/50 transition-colors`},[a(`div`,T,[a(`div`,E,[a(`div`,D,[a(`span`,O,p(t.name),1),t.network_mode===`egress`?(e(),o(`span`,k,[s(i(m),{class:`w-3 h-3`}),r[8]||=l(` egress `,-1)])):f(``,!0),t.auth_mode&&t.auth_mode!==`none`?(e(),o(`span`,A,[s(i(h),{class:`w-3 h-3`}),l(` `+p(t.auth_mode===`platform_key`?`key`:`signed`),1)])):f(``,!0)]),t.description?(e(),o(`p`,j,p(t.description),1)):f(``,!0),a(`div`,Ce,[a(`span`,null,p(t.runtime),1),a(`span`,null,p(t.cpus)+` CPU / `+p(t.memory_mb)+`MB`,1)])]),a(`div`,we,[s(x,{icon:i(g),title:`Edit function`,onClick:e=>i(P).push(`/functions/`+t.name)},null,8,[`icon`,`onClick`]),s(x,{icon:i(_),variant:`danger`,title:`Delete function`,disabled:B.value===t.id,onClick:e=>J(t)},null,8,[`icon`,`disabled`,`onClick`])])])]))),128)),!U.value.length&&!L.value&&R.value?(e(),o(`li`,Te,[a(`div`,null,`No matches for "`+p(R.value)+`".`,1),a(`button`,{class:`text-xs text-foreground hover:text-white underline underline-offset-2`,onClick:r[2]||=e=>R.value=``},` Clear search `)])):f(``,!0)]),a(`table`,Ee,[a(`thead`,De,[a(`tr`,null,[a(`th`,Oe,[a(`input`,{type:`checkbox`,checked:W.value,".indeterminate":it.value&&!W.value,class:`w-3.5 h-3.5 rounded border-border bg-background focus:outline-none focus:ring-1 focus:ring-white`,onChange:ot},null,40,ke)]),r[9]||=a(`th`,{class:`px-4 py-3 font-medium`},` Name `,-1),r[10]||=a(`th`,{class:`px-4 py-3 font-medium hidden sm:table-cell`},` Runtime `,-1),r[11]||=a(`th`,{class:`px-4 py-3 font-medium hidden lg:table-cell`},` Resources `,-1),r[12]||=a(`th`,{class:`px-4 py-3 font-medium hidden md:table-cell`},` Function ID `,-1),r[13]||=a(`th`,{class:`px-4 py-3 font-medium hidden xl:table-cell`},` Last Update `,-1),r[14]||=a(`th`,{class:`px-4 py-3 font-medium text-right`},` Actions `,-1)])]),a(`tbody`,Ae,[(e(!0),o(u,null,c(U.value,t=>(e(),o(`tr`,{key:t.id,class:re([`hover:bg-surface/50 transition-colors`,{"bg-surface/30":H.value.has(t.id)}])},[a(`td`,je,[a(`input`,{checked:H.value.has(t.id),type:`checkbox`,class:`w-3.5 h-3.5 rounded border-border bg-background focus:outline-none focus:ring-1 focus:ring-white`,onChange:e=>at(t.id)},null,40,Me)]),a(`td`,Ne,[a(`div`,Pe,[a(`span`,null,p(t.name),1),t.network_mode===`egress`?(e(),o(`span`,Fe,[s(i(m),{class:`w-3 h-3`}),r[15]||=l(` egress `,-1)])):f(``,!0),t.auth_mode&&t.auth_mode!==`none`?(e(),o(`span`,{key:1,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-info-tint text-info-fg border border-info-ring`,title:t.auth_mode===`platform_key`?`Requires Orva API key`:`Requires HMAC signature`},[s(i(h),{class:`w-3 h-3`}),l(` `+p(t.auth_mode===`platform_key`?`key`:`signed`),1)],8,Ie)):f(``,!0),t.rate_limit_per_min>0?(e(),o(`span`,{key:2,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] bg-primary/15 text-primary border border-primary/30 tabular-nums`,title:`Rate limit: ${t.rate_limit_per_min}/min per IP`},[s(i(ue),{class:`w-3 h-3`}),l(` `+p(t.rate_limit_per_min)+`/m `,1)],8,Le)):f(``,!0)]),t.description?(e(),o(`p`,{key:0,class:`mt-1 text-xs font-normal text-foreground-muted line-clamp-2`,title:t.description},p(t.description),9,Re)):f(``,!0)]),a(`td`,ze,[a(`span`,Be,p(t.runtime),1)]),a(`td`,M,p(t.cpus)+` CPU / `+p(t.memory_mb)+`MB `,1),a(`td`,Ve,[a(`div`,He,[a(`code`,{class:`text-xs font-mono text-foreground-muted bg-surface px-2 py-1 rounded border border-border truncate min-w-0 max-w-[14ch]`,title:t.id},p(t.id),9,Ue),s(x,{icon:z.value===t.id?i(oe):i(se),title:z.value===t.id?`Copied!`:`Copy invoke URL`,variant:z.value===t.id?`primary`:`default`,onClick:e=>st(t)},null,8,[`icon`,`title`,`variant`,`onClick`])])]),a(`td`,We,p(new Date(t.updated_at).toLocaleDateString()),1),a(`td`,Ge,[a(`div`,Ke,[s(x,{icon:i(g),title:`Edit function`,onClick:e=>i(P).push(`/functions/`+t.name)},null,8,[`icon`,`onClick`]),s(x,{icon:i(_),variant:`danger`,title:`Delete function`,disabled:B.value===t.id,onClick:e=>J(t)},null,8,[`icon`,`disabled`,`onClick`])])])],2))),128)),!U.value.length&&!L.value&&R.value?(e(),o(`tr`,qe,[a(`td`,Je,[a(`div`,Ye,[a(`div`,null,`No matches for "`+p(R.value)+`".`,1),a(`button`,{class:`text-xs text-foreground hover:text-white underline underline-offset-2`,onClick:r[3]||=e=>R.value=``},` Clear search `)])])])):f(``,!0)])]),rt.value?(e(),o(`div`,Xe,[a(`button`,{class:`text-xs text-foreground-muted hover:text-white transition-colors flex items-center gap-1.5`,disabled:L.value,onClick:ct},[L.value?(e(),ie(i(ce),{key:0,class:`w-3 h-3 animate-spin`})):f(``,!0),l(` `+p(L.value?`Loading…`:`Load more (${I.value-F.value.length} remaining)`),1)],8,Ze)])):f(``,!0)])])):f(``,!0),!L.value&&F.value.length===0?(e(),o(`div`,Qe,[r[17]||=a(`div`,{class:`space-y-1.5`},[a(`div`,{class:`text-sm text-white`},` No functions deployed yet `),a(`div`,{class:`text-xs text-foreground-muted max-w-prose mx-auto leading-body`},` Choose a runtime and deploy your first handler. `)],-1),a(`div`,null,[s(b,{onClick:r[4]||=e=>i(P).push(`/functions/new`)},{default:n(()=>[s(i(y),{class:`w-4 h-4`}),r[16]||=l(` Deploy your first function `,-1)]),_:1})])])):f(``,!0),s(fe,{name:`fade`},{default:n(()=>[H.value.size?(e(),o(`div`,$e,[a(`span`,et,p(H.value.size)+` selected `,1),r[18]||=a(`span`,{class:`w-px h-4 bg-border`},null,-1),a(`button`,{class:`text-xs text-foreground-muted hover:text-white transition-colors px-2 py-1`,onClick:r[5]||=e=>H.value=new Set},` Clear `),s(b,{variant:`danger`,size:`sm`,class:`!rounded-full px-4`,loading:V.value,onClick:lt},{default:n(()=>[s(i(_),{class:`w-3.5 h-3.5`}),l(` Delete `+p(H.value.size),1)]),_:1},8,[`loading`])])):f(``,!0)]),_:1})]))}};export{nt as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/InboundWebhooks-CFOyt9ev.js b/backend/internal/server/ui_dist/assets/InboundWebhooks-DlQkZ2lf.js similarity index 98% rename from backend/internal/server/ui_dist/assets/InboundWebhooks-CFOyt9ev.js rename to backend/internal/server/ui_dist/assets/InboundWebhooks-DlQkZ2lf.js index 757b7f1b..d6dd0f25 100644 --- a/backend/internal/server/ui_dist/assets/InboundWebhooks-CFOyt9ev.js +++ b/backend/internal/server/ui_dist/assets/InboundWebhooks-DlQkZ2lf.js @@ -1,4 +1,4 @@ -import{D as e,F as t,G as n,I as r,T as i,U as a,Z as o,c as s,d as c,gt as l,h as u,j as ee,k as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./refresh-cw-Cn8qkf-v.js";import{t as _}from"./trash-2-DaeYqnW_.js";import{It as ne,Lt as v,St as re,V as ie,_t as y,gt as ae,h as oe,jt as se,l as ce,pt as le}from"./index-DTqMKlE1.js";import{t as b}from"./Drawer-B98TBytl.js";import{t as x}from"./IconButton-CsCZOqWo.js";var S=se(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),ue={class:`space-y-6`},de={class:`flex items-start justify-between gap-4`},fe={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},pe={class:`flex items-center gap-2`},me={class:`text-xs text-foreground-muted`},he={key:0,class:`rounded-lg border border-amber-500/40 bg-amber-500/10 p-4 space-y-3`},ge={class:`flex items-center justify-between gap-4`},_e={class:`text-xs space-y-2`},ve={class:`ml-2 font-mono text-white break-all`},ye={class:`ml-2 font-mono text-white break-all`},C={class:`mt-1 bg-background border border-border rounded p-3 text-[11px] font-mono text-white whitespace-pre-wrap overflow-x-auto`},w={class:`bg-background border border-border rounded-lg overflow-x-auto`},T={class:`sm:hidden divide-y divide-border`},E={class:`flex items-start justify-between gap-2`},D={class:`min-w-0 flex-1`},O={class:`flex items-center gap-2 flex-wrap`},k={class:`font-medium text-white truncate`},A={class:`mt-1 text-[11px] text-foreground-muted font-mono break-all`},j={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},M={class:`font-mono`},N={class:`flex items-center gap-1 shrink-0`},P={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},be={class:`hidden sm:table w-full text-sm text-left`},xe={class:`divide-y divide-border`},Se={class:`px-4 py-3 font-medium text-white`},Ce={class:`flex flex-col`},we={class:`text-xs text-foreground-muted font-mono`},Te={class:`px-4 py-3 font-mono text-xs text-foreground-muted hidden md:table-cell`},Ee={class:`break-all`},De={class:`px-4 py-3 hidden sm:table-cell`},Oe={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-surface text-foreground-muted border-border font-mono`},ke={class:`px-4 py-3 font-mono text-xs text-foreground-muted hidden lg:table-cell`},Ae={class:`px-4 py-3 hidden md:table-cell`},je={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},Me={class:`px-4 py-3 text-right`},Ne={class:`inline-flex items-center gap-1`},Pe={key:0},F={class:`p-5 space-y-5 text-sm`},Fe={key:0,class:`text-xs text-danger-fg`},Ie={class:`flex items-center justify-end gap-2`},Le={key:0,class:`p-5 space-y-5 text-sm`},Re={class:`text-xs text-foreground-muted`},ze={key:0,class:`text-xs text-danger-fg`},Be={key:1,class:`space-y-1`},Ve={class:`text-xs uppercase tracking-wider text-foreground-muted`},He={class:`bg-background border border-border rounded p-3 text-[11px] font-mono text-white whitespace-pre-wrap overflow-x-auto`},Ue={class:`flex items-center justify-end gap-2`},I={__name:`InboundWebhooks`,setup(se){let I=le(),L=ae(),R=m(()=>I.params.name),z=n(``),B=n([]),V=n(!1),H=n(!1),U=n(!1),W=n(null),G=m(()=>window.location.origin),K=a({open:!1,name:``,format:`hmac_sha256_hex`,error:``}),q=a({open:!1,row:null,secret:``,body:`{"hello":"orva"}`,error:``,response:null}),J=e=>e?new Date(e).toLocaleString():`—`,Y=async()=>{V.value=!0;try{z.value||=R.value;let e=await ie(z.value);B.value=e.data?.inbound_webhooks||[]}catch(e){console.error(`load inbound webhooks failed`,e),L.notify({title:`Failed to load inbound webhooks`,message:e?.response?.data?.error?.message||e.message,danger:!0})}finally{V.value=!1}},We=()=>{K.name=``,K.format=`hmac_sha256_hex`,K.error=``,K.open=!0},Ge=async()=>{let e=K.name.trim();if(!e){K.error=`Name is required`;return}H.value=!0,K.error=``;try{let t=await ce(z.value,{name:e,signature_format:K.format});W.value={...t.data.inbound_webhook,secret:t.data.secret,trigger_url:t.data.trigger_url},K.open=!1,await Y()}catch(e){K.error=e?.response?.data?.error?.message||`Create failed`}finally{H.value=!1}},X=async e=>{if(await L.ask({title:`Delete inbound webhook?`,message:`Trigger "${e.name}" (${e.id}) will stop accepting calls immediately. This cannot be undone.`,confirmLabel:`Delete`,danger:!0}))try{await oe(z.value,e.id),await Y()}catch(e){L.notify({title:`Delete failed`,message:e?.response?.data?.error?.message||e.message,danger:!0})}},Z=e=>{q.row=e,q.secret=``,q.body=`{"hello":"orva"}`,q.error=``,q.response=null,q.open=!0},Q=async(e,t)=>{let n=new TextEncoder,r=await crypto.subtle.importKey(`raw`,n.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),i=await crypto.subtle.sign(`HMAC`,r,n.encode(t));return[...new Uint8Array(i)].map(e=>e.toString(16).padStart(2,`0`)).join(``)},Ke=async()=>{q.error=``,q.response=null,U.value=!0;try{let e=q.row.signature_format,t;if(e===`hmac_sha256_hex`)t=await Q(q.secret.trim(),q.body);else if(e===`github`)t=`sha256=`+await Q(q.secret.trim(),q.body);else{q.error=`Browser test only signs hmac_sha256_hex and github. For ${e}, use the CLI or curl with openssl.`;return}let n=G.value+`/webhook/`+q.row.id,r=await fetch(n,{method:`POST`,headers:{"Content-Type":`application/json`,[q.row.signature_header]:t},body:q.body}),i=await r.text();q.response={status:r.status,body:i}}catch(e){q.error=e.message||`Test failed`}finally{U.value=!1}},qe=e=>{let t=G.value+e.trigger_url,n=e.signature_format;return n===`github`?[`BODY='{"hello":"orva"}'`,`SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "${e.secret}" | sed 's/^.* //')`,`curl -X POST "${t}" \\`,` -H "Content-Type: application/json" \\`,` -H "${e.signature_header}: sha256=$SIG" \\`,` -d "$BODY"`].join(` +import{D as e,F as t,G as n,I as r,T as i,U as a,Z as o,c as s,d as c,gt as l,h as u,j as ee,k as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./refresh-cw-CEfUzOcv.js";import{t as _}from"./trash-2-Cz9PSE2q.js";import{It as ne,Lt as v,St as re,V as ie,_t as y,gt as ae,h as oe,jt as se,l as ce,pt as le}from"./index-pE9wnfTb.js";import{t as b}from"./Drawer-CSwYBfhJ.js";import{t as x}from"./IconButton-CsCZOqWo.js";var S=se(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),ue={class:`space-y-6`},de={class:`flex items-start justify-between gap-4`},fe={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},pe={class:`flex items-center gap-2`},me={class:`text-xs text-foreground-muted`},he={key:0,class:`rounded-lg border border-amber-500/40 bg-amber-500/10 p-4 space-y-3`},ge={class:`flex items-center justify-between gap-4`},_e={class:`text-xs space-y-2`},ve={class:`ml-2 font-mono text-white break-all`},ye={class:`ml-2 font-mono text-white break-all`},C={class:`mt-1 bg-background border border-border rounded p-3 text-[11px] font-mono text-white whitespace-pre-wrap overflow-x-auto`},w={class:`bg-background border border-border rounded-lg overflow-x-auto`},T={class:`sm:hidden divide-y divide-border`},E={class:`flex items-start justify-between gap-2`},D={class:`min-w-0 flex-1`},O={class:`flex items-center gap-2 flex-wrap`},k={class:`font-medium text-white truncate`},A={class:`mt-1 text-[11px] text-foreground-muted font-mono break-all`},j={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},M={class:`font-mono`},N={class:`flex items-center gap-1 shrink-0`},P={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},be={class:`hidden sm:table w-full text-sm text-left`},xe={class:`divide-y divide-border`},Se={class:`px-4 py-3 font-medium text-white`},Ce={class:`flex flex-col`},we={class:`text-xs text-foreground-muted font-mono`},Te={class:`px-4 py-3 font-mono text-xs text-foreground-muted hidden md:table-cell`},Ee={class:`break-all`},De={class:`px-4 py-3 hidden sm:table-cell`},Oe={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-surface text-foreground-muted border-border font-mono`},ke={class:`px-4 py-3 font-mono text-xs text-foreground-muted hidden lg:table-cell`},Ae={class:`px-4 py-3 hidden md:table-cell`},je={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},Me={class:`px-4 py-3 text-right`},Ne={class:`inline-flex items-center gap-1`},Pe={key:0},F={class:`p-5 space-y-5 text-sm`},Fe={key:0,class:`text-xs text-danger-fg`},Ie={class:`flex items-center justify-end gap-2`},Le={key:0,class:`p-5 space-y-5 text-sm`},Re={class:`text-xs text-foreground-muted`},ze={key:0,class:`text-xs text-danger-fg`},Be={key:1,class:`space-y-1`},Ve={class:`text-xs uppercase tracking-wider text-foreground-muted`},He={class:`bg-background border border-border rounded p-3 text-[11px] font-mono text-white whitespace-pre-wrap overflow-x-auto`},Ue={class:`flex items-center justify-end gap-2`},I={__name:`InboundWebhooks`,setup(se){let I=le(),L=ae(),R=m(()=>I.params.name),z=n(``),B=n([]),V=n(!1),H=n(!1),U=n(!1),W=n(null),G=m(()=>window.location.origin),K=a({open:!1,name:``,format:`hmac_sha256_hex`,error:``}),q=a({open:!1,row:null,secret:``,body:`{"hello":"orva"}`,error:``,response:null}),J=e=>e?new Date(e).toLocaleString():`—`,Y=async()=>{V.value=!0;try{z.value||=R.value;let e=await ie(z.value);B.value=e.data?.inbound_webhooks||[]}catch(e){console.error(`load inbound webhooks failed`,e),L.notify({title:`Failed to load inbound webhooks`,message:e?.response?.data?.error?.message||e.message,danger:!0})}finally{V.value=!1}},We=()=>{K.name=``,K.format=`hmac_sha256_hex`,K.error=``,K.open=!0},Ge=async()=>{let e=K.name.trim();if(!e){K.error=`Name is required`;return}H.value=!0,K.error=``;try{let t=await ce(z.value,{name:e,signature_format:K.format});W.value={...t.data.inbound_webhook,secret:t.data.secret,trigger_url:t.data.trigger_url},K.open=!1,await Y()}catch(e){K.error=e?.response?.data?.error?.message||`Create failed`}finally{H.value=!1}},X=async e=>{if(await L.ask({title:`Delete inbound webhook?`,message:`Trigger "${e.name}" (${e.id}) will stop accepting calls immediately. This cannot be undone.`,confirmLabel:`Delete`,danger:!0}))try{await oe(z.value,e.id),await Y()}catch(e){L.notify({title:`Delete failed`,message:e?.response?.data?.error?.message||e.message,danger:!0})}},Z=e=>{q.row=e,q.secret=``,q.body=`{"hello":"orva"}`,q.error=``,q.response=null,q.open=!0},Q=async(e,t)=>{let n=new TextEncoder,r=await crypto.subtle.importKey(`raw`,n.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),i=await crypto.subtle.sign(`HMAC`,r,n.encode(t));return[...new Uint8Array(i)].map(e=>e.toString(16).padStart(2,`0`)).join(``)},Ke=async()=>{q.error=``,q.response=null,U.value=!0;try{let e=q.row.signature_format,t;if(e===`hmac_sha256_hex`)t=await Q(q.secret.trim(),q.body);else if(e===`github`)t=`sha256=`+await Q(q.secret.trim(),q.body);else{q.error=`Browser test only signs hmac_sha256_hex and github. For ${e}, use the CLI or curl with openssl.`;return}let n=G.value+`/webhook/`+q.row.id,r=await fetch(n,{method:`POST`,headers:{"Content-Type":`application/json`,[q.row.signature_header]:t},body:q.body}),i=await r.text();q.response={status:r.status,body:i}}catch(e){q.error=e.message||`Test failed`}finally{U.value=!1}},qe=e=>{let t=G.value+e.trigger_url,n=e.signature_format;return n===`github`?[`BODY='{"hello":"orva"}'`,`SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "${e.secret}" | sed 's/^.* //')`,`curl -X POST "${t}" \\`,` -H "Content-Type: application/json" \\`,` -H "${e.signature_header}: sha256=$SIG" \\`,` -d "$BODY"`].join(` `):n===`stripe`?[`BODY='{"hello":"orva"}'`,`TS=$(date +%s)`,`SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "${e.secret}" | sed 's/^.* //')`,`curl -X POST "${t}" \\`,` -H "Content-Type: application/json" \\`,` -H "${e.signature_header}: t=$TS,v1=$SIG" \\`,` -d "$BODY"`].join(` `):n===`slack`?[`BODY='{"hello":"orva"}'`,`TS=$(date +%s)`,`SIG=$(printf 'v0:%s:%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "${e.secret}" | sed 's/^.* //')`,`curl -X POST "${t}" \\`,` -H "Content-Type: application/json" \\`,` -H "X-Slack-Request-Timestamp: $TS" \\`,` -H "${e.signature_header}: v0=$SIG" \\`,` -d "$BODY"`].join(` `):[`BODY='{"hello":"orva"}'`,`SIG=$(printf '%s' "$BODY" | ${n===`hmac_sha256_base64`?`openssl dgst -sha256 -hmac "${e.secret}" -binary | base64`:`openssl dgst -sha256 -hmac "${e.secret}" | sed 's/^.* //'`})`,`curl -X POST "${t}" \\`,` -H "Content-Type: application/json" \\`,` -H "${e.signature_header}: $SIG" \\`,` -d "$BODY"`].join(` diff --git a/backend/internal/server/ui_dist/assets/InvocationsLog-Bz2zpa_f.js b/backend/internal/server/ui_dist/assets/InvocationsLog-DEPmQG0y.js similarity index 97% rename from backend/internal/server/ui_dist/assets/InvocationsLog-Bz2zpa_f.js rename to backend/internal/server/ui_dist/assets/InvocationsLog-DEPmQG0y.js index a22fcdc8..2ac3910b 100644 --- a/backend/internal/server/ui_dist/assets/InvocationsLog-Bz2zpa_f.js +++ b/backend/internal/server/ui_dist/assets/InvocationsLog-DEPmQG0y.js @@ -1,4 +1,4 @@ -import{D as e,E as t,F as n,G as r,I as i,P as a,S as ee,T as te,Z as o,_ as ne,c as s,d as c,gt as l,h as u,k as d,l as re,m as f,r as p,s as m,u as h,v as g,vt as _,w as ie}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ae}from"./check-BNre7JFR.js";import{t as oe}from"./circle-alert-BnUYYhGE.js";import{t as se}from"./play-CmQifd74.js";import{t as v}from"./refresh-cw-Cn8qkf-v.js";import{t as ce}from"./rotate-ccw-DWwjKCqh.js";import{t as le}from"./sparkles-DTHEIS5T.js";import{t as ue}from"./trash-2-DaeYqnW_.js";import{t as de}from"./client-BF51V3uE.js";import{B as fe,Bt as y,C as pe,Dt as me,E as he,H as ge,It as _e,Lt as ve,Mt as ye,S as be,T as xe,Y as Se,_t as b,gt as Ce,mt as we,w as Te,wt as Ee,xt as De}from"./index-DTqMKlE1.js";import{t as Oe}from"./Drawer-B98TBytl.js";import{t as ke}from"./clipboard-D_9N0yai.js";import{t as x}from"./StatusBadge-Baoe7YAb.js";import{n as Ae}from"./aiPrompts-XrsFCpj_.js";var je={class:`space-y-6`},Me={class:`flex items-center justify-between`},Ne={class:`flex items-center gap-2 flex-wrap`},Pe={class:`relative flex-1 min-w-[280px] max-w-[440px]`},Fe=[`value`],Ie={key:0,class:`bg-background border border-border rounded-lg px-6 py-12 text-center`},Le={class:`mt-1 text-xs text-foreground-muted`},Re={key:1,class:`bg-background border border-border rounded-lg overflow-x-auto`},ze={class:`sm:hidden divide-y divide-border`},Be=[`onClick`],Ve={class:`flex items-start gap-3`},He=[`checked`,`onChange`],Ue={class:`min-w-0 flex-1`},We={class:`flex items-center justify-between gap-2`},Ge={class:`font-medium text-white truncate`},Ke={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},qe={key:0,class:`font-mono`},Je={key:1,class:`font-mono`},Ye={key:2,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] border bg-background font-mono text-info-fg border-info-ring`},Xe={key:0,class:`mt-1 text-[11px] text-foreground-muted font-mono break-all`},Ze={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},Qe={class:`hidden sm:table w-full text-sm text-left`},$e={class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},et={class:`px-4 py-3 w-8`},tt=[`checked`],nt={class:`divide-y divide-border`},rt=[`onClick`],it=[`checked`,`onChange`],at={class:`px-4 py-3 text-foreground`},ot={class:`px-4 py-3 font-medium text-white`},st=[`onClick`],ct={class:`px-4 py-3`},lt={class:`px-4 py-3 hidden md:table-cell`},ut={key:0,class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-info-fg border-info-ring`},dt={key:1,class:`text-foreground-muted text-xs`},ft={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden lg:table-cell`},pt={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden sm:table-cell`},mt={class:`px-4 py-3 hidden lg:table-cell`},ht=[`title`,`onClick`],gt={key:1,class:`text-foreground-muted`},_t={class:`px-4 py-3 text-right text-foreground-muted font-mono text-xs hidden xl:table-cell`},vt={key:0},yt={colspan:`9`,class:`px-6 py-8 text-center text-foreground-muted`},bt={key:0,class:`flex justify-center border-t border-border py-3 bg-surface/30`},xt=[`disabled`],St={key:0,class:`fixed bottom-4 left-1/2 -translate-x-1/2 z-30 flex items-center gap-3 bg-background border border-border shadow-lg rounded-full pl-4 pr-2 py-2`},Ct={class:`text-xs text-white`},wt={key:0,class:`p-6 text-sm text-foreground-muted`},Tt={key:1,class:`p-8 text-center`},Et={class:`mt-1 text-xs text-foreground-muted`},Dt={key:2,class:`p-6 text-sm text-foreground-muted`},Ot={key:3,class:`p-5 space-y-5`},kt={class:`flex items-center gap-2 flex-wrap`},At={key:0,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-info-fg border-info-ring`},jt={key:1,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-foreground-muted`},Mt={class:`grid grid-cols-2 gap-3 text-sm`},Nt={key:0},Pt={class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg font-mono whitespace-pre-wrap break-words`},Ft={key:1},It={class:`bg-surface border border-border rounded p-3 space-y-3`},Lt={class:`flex items-center gap-2 font-mono text-xs`},Rt={class:`px-2 py-0.5 rounded bg-background text-white border border-border`},zt={class:`text-foreground-muted truncate`},Bt={key:0},Vt={class:`bg-background border border-border rounded p-2 max-h-40 overflow-auto`},Ht={class:`text-foreground-muted shrink-0`},Ut={key:1},Wt={class:`bg-background border border-border rounded p-2 text-xs text-foreground font-mono overflow-auto max-h-40 whitespace-pre-wrap break-words`},Gt={key:2,class:`text-[11px] text-warning-fg`},Kt={key:2},qt={class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},Jt={class:`bg-surface border border-border rounded p-3 text-xs font-mono space-y-1 max-h-72 overflow-auto`},Yt={class:`text-foreground-muted text-[10px] tabular-nums`},Xt={class:`text-white truncate`},Zt={key:0,class:`text-[10px] text-foreground-muted truncate`},Qt={class:`flex items-center justify-between mb-2`},$t={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-72 whitespace-pre-wrap break-words`},en={class:`pt-2 border-t border-border flex items-center gap-3`},tn={key:1,class:`text-xs text-foreground-muted`},nn=50,rn={__name:`InvocationsLog`,setup(rn){let S=Ce(),C=we(),w=r([]),T=r(0),E=r(!1),D=r(``),O=r(!1),k=r(!1),an=r(!1),A=r(``),j=r(null),M=r(new Set),N=r(``),P=r([]),on=e=>{switch(e){case`error`:return`text-danger-fg`;case`warn`:return`text-warning-fg`;case`debug`:return`text-foreground-muted`;default:return`text-primary-light`}},sn=e=>{if(!e)return``;try{let t=new Date(e);return t.toLocaleTimeString(void 0,{hour12:!1})+`.`+String(t.getMilliseconds()).padStart(3,`0`)}catch{return e}},F=r(!1),I=r({}),L=r(null),R=r(!1),z=r(!1),B=r(!1),V=r(null),H=null,cn=m(()=>w.value.lengthw.value.length>0&&w.value.every(e=>M.value.has(e.id))),ln=m(()=>w.value.some(e=>M.value.has(e.id))),W=r(null);a(()=>ln.value&&!U.value,e=>{W.value&&(W.value.indeterminate=e)},{immediate:!0});let un=e=>{let t=new Set(M.value);t.has(e)?t.delete(e):t.add(e),M.value=t},dn=()=>{if(U.value)M.value=new Set;else{let e=new Set(M.value);w.value.forEach(t=>e.add(t.id)),M.value=e}},G=r({fnId:``,status:``,range:``,q:``}),fn=[{value:``,label:`All`},{value:`success`,label:`Success`},{value:`error`,label:`Error`}],pn=[{value:``,label:`All time`},{value:`1h`,label:`1h`},{value:`24h`,label:`24h`},{value:`7d`,label:`7d`}],K=m(()=>!!(G.value.fnId||G.value.status||G.value.range||G.value.q)),mn=()=>{G.value={fnId:``,status:``,range:``,q:``},Q()},q=null,hn=()=>{q&&clearTimeout(q),q=setTimeout(()=>Q(),300)},J=()=>Q(),gn=e=>{if(!e)return``;let t={"1h":36e5,"24h":864e5,"7d":6048e5}[e];return t?new Date(Date.now()-t).toISOString():``},_n=m(()=>j.value?`Invocation · ${j.value.id?.substring(0,14)}`:`Invocation`),vn=m(()=>R.value?`request not captured`:L.value?.truncated?`body was truncated; replay would be inaccurate`:`Re-run this exact request against the current code`),yn=m(()=>{let e=j.value;return e?typeof e.status_code==`number`&&e.status_code>=500||!!e.error_message:!1}),bn=m(()=>N.value?`Build a paste-ready debug prompt with source + request + stderr`:`no stderr to debug from`),Y={props:{label:String,value:[String,Number],mono:Boolean},template:` +import{D as e,E as t,F as n,G as r,I as i,P as a,S as ee,T as te,Z as o,_ as ne,c as s,d as c,gt as l,h as u,k as d,l as re,m as f,r as p,s as m,u as h,v as g,vt as _,w as ie}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ae}from"./check-CZmR72iA.js";import{t as oe}from"./circle-alert-CwieDBHo.js";import{t as se}from"./play-CnkMURxf.js";import{t as v}from"./refresh-cw-CEfUzOcv.js";import{t as ce}from"./rotate-ccw-DgujV-4F.js";import{t as le}from"./sparkles-BZcVxan3.js";import{t as ue}from"./trash-2-Cz9PSE2q.js";import{t as de}from"./client-BF51V3uE.js";import{B as fe,Bt as y,C as pe,Dt as me,E as he,H as ge,It as _e,Lt as ve,Mt as ye,S as be,T as xe,Y as Se,_t as b,gt as Ce,mt as we,w as Te,wt as Ee,xt as De}from"./index-pE9wnfTb.js";import{t as Oe}from"./Drawer-CSwYBfhJ.js";import{t as ke}from"./clipboard-D_9N0yai.js";import{t as x}from"./StatusBadge-BpEw6z9Z.js";import{n as Ae}from"./aiPrompts-XrsFCpj_.js";var je={class:`space-y-6`},Me={class:`flex items-center justify-between`},Ne={class:`flex items-center gap-2 flex-wrap`},Pe={class:`relative flex-1 min-w-[280px] max-w-[440px]`},Fe=[`value`],Ie={key:0,class:`bg-background border border-border rounded-lg px-6 py-12 text-center`},Le={class:`mt-1 text-xs text-foreground-muted`},Re={key:1,class:`bg-background border border-border rounded-lg overflow-x-auto`},ze={class:`sm:hidden divide-y divide-border`},Be=[`onClick`],Ve={class:`flex items-start gap-3`},He=[`checked`,`onChange`],Ue={class:`min-w-0 flex-1`},We={class:`flex items-center justify-between gap-2`},Ge={class:`font-medium text-white truncate`},Ke={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-muted`},qe={key:0,class:`font-mono`},Je={key:1,class:`font-mono`},Ye={key:2,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] border bg-background font-mono text-info-fg border-info-ring`},Xe={key:0,class:`mt-1 text-[11px] text-foreground-muted font-mono break-all`},Ze={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},Qe={class:`hidden sm:table w-full text-sm text-left`},$e={class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},et={class:`px-4 py-3 w-8`},tt=[`checked`],nt={class:`divide-y divide-border`},rt=[`onClick`],it=[`checked`,`onChange`],at={class:`px-4 py-3 text-foreground`},ot={class:`px-4 py-3 font-medium text-white`},st=[`onClick`],ct={class:`px-4 py-3`},lt={class:`px-4 py-3 hidden md:table-cell`},ut={key:0,class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-info-fg border-info-ring`},dt={key:1,class:`text-foreground-muted text-xs`},ft={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden lg:table-cell`},pt={class:`px-4 py-3 text-foreground-muted font-mono text-xs hidden sm:table-cell`},mt={class:`px-4 py-3 hidden lg:table-cell`},ht=[`title`,`onClick`],gt={key:1,class:`text-foreground-muted`},_t={class:`px-4 py-3 text-right text-foreground-muted font-mono text-xs hidden xl:table-cell`},vt={key:0},yt={colspan:`9`,class:`px-6 py-8 text-center text-foreground-muted`},bt={key:0,class:`flex justify-center border-t border-border py-3 bg-surface/30`},xt=[`disabled`],St={key:0,class:`fixed bottom-4 left-1/2 -translate-x-1/2 z-30 flex items-center gap-3 bg-background border border-border shadow-lg rounded-full pl-4 pr-2 py-2`},Ct={class:`text-xs text-white`},wt={key:0,class:`p-6 text-sm text-foreground-muted`},Tt={key:1,class:`p-8 text-center`},Et={class:`mt-1 text-xs text-foreground-muted`},Dt={key:2,class:`p-6 text-sm text-foreground-muted`},Ot={key:3,class:`p-5 space-y-5`},kt={class:`flex items-center gap-2 flex-wrap`},At={key:0,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-info-fg border-info-ring`},jt={key:1,class:`inline-flex items-center px-2.5 py-1 rounded text-xs border bg-background font-mono text-foreground-muted`},Mt={class:`grid grid-cols-2 gap-3 text-sm`},Nt={key:0},Pt={class:`bg-danger-tint border border-danger-ring rounded p-3 text-xs text-danger-fg font-mono whitespace-pre-wrap break-words`},Ft={key:1},It={class:`bg-surface border border-border rounded p-3 space-y-3`},Lt={class:`flex items-center gap-2 font-mono text-xs`},Rt={class:`px-2 py-0.5 rounded bg-background text-white border border-border`},zt={class:`text-foreground-muted truncate`},Bt={key:0},Vt={class:`bg-background border border-border rounded p-2 max-h-40 overflow-auto`},Ht={class:`text-foreground-muted shrink-0`},Ut={key:1},Wt={class:`bg-background border border-border rounded p-2 text-xs text-foreground font-mono overflow-auto max-h-40 whitespace-pre-wrap break-words`},Gt={key:2,class:`text-[11px] text-warning-fg`},Kt={key:2},qt={class:`text-xs uppercase tracking-wider text-foreground-muted mb-2`},Jt={class:`bg-surface border border-border rounded p-3 text-xs font-mono space-y-1 max-h-72 overflow-auto`},Yt={class:`text-foreground-muted text-[10px] tabular-nums`},Xt={class:`text-white truncate`},Zt={key:0,class:`text-[10px] text-foreground-muted truncate`},Qt={class:`flex items-center justify-between mb-2`},$t={class:`bg-surface border border-border rounded p-3 text-xs text-foreground font-mono overflow-auto max-h-72 whitespace-pre-wrap break-words`},en={class:`pt-2 border-t border-border flex items-center gap-3`},tn={key:1,class:`text-xs text-foreground-muted`},nn=50,rn={__name:`InvocationsLog`,setup(rn){let S=Ce(),C=we(),w=r([]),T=r(0),E=r(!1),D=r(``),O=r(!1),k=r(!1),an=r(!1),A=r(``),j=r(null),M=r(new Set),N=r(``),P=r([]),on=e=>{switch(e){case`error`:return`text-danger-fg`;case`warn`:return`text-warning-fg`;case`debug`:return`text-foreground-muted`;default:return`text-primary-light`}},sn=e=>{if(!e)return``;try{let t=new Date(e);return t.toLocaleTimeString(void 0,{hour12:!1})+`.`+String(t.getMilliseconds()).padStart(3,`0`)}catch{return e}},F=r(!1),I=r({}),L=r(null),R=r(!1),z=r(!1),B=r(!1),V=r(null),H=null,cn=m(()=>w.value.lengthw.value.length>0&&w.value.every(e=>M.value.has(e.id))),ln=m(()=>w.value.some(e=>M.value.has(e.id))),W=r(null);a(()=>ln.value&&!U.value,e=>{W.value&&(W.value.indeterminate=e)},{immediate:!0});let un=e=>{let t=new Set(M.value);t.has(e)?t.delete(e):t.add(e),M.value=t},dn=()=>{if(U.value)M.value=new Set;else{let e=new Set(M.value);w.value.forEach(t=>e.add(t.id)),M.value=e}},G=r({fnId:``,status:``,range:``,q:``}),fn=[{value:``,label:`All`},{value:`success`,label:`Success`},{value:`error`,label:`Error`}],pn=[{value:``,label:`All time`},{value:`1h`,label:`1h`},{value:`24h`,label:`24h`},{value:`7d`,label:`7d`}],K=m(()=>!!(G.value.fnId||G.value.status||G.value.range||G.value.q)),mn=()=>{G.value={fnId:``,status:``,range:``,q:``},Q()},q=null,hn=()=>{q&&clearTimeout(q),q=setTimeout(()=>Q(),300)},J=()=>Q(),gn=e=>{if(!e)return``;let t={"1h":36e5,"24h":864e5,"7d":6048e5}[e];return t?new Date(Date.now()-t).toISOString():``},_n=m(()=>j.value?`Invocation · ${j.value.id?.substring(0,14)}`:`Invocation`),vn=m(()=>R.value?`request not captured`:L.value?.truncated?`body was truncated; replay would be inaccurate`:`Re-run this exact request against the current code`),yn=m(()=>{let e=j.value;return e?typeof e.status_code==`number`&&e.status_code>=500||!!e.error_message:!1}),bn=m(()=>N.value?`Build a paste-ready debug prompt with source + request + stderr`:`no stderr to debug from`),Y={props:{label:String,value:[String,Number],mono:Boolean},template:`
{{ label }}
{{ value }}
diff --git a/backend/internal/server/ui_dist/assets/Jobs-CfHJpgrS.js b/backend/internal/server/ui_dist/assets/Jobs-DuQCYFLA.js similarity index 97% rename from backend/internal/server/ui_dist/assets/Jobs-CfHJpgrS.js rename to backend/internal/server/ui_dist/assets/Jobs-DuQCYFLA.js index 975abbe7..2b671eb4 100644 --- a/backend/internal/server/ui_dist/assets/Jobs-CfHJpgrS.js +++ b/backend/internal/server/ui_dist/assets/Jobs-DuQCYFLA.js @@ -1 +1 @@ -import{C as e,D as t,F as n,G as r,I as i,M as a,T as o,U as ee,Z as s,c,d as l,gt as u,h as d,k as f,l as p,m,r as h,s as g,u as _,vt as v}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as te,t as y}from"./clock-CiH8bQVI.js";import{n as ne,t as re}from"./circle-NOse79gh.js";import{t as b}from"./rotate-ccw-DWwjKCqh.js";import{t as x}from"./trash-2-DaeYqnW_.js";import{B as ie,It as ae,Lt as S,Nt as oe,St as se,U as ce,X as le,_t as C,g as ue,gt as de,jt as fe,y as pe}from"./index-DTqMKlE1.js";import{t as me}from"./Drawer-B98TBytl.js";import{t as w}from"./IconButton-CsCZOqWo.js";var T=fe(`refresh-ccw`,[[`path`,{d:`M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`14sxne`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16`,key:`1hlbsb`}],[`path`,{d:`M16 16h5v5`,key:`ccwih5`}]]),E={class:`space-y-4`},D={class:`flex items-start justify-between gap-4 flex-wrap`},O={class:`flex items-center gap-2 text-xs text-foreground-muted`},k={class:`flex items-center gap-2`},A={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0 flex-1`},j={key:0,class:`ml-1 opacity-70 tabular-nums`},M={class:`flex items-center gap-2 shrink-0`},N={class:`p-5 space-y-5 text-sm`},P=[`value`],F={class:`flex items-center gap-2 text-xs text-foreground-muted`},I={key:0},L={key:1,class:`text-xs text-danger-fg`},R={class:`flex items-center justify-end gap-2`},z={class:`bg-background border border-border rounded-lg overflow-x-auto`},he={class:`sm:hidden divide-y divide-border`},ge={class:`flex items-start justify-between gap-2`},_e={class:`min-w-0 flex-1`},ve={class:`font-medium text-white truncate`},ye={class:`text-[10px] text-foreground-muted font-mono break-all`},be={class:`mt-2`},xe=[`title`],Se={class:`mt-2 grid grid-cols-2 gap-x-3 gap-y-1 text-[11px] text-foreground-muted`},Ce={class:`col-span-2`},we={class:`flex items-center gap-1 shrink-0`},B={key:0,class:`px-4 py-12 text-center`},Te={class:`text-foreground-muted text-sm`},Ee={class:`hidden sm:table w-full text-sm text-left`},De={class:`divide-y divide-border`},Oe={class:`px-4 py-3 font-medium text-white`},ke={class:`flex flex-col`},Ae={class:`text-[10px] text-foreground-muted font-mono`},je={class:`px-4 py-3`},Me=[`title`],Ne={class:`px-4 py-3 text-foreground-muted text-xs hidden md:table-cell`},Pe={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},Fe={class:`px-4 py-3 text-foreground-muted text-xs hidden xl:table-cell`},Ie={class:`px-4 py-3 text-right`},Le={class:`inline-flex items-center gap-1`},Re={key:0},ze={colspan:`6`,class:`px-4 py-12 text-center`},Be={class:`text-foreground-muted text-sm`},V=Object.assign({name:`JobsView`},{__name:`Jobs`,setup(fe){let V=de(),H=r([]),U=r([]),W=r(`all`),G=null,K=ee({open:!1,fnId:``,payload:`{}`,scheduleLater:!1,scheduledAt:``,saving:!1,error:``}),Ve=[{value:`all`,label:`All`},{value:`pending`,label:`Pending`},{value:`running`,label:`Running`},{value:`succeeded`,label:`Succeeded`},{value:`failed`,label:`Failed`}],He=g(()=>H.value.length),q=g(()=>W.value===`all`?H.value:H.value.filter(e=>e.status===W.value)),J=g(()=>{let e={all:H.value.length};for(let t of H.value)e[t.status]=(e[t.status]||0)+1;return e}),Y=e=>{switch(e){case`pending`:return{classes:`bg-warning-tint text-warning-fg border-warning-ring`,icon:y};case`running`:return{classes:`bg-info-tint text-info-fg border-info-ring`,icon:y};case`succeeded`:return{classes:`bg-success-tint text-success-fg border-success-ring`,icon:te};case`failed`:return{classes:`bg-danger-tint text-danger-fg border-danger-ring`,icon:ne};default:return{classes:`bg-surface text-foreground-muted border-border`,icon:re}}},X=e=>e?new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}):`—`,Z=async()=>{try{let e=await ce({limit:200});H.value=e.data.jobs||[]}catch(e){console.error(`Failed to load jobs`,e)}},Q=async e=>{try{await le(e.id),await Z()}catch(e){V.notify({title:`Retry failed`,message:e.message,danger:!0})}},$=async e=>{if(await V.ask({title:`Delete job?`,message:`Job ${e.id} will be removed. This cannot be undone.`,confirmLabel:`Delete`,danger:!0}))try{await ue(e.id),await Z()}catch(e){V.notify({title:`Delete failed`,message:e.message,danger:!0})}},Ue=async()=>{if(K.error=``,K.payload=`{}`,K.scheduleLater=!1,K.scheduledAt=``,U.value.length===0)try{let e=await ie();U.value=e.data?.functions||[],U.value.length&&!K.fnId&&(K.fnId=U.value[0].id)}catch(e){console.error(`list functions failed`,e)}K.open=!0},We=async()=>{K.error=``;let e;try{e=K.payload.trim()?JSON.parse(K.payload):{}}catch(e){K.error=`Payload must be valid JSON: `+e.message;return}let t={function_id:K.fnId,payload:e};if(K.scheduleLater){if(!K.scheduledAt){K.error=`Pick a date/time, or untick "Schedule for later".`;return}t.scheduled_at=new Date(K.scheduledAt).toISOString()}K.saving=!0;try{await pe(t),K.open=!1,await Z()}catch(e){K.error=e?.response?.data?.error?.message||e.message||`Enqueue failed`}finally{K.saving=!1}};return o(()=>{Z(),G||=setInterval(Z,5e3)}),e(()=>{G&&=(clearInterval(G),null)}),(e,r)=>(t(),l(`div`,E,[c(`div`,D,[r[6]||=c(`div`,null,[c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Jobs `),c(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Queued background work with automatic retries. `)],-1),c(`div`,O,` Background queue · `+v(He.value)+` jobs `,1)]),c(`div`,k,[c(`div`,A,[(t(),l(h,null,f(Ve,e=>d(C,{key:e.value,variant:`chip`,size:`xs`,active:W.value===e.value,class:`shrink-0 snap-start`,onClick:t=>W.value=e.value},{default:n(()=>[m(v(e.label)+` `,1),J.value[e.value]===void 0?_(``,!0):(t(),l(`span`,j,v(J.value[e.value]),1))]),_:2},1032,[`active`,`onClick`])),64))]),c(`div`,M,[d(C,{size:`xs`,onClick:Ue},{default:n(()=>[d(s(se),{class:`w-3 h-3`}),r[7]||=m(` Enqueue `,-1)]),_:1}),d(C,{variant:`secondary`,size:`xs`,onClick:Z},{default:n(()=>[d(s(T),{class:`w-3 h-3`}),r[8]||=m(` Refresh `,-1)]),_:1})])]),d(me,{modelValue:K.open,"onUpdate:modelValue":r[5]||=e=>K.open=e,title:`Enqueue a job`,width:`560px`},{footer:n(()=>[c(`div`,R,[d(C,{variant:`ghost`,size:`sm`,onClick:r[4]||=e=>K.open=!1},{default:n(()=>[...r[14]||=[m(` Cancel `,-1)]]),_:1}),d(C,{size:`sm`,disabled:!K.fnId||K.saving,loading:K.saving,onClick:We},{default:n(()=>[...r[15]||=[m(` Enqueue `,-1)]]),_:1},8,[`disabled`,`loading`])])]),default:n(()=>[c(`div`,N,[c(`div`,null,[r[9]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Function`,-1),i(c(`select`,{"onUpdate:modelValue":r[0]||=e=>K.fnId=e,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white focus:outline-none focus:border-white`},[(t(!0),l(h,null,f(U.value,e=>(t(),l(`option`,{key:e.id,value:e.id},v(e.name)+` (`+v(e.runtime)+`) `,9,P))),128))],512),[[ae,K.fnId]])]),c(`div`,null,[r[10]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Payload (JSON)`,-1),i(c(`textarea`,{"onUpdate:modelValue":r[1]||=e=>K.payload=e,rows:`6`,spellcheck:`false`,class:`mt-2 w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono focus:outline-none focus:border-white`,placeholder:`{"hello":"world"}`},null,512),[[S,K.payload]])]),c(`div`,null,[c(`label`,F,[i(c(`input`,{"onUpdate:modelValue":r[2]||=e=>K.scheduleLater=e,type:`checkbox`},null,512),[[oe,K.scheduleLater]]),r[11]||=m(` Schedule for later `,-1)]),r[12]||=c(`p`,{class:`text-[11px] text-foreground-muted mt-1`},` Off: runs on the next scheduler tick (~5s). On: holds until the timestamp below. `,-1)]),K.scheduleLater?(t(),l(`div`,I,[r[13]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Run at (local time)`,-1),i(c(`input`,{"onUpdate:modelValue":r[3]||=e=>K.scheduledAt=e,type:`datetime-local`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white focus:outline-none focus:border-white`},null,512),[[S,K.scheduledAt]])])):_(``,!0),K.error?(t(),l(`div`,L,v(K.error),1)):_(``,!0)])]),_:1},8,[`modelValue`]),c(`div`,z,[c(`ul`,he,[(t(!0),l(h,null,f(q.value,e=>(t(),l(`li`,{key:e.id,class:`px-4 py-3`},[c(`div`,ge,[c(`div`,_e,[c(`div`,ve,v(e.function_name||e.function_id),1),c(`div`,ye,v(e.id),1),c(`div`,be,[c(`span`,{class:u([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium border`,Y(e.status).classes])},[(t(),p(a(Y(e.status).icon),{class:`w-3 h-3 shrink-0`,"aria-hidden":`true`})),m(` `+v(e.status),1)],2)]),e.last_error?(t(),l(`p`,{key:0,class:`text-[11px] text-danger-fg mt-1 break-all`,title:e.last_error},v(e.last_error),9,xe)):_(``,!0),c(`dl`,Se,[c(`div`,null,[r[16]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Attempts `,-1),c(`dd`,null,v(e.attempts)+` / `+v(e.max_attempts),1)]),c(`div`,null,[r[17]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Scheduled `,-1),c(`dd`,null,v(X(e.scheduled_at)),1)]),c(`div`,Ce,[r[18]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Finished `,-1),c(`dd`,null,v(e.finished_at?X(e.finished_at):s(`—`)),1)])])]),c(`div`,we,[e.status===`failed`?(t(),p(w,{key:0,icon:s(b),variant:`success`,title:`Retry`,onClick:t=>Q(e)},null,8,[`icon`,`onClick`])):_(``,!0),d(w,{icon:s(x),variant:`danger`,title:`Delete`,onClick:t=>$(e)},null,8,[`icon`,`onClick`])])])]))),128)),q.value.length===0?(t(),l(`li`,B,[c(`p`,Te,v(W.value===`all`?`No jobs yet.`:`No ${W.value} jobs.`),1),r[19]||=c(`p`,{class:`text-foreground-muted text-xs mt-1`},[m(` Enqueue jobs from a function with `),c(`code`,{class:`font-mono text-xs`},`orva.jobs.enqueue()`),m(`. `)],-1)])):_(``,!0)]),c(`table`,Ee,[r[21]||=c(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[c(`tr`,null,[c(`th`,{class:`px-4 py-3 font-medium`},` Function `),c(`th`,{class:`px-4 py-3 font-medium`},` Status `),c(`th`,{class:`px-4 py-3 font-medium hidden md:table-cell`},` Attempts `),c(`th`,{class:`px-4 py-3 font-medium hidden lg:table-cell`},` Scheduled `),c(`th`,{class:`px-4 py-3 font-medium hidden xl:table-cell`},` Finished `),c(`th`,{class:`px-4 py-3 font-medium text-right`},` Actions `)])],-1),c(`tbody`,De,[(t(!0),l(h,null,f(q.value,e=>(t(),l(`tr`,{key:e.id,class:`hover:bg-surface/50 transition-colors`},[c(`td`,Oe,[c(`div`,ke,[c(`span`,null,v(e.function_name||e.function_id),1),c(`span`,Ae,v(e.id),1)])]),c(`td`,je,[c(`span`,{class:u([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium border`,Y(e.status).classes])},[(t(),p(a(Y(e.status).icon),{class:`w-3 h-3 shrink-0`,"aria-hidden":`true`})),m(` `+v(e.status),1)],2),e.last_error?(t(),l(`p`,{key:0,class:`text-[11px] text-danger-fg mt-1 truncate max-w-xs`,title:e.last_error},v(e.last_error),9,Me)):_(``,!0)]),c(`td`,Ne,v(e.attempts)+` / `+v(e.max_attempts),1),c(`td`,Pe,v(X(e.scheduled_at)),1),c(`td`,Fe,v(e.finished_at?X(e.finished_at):s(`—`)),1),c(`td`,Ie,[c(`div`,Le,[e.status===`failed`?(t(),p(w,{key:0,icon:s(b),variant:`success`,title:`Retry`,onClick:t=>Q(e)},null,8,[`icon`,`onClick`])):_(``,!0),d(w,{icon:s(x),variant:`danger`,title:`Delete`,onClick:t=>$(e)},null,8,[`icon`,`onClick`])])])]))),128)),q.value.length===0?(t(),l(`tr`,Re,[c(`td`,ze,[c(`p`,Be,v(W.value===`all`?`No jobs yet.`:`No ${W.value} jobs.`),1),r[20]||=c(`p`,{class:`text-foreground-muted text-xs mt-1`},[m(` Enqueue jobs from a function with `),c(`code`,{class:`font-mono text-xs`},`orva.jobs.enqueue()`),m(`. `)],-1)])])):_(``,!0)])])])]))}});export{V as default}; \ No newline at end of file +import{C as e,D as t,F as n,G as r,I as i,M as a,T as o,U as ee,Z as s,c,d as l,gt as u,h as d,k as f,l as p,m,r as h,s as g,u as _,vt as v}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as te,t as y}from"./clock-CIjbNepe.js";import{n as ne,t as re}from"./circle-DhZmtdqu.js";import{t as b}from"./rotate-ccw-DgujV-4F.js";import{t as x}from"./trash-2-Cz9PSE2q.js";import{B as ie,It as ae,Lt as S,Nt as oe,St as se,U as ce,X as le,_t as C,g as ue,gt as de,jt as fe,y as pe}from"./index-pE9wnfTb.js";import{t as me}from"./Drawer-CSwYBfhJ.js";import{t as w}from"./IconButton-CsCZOqWo.js";var T=fe(`refresh-ccw`,[[`path`,{d:`M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`14sxne`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16`,key:`1hlbsb`}],[`path`,{d:`M16 16h5v5`,key:`ccwih5`}]]),E={class:`space-y-4`},D={class:`flex items-start justify-between gap-4 flex-wrap`},O={class:`flex items-center gap-2 text-xs text-foreground-muted`},k={class:`flex items-center gap-2`},A={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0 flex-1`},j={key:0,class:`ml-1 opacity-70 tabular-nums`},M={class:`flex items-center gap-2 shrink-0`},N={class:`p-5 space-y-5 text-sm`},P=[`value`],F={class:`flex items-center gap-2 text-xs text-foreground-muted`},I={key:0},L={key:1,class:`text-xs text-danger-fg`},R={class:`flex items-center justify-end gap-2`},z={class:`bg-background border border-border rounded-lg overflow-x-auto`},he={class:`sm:hidden divide-y divide-border`},ge={class:`flex items-start justify-between gap-2`},_e={class:`min-w-0 flex-1`},ve={class:`font-medium text-white truncate`},ye={class:`text-[10px] text-foreground-muted font-mono break-all`},be={class:`mt-2`},xe=[`title`],Se={class:`mt-2 grid grid-cols-2 gap-x-3 gap-y-1 text-[11px] text-foreground-muted`},Ce={class:`col-span-2`},we={class:`flex items-center gap-1 shrink-0`},B={key:0,class:`px-4 py-12 text-center`},Te={class:`text-foreground-muted text-sm`},Ee={class:`hidden sm:table w-full text-sm text-left`},De={class:`divide-y divide-border`},Oe={class:`px-4 py-3 font-medium text-white`},ke={class:`flex flex-col`},Ae={class:`text-[10px] text-foreground-muted font-mono`},je={class:`px-4 py-3`},Me=[`title`],Ne={class:`px-4 py-3 text-foreground-muted text-xs hidden md:table-cell`},Pe={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},Fe={class:`px-4 py-3 text-foreground-muted text-xs hidden xl:table-cell`},Ie={class:`px-4 py-3 text-right`},Le={class:`inline-flex items-center gap-1`},Re={key:0},ze={colspan:`6`,class:`px-4 py-12 text-center`},Be={class:`text-foreground-muted text-sm`},V=Object.assign({name:`JobsView`},{__name:`Jobs`,setup(fe){let V=de(),H=r([]),U=r([]),W=r(`all`),G=null,K=ee({open:!1,fnId:``,payload:`{}`,scheduleLater:!1,scheduledAt:``,saving:!1,error:``}),Ve=[{value:`all`,label:`All`},{value:`pending`,label:`Pending`},{value:`running`,label:`Running`},{value:`succeeded`,label:`Succeeded`},{value:`failed`,label:`Failed`}],He=g(()=>H.value.length),q=g(()=>W.value===`all`?H.value:H.value.filter(e=>e.status===W.value)),J=g(()=>{let e={all:H.value.length};for(let t of H.value)e[t.status]=(e[t.status]||0)+1;return e}),Y=e=>{switch(e){case`pending`:return{classes:`bg-warning-tint text-warning-fg border-warning-ring`,icon:y};case`running`:return{classes:`bg-info-tint text-info-fg border-info-ring`,icon:y};case`succeeded`:return{classes:`bg-success-tint text-success-fg border-success-ring`,icon:te};case`failed`:return{classes:`bg-danger-tint text-danger-fg border-danger-ring`,icon:ne};default:return{classes:`bg-surface text-foreground-muted border-border`,icon:re}}},X=e=>e?new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}):`—`,Z=async()=>{try{let e=await ce({limit:200});H.value=e.data.jobs||[]}catch(e){console.error(`Failed to load jobs`,e)}},Q=async e=>{try{await le(e.id),await Z()}catch(e){V.notify({title:`Retry failed`,message:e.message,danger:!0})}},$=async e=>{if(await V.ask({title:`Delete job?`,message:`Job ${e.id} will be removed. This cannot be undone.`,confirmLabel:`Delete`,danger:!0}))try{await ue(e.id),await Z()}catch(e){V.notify({title:`Delete failed`,message:e.message,danger:!0})}},Ue=async()=>{if(K.error=``,K.payload=`{}`,K.scheduleLater=!1,K.scheduledAt=``,U.value.length===0)try{let e=await ie();U.value=e.data?.functions||[],U.value.length&&!K.fnId&&(K.fnId=U.value[0].id)}catch(e){console.error(`list functions failed`,e)}K.open=!0},We=async()=>{K.error=``;let e;try{e=K.payload.trim()?JSON.parse(K.payload):{}}catch(e){K.error=`Payload must be valid JSON: `+e.message;return}let t={function_id:K.fnId,payload:e};if(K.scheduleLater){if(!K.scheduledAt){K.error=`Pick a date/time, or untick "Schedule for later".`;return}t.scheduled_at=new Date(K.scheduledAt).toISOString()}K.saving=!0;try{await pe(t),K.open=!1,await Z()}catch(e){K.error=e?.response?.data?.error?.message||e.message||`Enqueue failed`}finally{K.saving=!1}};return o(()=>{Z(),G||=setInterval(Z,5e3)}),e(()=>{G&&=(clearInterval(G),null)}),(e,r)=>(t(),l(`div`,E,[c(`div`,D,[r[6]||=c(`div`,null,[c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Jobs `),c(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Queued background work with automatic retries. `)],-1),c(`div`,O,` Background queue · `+v(He.value)+` jobs `,1)]),c(`div`,k,[c(`div`,A,[(t(),l(h,null,f(Ve,e=>d(C,{key:e.value,variant:`chip`,size:`xs`,active:W.value===e.value,class:`shrink-0 snap-start`,onClick:t=>W.value=e.value},{default:n(()=>[m(v(e.label)+` `,1),J.value[e.value]===void 0?_(``,!0):(t(),l(`span`,j,v(J.value[e.value]),1))]),_:2},1032,[`active`,`onClick`])),64))]),c(`div`,M,[d(C,{size:`xs`,onClick:Ue},{default:n(()=>[d(s(se),{class:`w-3 h-3`}),r[7]||=m(` Enqueue `,-1)]),_:1}),d(C,{variant:`secondary`,size:`xs`,onClick:Z},{default:n(()=>[d(s(T),{class:`w-3 h-3`}),r[8]||=m(` Refresh `,-1)]),_:1})])]),d(me,{modelValue:K.open,"onUpdate:modelValue":r[5]||=e=>K.open=e,title:`Enqueue a job`,width:`560px`},{footer:n(()=>[c(`div`,R,[d(C,{variant:`ghost`,size:`sm`,onClick:r[4]||=e=>K.open=!1},{default:n(()=>[...r[14]||=[m(` Cancel `,-1)]]),_:1}),d(C,{size:`sm`,disabled:!K.fnId||K.saving,loading:K.saving,onClick:We},{default:n(()=>[...r[15]||=[m(` Enqueue `,-1)]]),_:1},8,[`disabled`,`loading`])])]),default:n(()=>[c(`div`,N,[c(`div`,null,[r[9]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Function`,-1),i(c(`select`,{"onUpdate:modelValue":r[0]||=e=>K.fnId=e,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white focus:outline-none focus:border-white`},[(t(!0),l(h,null,f(U.value,e=>(t(),l(`option`,{key:e.id,value:e.id},v(e.name)+` (`+v(e.runtime)+`) `,9,P))),128))],512),[[ae,K.fnId]])]),c(`div`,null,[r[10]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Payload (JSON)`,-1),i(c(`textarea`,{"onUpdate:modelValue":r[1]||=e=>K.payload=e,rows:`6`,spellcheck:`false`,class:`mt-2 w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono focus:outline-none focus:border-white`,placeholder:`{"hello":"world"}`},null,512),[[S,K.payload]])]),c(`div`,null,[c(`label`,F,[i(c(`input`,{"onUpdate:modelValue":r[2]||=e=>K.scheduleLater=e,type:`checkbox`},null,512),[[oe,K.scheduleLater]]),r[11]||=m(` Schedule for later `,-1)]),r[12]||=c(`p`,{class:`text-[11px] text-foreground-muted mt-1`},` Off: runs on the next scheduler tick (~5s). On: holds until the timestamp below. `,-1)]),K.scheduleLater?(t(),l(`div`,I,[r[13]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Run at (local time)`,-1),i(c(`input`,{"onUpdate:modelValue":r[3]||=e=>K.scheduledAt=e,type:`datetime-local`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white focus:outline-none focus:border-white`},null,512),[[S,K.scheduledAt]])])):_(``,!0),K.error?(t(),l(`div`,L,v(K.error),1)):_(``,!0)])]),_:1},8,[`modelValue`]),c(`div`,z,[c(`ul`,he,[(t(!0),l(h,null,f(q.value,e=>(t(),l(`li`,{key:e.id,class:`px-4 py-3`},[c(`div`,ge,[c(`div`,_e,[c(`div`,ve,v(e.function_name||e.function_id),1),c(`div`,ye,v(e.id),1),c(`div`,be,[c(`span`,{class:u([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium border`,Y(e.status).classes])},[(t(),p(a(Y(e.status).icon),{class:`w-3 h-3 shrink-0`,"aria-hidden":`true`})),m(` `+v(e.status),1)],2)]),e.last_error?(t(),l(`p`,{key:0,class:`text-[11px] text-danger-fg mt-1 break-all`,title:e.last_error},v(e.last_error),9,xe)):_(``,!0),c(`dl`,Se,[c(`div`,null,[r[16]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Attempts `,-1),c(`dd`,null,v(e.attempts)+` / `+v(e.max_attempts),1)]),c(`div`,null,[r[17]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Scheduled `,-1),c(`dd`,null,v(X(e.scheduled_at)),1)]),c(`div`,Ce,[r[18]||=c(`dt`,{class:`uppercase tracking-wider text-[10px]`},` Finished `,-1),c(`dd`,null,v(e.finished_at?X(e.finished_at):s(`—`)),1)])])]),c(`div`,we,[e.status===`failed`?(t(),p(w,{key:0,icon:s(b),variant:`success`,title:`Retry`,onClick:t=>Q(e)},null,8,[`icon`,`onClick`])):_(``,!0),d(w,{icon:s(x),variant:`danger`,title:`Delete`,onClick:t=>$(e)},null,8,[`icon`,`onClick`])])])]))),128)),q.value.length===0?(t(),l(`li`,B,[c(`p`,Te,v(W.value===`all`?`No jobs yet.`:`No ${W.value} jobs.`),1),r[19]||=c(`p`,{class:`text-foreground-muted text-xs mt-1`},[m(` Enqueue jobs from a function with `),c(`code`,{class:`font-mono text-xs`},`orva.jobs.enqueue()`),m(`. `)],-1)])):_(``,!0)]),c(`table`,Ee,[r[21]||=c(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[c(`tr`,null,[c(`th`,{class:`px-4 py-3 font-medium`},` Function `),c(`th`,{class:`px-4 py-3 font-medium`},` Status `),c(`th`,{class:`px-4 py-3 font-medium hidden md:table-cell`},` Attempts `),c(`th`,{class:`px-4 py-3 font-medium hidden lg:table-cell`},` Scheduled `),c(`th`,{class:`px-4 py-3 font-medium hidden xl:table-cell`},` Finished `),c(`th`,{class:`px-4 py-3 font-medium text-right`},` Actions `)])],-1),c(`tbody`,De,[(t(!0),l(h,null,f(q.value,e=>(t(),l(`tr`,{key:e.id,class:`hover:bg-surface/50 transition-colors`},[c(`td`,Oe,[c(`div`,ke,[c(`span`,null,v(e.function_name||e.function_id),1),c(`span`,Ae,v(e.id),1)])]),c(`td`,je,[c(`span`,{class:u([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium border`,Y(e.status).classes])},[(t(),p(a(Y(e.status).icon),{class:`w-3 h-3 shrink-0`,"aria-hidden":`true`})),m(` `+v(e.status),1)],2),e.last_error?(t(),l(`p`,{key:0,class:`text-[11px] text-danger-fg mt-1 truncate max-w-xs`,title:e.last_error},v(e.last_error),9,Me)):_(``,!0)]),c(`td`,Ne,v(e.attempts)+` / `+v(e.max_attempts),1),c(`td`,Pe,v(X(e.scheduled_at)),1),c(`td`,Fe,v(e.finished_at?X(e.finished_at):s(`—`)),1),c(`td`,Ie,[c(`div`,Le,[e.status===`failed`?(t(),p(w,{key:0,icon:s(b),variant:`success`,title:`Retry`,onClick:t=>Q(e)},null,8,[`icon`,`onClick`])):_(``,!0),d(w,{icon:s(x),variant:`danger`,title:`Delete`,onClick:t=>$(e)},null,8,[`icon`,`onClick`])])])]))),128)),q.value.length===0?(t(),l(`tr`,Re,[c(`td`,ze,[c(`p`,Be,v(W.value===`all`?`No jobs yet.`:`No ${W.value} jobs.`),1),r[20]||=c(`p`,{class:`text-foreground-muted text-xs mt-1`},[m(` Enqueue jobs from a function with `),c(`code`,{class:`font-mono text-xs`},`orva.jobs.enqueue()`),m(`. `)],-1)])])):_(``,!0)])])])]))}});export{V as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/KVStore-DzgumyT2.js b/backend/internal/server/ui_dist/assets/KVStore-B42u_-WY.js similarity index 98% rename from backend/internal/server/ui_dist/assets/KVStore-DzgumyT2.js rename to backend/internal/server/ui_dist/assets/KVStore-B42u_-WY.js index 92842ea5..73988a09 100644 --- a/backend/internal/server/ui_dist/assets/KVStore-DzgumyT2.js +++ b/backend/internal/server/ui_dist/assets/KVStore-B42u_-WY.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,S as i,T as a,U as o,Z as s,c,d as l,gt as u,h as d,j as ee,k as f,m as p,r as m,s as h,u as g,vt as _,w as te}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ne}from"./refresh-cw-Cn8qkf-v.js";import{t as v}from"./trash-2-DaeYqnW_.js";import{A as re,Bt as y,Lt as b,M as x,St as ie,_t as S,gt as ae,j as oe,pt as se,xt as ce}from"./index-DTqMKlE1.js";import{t as C}from"./Drawer-B98TBytl.js";import{t as w}from"./IconButton-CsCZOqWo.js";var le={class:`space-y-6`},ue={class:`flex items-start justify-between gap-4`},de={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},fe={class:`flex items-center gap-2`},pe={class:`text-xs text-foreground-muted`},me={key:0},he={class:`flex items-center gap-2 flex-wrap`},ge={class:`relative flex-1 min-w-[260px] max-w-[420px]`},_e={key:1,class:`text-xs text-amber-400/80`},ve={class:`bg-background border border-border rounded-lg overflow-x-auto`},ye={class:`sm:hidden divide-y divide-border`},be=[`onClick`],xe={class:`flex items-start justify-between gap-2`},Se={class:`min-w-0 flex-1`},Ce={class:`font-mono text-xs text-white break-all`},we={class:`mt-1 font-mono text-xs text-foreground-muted break-all`},T={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-foreground-muted`},E={class:`font-mono`},D={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},O={class:`bg-surface px-1.5 py-0.5 rounded text-xs font-mono`},k={class:`hidden sm:table w-full text-sm text-left`},Te={class:`divide-y divide-border`},Ee=[`onClick`],De={class:`px-4 py-3 font-mono text-xs text-white truncate max-w-[360px]`},Oe={class:`px-4 py-3 font-mono text-xs text-foreground-muted truncate max-w-[420px] hidden md:table-cell`},ke={class:`px-4 py-3 hidden sm:table-cell`},Ae={key:1,class:`text-foreground-muted text-xs`},je={class:`px-4 py-3 text-xs font-mono text-foreground-muted hidden lg:table-cell`},Me={class:`px-4 py-3 text-xs text-foreground-muted hidden md:table-cell`},Ne={key:0},Pe={colspan:`6`,class:`px-4 py-12 text-center text-foreground-muted text-sm`},Fe={class:`bg-surface px-1.5 py-0.5 rounded text-xs font-mono`},Ie={key:0,class:`p-5 space-y-5 text-sm`},Le={class:`grid grid-cols-2 gap-3`},Re={class:`bg-surface border border-border rounded p-3 min-w-0`},ze={class:`text-xs text-white font-mono break-all`},Be={class:`bg-surface border border-border rounded p-3 min-w-0`},Ve={class:`bg-surface border border-border rounded p-3 min-w-0`},He={class:`text-xs text-white font-mono truncate`},Ue={class:`bg-surface border border-border rounded p-3 min-w-0`},We={class:`text-xs text-white font-mono`},Ge={class:`flex items-center justify-between mb-2`},Ke={key:0,class:`text-xs text-red-400`},qe={class:`flex items-center justify-between`},Je={class:`flex items-center gap-2`},Ye={class:`p-5 space-y-5 text-sm`},Xe={class:`flex items-center justify-between mb-2`},Ze={key:0,class:`text-xs text-red-400`},Qe={class:`flex items-center justify-end gap-2`},$e=31536e3,et={__name:`KVStore`,setup(et){let tt=se(),A=ae(),j=h(()=>tt.params.name),M=n([]),N=n(0),P=n(!1),F=n(!1),I=n(!1),L=n(``),R=o({open:!1,row:null,text:``,ttlSeconds:0,ttlTouched:!1,error:``}),z=o({open:!1,key:``,text:``,ttlSeconds:0,ttlTouched:!1,error:``}),B=e=>{let t=Number(e);return!Number.isFinite(t)||t<0||t>$e},V=h(()=>M.value.reduce((e,t)=>e+(t.size_bytes||0),0)),H=async()=>{F.value=!0;try{let e={limit:200};L.value&&(e.prefix=L.value);let t=await oe(j.value,e);M.value=t.data?.entries||[],N.value=t.data?.total??M.value.length,P.value=!!t.data?.truncated}catch(e){console.error(`kvList failed`,e),A.notify({title:`Failed to load KV`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}finally{F.value=!1}},U=null,nt=()=>{clearTimeout(U),U=setTimeout(H,250)},W=e=>{R.row=e,R.text=ot(e.value),R.ttlSeconds=e.expires_at?Math.max(0,Math.floor((new Date(e.expires_at)-Date.now())/1e3)):0,R.ttlTouched=!1,R.error=``,R.open=!0},rt=async()=>{if(B(R.ttlSeconds)){R.error=`TTL must be between 0 and 31536000 (1 year).`;return}let e;try{e=JSON.parse(R.text)}catch(e){R.error=`Invalid JSON: `+e.message;return}R.error=``,I.value=!0;try{let t={value:e};R.ttlTouched&&(t.ttl_seconds=R.ttlSeconds),await x(j.value,R.row.key,t),R.open=!1,await H()}catch(e){R.error=e?.response?.data?.error?.message||`Save failed`}finally{I.value=!1}},it=async()=>{R.row&&await A.ask({title:`Delete key?`,message:`"${R.row.key}" will be removed from this function's KV store. This cannot be undone.`,confirmLabel:`Delete`,danger:!0})&&(await q(R.row.key),R.open=!1)},at=()=>{z.key=``,z.text=``,z.ttlSeconds=0,z.ttlTouched=!1,z.error=``,z.open=!0},G=async()=>{let e=z.key.trim();if(!e){z.error=`Key is required`;return}if(B(z.ttlSeconds)){z.error=`TTL must be between 0 and 31536000 (1 year).`;return}let t=z.text.trim()||`""`,n;try{n=JSON.parse(t)}catch(e){z.error=`Invalid JSON: `+e.message;return}z.error=``,I.value=!0;try{let t={value:n};z.ttlTouched&&(t.ttl_seconds=z.ttlSeconds),await x(j.value,e,t),z.open=!1,await H()}catch(e){z.error=e?.response?.data?.error?.message||`Save failed`}finally{I.value=!1}},K=async e=>{await A.ask({title:`Delete key?`,message:`"${e.key}" will be removed from this function's KV store.`,confirmLabel:`Delete`,danger:!0})&&await q(e.key)},q=async e=>{try{await re(j.value,e),await H()}catch(e){A.notify({title:`Failed to delete key`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}},J=(e,t=3)=>{if(t<=0||typeof e!=`string`)return e;let n=e.trim();if(!n||!`{["tfn0123456789-`.includes(n[0]))return e;try{let e=JSON.parse(n);return J(e,t-1)}catch{return e}},ot=e=>{let t=J(e);try{return JSON.stringify(t,null,2)}catch{return String(e)}},Y=e=>{if(e==null)return`—`;let t=J(e);if(typeof t==`string`){let e=JSON.stringify(t);return e.length>80?e.slice(0,80)+`…`:e}try{let e=JSON.stringify(t);return e.length>80?e.slice(0,80)+`…`:e}catch{return String(t)}},X=e=>e==null?`—`:e<1024?e+` B`:e<1048576?(e/1024).toFixed(1)+` KB`:(e/1024/1024).toFixed(1)+` MB`,Z=e=>{if(!e)return`—`;let t=Date.now()-new Date(e).getTime();if(t<0)return`just now`;let n=Math.floor(t/1e3);if(n<60)return n+`s ago`;let r=Math.floor(n/60);if(r<60)return r+`m ago`;let i=Math.floor(r/60);return i<24?i+`h ago`:Math.floor(i/24)+`d ago`},st=e=>e?new Date(e).toLocaleString():`—`,Q=e=>{let t=new Date(e).getTime()-Date.now();if(t<=0)return`expired`;let n=Math.floor(t/1e3);if(n<60)return`in `+n+`s`;let r=Math.floor(n/60);if(r<60)return`in `+r+`m`;let i=Math.floor(r/60);return i<24?`in `+i+`h `+r%60+`m`:`in `+Math.floor(i/24)+`d `+i%24+`h`},$=e=>{if(!e)return`text-foreground-muted`;let t=new Date(e).getTime()-Date.now();return t<=6e4?`text-red-400`:t<=3e5?`text-amber-400`:`text-foreground-muted`};return a(H),i(H),te(()=>{clearTimeout(U)}),(n,i)=>{let a=ee(`router-link`);return e(),l(`div`,le,[c(`div`,ue,[c(`div`,null,[i[18]||=c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` KV Store `,-1),c(`p`,de,[i[16]||=p(` JSON state for `,-1),d(a,{to:`/functions/${j.value}`,class:`text-white underline`},{default:t(()=>[p(_(j.value),1)]),_:1},8,[`to`]),i[17]||=p(` with optional TTL. `,-1)])]),c(`div`,fe,[c(`span`,pe,[p(_(N.value)+` `+_(N.value===1?`key`:`keys`)+` `,1),V.value>0?(e(),l(`span`,me,`· `+_(X(V.value)),1)):g(``,!0)]),d(S,{variant:`secondary`,size:`sm`,onClick:H},{default:t(()=>[d(s(ne),{class:u([`w-3.5 h-3.5`,{"animate-spin":F.value}])},null,8,[`class`]),i[19]||=p(` Refresh `,-1)]),_:1}),d(S,{size:`sm`,onClick:i[0]||=e=>at()},{default:t(()=>[d(s(ie),{class:`w-3.5 h-3.5`}),i[20]||=p(` Set key `,-1)]),_:1})])]),c(`div`,he,[c(`div`,ge,[d(s(ce),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),r(c(`input`,{"onUpdate:modelValue":i[1]||=e=>L.value=e,"aria-label":`Search keys by prefix`,placeholder:`Search by key prefix… (e.g. user:)`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:nt},null,544),[[b,L.value]])]),L.value?(e(),l(`button`,{key:0,class:`text-xs text-foreground-muted hover:text-white px-2 py-1.5 transition-colors`,onClick:i[2]||=e=>{L.value=``,H()}},` Clear `)):g(``,!0),P.value?(e(),l(`span`,_e,` Showing first `+_(M.value.length)+`. Narrow the prefix to see more. `,1)):g(``,!0)]),c(`div`,ve,[c(`ul`,ye,[(e(!0),l(m,null,f(M.value,t=>(e(),l(`li`,{key:t.key,class:`px-4 py-3 cursor-pointer hover:bg-surface-hover transition-colors`,onClick:e=>W(t)},[c(`div`,xe,[c(`div`,Se,[c(`div`,Ce,_(t.key),1),c(`div`,we,_(Y(t.value)),1),c(`div`,T,[t.expires_at?(e(),l(`span`,{key:0,class:u($(t.expires_at))},_(Q(t.expires_at)),3)):g(``,!0),c(`span`,E,_(X(t.size_bytes)),1),c(`span`,null,_(Z(t.updated_at)),1)])]),c(`div`,{class:`shrink-0`,onClick:i[3]||=y(()=>{},[`stop`])},[d(w,{icon:s(v),variant:`danger`,title:`Delete key`,onClick:e=>K(t)},null,8,[`icon`,`onClick`])])])],8,be))),128)),!F.value&&!M.value.length?(e(),l(`li`,D,[L.value?(e(),l(m,{key:0},[i[21]||=p(` No keys match `,-1),c(`code`,O,_(L.value),1),i[22]||=p(`. `,-1)],64)):(e(),l(m,{key:1},[i[23]||=p(` No keys yet. Values written with `,-1),i[24]||=c(`code`,{class:`font-mono text-xs`},`orva.kv.put()`,-1),i[25]||=p(` appear here. `,-1)],64))])):g(``,!0)]),c(`table`,k,[i[31]||=c(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[c(`tr`,null,[c(`th`,{class:`px-4 py-3`},` Key `),c(`th`,{class:`px-4 py-3 hidden md:table-cell`},` Value preview `),c(`th`,{class:`px-4 py-3 w-28 hidden sm:table-cell`},` TTL `),c(`th`,{class:`px-4 py-3 w-20 hidden lg:table-cell`},` Size `),c(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Updated `),c(`th`,{class:`px-4 py-3 w-10 text-right`})])],-1),c(`tbody`,Te,[(e(!0),l(m,null,f(M.value,t=>(e(),l(`tr`,{key:t.key,class:`hover:bg-surface-hover cursor-pointer transition-colors`,onClick:e=>W(t)},[c(`td`,De,_(t.key),1),c(`td`,Oe,_(Y(t.value)),1),c(`td`,ke,[t.expires_at?(e(),l(`span`,{key:0,class:u([`text-xs`,$(t.expires_at)])},_(Q(t.expires_at)),3)):(e(),l(`span`,Ae,_(s(`—`)),1))]),c(`td`,je,_(X(t.size_bytes)),1),c(`td`,Me,_(Z(t.updated_at)),1),c(`td`,{class:`px-4 py-3 text-right`,onClick:i[4]||=y(()=>{},[`stop`])},[d(w,{icon:s(v),variant:`danger`,title:`Delete key`,onClick:e=>K(t)},null,8,[`icon`,`onClick`])])],8,Ee))),128)),!F.value&&!M.value.length?(e(),l(`tr`,Ne,[c(`td`,Pe,[L.value?(e(),l(m,{key:0},[i[26]||=p(` No keys match `,-1),c(`code`,Fe,_(L.value),1),i[27]||=p(`. `,-1)],64)):(e(),l(m,{key:1},[i[28]||=p(` No keys yet. Values written with `,-1),i[29]||=c(`code`,{class:`font-mono text-xs`},`orva.kv.put()`,-1),i[30]||=p(` appear here. `,-1)],64))])])):g(``,!0)])])]),d(C,{modelValue:R.open,"onUpdate:modelValue":i[9]||=e=>R.open=e,title:R.row?R.row.key:`Inspect key`,width:`640px`},{footer:t(()=>[c(`div`,qe,[d(S,{variant:`danger`,size:`sm`,disabled:I.value,onClick:it},{default:t(()=>[d(s(v),{class:`w-3.5 h-3.5`}),i[38]||=p(` Delete `,-1)]),_:1},8,[`disabled`]),c(`div`,Je,[d(S,{variant:`ghost`,size:`sm`,onClick:i[8]||=e=>R.open=!1},{default:t(()=>[...i[39]||=[p(` Cancel `,-1)]]),_:1}),d(S,{size:`sm`,disabled:I.value,loading:I.value,onClick:rt},{default:t(()=>[...i[40]||=[p(` Save `,-1)]]),_:1},8,[`disabled`,`loading`])])])]),default:t(()=>[R.row?(e(),l(`div`,Ie,[c(`div`,Le,[c(`div`,Re,[i[32]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Key `,-1),c(`div`,ze,_(R.row.key),1)]),c(`div`,Be,[i[33]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` TTL `,-1),c(`div`,{class:u([`text-xs text-white font-mono`,$(R.row.expires_at)])},_(R.row.expires_at?Q(R.row.expires_at):`Never`),3)]),c(`div`,Ve,[i[34]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Updated `,-1),c(`div`,He,_(st(R.row.updated_at)),1)]),c(`div`,Ue,[i[35]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Size `,-1),c(`div`,We,_(X(R.row.size_bytes)),1)])]),c(`div`,null,[i[36]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` TTL seconds (0 = never) `,-1),r(c(`input`,{"onUpdate:modelValue":i[5]||=e=>R.ttlSeconds=e,type:`number`,min:`0`,max:`31536000`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:i[6]||=e=>R.ttlTouched=!0},null,544),[[b,R.ttlSeconds,void 0,{number:!0}]]),c(`p`,{class:u([`text-xs mt-1.5`,B(R.ttlSeconds)?`text-danger-fg`:`text-foreground-muted`])},` Must be between 0 and 31536000 (1 year). `,2)]),c(`div`,null,[c(`div`,Ge,[i[37]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Value (JSON)`,-1),R.error?(e(),l(`span`,Ke,_(R.error),1)):g(``,!0)]),r(c(`textarea`,{"onUpdate:modelValue":i[7]||=e=>R.text=e,rows:`14`,spellcheck:`false`,class:`w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono leading-relaxed focus:outline-none focus:border-white whitespace-pre overflow-x-auto`},null,512),[[b,R.text]])])])):g(``,!0)]),_:1},8,[`modelValue`,`title`]),d(C,{modelValue:z.open,"onUpdate:modelValue":i[15]||=e=>z.open=e,title:`Set key`,width:`640px`},{footer:t(()=>[c(`div`,Qe,[d(S,{variant:`ghost`,size:`sm`,onClick:i[14]||=e=>z.open=!1},{default:t(()=>[...i[44]||=[p(` Cancel `,-1)]]),_:1}),d(S,{size:`sm`,disabled:I.value||!z.key.trim(),loading:I.value,onClick:G},{default:t(()=>[...i[45]||=[p(` Save `,-1)]]),_:1},8,[`disabled`,`loading`])])]),default:t(()=>[c(`div`,Ye,[c(`div`,null,[i[41]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Key`,-1),r(c(`input`,{"onUpdate:modelValue":i[10]||=e=>z.key=e,placeholder:`e.g. user:42`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:border-white`,spellcheck:`false`},null,512),[[b,z.key]])]),c(`div`,null,[i[42]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` TTL seconds (0 = never) `,-1),r(c(`input`,{"onUpdate:modelValue":i[11]||=e=>z.ttlSeconds=e,type:`number`,min:`0`,max:`31536000`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:i[12]||=e=>z.ttlTouched=!0},null,544),[[b,z.ttlSeconds,void 0,{number:!0}]]),c(`p`,{class:u([`text-xs mt-1.5`,B(z.ttlSeconds)?`text-danger-fg`:`text-foreground-muted`])},` Must be between 0 and 31536000 (1 year). `,2)]),c(`div`,null,[c(`div`,Xe,[i[43]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Value (JSON)`,-1),z.error?(e(),l(`span`,Ze,_(z.error),1)):g(``,!0)]),r(c(`textarea`,{"onUpdate:modelValue":i[13]||=e=>z.text=e,rows:`14`,spellcheck:`false`,placeholder:`{"hello": "world"}`,class:`w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono leading-relaxed focus:outline-none focus:border-white whitespace-pre overflow-x-auto`},null,512),[[b,z.text]])])])]),_:1},8,[`modelValue`])])}}};export{et as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,S as i,T as a,U as o,Z as s,c,d as l,gt as u,h as d,j as ee,k as f,m as p,r as m,s as h,u as g,vt as _,w as te}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as ne}from"./refresh-cw-CEfUzOcv.js";import{t as v}from"./trash-2-Cz9PSE2q.js";import{A as re,Bt as y,Lt as b,M as x,St as ie,_t as S,gt as ae,j as oe,pt as se,xt as ce}from"./index-pE9wnfTb.js";import{t as C}from"./Drawer-CSwYBfhJ.js";import{t as w}from"./IconButton-CsCZOqWo.js";var le={class:`space-y-6`},ue={class:`flex items-start justify-between gap-4`},de={class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},fe={class:`flex items-center gap-2`},pe={class:`text-xs text-foreground-muted`},me={key:0},he={class:`flex items-center gap-2 flex-wrap`},ge={class:`relative flex-1 min-w-[260px] max-w-[420px]`},_e={key:1,class:`text-xs text-amber-400/80`},ve={class:`bg-background border border-border rounded-lg overflow-x-auto`},ye={class:`sm:hidden divide-y divide-border`},be=[`onClick`],xe={class:`flex items-start justify-between gap-2`},Se={class:`min-w-0 flex-1`},Ce={class:`font-mono text-xs text-white break-all`},we={class:`mt-1 font-mono text-xs text-foreground-muted break-all`},T={class:`mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-foreground-muted`},E={class:`font-mono`},D={key:0,class:`px-6 py-12 text-center text-sm text-foreground-muted`},O={class:`bg-surface px-1.5 py-0.5 rounded text-xs font-mono`},k={class:`hidden sm:table w-full text-sm text-left`},Te={class:`divide-y divide-border`},Ee=[`onClick`],De={class:`px-4 py-3 font-mono text-xs text-white truncate max-w-[360px]`},Oe={class:`px-4 py-3 font-mono text-xs text-foreground-muted truncate max-w-[420px] hidden md:table-cell`},ke={class:`px-4 py-3 hidden sm:table-cell`},Ae={key:1,class:`text-foreground-muted text-xs`},je={class:`px-4 py-3 text-xs font-mono text-foreground-muted hidden lg:table-cell`},Me={class:`px-4 py-3 text-xs text-foreground-muted hidden md:table-cell`},Ne={key:0},Pe={colspan:`6`,class:`px-4 py-12 text-center text-foreground-muted text-sm`},Fe={class:`bg-surface px-1.5 py-0.5 rounded text-xs font-mono`},Ie={key:0,class:`p-5 space-y-5 text-sm`},Le={class:`grid grid-cols-2 gap-3`},Re={class:`bg-surface border border-border rounded p-3 min-w-0`},ze={class:`text-xs text-white font-mono break-all`},Be={class:`bg-surface border border-border rounded p-3 min-w-0`},Ve={class:`bg-surface border border-border rounded p-3 min-w-0`},He={class:`text-xs text-white font-mono truncate`},Ue={class:`bg-surface border border-border rounded p-3 min-w-0`},We={class:`text-xs text-white font-mono`},Ge={class:`flex items-center justify-between mb-2`},Ke={key:0,class:`text-xs text-red-400`},qe={class:`flex items-center justify-between`},Je={class:`flex items-center gap-2`},Ye={class:`p-5 space-y-5 text-sm`},Xe={class:`flex items-center justify-between mb-2`},Ze={key:0,class:`text-xs text-red-400`},Qe={class:`flex items-center justify-end gap-2`},$e=31536e3,et={__name:`KVStore`,setup(et){let tt=se(),A=ae(),j=h(()=>tt.params.name),M=n([]),N=n(0),P=n(!1),F=n(!1),I=n(!1),L=n(``),R=o({open:!1,row:null,text:``,ttlSeconds:0,ttlTouched:!1,error:``}),z=o({open:!1,key:``,text:``,ttlSeconds:0,ttlTouched:!1,error:``}),B=e=>{let t=Number(e);return!Number.isFinite(t)||t<0||t>$e},V=h(()=>M.value.reduce((e,t)=>e+(t.size_bytes||0),0)),H=async()=>{F.value=!0;try{let e={limit:200};L.value&&(e.prefix=L.value);let t=await oe(j.value,e);M.value=t.data?.entries||[],N.value=t.data?.total??M.value.length,P.value=!!t.data?.truncated}catch(e){console.error(`kvList failed`,e),A.notify({title:`Failed to load KV`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}finally{F.value=!1}},U=null,nt=()=>{clearTimeout(U),U=setTimeout(H,250)},W=e=>{R.row=e,R.text=ot(e.value),R.ttlSeconds=e.expires_at?Math.max(0,Math.floor((new Date(e.expires_at)-Date.now())/1e3)):0,R.ttlTouched=!1,R.error=``,R.open=!0},rt=async()=>{if(B(R.ttlSeconds)){R.error=`TTL must be between 0 and 31536000 (1 year).`;return}let e;try{e=JSON.parse(R.text)}catch(e){R.error=`Invalid JSON: `+e.message;return}R.error=``,I.value=!0;try{let t={value:e};R.ttlTouched&&(t.ttl_seconds=R.ttlSeconds),await x(j.value,R.row.key,t),R.open=!1,await H()}catch(e){R.error=e?.response?.data?.error?.message||`Save failed`}finally{I.value=!1}},it=async()=>{R.row&&await A.ask({title:`Delete key?`,message:`"${R.row.key}" will be removed from this function's KV store. This cannot be undone.`,confirmLabel:`Delete`,danger:!0})&&(await q(R.row.key),R.open=!1)},at=()=>{z.key=``,z.text=``,z.ttlSeconds=0,z.ttlTouched=!1,z.error=``,z.open=!0},G=async()=>{let e=z.key.trim();if(!e){z.error=`Key is required`;return}if(B(z.ttlSeconds)){z.error=`TTL must be between 0 and 31536000 (1 year).`;return}let t=z.text.trim()||`""`,n;try{n=JSON.parse(t)}catch(e){z.error=`Invalid JSON: `+e.message;return}z.error=``,I.value=!0;try{let t={value:n};z.ttlTouched&&(t.ttl_seconds=z.ttlSeconds),await x(j.value,e,t),z.open=!1,await H()}catch(e){z.error=e?.response?.data?.error?.message||`Save failed`}finally{I.value=!1}},K=async e=>{await A.ask({title:`Delete key?`,message:`"${e.key}" will be removed from this function's KV store.`,confirmLabel:`Delete`,danger:!0})&&await q(e.key)},q=async e=>{try{await re(j.value,e),await H()}catch(e){A.notify({title:`Failed to delete key`,message:e?.response?.data?.error?.message||`Unknown error`,danger:!0})}},J=(e,t=3)=>{if(t<=0||typeof e!=`string`)return e;let n=e.trim();if(!n||!`{["tfn0123456789-`.includes(n[0]))return e;try{let e=JSON.parse(n);return J(e,t-1)}catch{return e}},ot=e=>{let t=J(e);try{return JSON.stringify(t,null,2)}catch{return String(e)}},Y=e=>{if(e==null)return`—`;let t=J(e);if(typeof t==`string`){let e=JSON.stringify(t);return e.length>80?e.slice(0,80)+`…`:e}try{let e=JSON.stringify(t);return e.length>80?e.slice(0,80)+`…`:e}catch{return String(t)}},X=e=>e==null?`—`:e<1024?e+` B`:e<1048576?(e/1024).toFixed(1)+` KB`:(e/1024/1024).toFixed(1)+` MB`,Z=e=>{if(!e)return`—`;let t=Date.now()-new Date(e).getTime();if(t<0)return`just now`;let n=Math.floor(t/1e3);if(n<60)return n+`s ago`;let r=Math.floor(n/60);if(r<60)return r+`m ago`;let i=Math.floor(r/60);return i<24?i+`h ago`:Math.floor(i/24)+`d ago`},st=e=>e?new Date(e).toLocaleString():`—`,Q=e=>{let t=new Date(e).getTime()-Date.now();if(t<=0)return`expired`;let n=Math.floor(t/1e3);if(n<60)return`in `+n+`s`;let r=Math.floor(n/60);if(r<60)return`in `+r+`m`;let i=Math.floor(r/60);return i<24?`in `+i+`h `+r%60+`m`:`in `+Math.floor(i/24)+`d `+i%24+`h`},$=e=>{if(!e)return`text-foreground-muted`;let t=new Date(e).getTime()-Date.now();return t<=6e4?`text-red-400`:t<=3e5?`text-amber-400`:`text-foreground-muted`};return a(H),i(H),te(()=>{clearTimeout(U)}),(n,i)=>{let a=ee(`router-link`);return e(),l(`div`,le,[c(`div`,ue,[c(`div`,null,[i[18]||=c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` KV Store `,-1),c(`p`,de,[i[16]||=p(` JSON state for `,-1),d(a,{to:`/functions/${j.value}`,class:`text-white underline`},{default:t(()=>[p(_(j.value),1)]),_:1},8,[`to`]),i[17]||=p(` with optional TTL. `,-1)])]),c(`div`,fe,[c(`span`,pe,[p(_(N.value)+` `+_(N.value===1?`key`:`keys`)+` `,1),V.value>0?(e(),l(`span`,me,`· `+_(X(V.value)),1)):g(``,!0)]),d(S,{variant:`secondary`,size:`sm`,onClick:H},{default:t(()=>[d(s(ne),{class:u([`w-3.5 h-3.5`,{"animate-spin":F.value}])},null,8,[`class`]),i[19]||=p(` Refresh `,-1)]),_:1}),d(S,{size:`sm`,onClick:i[0]||=e=>at()},{default:t(()=>[d(s(ie),{class:`w-3.5 h-3.5`}),i[20]||=p(` Set key `,-1)]),_:1})])]),c(`div`,he,[c(`div`,ge,[d(s(ce),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),r(c(`input`,{"onUpdate:modelValue":i[1]||=e=>L.value=e,"aria-label":`Search keys by prefix`,placeholder:`Search by key prefix… (e.g. user:)`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:nt},null,544),[[b,L.value]])]),L.value?(e(),l(`button`,{key:0,class:`text-xs text-foreground-muted hover:text-white px-2 py-1.5 transition-colors`,onClick:i[2]||=e=>{L.value=``,H()}},` Clear `)):g(``,!0),P.value?(e(),l(`span`,_e,` Showing first `+_(M.value.length)+`. Narrow the prefix to see more. `,1)):g(``,!0)]),c(`div`,ve,[c(`ul`,ye,[(e(!0),l(m,null,f(M.value,t=>(e(),l(`li`,{key:t.key,class:`px-4 py-3 cursor-pointer hover:bg-surface-hover transition-colors`,onClick:e=>W(t)},[c(`div`,xe,[c(`div`,Se,[c(`div`,Ce,_(t.key),1),c(`div`,we,_(Y(t.value)),1),c(`div`,T,[t.expires_at?(e(),l(`span`,{key:0,class:u($(t.expires_at))},_(Q(t.expires_at)),3)):g(``,!0),c(`span`,E,_(X(t.size_bytes)),1),c(`span`,null,_(Z(t.updated_at)),1)])]),c(`div`,{class:`shrink-0`,onClick:i[3]||=y(()=>{},[`stop`])},[d(w,{icon:s(v),variant:`danger`,title:`Delete key`,onClick:e=>K(t)},null,8,[`icon`,`onClick`])])])],8,be))),128)),!F.value&&!M.value.length?(e(),l(`li`,D,[L.value?(e(),l(m,{key:0},[i[21]||=p(` No keys match `,-1),c(`code`,O,_(L.value),1),i[22]||=p(`. `,-1)],64)):(e(),l(m,{key:1},[i[23]||=p(` No keys yet. Values written with `,-1),i[24]||=c(`code`,{class:`font-mono text-xs`},`orva.kv.put()`,-1),i[25]||=p(` appear here. `,-1)],64))])):g(``,!0)]),c(`table`,k,[i[31]||=c(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[c(`tr`,null,[c(`th`,{class:`px-4 py-3`},` Key `),c(`th`,{class:`px-4 py-3 hidden md:table-cell`},` Value preview `),c(`th`,{class:`px-4 py-3 w-28 hidden sm:table-cell`},` TTL `),c(`th`,{class:`px-4 py-3 w-20 hidden lg:table-cell`},` Size `),c(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Updated `),c(`th`,{class:`px-4 py-3 w-10 text-right`})])],-1),c(`tbody`,Te,[(e(!0),l(m,null,f(M.value,t=>(e(),l(`tr`,{key:t.key,class:`hover:bg-surface-hover cursor-pointer transition-colors`,onClick:e=>W(t)},[c(`td`,De,_(t.key),1),c(`td`,Oe,_(Y(t.value)),1),c(`td`,ke,[t.expires_at?(e(),l(`span`,{key:0,class:u([`text-xs`,$(t.expires_at)])},_(Q(t.expires_at)),3)):(e(),l(`span`,Ae,_(s(`—`)),1))]),c(`td`,je,_(X(t.size_bytes)),1),c(`td`,Me,_(Z(t.updated_at)),1),c(`td`,{class:`px-4 py-3 text-right`,onClick:i[4]||=y(()=>{},[`stop`])},[d(w,{icon:s(v),variant:`danger`,title:`Delete key`,onClick:e=>K(t)},null,8,[`icon`,`onClick`])])],8,Ee))),128)),!F.value&&!M.value.length?(e(),l(`tr`,Ne,[c(`td`,Pe,[L.value?(e(),l(m,{key:0},[i[26]||=p(` No keys match `,-1),c(`code`,Fe,_(L.value),1),i[27]||=p(`. `,-1)],64)):(e(),l(m,{key:1},[i[28]||=p(` No keys yet. Values written with `,-1),i[29]||=c(`code`,{class:`font-mono text-xs`},`orva.kv.put()`,-1),i[30]||=p(` appear here. `,-1)],64))])])):g(``,!0)])])]),d(C,{modelValue:R.open,"onUpdate:modelValue":i[9]||=e=>R.open=e,title:R.row?R.row.key:`Inspect key`,width:`640px`},{footer:t(()=>[c(`div`,qe,[d(S,{variant:`danger`,size:`sm`,disabled:I.value,onClick:it},{default:t(()=>[d(s(v),{class:`w-3.5 h-3.5`}),i[38]||=p(` Delete `,-1)]),_:1},8,[`disabled`]),c(`div`,Je,[d(S,{variant:`ghost`,size:`sm`,onClick:i[8]||=e=>R.open=!1},{default:t(()=>[...i[39]||=[p(` Cancel `,-1)]]),_:1}),d(S,{size:`sm`,disabled:I.value,loading:I.value,onClick:rt},{default:t(()=>[...i[40]||=[p(` Save `,-1)]]),_:1},8,[`disabled`,`loading`])])])]),default:t(()=>[R.row?(e(),l(`div`,Ie,[c(`div`,Le,[c(`div`,Re,[i[32]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Key `,-1),c(`div`,ze,_(R.row.key),1)]),c(`div`,Be,[i[33]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` TTL `,-1),c(`div`,{class:u([`text-xs text-white font-mono`,$(R.row.expires_at)])},_(R.row.expires_at?Q(R.row.expires_at):`Never`),3)]),c(`div`,Ve,[i[34]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Updated `,-1),c(`div`,He,_(st(R.row.updated_at)),1)]),c(`div`,Ue,[i[35]||=c(`div`,{class:`text-xs uppercase tracking-wider text-foreground-muted mb-1`},` Size `,-1),c(`div`,We,_(X(R.row.size_bytes)),1)])]),c(`div`,null,[i[36]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` TTL seconds (0 = never) `,-1),r(c(`input`,{"onUpdate:modelValue":i[5]||=e=>R.ttlSeconds=e,type:`number`,min:`0`,max:`31536000`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:i[6]||=e=>R.ttlTouched=!0},null,544),[[b,R.ttlSeconds,void 0,{number:!0}]]),c(`p`,{class:u([`text-xs mt-1.5`,B(R.ttlSeconds)?`text-danger-fg`:`text-foreground-muted`])},` Must be between 0 and 31536000 (1 year). `,2)]),c(`div`,null,[c(`div`,Ge,[i[37]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Value (JSON)`,-1),R.error?(e(),l(`span`,Ke,_(R.error),1)):g(``,!0)]),r(c(`textarea`,{"onUpdate:modelValue":i[7]||=e=>R.text=e,rows:`14`,spellcheck:`false`,class:`w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono leading-relaxed focus:outline-none focus:border-white whitespace-pre overflow-x-auto`},null,512),[[b,R.text]])])])):g(``,!0)]),_:1},8,[`modelValue`,`title`]),d(C,{modelValue:z.open,"onUpdate:modelValue":i[15]||=e=>z.open=e,title:`Set key`,width:`640px`},{footer:t(()=>[c(`div`,Qe,[d(S,{variant:`ghost`,size:`sm`,onClick:i[14]||=e=>z.open=!1},{default:t(()=>[...i[44]||=[p(` Cancel `,-1)]]),_:1}),d(S,{size:`sm`,disabled:I.value||!z.key.trim(),loading:I.value,onClick:G},{default:t(()=>[...i[45]||=[p(` Save `,-1)]]),_:1},8,[`disabled`,`loading`])])]),default:t(()=>[c(`div`,Ye,[c(`div`,null,[i[41]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Key`,-1),r(c(`input`,{"onUpdate:modelValue":i[10]||=e=>z.key=e,placeholder:`e.g. user:42`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:border-white`,spellcheck:`false`},null,512),[[b,z.key]])]),c(`div`,null,[i[42]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},` TTL seconds (0 = never) `,-1),r(c(`input`,{"onUpdate:modelValue":i[11]||=e=>z.ttlSeconds=e,type:`number`,min:`0`,max:`31536000`,class:`mt-2 w-full bg-surface border border-border rounded px-3 py-2 text-sm text-white font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onInput:i[12]||=e=>z.ttlTouched=!0},null,544),[[b,z.ttlSeconds,void 0,{number:!0}]]),c(`p`,{class:u([`text-xs mt-1.5`,B(z.ttlSeconds)?`text-danger-fg`:`text-foreground-muted`])},` Must be between 0 and 31536000 (1 year). `,2)]),c(`div`,null,[c(`div`,Xe,[i[43]||=c(`label`,{class:`text-xs uppercase tracking-wider text-foreground-muted`},`Value (JSON)`,-1),z.error?(e(),l(`span`,Ze,_(z.error),1)):g(``,!0)]),r(c(`textarea`,{"onUpdate:modelValue":i[13]||=e=>z.text=e,rows:`14`,spellcheck:`false`,placeholder:`{"hello": "world"}`,class:`w-full bg-surface border border-border rounded p-3 text-xs text-white font-mono leading-relaxed focus:outline-none focus:border-white whitespace-pre overflow-x-auto`},null,512),[[b,z.text]])])])]),_:1},8,[`modelValue`])])}}};export{et as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Login-DscOTSMy.js b/backend/internal/server/ui_dist/assets/Login-yy2M_6WN.js similarity index 93% rename from backend/internal/server/ui_dist/assets/Login-DscOTSMy.js rename to backend/internal/server/ui_dist/assets/Login-yy2M_6WN.js index bc8c125e..f7532fed 100644 --- a/backend/internal/server/ui_dist/assets/Login-DscOTSMy.js +++ b/backend/internal/server/ui_dist/assets/Login-yy2M_6WN.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,m as l,u,vt as d}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as f}from"./circle-alert-BnUYYhGE.js";import{Bt as p,Lt as m,_t as h,dt as g,jt as _,lt as v,mt as y}from"./index-DTqMKlE1.js";var b=_(`log-in`,[[`path`,{d:`m10 17 5-5-5-5`,key:`1bsop3`}],[`path`,{d:`M15 12H3`,key:`6jk70r`}],[`path`,{d:`M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4`,key:`u53s6r`}]]),x={class:`min-h-screen flex items-center justify-center bg-background p-4`},S={class:`w-full max-w-md`},C={class:`text-center mb-8`},w={class:`flex items-center justify-center gap-3 mb-4`},T={class:`bg-surface border border-border rounded-lg shadow-lg p-8`},E=[`disabled`],D=[`disabled`],O={key:0,class:`bg-danger-tint border border-danger-ring rounded-md px-4 py-3 flex items-start gap-2`,role:`alert`},k={class:`text-sm text-danger-fg`},A={__name:`Login`,setup(_){let A=y(),j=g();i(async()=>{await j.fetchAuthStatus()===!1&&A.replace(`/onboarding`)});let M=n({username:``,password:``}),N=n(``),P=n(!1),F=async()=>{N.value=``,P.value=!0;let e=await j.login(M.value.username,M.value.password);P.value=!1,e.success?A.push(`/`):e.code===`ONBOARDING_REQUIRED`?A.push(`/onboarding`):N.value=e.error};return(n,i)=>(e(),s(`div`,x,[o(`div`,S,[o(`div`,C,[o(`div`,w,[c(v,{class:`w-12 h-12`}),i[2]||=o(`h1`,{class:`text-3xl font-bold tracking-tight text-foreground`},` Orva `,-1)]),i[3]||=o(`p`,{class:`text-foreground-muted text-sm`},` Sign in to this instance `,-1)]),o(`div`,T,[i[7]||=o(`h2`,{class:`text-xl font-semibold text-foreground mb-6`},` Sign In `,-1),o(`form`,{class:`space-y-5`,onSubmit:p(F,[`prevent`])},[o(`div`,null,[i[4]||=o(`label`,{for:`login-username`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` Username `,-1),r(o(`input`,{id:`login-username`,"onUpdate:modelValue":i[0]||=e=>M.value.username=e,type:`text`,required:``,autocomplete:`username`,class:`w-full bg-background border border-border rounded-md px-4 py-2.5 text-sm text-foreground placeholder-foreground-muted focus:outline-none focus:ring-2 focus:ring-primary transition-colors`,placeholder:`Enter your username`,disabled:P.value},null,8,E),[[m,M.value.username]])]),o(`div`,null,[i[5]||=o(`label`,{for:`login-password`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` Password `,-1),r(o(`input`,{id:`login-password`,"onUpdate:modelValue":i[1]||=e=>M.value.password=e,type:`password`,required:``,autocomplete:`current-password`,class:`w-full bg-background border border-border rounded-md px-4 py-2.5 text-sm text-foreground placeholder-foreground-muted focus:outline-none focus:ring-2 focus:ring-primary transition-colors`,placeholder:`Enter your password`,disabled:P.value},null,8,D),[[m,M.value.password]])]),N.value?(e(),s(`div`,O,[c(a(f),{class:`w-5 h-5 text-danger-fg shrink-0 mt-0.5`}),o(`p`,k,d(N.value),1)])):u(``,!0),c(h,{type:`submit`,class:`w-full`,loading:P.value,disabled:!M.value.username||!M.value.password||P.value},{default:t(()=>[c(a(b),{class:`w-4 h-4`}),i[6]||=l(` Sign In `,-1)]),_:1},8,[`loading`,`disabled`])],32)])])]))}};export{A as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,m as l,u,vt as d}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as f}from"./circle-alert-CwieDBHo.js";import{Bt as p,Lt as m,_t as h,dt as g,jt as _,lt as v,mt as y}from"./index-pE9wnfTb.js";var b=_(`log-in`,[[`path`,{d:`m10 17 5-5-5-5`,key:`1bsop3`}],[`path`,{d:`M15 12H3`,key:`6jk70r`}],[`path`,{d:`M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4`,key:`u53s6r`}]]),x={class:`min-h-screen flex items-center justify-center bg-background p-4`},S={class:`w-full max-w-md`},C={class:`text-center mb-8`},w={class:`flex items-center justify-center gap-3 mb-4`},T={class:`bg-surface border border-border rounded-lg shadow-lg p-8`},E=[`disabled`],D=[`disabled`],O={key:0,class:`bg-danger-tint border border-danger-ring rounded-md px-4 py-3 flex items-start gap-2`,role:`alert`},k={class:`text-sm text-danger-fg`},A={__name:`Login`,setup(_){let A=y(),j=g();i(async()=>{await j.fetchAuthStatus()===!1&&A.replace(`/onboarding`)});let M=n({username:``,password:``}),N=n(``),P=n(!1),F=async()=>{N.value=``,P.value=!0;let e=await j.login(M.value.username,M.value.password);P.value=!1,e.success?A.push(`/`):e.code===`ONBOARDING_REQUIRED`?A.push(`/onboarding`):N.value=e.error};return(n,i)=>(e(),s(`div`,x,[o(`div`,S,[o(`div`,C,[o(`div`,w,[c(v,{class:`w-12 h-12`}),i[2]||=o(`h1`,{class:`text-3xl font-bold tracking-tight text-foreground`},` Orva `,-1)]),i[3]||=o(`p`,{class:`text-foreground-muted text-sm`},` Sign in to this instance `,-1)]),o(`div`,T,[i[7]||=o(`h2`,{class:`text-xl font-semibold text-foreground mb-6`},` Sign In `,-1),o(`form`,{class:`space-y-5`,onSubmit:p(F,[`prevent`])},[o(`div`,null,[i[4]||=o(`label`,{for:`login-username`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` Username `,-1),r(o(`input`,{id:`login-username`,"onUpdate:modelValue":i[0]||=e=>M.value.username=e,type:`text`,required:``,autocomplete:`username`,class:`w-full bg-background border border-border rounded-md px-4 py-2.5 text-sm text-foreground placeholder-foreground-muted focus:outline-none focus:ring-2 focus:ring-primary transition-colors`,placeholder:`Enter your username`,disabled:P.value},null,8,E),[[m,M.value.username]])]),o(`div`,null,[i[5]||=o(`label`,{for:`login-password`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-2`},` Password `,-1),r(o(`input`,{id:`login-password`,"onUpdate:modelValue":i[1]||=e=>M.value.password=e,type:`password`,required:``,autocomplete:`current-password`,class:`w-full bg-background border border-border rounded-md px-4 py-2.5 text-sm text-foreground placeholder-foreground-muted focus:outline-none focus:ring-2 focus:ring-primary transition-colors`,placeholder:`Enter your password`,disabled:P.value},null,8,D),[[m,M.value.password]])]),N.value?(e(),s(`div`,O,[c(a(f),{class:`w-5 h-5 text-danger-fg shrink-0 mt-0.5`}),o(`p`,k,d(N.value),1)])):u(``,!0),c(h,{type:`submit`,class:`w-full`,loading:P.value,disabled:!M.value.username||!M.value.password||P.value},{default:t(()=>[c(a(b),{class:`w-4 h-4`}),i[6]||=l(` Sign In `,-1)]),_:1},8,[`loading`,`disabled`])],32)])])]))}};export{A as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Modal-BAoZams6.js b/backend/internal/server/ui_dist/assets/Modal-C1IBLm0r.js similarity index 97% rename from backend/internal/server/ui_dist/assets/Modal-BAoZams6.js rename to backend/internal/server/ui_dist/assets/Modal-C1IBLm0r.js index b79c78aa..f93314b1 100644 --- a/backend/internal/server/ui_dist/assets/Modal-BAoZams6.js +++ b/backend/internal/server/ui_dist/assets/Modal-C1IBLm0r.js @@ -1 +1 @@ -import{A as e,D as t,E as n,F as r,G as i,M as a,T as o,Y as s,Z as c,a as l,c as u,d,gt as f,h as p,l as m,s as h,u as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{Bt as v,Mt as y,ht as b,vt as x}from"./index-DTqMKlE1.js";var S={class:`flex items-center justify-between px-5 py-3 border-b border-border shrink-0`},C={class:`flex items-center gap-2 min-w-0`},w=[`aria-label`],T={class:`p-5 overflow-y-auto scrollable flex-1 max-h-[calc(100dvh-9rem)] sm:max-h-[70vh]`},E={key:0,class:`px-5 py-3 border-t border-border flex items-center justify-end gap-2 bg-surface/40 shrink-0`},D=Object.assign({name:`CommonModal`},{__name:`Modal`,props:{modelValue:{type:Boolean,default:!1},title:{type:String,required:!0},icon:{type:[Object,Function],default:null},size:{type:String,default:`md`,validator:e=>[`sm`,`md`,`lg`,`xl`].includes(e)}},emits:[`update:modelValue`],setup(D,{emit:O}){let k=D,A=O,j=`modal-title-${Math.random().toString(36).slice(2,10)}`,M=i(null);b(M,s(k,`modelValue`));let N=h(()=>{switch(k.size){case`sm`:return`sm:max-w-sm`;case`lg`:return`sm:max-w-2xl`;case`xl`:return`sm:max-w-4xl`;default:return`sm:max-w-lg`}}),P=()=>A(`update:modelValue`,!1),F=e=>{e.key===`Escape`&&k.modelValue&&P()};return o(()=>window.addEventListener(`keydown`,F)),n(()=>window.removeEventListener(`keydown`,F)),(n,i)=>(t(),m(l,{to:`body`},[p(y,{name:`fade`},{default:r(()=>[D.modelValue?(t(),d(`div`,{key:0,class:`fixed inset-0 z-40 flex items-stretch sm:items-center justify-center overflow-y-auto bg-black/60 backdrop-blur-sm pt-safe pb-safe pl-safe pr-safe p-2 sm:p-4`,onClick:v(P,[`self`])},[u(`div`,{ref_key:`dialogRoot`,ref:M,class:f([`w-full bg-background border border-border rounded-lg shadow-xl my-0 sm:my-auto flex flex-col max-w-full`,N.value]),role:`dialog`,"aria-modal":`true`,"aria-labelledby":j},[u(`header`,S,[u(`div`,C,[D.icon?(t(),m(a(D.icon),{key:0,class:`w-4 h-4 text-foreground-muted shrink-0`})):g(``,!0),u(`h3`,{id:j,class:`text-sm font-semibold text-white tracking-tight truncate`},_(D.title),1)]),u(`button`,{class:`p-1.5 -mr-1.5 rounded text-foreground-muted hover:text-white hover:bg-surface-hover transition-colors touch-expand-iconbtn shrink-0`,"aria-label":`Close ${D.title}`,onClick:P},[p(c(x),{class:`w-4 h-4`})],8,w)]),u(`div`,T,[e(n.$slots,`default`)]),n.$slots.footer?(t(),d(`footer`,E,[e(n.$slots,`footer`)])):g(``,!0)],2)])):g(``,!0)]),_:3})]))}});export{D as t}; \ No newline at end of file +import{A as e,D as t,E as n,F as r,G as i,M as a,T as o,Y as s,Z as c,a as l,c as u,d,gt as f,h as p,l as m,s as h,u as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{Bt as v,Mt as y,ht as b,vt as x}from"./index-pE9wnfTb.js";var S={class:`flex items-center justify-between px-5 py-3 border-b border-border shrink-0`},C={class:`flex items-center gap-2 min-w-0`},w=[`aria-label`],T={class:`p-5 overflow-y-auto scrollable flex-1 max-h-[calc(100dvh-9rem)] sm:max-h-[70vh]`},E={key:0,class:`px-5 py-3 border-t border-border flex items-center justify-end gap-2 bg-surface/40 shrink-0`},D=Object.assign({name:`CommonModal`},{__name:`Modal`,props:{modelValue:{type:Boolean,default:!1},title:{type:String,required:!0},icon:{type:[Object,Function],default:null},size:{type:String,default:`md`,validator:e=>[`sm`,`md`,`lg`,`xl`].includes(e)}},emits:[`update:modelValue`],setup(D,{emit:O}){let k=D,A=O,j=`modal-title-${Math.random().toString(36).slice(2,10)}`,M=i(null);b(M,s(k,`modelValue`));let N=h(()=>{switch(k.size){case`sm`:return`sm:max-w-sm`;case`lg`:return`sm:max-w-2xl`;case`xl`:return`sm:max-w-4xl`;default:return`sm:max-w-lg`}}),P=()=>A(`update:modelValue`,!1),F=e=>{e.key===`Escape`&&k.modelValue&&P()};return o(()=>window.addEventListener(`keydown`,F)),n(()=>window.removeEventListener(`keydown`,F)),(n,i)=>(t(),m(l,{to:`body`},[p(y,{name:`fade`},{default:r(()=>[D.modelValue?(t(),d(`div`,{key:0,class:`fixed inset-0 z-40 flex items-stretch sm:items-center justify-center overflow-y-auto bg-black/60 backdrop-blur-sm pt-safe pb-safe pl-safe pr-safe p-2 sm:p-4`,onClick:v(P,[`self`])},[u(`div`,{ref_key:`dialogRoot`,ref:M,class:f([`w-full bg-background border border-border rounded-lg shadow-xl my-0 sm:my-auto flex flex-col max-w-full`,N.value]),role:`dialog`,"aria-modal":`true`,"aria-labelledby":j},[u(`header`,S,[u(`div`,C,[D.icon?(t(),m(a(D.icon),{key:0,class:`w-4 h-4 text-foreground-muted shrink-0`})):g(``,!0),u(`h3`,{id:j,class:`text-sm font-semibold text-white tracking-tight truncate`},_(D.title),1)]),u(`button`,{class:`p-1.5 -mr-1.5 rounded text-foreground-muted hover:text-white hover:bg-surface-hover transition-colors touch-expand-iconbtn shrink-0`,"aria-label":`Close ${D.title}`,onClick:P},[p(c(x),{class:`w-4 h-4`})],8,w)]),u(`div`,T,[e(n.$slots,`default`)]),n.$slots.footer?(t(),d(`footer`,E,[e(n.$slots,`footer`)])):g(``,!0)],2)])):g(``,!0)]),_:3})]))}});export{D as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/ModelMenu-BtMjUXcx.js b/backend/internal/server/ui_dist/assets/ModelMenu-D7Iysg0v.js similarity index 98% rename from backend/internal/server/ui_dist/assets/ModelMenu-BtMjUXcx.js rename to backend/internal/server/ui_dist/assets/ModelMenu-D7Iysg0v.js index ca79e166..e00b0091 100644 --- a/backend/internal/server/ui_dist/assets/ModelMenu-BtMjUXcx.js +++ b/backend/internal/server/ui_dist/assets/ModelMenu-D7Iysg0v.js @@ -1,4 +1,4 @@ -import{A as e,D as t,E as n,F as r,G as i,I as a,P as o,T as s,Z as c,_t as l,a as u,c as d,d as f,gt as p,h as m,k as h,l as g,r as _,s as v,u as y,vt as b,x}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as S}from"./pinia-B41TZNUX.js";import{t as C}from"./check-BNre7JFR.js";import{r as w,t as T}from"./client-BF51V3uE.js";import{Dt as E,Lt as D,Mt as O,jt as k,xt as A,zt as j}from"./index-DTqMKlE1.js";import{t as M}from"./Drawer-B98TBytl.js";var N=k(`cpu`,[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]),P=k(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),F=S(`ai`,()=>{let e=i([]),t=i(null),n=i([]),r=i(!1),a=i(!1),o=i(``),s=i(null),c=i([]),l=i(!1),u=i(null),d=i(``),f=i(``),p=i(`off`),m=i([]),h=i(``),g=i(!1),_=-1,v=null,y=null;function b(){let e={thinking:p.value};return d.value&&(e.provider=d.value),f.value&&(e.model=f.value),e}let x=0;function S(e,t){o.value=e,n.value.push({kind:`error`,id:`err-${++x}`,message:e,code:t||``})}function C(e){n.value=n.value.filter(t=>t.kind!==`error`||t.id!==e)}function E(){n.value=n.value.filter(e=>e.kind!==`error`)}async function D(){if(t.value)try{let{data:e}=await T.get(`/ai/conversations/${t.value}`),r=n.value.filter(e=>e.kind===`error`);n.value=[...H(e),...r]}catch{}}function O(){_>=0&&n.value[_]?.kind===`message`||(n.value.push({kind:`message`,role:`assistant`,parts:[]}),_=n.value.length-1)}function k(e){let t=n.value[_];if(!t)return;let r={...t,parts:t.parts.slice()};e(r),n.value[_]=r}function A(e){let t=`message`,n=``;for(let r of e.split(` +import{A as e,D as t,E as n,F as r,G as i,I as a,P as o,T as s,Z as c,_t as l,a as u,c as d,d as f,gt as p,h as m,k as h,l as g,r as _,s as v,u as y,vt as b,x}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as S}from"./pinia-B41TZNUX.js";import{t as C}from"./check-CZmR72iA.js";import{r as w,t as T}from"./client-BF51V3uE.js";import{Dt as E,Lt as D,Mt as O,jt as k,xt as A,zt as j}from"./index-pE9wnfTb.js";import{t as M}from"./Drawer-CSwYBfhJ.js";var N=k(`cpu`,[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]),P=k(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),F=S(`ai`,()=>{let e=i([]),t=i(null),n=i([]),r=i(!1),a=i(!1),o=i(``),s=i(null),c=i([]),l=i(!1),u=i(null),d=i(``),f=i(``),p=i(`off`),m=i([]),h=i(``),g=i(!1),_=-1,v=null,y=null;function b(){let e={thinking:p.value};return d.value&&(e.provider=d.value),f.value&&(e.model=f.value),e}let x=0;function S(e,t){o.value=e,n.value.push({kind:`error`,id:`err-${++x}`,message:e,code:t||``})}function C(e){n.value=n.value.filter(t=>t.kind!==`error`||t.id!==e)}function E(){n.value=n.value.filter(e=>e.kind!==`error`)}async function D(){if(t.value)try{let{data:e}=await T.get(`/ai/conversations/${t.value}`),r=n.value.filter(e=>e.kind===`error`);n.value=[...H(e),...r]}catch{}}function O(){_>=0&&n.value[_]?.kind===`message`||(n.value.push({kind:`message`,role:`assistant`,parts:[]}),_=n.value.length-1)}function k(e){let t=n.value[_];if(!t)return;let r={...t,parts:t.parts.slice()};e(r),n.value[_]=r}function A(e){let t=`message`,n=``;for(let r of e.split(` `))r.startsWith(`event:`)?t=r.slice(6).trim():r.startsWith(`data:`)&&(n+=r.slice(5).trim());let r={};if(n)try{r=JSON.parse(n)}catch{r={raw:n}}return{event:t,data:r}}function j(i,o){switch(i){case`conversation`:t.value=o.id,e.value.find(e=>e.id===o.id)||e.value.unshift({id:o.id,title:o.title||`New conversation`,updated_at:new Date().toISOString()});break;case`message_start`:n.value.push({kind:`message`,role:`assistant`,id:o.message_id,parts:[]}),_=n.value.length-1;break;case`delta`:O(),k(e=>{let t=e.parts[e.parts.length-1];t&&t.type===`text`?e.parts[e.parts.length-1]={...t,text:t.text+o.text}:e.parts.push({type:`text`,text:o.text})});break;case`thinking`:O(),k(e=>{let t=e.parts.findIndex(e=>e.type===`thinking`);t>=0?e.parts[t]={...e.parts[t],text:e.parts[t].text+o.text}:e.parts.unshift({type:`thinking`,text:o.text,streaming:!0,startedAt:Date.now()})});break;case`tool_call`:n.value.push({kind:`tool`,id:o.id,call_id:o.call_id,name:o.name,group:o.group,args:o.args,status:o.requires_approval?`pending_approval`:`running`,result:null});break;case`tool_result`:for(let e=n.value.length-1;e>=0;e--){let t=n.value[e];if(t.kind===`tool`&&t.id===o.id){n.value[e]={...t,status:o.status,result:o.result};break}}break;case`awaiting_approval`:a.value=!0,r.value=!1,_>=0&&k(e=>{let t=e.parts.findIndex(e=>e.type===`thinking`);t>=0&&(e.parts[t]={...e.parts[t],streaming:!1})});break;case`message_end`:_>=0&&k(e=>{let t=e.parts.findIndex(e=>e.type===`thinking`);t>=0&&(e.parts[t]={...e.parts[t],streaming:!1})}),_=-1;break;case`done`:r.value=!1;break;case`error`:S(o.message||`stream error`,o.code),r.value=!1,_>=0&&k(e=>{let t=e.parts.findIndex(e=>e.type===`thinking`);t>=0&&(e.parts[t]={...e.parts[t],streaming:!1})}),_=-1}}async function M(e,t){let n={"Content-Type":`application/json`},r=w();r&&(n[`X-Orva-API-Key`]=r);let i=await fetch(e,{method:`POST`,credentials:`include`,headers:n,body:JSON.stringify(t),signal:v?.signal});if(!i.ok||!i.body)throw Error(`chat request failed (${i.status})`);let a=i.body.getReader(),o=new TextDecoder,s=``;for(;;){let{done:e,value:t}=await a.read();if(e)break;s+=o.decode(t,{stream:!0});let n;for(;(n=s.indexOf(` `))>=0;){let e=s.slice(0,n);if(s=s.slice(n+2),e.trim()){let{event:t,data:n}=A(e);j(t,n)}}}}async function N(e){if(!(!e.trim()||r.value)){o.value=``,E(),a.value=!1,y={type:`chat`,content:e},n.value.push({kind:`message`,role:`user`,parts:[{type:`text`,text:e}]}),r.value=!0,_=-1,v=new AbortController;try{let n={content:e,...b()};t.value&&(n.conversation_id=t.value),await M(`/api/v1/ai/chat`,n)}catch(e){e.name!==`AbortError`&&S(e.message)}finally{r.value=!1,v=null,await D()}}}async function P(){if(r.value||!t.value)return;let e=n.value,i=e.length;for(let t=e.length-1;t>=0&&(e[t].kind!==`message`||e[t].role!==`user`);t--)i=t;n.value=e.slice(0,i),o.value=``,a.value=!1,y={type:`regenerate`},r.value=!0,_=-1,v=new AbortController;try{await M(`/api/v1/ai/conversations/${t.value}/regenerate`,b())}catch(e){e.name!==`AbortError`&&S(e.message)}finally{r.value=!1,v=null,await D()}}async function F(e,i){if(r.value||!t.value||!i.trim())return;let s=n.value,c=s.findIndex(t=>t.kind===`message`&&t.id===e);if(!(c<0)){n.value=[...s.slice(0,c),{...s[c],parts:[{type:`text`,text:i}]}],o.value=``,a.value=!1,y={type:`edit`,messageId:e,content:i},r.value=!0,_=-1,v=new AbortController;try{await M(`/api/v1/ai/conversations/${t.value}/messages/${e}/edit`,{content:i,...b()})}catch(e){e.name!==`AbortError`&&S(e.message)}finally{r.value=!1,v=null,await D()}}}async function I(e){if(!t.value||r.value)return;let i=n.value,a=i.findIndex(t=>t.kind===`message`&&t.id===e);if(!(a<0)){n.value=i.slice(0,a);try{await T.delete(`/ai/conversations/${t.value}/messages/${e}`)}catch(e){S(e.message),await D()}}}async function L(){E();let e=y;if(e?.type===`tool`)return z(e.rowId,e.approved);if(e?.type===`regenerate`)return P();await D();let t=n.value[n.value.length-1];if(t&&t.kind===`message`&&t.role===`user`)return P();if(e?.content)return N(e.content)}function R(){v&&v.abort(),r.value=!1}async function z(e,t){if(r.value)return;o.value=``,E(),a.value=!1,y={type:`tool`,rowId:e,approved:t},r.value=!0,_=-1,v=new AbortController;let n=t?`approve`:`reject`;try{await M(`/api/v1/ai/tool-calls/${e}/${n}`,{})}catch(e){e.name!==`AbortError`&&S(e.message)}finally{r.value=!1,v=null,await D()}}let B=e=>z(e,!0),V=e=>z(e,!1);function H(e){let t=[],n={};for(let t of e.tool_calls||[])(n[t.message_id]||=[]).push(t);for(let r of e.messages||[]){let e=U(r.parts);if(r.role===`user`)t.push({kind:`message`,role:`user`,id:r.id,parts:e});else if(r.role===`assistant`){t.push({kind:`message`,role:`assistant`,id:r.id,parts:e});for(let e of n[r.id]||[])t.push({kind:`tool`,id:e.id,call_id:e.call_id,name:e.tool_name,group:e.tool_group,args:e.args,status:e.status,result:e.result})}}return t}function U(e){let t;try{t=JSON.parse(e||`[]`)}catch{t=[]}return t.filter(e=>e.type===`text`||e.type===`thinking`)}async function W(){let{data:t}=await T.get(`/ai/conversations`);e.value=t.conversations||[]}async function G(e){R(),_=-1;let{data:r}=await T.get(`/ai/conversations/${e}`);t.value=e,n.value=H(r),a.value=!1,o.value=``}function K(){R(),_=-1,t.value=null,n.value=[],a.value=!1,o.value=``}async function q(n){await T.delete(`/ai/conversations/${n}`),e.value=e.value.filter(e=>e.id!==n),t.value===n&&K()}async function J(){R();let{data:t}=await T.delete(`/ai/conversations`);return e.value=[],K(),t.deleted||0}function Y(){let r=n.value;if(!r.length)return;let i=e.value.find(e=>e.id===t.value),a=[`# ${i?.title||`Conversation`}`,``];for(let e of r)if(e.kind===`message`){let t=(e.parts||[]).filter(e=>e.type===`text`&&e.text).map(e=>e.text).join(` diff --git a/backend/internal/server/ui_dist/assets/NotFound-b7MSgvru.js b/backend/internal/server/ui_dist/assets/NotFound-PtAc3nsW.js similarity index 93% rename from backend/internal/server/ui_dist/assets/NotFound-b7MSgvru.js rename to backend/internal/server/ui_dist/assets/NotFound-PtAc3nsW.js index 866922ab..11ca76de 100644 --- a/backend/internal/server/ui_dist/assets/NotFound-b7MSgvru.js +++ b/backend/internal/server/ui_dist/assets/NotFound-PtAc3nsW.js @@ -1 +1 @@ -import{D as e,Z as t,c as n,d as r,h as i,m as a,s as o,vt as s}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as c}from"./arrow-left-Ba3OArNt.js";import{t as l}from"./book-open-B7-cMpW6.js";import{lt as u,mt as d,pt as f}from"./index-DTqMKlE1.js";var p={class:`min-h-screen flex items-center justify-center bg-background px-6 py-16`},m={class:`max-w-lg w-full`},h={class:`flex items-center gap-3 mb-10`},g={class:`bg-surface border border-border rounded-md px-3 py-2 mb-8 overflow-x-auto`},_={class:`text-xs font-mono text-foreground break-all`},v={class:`flex flex-wrap gap-3`},y={__name:`NotFound`,setup(y){let b=f(),x=d(),S=o(()=>b.fullPath||`/`),C=()=>x.push(`/functions`),w=()=>x.push(`/docs`);return(o,d)=>(e(),r(`div`,p,[n(`div`,m,[n(`div`,h,[i(u,{class:`w-7 h-7`}),d[0]||=n(`span`,{class:`font-semibold tracking-tight text-foreground text-lg`},`Orva`,-1)]),d[3]||=n(`p`,{class:`text-xs uppercase tracking-[0.2em] text-foreground-muted mb-3`},` Error 404 `,-1),d[4]||=n(`h1`,{class:`text-3xl sm:text-4xl font-semibold text-foreground mb-4 leading-tight`},` Page not found. `,-1),d[5]||=n(`p`,{class:`text-sm text-foreground-muted mb-4`},` This Orva instance has no page at: `,-1),n(`div`,g,[n(`code`,_,s(S.value),1)]),n(`div`,v,[n(`button`,{class:`inline-flex items-center gap-2 px-4 py-2 rounded-md bg-white text-black text-sm font-medium hover:bg-white/90 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`,onClick:C},[i(t(c),{class:`w-4 h-4`}),d[1]||=a(` Go to Functions `,-1)]),n(`button`,{class:`inline-flex items-center gap-2 px-4 py-2 rounded-md border border-border text-sm text-foreground hover:bg-surface-hover transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`,onClick:w},[i(t(l),{class:`w-4 h-4`}),d[2]||=a(` Open docs `,-1)])])])]))}};export{y as default}; \ No newline at end of file +import{D as e,Z as t,c as n,d as r,h as i,m as a,s as o,vt as s}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as c}from"./arrow-left-DTH7GseC.js";import{t as l}from"./book-open-DQ3Rz8Ui.js";import{lt as u,mt as d,pt as f}from"./index-pE9wnfTb.js";var p={class:`min-h-screen flex items-center justify-center bg-background px-6 py-16`},m={class:`max-w-lg w-full`},h={class:`flex items-center gap-3 mb-10`},g={class:`bg-surface border border-border rounded-md px-3 py-2 mb-8 overflow-x-auto`},_={class:`text-xs font-mono text-foreground break-all`},v={class:`flex flex-wrap gap-3`},y={__name:`NotFound`,setup(y){let b=f(),x=d(),S=o(()=>b.fullPath||`/`),C=()=>x.push(`/functions`),w=()=>x.push(`/docs`);return(o,d)=>(e(),r(`div`,p,[n(`div`,m,[n(`div`,h,[i(u,{class:`w-7 h-7`}),d[0]||=n(`span`,{class:`font-semibold tracking-tight text-foreground text-lg`},`Orva`,-1)]),d[3]||=n(`p`,{class:`text-xs uppercase tracking-[0.2em] text-foreground-muted mb-3`},` Error 404 `,-1),d[4]||=n(`h1`,{class:`text-3xl sm:text-4xl font-semibold text-foreground mb-4 leading-tight`},` Page not found. `,-1),d[5]||=n(`p`,{class:`text-sm text-foreground-muted mb-4`},` This Orva instance has no page at: `,-1),n(`div`,g,[n(`code`,_,s(S.value),1)]),n(`div`,v,[n(`button`,{class:`inline-flex items-center gap-2 px-4 py-2 rounded-md bg-white text-black text-sm font-medium hover:bg-white/90 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`,onClick:C},[i(t(c),{class:`w-4 h-4`}),d[1]||=a(` Go to Functions `,-1)]),n(`button`,{class:`inline-flex items-center gap-2 px-4 py-2 rounded-md border border-border text-sm text-foreground hover:bg-surface-hover transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`,onClick:w},[i(t(l),{class:`w-4 h-4`}),d[2]||=a(` Open docs `,-1)])])])]))}};export{y as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Onboarding-CI9ktN7I.js b/backend/internal/server/ui_dist/assets/Onboarding-CEzpQ2g5.js similarity index 97% rename from backend/internal/server/ui_dist/assets/Onboarding-CI9ktN7I.js rename to backend/internal/server/ui_dist/assets/Onboarding-CEzpQ2g5.js index e45e5717..4bd6ccc6 100644 --- a/backend/internal/server/ui_dist/assets/Onboarding-CI9ktN7I.js +++ b/backend/internal/server/ui_dist/assets/Onboarding-CEzpQ2g5.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as _}from"./circle-alert-BnUYYhGE.js";import{t as v}from"./copy-BqdwwcxC.js";import{Bt as y,Lt as b,Pt as x,_t as S,dt as C,jt as w,lt as T,mt as E}from"./index-DTqMKlE1.js";var D=w(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]),O=w(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),k={class:`min-h-screen flex flex-col items-center justify-center bg-background pt-safe pb-safe pl-safe pr-safe px-page py-8 sm:py-12`},A={class:`w-full max-w-md space-y-8`},j={class:`space-y-3`},M={class:`flex items-center gap-3`},N=[`disabled`],P={class:`flex flex-col sm:flex-row gap-2`},F={class:`relative flex-1 min-w-0`},I=[`type`,`disabled`],L={class:`absolute right-1.5 top-1/2 -translate-y-1/2 flex gap-0.5`},R=[`disabled`],ee=[`disabled`,`aria-label`,`title`],z=[`disabled`],B={class:`mt-3 grid grid-cols-2 gap-y-1.5 gap-x-3`},V={key:0,class:`bg-danger/10 border border-danger/30 rounded-md px-4 py-3 flex items-start gap-3`},H={class:`text-sm text-danger`},U={__name:`Onboarding`,setup(w){let U=E(),W=C(),G=n({username:`orva`,password:``}),K=n(``),q=n(!1),J=n(!1),Y=m(()=>({length:G.value.password.length>=10,lower:/[a-z]/.test(G.value.password),upper:/[A-Z]/.test(G.value.password),digit:/[0-9]/.test(G.value.password),symbol:/[^A-Za-z0-9]/.test(G.value.password)})),X=m(()=>{let e=Y.value;return e.length&&e.lower&&e.upper&&e.digit&&e.symbol}),Z=e=>({length:`10+ characters`,lower:`Lowercase`,upper:`Uppercase`,digit:`Number`,symbol:`Symbol`})[e]||e,Q=()=>{let e=e=>{let t=Math.floor(4294967295/e)*e,n;do n=crypto.getRandomValues(new Uint32Array(1))[0];while(n>=t);return n%e},t=t=>t[e(t.length)],n=[t(`abcdefghijklmnopqrstuvwxyz`),t(`ABCDEFGHIJKLMNOPQRSTUVWXYZ`),t(`0123456789`),t(`!@#$%^&*()-_=+[]{}|;:,.<>?`)];for(let e=n.length;e<16;e+=1)n.push(t(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|;:,.<>?`));for(let t=n.length-1;t>0;--t){let r=e(t+1);[n[t],n[r]]=[n[r],n[t]]}G.value.password=n.join(``)},$=async()=>{try{await navigator.clipboard.writeText(G.value.password)}catch(e){console.error(`Failed to copy password:`,e)}},te=async()=>{K.value=``,q.value=!0;let e=await W.onboard(G.value.username,G.value.password);q.value=!1,e.success?U.push(`/`):K.value=e.error};return i(async()=>{await W.fetchAuthStatus()&&U.push(`/login`)}),(n,i)=>(e(),s(`div`,k,[o(`div`,A,[o(`div`,j,[o(`div`,M,[l(T,{class:`w-9 h-9`}),i[3]||=o(`span`,{class:`text-2xl font-semibold tracking-tight text-white`},`Orva`,-1)]),i[4]||=o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Set up admin access `,-1),i[5]||=o(`p`,{class:`text-sm text-foreground-muted leading-relaxed`},` Create the root user for this Orva instance. Store the password securely. `,-1)]),o(`form`,{class:`space-y-5`,onSubmit:y(te,[`prevent`])},[o(`div`,null,[i[6]||=o(`label`,{for:`onboard-username`,class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},`Username`,-1),r(o(`input`,{id:`onboard-username`,"onUpdate:modelValue":i[0]||=e=>G.value.username=e,type:`text`,required:``,autocomplete:`username`,class:`w-full bg-background border border-border rounded-md px-3 py-2.5 text-base sm:text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white transition-colors`,placeholder:`orva`,disabled:q.value},null,8,N),[[b,G.value.username]])]),o(`div`,null,[i[7]||=o(`label`,{for:`onboard-password`,class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},`Password`,-1),o(`div`,P,[o(`div`,F,[r(o(`input`,{id:`onboard-password`,"onUpdate:modelValue":i[1]||=e=>G.value.password=e,type:J.value?`text`:`password`,required:``,autocomplete:`new-password`,class:`w-full bg-background border border-border rounded-md px-3 py-2.5 pr-20 text-base sm:text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white transition-colors font-mono`,placeholder:`Minimum 10 characters`,disabled:q.value},null,8,I),[[x,G.value.password]]),o(`div`,L,[G.value.password?(e(),s(`button`,{key:0,type:`button`,class:`p-1.5 rounded hover:bg-surface-hover transition-colors touch-expand-iconbtn`,disabled:q.value,"aria-label":`Copy password`,title:`Copy password`,onClick:$},[l(a(v),{class:`w-4 h-4 text-foreground-muted hover:text-foreground`})],8,R)):h(``,!0),o(`button`,{type:`button`,class:`p-1.5 rounded hover:bg-surface-hover transition-colors touch-expand-iconbtn`,disabled:q.value,"aria-label":J.value?`Hide password`:`Show password`,title:J.value?`Hide password`:`Show password`,onClick:i[2]||=e=>J.value=!J.value},[J.value?(e(),d(a(D),{key:1,class:`w-4 h-4 text-foreground-muted hover:text-foreground`})):(e(),d(a(O),{key:0,class:`w-4 h-4 text-foreground-muted hover:text-foreground`}))],8,ee)])]),o(`button`,{type:`button`,class:`px-4 py-2.5 rounded-md border border-border bg-surface hover:bg-surface-hover text-sm font-medium text-foreground transition-colors shrink-0`,disabled:q.value,onClick:Q},` Generate `,8,z)]),o(`div`,B,[(e(!0),s(p,null,u(Y.value,(t,n)=>(e(),s(`div`,{key:n,class:c([`flex items-center gap-1.5 text-xs transition-colors duration-200`,t?`text-success`:`text-foreground-muted`])},[o(`div`,{class:c([`w-1.5 h-1.5 rounded-full`,t?`bg-success`:`bg-foreground-muted/40`])},null,2),o(`span`,null,g(Z(n)),1)],2))),128))])]),K.value?(e(),s(`div`,V,[l(a(_),{class:`w-5 h-5 text-danger shrink-0 mt-0.5`}),o(`p`,H,g(K.value),1)])):h(``,!0),l(S,{type:`submit`,class:`w-full`,loading:q.value,disabled:!X.value||!G.value.username||q.value},{default:t(()=>[...i[8]||=[f(` Create account `,-1)]]),_:1},8,[`loading`,`disabled`]),i[9]||=o(`p`,{class:`text-xs text-center text-foreground-muted pt-2`},` This action initialises your instance and cannot be undone. `,-1)],32)])]))}};export{U as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as _}from"./circle-alert-CwieDBHo.js";import{t as v}from"./copy-3UAsea5P.js";import{Bt as y,Lt as b,Pt as x,_t as S,dt as C,jt as w,lt as T,mt as E}from"./index-pE9wnfTb.js";var D=w(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]),O=w(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),k={class:`min-h-screen flex flex-col items-center justify-center bg-background pt-safe pb-safe pl-safe pr-safe px-page py-8 sm:py-12`},A={class:`w-full max-w-md space-y-8`},j={class:`space-y-3`},M={class:`flex items-center gap-3`},N=[`disabled`],P={class:`flex flex-col sm:flex-row gap-2`},F={class:`relative flex-1 min-w-0`},I=[`type`,`disabled`],L={class:`absolute right-1.5 top-1/2 -translate-y-1/2 flex gap-0.5`},R=[`disabled`],ee=[`disabled`,`aria-label`,`title`],z=[`disabled`],B={class:`mt-3 grid grid-cols-2 gap-y-1.5 gap-x-3`},V={key:0,class:`bg-danger/10 border border-danger/30 rounded-md px-4 py-3 flex items-start gap-3`},H={class:`text-sm text-danger`},U={__name:`Onboarding`,setup(w){let U=E(),W=C(),G=n({username:`orva`,password:``}),K=n(``),q=n(!1),J=n(!1),Y=m(()=>({length:G.value.password.length>=10,lower:/[a-z]/.test(G.value.password),upper:/[A-Z]/.test(G.value.password),digit:/[0-9]/.test(G.value.password),symbol:/[^A-Za-z0-9]/.test(G.value.password)})),X=m(()=>{let e=Y.value;return e.length&&e.lower&&e.upper&&e.digit&&e.symbol}),Z=e=>({length:`10+ characters`,lower:`Lowercase`,upper:`Uppercase`,digit:`Number`,symbol:`Symbol`})[e]||e,Q=()=>{let e=e=>{let t=Math.floor(4294967295/e)*e,n;do n=crypto.getRandomValues(new Uint32Array(1))[0];while(n>=t);return n%e},t=t=>t[e(t.length)],n=[t(`abcdefghijklmnopqrstuvwxyz`),t(`ABCDEFGHIJKLMNOPQRSTUVWXYZ`),t(`0123456789`),t(`!@#$%^&*()-_=+[]{}|;:,.<>?`)];for(let e=n.length;e<16;e+=1)n.push(t(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|;:,.<>?`));for(let t=n.length-1;t>0;--t){let r=e(t+1);[n[t],n[r]]=[n[r],n[t]]}G.value.password=n.join(``)},$=async()=>{try{await navigator.clipboard.writeText(G.value.password)}catch(e){console.error(`Failed to copy password:`,e)}},te=async()=>{K.value=``,q.value=!0;let e=await W.onboard(G.value.username,G.value.password);q.value=!1,e.success?U.push(`/`):K.value=e.error};return i(async()=>{await W.fetchAuthStatus()&&U.push(`/login`)}),(n,i)=>(e(),s(`div`,k,[o(`div`,A,[o(`div`,j,[o(`div`,M,[l(T,{class:`w-9 h-9`}),i[3]||=o(`span`,{class:`text-2xl font-semibold tracking-tight text-white`},`Orva`,-1)]),i[4]||=o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Set up admin access `,-1),i[5]||=o(`p`,{class:`text-sm text-foreground-muted leading-relaxed`},` Create the root user for this Orva instance. Store the password securely. `,-1)]),o(`form`,{class:`space-y-5`,onSubmit:y(te,[`prevent`])},[o(`div`,null,[i[6]||=o(`label`,{for:`onboard-username`,class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},`Username`,-1),r(o(`input`,{id:`onboard-username`,"onUpdate:modelValue":i[0]||=e=>G.value.username=e,type:`text`,required:``,autocomplete:`username`,class:`w-full bg-background border border-border rounded-md px-3 py-2.5 text-base sm:text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white transition-colors`,placeholder:`orva`,disabled:q.value},null,8,N),[[b,G.value.username]])]),o(`div`,null,[i[7]||=o(`label`,{for:`onboard-password`,class:`block text-xs font-medium text-foreground-muted uppercase tracking-wide mb-1.5`},`Password`,-1),o(`div`,P,[o(`div`,F,[r(o(`input`,{id:`onboard-password`,"onUpdate:modelValue":i[1]||=e=>G.value.password=e,type:J.value?`text`:`password`,required:``,autocomplete:`new-password`,class:`w-full bg-background border border-border rounded-md px-3 py-2.5 pr-20 text-base sm:text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white transition-colors font-mono`,placeholder:`Minimum 10 characters`,disabled:q.value},null,8,I),[[x,G.value.password]]),o(`div`,L,[G.value.password?(e(),s(`button`,{key:0,type:`button`,class:`p-1.5 rounded hover:bg-surface-hover transition-colors touch-expand-iconbtn`,disabled:q.value,"aria-label":`Copy password`,title:`Copy password`,onClick:$},[l(a(v),{class:`w-4 h-4 text-foreground-muted hover:text-foreground`})],8,R)):h(``,!0),o(`button`,{type:`button`,class:`p-1.5 rounded hover:bg-surface-hover transition-colors touch-expand-iconbtn`,disabled:q.value,"aria-label":J.value?`Hide password`:`Show password`,title:J.value?`Hide password`:`Show password`,onClick:i[2]||=e=>J.value=!J.value},[J.value?(e(),d(a(D),{key:1,class:`w-4 h-4 text-foreground-muted hover:text-foreground`})):(e(),d(a(O),{key:0,class:`w-4 h-4 text-foreground-muted hover:text-foreground`}))],8,ee)])]),o(`button`,{type:`button`,class:`px-4 py-2.5 rounded-md border border-border bg-surface hover:bg-surface-hover text-sm font-medium text-foreground transition-colors shrink-0`,disabled:q.value,onClick:Q},` Generate `,8,z)]),o(`div`,B,[(e(!0),s(p,null,u(Y.value,(t,n)=>(e(),s(`div`,{key:n,class:c([`flex items-center gap-1.5 text-xs transition-colors duration-200`,t?`text-success`:`text-foreground-muted`])},[o(`div`,{class:c([`w-1.5 h-1.5 rounded-full`,t?`bg-success`:`bg-foreground-muted/40`])},null,2),o(`span`,null,g(Z(n)),1)],2))),128))])]),K.value?(e(),s(`div`,V,[l(a(_),{class:`w-5 h-5 text-danger shrink-0 mt-0.5`}),o(`p`,H,g(K.value),1)])):h(``,!0),l(S,{type:`submit`,class:`w-full`,loading:q.value,disabled:!X.value||!G.value.username||q.value},{default:t(()=>[...i[8]||=[f(` Create account `,-1)]]),_:1},8,[`loading`,`disabled`]),i[9]||=o(`p`,{class:`text-xs text-center text-foreground-muted pt-2`},` This action initialises your instance and cannot be undone. `,-1)],32)])]))}};export{U as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Settings-Bjj6gg_h.js b/backend/internal/server/ui_dist/assets/Settings-CTZtncIj.js similarity index 99% rename from backend/internal/server/ui_dist/assets/Settings-Bjj6gg_h.js rename to backend/internal/server/ui_dist/assets/Settings-CTZtncIj.js index ed3534d8..50f21d90 100644 --- a/backend/internal/server/ui_dist/assets/Settings-Bjj6gg_h.js +++ b/backend/internal/server/ui_dist/assets/Settings-CTZtncIj.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,M as i,T as a,Z as o,_t as s,c,d as l,gt as u,h as d,k as f,l as ee,m as p,r as m,s as h,u as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./copy-BqdwwcxC.js";import{i as ne,r as re,t as v}from"./ModelMenu-BtMjUXcx.js";import{t as y}from"./key-round-BKXtbC85.js";import{t as b}from"./terminal-BQdlNiyt.js";import{t as x}from"./trash-2-DaeYqnW_.js";import{$ as S,Bt as C,Ct as w,D as ie,Ft as ae,G as oe,I as T,It as se,Lt as E,Q as ce,Tt as le,_t as D,ct as ue,dt as de,ft as fe,gt as pe,jt as O,mt as me,n as he,nt as ge,ut as k}from"./index-DTqMKlE1.js";import{t as _e}from"./clipboard-D_9N0yai.js";import{t as A}from"./time-D8OmbYzY.js";import{t as j}from"./Input-DQ-tWGkn.js";var ve=O(`code-xml`,[[`path`,{d:`m18 16 4-4-4-4`,key:`1inbqp`}],[`path`,{d:`m6 8-4 4 4 4`,key:`15zrgr`}],[`path`,{d:`m14.5 4-5 16`,key:`e7oirm`}]]),ye=O(`database-backup`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 12a9 3 0 0 0 5 2.69`,key:`1ui2ym`}],[`path`,{d:`M21 9.3V5`,key:`6k6cib`}],[`path`,{d:`M3 5v14a9 3 0 0 0 6.47 2.88`,key:`i62tjy`}],[`path`,{d:`M12 12v4h4`,key:`1bxaet`}],[`path`,{d:`M13 20a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L12 16`,key:`1f4ei9`}]]),be=O(`hard-drive`,[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]),xe=O(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),Se=O(`log-out`,[[`path`,{d:`m16 17 5-5-5-5`,key:`1bji2h`}],[`path`,{d:`M21 12H9`,key:`dn1m92`}],[`path`,{d:`M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4`,key:`1uf3rs`}]]),Ce=O(`monitor`,[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`,key:`48i651`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`,key:`1svkeh`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`,key:`vw1qmm`}]]),M=O(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),we=O(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]),Te=O(`wand-sparkles`,[[`path`,{d:`m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72`,key:`ul74o6`}],[`path`,{d:`m14 7 3 3`,key:`1r5n42`}],[`path`,{d:`M5 6v4`,key:`ilb8ba`}],[`path`,{d:`M19 14v4`,key:`blhpug`}],[`path`,{d:`M10 2v2`,key:`7u0qdc`}],[`path`,{d:`M7 8H3`,key:`zfb6yr`}],[`path`,{d:`M21 16h-4`,key:`1cnmox`}],[`path`,{d:`M11 3H9`,key:`1obp7u`}]]),N={class:`space-y-6`},P={class:`space-y-3`},F={key:0,class:`grid grid-cols-1 gap-3 sm:grid-cols-2 sm:items-start`},Ee=[`value`],De=[`value`],I={class:`mt-1.5`},L={key:0,class:`text-xs text-danger-fg sm:col-span-2`},R={class:`divide-y divide-border border-y border-border`},z={class:`flex items-center gap-2 px-3 py-2`},B={class:`font-mono text-sm text-foreground`},V={key:0,class:`text-xs text-foreground-muted`},H={key:1,class:`text-xs uppercase tracking-label rounded px-1.5 py-0.5 bg-primary/15 text-primary-hover`},U={key:0,class:`text-xs text-foreground-muted`},W={class:`group border-t border-border pt-4`},G={class:`mt-4 space-y-3`},Oe=[`value`],ke={key:0,class:`space-y-3 border-t border-border pt-5`},Ae={class:`space-y-2`},je=[`value`],Me={key:0,class:`h-2 w-2 rounded-full bg-primary`},K={class:`min-w-0`},q={class:`block text-sm font-medium text-foreground`},J={class:`mt-0.5 block text-xs text-foreground-muted leading-snug`},Ne={__name:`AISettingsPanel`,setup(i){let s=re(),ee=pe();async function te(e){await ee.ask({title:`Remove provider?`,message:`This permanently removes the provider and its encrypted API key.`,danger:!0,confirmLabel:`Remove`})&&s.deleteProvider(e)}let ne=[`openai`,`anthropic`,`groq`,`gemini`,`ollama`,`mistral`,`openrouter`,`xai`,`cohere`],y=[{value:`all_writes`,label:`Ask before changes (recommended)`,hint:`Confirm creates, updates, and deletes.`},{value:`destructive_only`,label:`Ask before deletes only`,hint:`Confirm deletes; run other changes automatically.`},{value:`auto`,label:`Bypass: allow everything`,hint:`Run every action without confirmation.`}],b=n({provider:`openai`,label:``,api_key:``,base_url:``}),x=[`ollama`],S=h(()=>x.includes(b.value.provider)),C=h(()=>S.value&&!b.value.base_url.trim()?`Base URL is required for Ollama.`:``),w=h(()=>!!b.value.provider&&!C.value),ie=h(()=>S.value?`http://192.168.1.50:11434 or http://ollama.lan:11434`:`https://api.openai.com/v1 or https://your-host/v1`),oe=h(()=>S.value?`Where your server is listening. A private LAN address works; Orva permits it when your egress blocklist does.`:`For custom / self-hosted endpoints. Either with or without /v1 works. A private LAN address works too.`),T=n(!1),E=n(!1);a(async()=>{await s.loadSettings(),await s.loadProviders()});async function ce(e){await s.selectProvider(e.target.value)}async function le(){if(w.value){T.value=!0;try{await s.saveProvider({provider:b.value.provider,label:b.value.label,api_key:b.value.api_key,base_url:b.value.base_url,enabled:!0}),b.value.api_key=``}finally{T.value=!1}}}async function ue(){E.value=!0;try{await s.saveSettings(s.settings)}finally{E.value=!1}}return(n,i)=>(e(),l(`div`,N,[c(`section`,P,[i[9]||=c(`div`,null,[c(`h3`,{class:`text-sm font-semibold text-foreground`},` Providers `),c(`p`,{class:`text-xs text-foreground-muted mt-1.5 max-w-prose leading-snug`},` Keys are encrypted at rest. Choose which provider and model Chat uses. `)],-1),o(s).providers.length?(e(),l(`div`,F,[c(`div`,null,[i[5]||=c(`label`,{for:`ai-active-provider`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Active provider`,-1),c(`select`,{id:`ai-active-provider`,value:o(s).selectedProviderId||``,class:`mt-1.5 h-10 w-full bg-background border border-border rounded-md text-sm px-3 text-foreground transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:ce},[(e(!0),l(m,null,f(o(s).providers,t=>(e(),l(`option`,{key:t.id,value:t.id},_(t.label?`${t.provider} (${t.label})`:t.provider),9,De))),128))],40,Ee)]),c(`div`,null,[i[6]||=c(`label`,{for:`ai-active-model`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},` Active model `,-1),c(`div`,I,[d(v,{wide:``,"trigger-id":`ai-active-model`})])]),o(s).modelsError?(e(),l(`p`,L,` Models could not be loaded. Check the provider endpoint and credentials. `)):g(``,!0)])):g(``,!0),c(`div`,R,[(e(!0),l(m,null,f(o(s).providers,n=>(e(),l(`div`,{key:n.id,class:`py-1`},[c(`div`,z,[c(`span`,B,_(n.provider),1),n.label?(e(),l(`span`,V,_(n.label),1)):g(``,!0),o(s).selectedProviderId===n.id?(e(),l(`span`,H,`active`)):g(``,!0),c(`span`,{class:u([`text-xs uppercase tracking-label rounded px-1.5 py-0.5`,n.has_key?`bg-success-tint text-success-fg`:`bg-surface-hover text-foreground-muted`])},_(n.has_key?`key set`:`no key`),3),i[8]||=c(`span`,{class:`flex-1`},null,-1),d(D,{size:`xs`,variant:`ghost`,onClick:e=>te(n.id)},{default:t(()=>[...i[7]||=[p(` Remove `,-1)]]),_:1},8,[`onClick`])])]))),128)),o(s).providers.length?g(``,!0):(e(),l(`p`,U,` No providers configured yet. `))])]),c(`details`,W,[i[13]||=c(`summary`,{class:`flex cursor-pointer list-none items-center justify-between rounded-sm text-sm font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},[p(` Add provider `),c(`span`,{class:`text-foreground-muted transition-transform group-open:rotate-45`,"aria-hidden":`true`},`+`)],-1),c(`div`,G,[i[12]||=c(`p`,{class:`text-xs text-foreground-muted max-w-prose leading-snug`},[p(` For compatible endpoints, choose `),c(`span`,{class:`font-mono`},`openai`),p(` and add the Base URL. `)],-1),c(`div`,null,[i[10]||=c(`label`,{for:`ai-provider`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Provider`,-1),r(c(`select`,{id:`ai-provider`,"onUpdate:modelValue":i[0]||=e=>b.value.provider=e,class:`mt-1.5 w-full bg-background border border-border rounded-md text-sm px-3 py-2 text-foreground transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},[(e(),l(m,null,f(ne,e=>c(`option`,{key:e,value:e},_(e),9,Oe)),64))],512),[[se,b.value.provider]])]),d(j,{modelValue:b.value.label,"onUpdate:modelValue":i[1]||=e=>b.value.label=e,label:`Label`,placeholder:`e.g. personal, work (optional)`},null,8,[`modelValue`]),d(j,{modelValue:b.value.base_url,"onUpdate:modelValue":i[2]||=e=>b.value.base_url=e,label:S.value?`Base URL (required)`:`Base URL (optional)`,placeholder:ie.value,hint:oe.value,error:C.value,required:S.value},null,8,[`modelValue`,`label`,`placeholder`,`hint`,`error`,`required`]),d(j,{modelValue:b.value.api_key,"onUpdate:modelValue":i[3]||=e=>b.value.api_key=e,label:`API key`,type:`password`,placeholder:`sk-…`,hint:`Stored encrypted; never shown again. Leave blank when updating to keep the current key.`},null,8,[`modelValue`]),d(D,{variant:`primary`,loading:T.value,disabled:!w.value,onClick:le},{default:t(()=>[...i[11]||=[p(` Save provider `,-1)]]),_:1},8,[`loading`,`disabled`])])]),o(s).settings?(e(),l(`section`,ke,[i[17]||=c(`h3`,{class:`text-sm font-semibold text-foreground`},` Defaults `,-1),c(`fieldset`,Ae,[i[14]||=c(`legend`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},` Approval policy `,-1),i[15]||=c(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Choose when changes require confirmation. `,-1),(e(),l(m,null,f(y,t=>c(`label`,{key:t.value,class:`flex cursor-pointer items-start gap-3 px-1 py-2 transition-colors hover:bg-surface-hover focus-within:outline-none focus-within:ring-2 focus-within:ring-inset focus-within:ring-primary`},[r(c(`input`,{"onUpdate:modelValue":i[4]||=e=>o(s).settings.approval_policy=e,type:`radio`,name:`approval-policy`,value:t.value,class:`sr-only`},null,8,je),[[ae,o(s).settings.approval_policy]]),c(`span`,{class:u([`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full border transition-colors`,o(s).settings.approval_policy===t.value?`border-primary`:`border-foreground-muted/50`])},[o(s).settings.approval_policy===t.value?(e(),l(`span`,Me)):g(``,!0)],2),c(`span`,K,[c(`span`,q,_(t.label),1),c(`span`,J,_(t.hint),1)])])),64))]),d(D,{variant:`primary`,loading:E.value,onClick:ue},{default:t(()=>[...i[16]||=[p(` Save defaults `,-1)]]),_:1},8,[`loading`])])):g(``,!0)]))}},Y={},X={xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 24 24`,fill:`currentColor`,"aria-hidden":`true`};function Pe(t,n){return e(),l(`svg`,X,[...n[0]||=[c(`path`,{d:`M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.4069-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z`},null,-1)]])}var Fe=k(Y,[[`render`,Pe]]),Ie={},Le={xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 24 24`,fill:`currentColor`,"aria-hidden":`true`};function Z(t,n){return e(),l(`svg`,Le,[...n[0]||=[c(`path`,{d:`M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.146-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.418 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.349-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.658-.851-.747-1.926-1.622h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z`},null,-1)]])}var Q=k(Ie,[[`render`,Z]]);function Re(e){let t=(e||``).toLowerCase();return t.includes(`claude code`)?{icon:b,accent:`text-orange-400`}:t.includes(`chatgpt`)||t.includes(`openai`)?{icon:Fe,accent:`text-emerald-400`}:t.includes(`claude`)||t.includes(`anthropic`)?{icon:Q,accent:`text-orange-400`}:t.includes(`cursor`)?{icon:M,accent:`text-blue-400`}:t.includes(`vscode`)||t.includes(`vs code`)||t.includes(`code`)?{icon:ve,accent:`text-blue-400`}:{icon:w,accent:`text-foreground-muted`}}var ze={class:`space-y-8`},Be={class:`group border-b border-border pb-6`},Ve={class:`flex cursor-pointer list-none items-center gap-2 text-sm font-semibold text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary [&::-webkit-details-marker]:hidden`},He={class:`ml-auto text-xs font-normal text-foreground-muted group-open:hidden`},Ue={class:`mt-4 grid grid-cols-[max-content,1fr] gap-x-6 gap-y-2 text-xs`},We={class:`font-mono text-white`},Ge={class:`font-mono text-white`},Ke={class:`font-mono text-white`},qe={class:`font-mono text-white flex items-center gap-2 min-w-0`},Je={class:`truncate`},Ye={key:1,class:`text-xs text-primary-hover shrink-0`},Xe={id:`ai`,class:`scroll-mt-6 space-y-4 border-b border-border pb-8`},Ze={class:`text-base font-semibold text-white flex items-center gap-2`},Qe={class:`space-y-4 border-b border-border pb-8`},$e={class:`flex items-start justify-between gap-4`},et={class:`text-base font-semibold text-white flex items-center gap-2`},tt={key:0,class:`text-xs text-foreground-muted italic`},nt={key:1,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},rt={class:`font-mono break-all`},it={key:2,class:`space-y-3`},at={class:`h-2 w-full rounded-full overflow-hidden bg-border/60 flex`},ot=[`title`],st=[`title`],ct=[`title`],lt={class:`grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-1.5 text-xs`},ut={class:`flex items-center justify-between`},dt={class:`font-mono text-white`},ft={class:`flex items-center justify-between`},pt={class:`font-mono text-white`},mt={key:0,class:`flex items-center justify-between`},ht={class:`font-mono text-white`},gt={class:`flex items-center justify-between`},_t={class:`font-mono text-white font-semibold`},vt={key:0,class:`text-xs text-foreground-muted pt-1 border-t border-border`},yt={key:3,class:`rounded-md border border-success-ring bg-success-tint p-3 text-xs text-success-fg`},bt={class:`font-mono`},xt={key:4,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},St={class:`font-mono break-all`},Ct={class:`space-y-4 border-b border-border pb-8`},wt={class:`text-base font-semibold text-white flex items-center gap-2`},Tt={class:`grid grid-cols-1 sm:grid-cols-3 gap-3`},Et={class:`flex flex-col gap-1`},Dt={class:`flex flex-col gap-1`},Ot={class:`flex flex-col gap-1`},kt={key:0,id:`pw-error`,class:`rounded-md border border-danger-ring bg-danger-tint p-2.5 text-xs text-danger-fg`},At={key:1,class:`rounded-md border border-success-ring bg-success-tint p-2.5 text-xs text-success-fg`},jt={class:`pt-2 border-t border-border`},Mt={class:`space-y-4 border-b border-border pb-8`},Nt={class:`flex items-start justify-between gap-4`},Pt={class:`text-base font-semibold text-white flex items-center gap-2`},Ft={class:`text-xs text-foreground-muted mt-1 max-w-prose`},It={key:0,class:`text-xs text-foreground-muted self-center`},Lt={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},Rt={class:`font-mono break-all`},zt={key:1,class:`text-xs text-foreground-muted italic`},Bt={key:2,class:`py-3`},Vt={key:3,class:`divide-y divide-border -mx-5`},Ht={class:`flex-1 min-w-0`},Ut={class:`text-sm font-medium text-white truncate`},Wt={class:`text-xs text-foreground-muted mt-0.5 flex flex-wrap gap-x-3 gap-y-0.5`},Gt={key:0},Kt={key:1,class:`italic opacity-70`},qt={key:2},Jt={class:`flex flex-wrap gap-1 mt-2`},Yt=[`disabled`,`onClick`],Xt={class:`space-y-4 border-b border-border pb-8`},Zt={class:`flex items-start justify-between gap-4`},Qt={class:`text-base font-semibold text-white flex items-center gap-2`},$t={key:0,class:`text-xs text-foreground-muted self-center`},en={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},tn={class:`font-mono break-all`},nn={key:1,class:`divide-y divide-border -mx-5`},rn={class:`flex-1 min-w-0`},an={class:`text-sm font-medium text-white flex items-center gap-2 flex-wrap`},on={key:0},sn={key:1,class:`font-mono text-xs`},cn={key:2,class:`text-xs px-1.5 py-0.5 rounded bg-success-tint text-success-fg font-medium`},ln={class:`text-xs text-foreground-muted mt-0.5`},un=[`disabled`,`onClick`],dn={class:`space-y-4`},fn={class:`flex items-start justify-between gap-4`},pn={class:`text-base font-semibold text-white flex items-center gap-2`},mn={class:`flex flex-col sm:flex-row gap-3 pt-2 border-t border-border`},hn={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},gn={class:`font-mono break-all`},_n={key:1,class:`rounded-md border border-success-ring bg-success-tint p-3 text-xs text-success-fg`},$=Object.assign({name:`SettingsView`},{__name:`Settings`,setup(re){let v=pe(),b=de(),ae=me(),se=he(),O=h(()=>se.buildInfo),k=n(!1),j=async()=>{O.value?.image&&await _e(O.value.image)&&(k.value=!0,setTimeout(()=>{k.value=!1},1500))},ve=e=>{if(!e||e===`unknown`)return`—`;try{return new Date(e).toISOString().replace(`T`,` `).replace(/\.\d+Z$/,` UTC`)}catch{return e}},M=n({current:``,next:``,confirm:``}),N=n(!1),P=n(``),F=n(!1),Ee=async()=>{if(P.value=``,F.value=!1,!M.value.current||!M.value.next||!M.value.confirm){P.value=`All three fields are required.`;return}if(M.value.next.length<8){P.value=`New password must be at least 8 characters.`;return}if(M.value.next!==M.value.confirm){P.value=`New password and confirmation do not match.`;return}N.value=!0;try{await b.changePassword(M.value.current,M.value.next),F.value=!0,M.value={current:``,next:``,confirm:``}}catch(e){P.value=e?.response?.data?.error?.message||`Failed to update password.`}finally{N.value=!1}},De=async()=>{await b.logout(),ae.push(`/login`)},I=n(null),L=n(!1),R=n(``),z=n(!1),B=n(null),V=n(``),H=n(!1),U=n(``),W=n(null),G=h(()=>B.value&&B.value.total_bytes>0?Math.max(.5,B.value.db_bytes/B.value.total_bytes*100):0),Oe=h(()=>B.value&&B.value.total_bytes>0&&B.value.wal_bytes>0?Math.max(.5,B.value.wal_bytes/B.value.total_bytes*100):0),ke=h(()=>B.value&&B.value.total_bytes>0?Math.max(.5,B.value.functions_bytes/B.value.total_bytes*100):0),Ae=h(()=>B.value?(B.value.db_free_pages||0)*(B.value.db_page_size||0):0),je=async()=>{try{V.value=``;let e=await ie();B.value=e.data}catch(e){V.value=e?.response?.data?.error?.message||e?.message||`unknown error`}},Me=async()=>{if(await v.ask({title:`Compact database?`,message:`VACUUM rewrites orva.db to drop the freelist and shrink the file. It holds an exclusive lock for the duration; every other writer (deploys, invocations recording executions, KV puts, job enqueues) blocks until it returns. Typical runtime is sub-second, but a heavily-loaded instance can stall for several seconds.`,confirmLabel:`Compact`,danger:!1})){H.value=!0,U.value=``,W.value=null;try{let e=await ge();W.value=e.data,await je()}catch(e){U.value=e?.response?.data?.error?.message||e?.message||`vacuum failed`}finally{H.value=!1}}},K=e=>{if(e==null||isNaN(e))return`—`;let t=1024;if(e=t&&i{window.location.hash===`#ai`&&window.requestAnimationFrame(()=>{document.getElementById(`ai`)?.scrollIntoView({behavior:`smooth`,block:`start`})})});let q=n([]),J=n(!1),Y=n(``),X=n(``),Pe=async()=>{J.value=!0,Y.value=``;try{let e=await T();q.value=e.data.apps||[]}catch(e){Y.value=e?.response?.data?.error?.message||e?.message||`unknown error`}finally{J.value=!1}},Fe=async e=>{if(await v.ask({title:`Revoke ${e.client_name}?`,message:`${e.client_name} will lose access immediately. Any in-flight request will fail with 401. The connector can be re-authorized at any time from the originating app.`,confirmLabel:`Revoke`,danger:!0})){X.value=e.id;try{await ce(e.id),await Pe()}catch(e){Y.value=e?.response?.data?.error?.message||e?.message||`failed to revoke`}finally{X.value=``}}},Ie=e=>(e||``).split(/\s+/).filter(Boolean),Le=e=>{switch(e){case`admin`:return`bg-danger-tint text-danger-fg`;case`write`:return`bg-warning-tint text-warning-fg`;case`invoke`:return`bg-info-tint text-info-fg`;case`read`:return`bg-foreground-muted/15 text-foreground-muted`;default:return`bg-foreground-muted/10 text-foreground-muted`}},Z=n([]),Q=n(``),$=n(``),vn=async()=>{Q.value=``;try{let e=await oe();Z.value=e.data.sessions||[]}catch(e){Q.value=e?.response?.data?.error?.message||e?.message||`unknown error`}},yn=async e=>{if(await v.ask({title:`Revoke this session?`,message:`The browser using this session will be logged out on its next request. Use this if you suspect a device was lost or to clean up old logins.`,confirmLabel:`Revoke`,danger:!0})){$.value=e.prefix;try{await S(e.prefix),await vn()}catch(e){Q.value=e?.response?.data?.error?.message||e?.message||`failed to revoke`}finally{$.value=``}}},bn=e=>!e||e.length<8?e:e.slice(0,1)+`••••••••`+e.slice(-4);a(Pe),a(vn);let xn=()=>{window.location.assign(`/api/v1/backup?ts=`+Date.now())},Sn=()=>{R.value=``,z.value=!1,I.value?.click()},Cn=async e=>{let t=e.target.files?.[0];if(e.target.value=``,t&&await v.ask({title:`Restore from backup?`,message:`This will replace the live database and function code with the contents of "${t.name}". The current orva.db is moved aside as orva.db.before-restore- in case rollback is needed. You will need to reload after restore completes.`,confirmLabel:`Restore`,danger:!0})){L.value=!0,R.value=``,z.value=!1;try{await ue(t),z.value=!0}catch(e){R.value=e?.response?.data?.error?.message||e?.message||`Restore failed`}finally{L.value=!1}}},wn=()=>{window.location.reload()};return(n,a)=>(e(),l(`div`,ze,[a[43]||=c(`div`,null,[c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Settings `),c(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Instance, access, storage, backups, and AI. `)],-1),c(`details`,Be,[c(`summary`,Ve,[d(o(xe),{class:`w-4 h-4 text-foreground-muted`}),a[3]||=p(` Build info `,-1),c(`span`,He,_(O.value?.version||o(`—`)),1)]),c(`dl`,Ue,[a[4]||=c(`dt`,{class:`text-foreground-muted`},` Version `,-1),c(`dd`,We,_(O.value?.version||o(`—`)),1),a[5]||=c(`dt`,{class:`text-foreground-muted`},` Commit `,-1),c(`dd`,Ge,_(O.value?.commit&&O.value.commit!==`unknown`?O.value.commit:`dev build`),1),a[6]||=c(`dt`,{class:`text-foreground-muted`},` Built `,-1),c(`dd`,Ke,_(ve(O.value?.buildTime)),1),a[7]||=c(`dt`,{class:`text-foreground-muted`},` Image `,-1),c(`dd`,qe,[c(`span`,Je,_(O.value?.image||o(`—`)),1),O.value?.image?(e(),l(`button`,{key:0,class:`p-1 rounded hover:bg-surface text-foreground-muted hover:text-white transition-colors shrink-0`,title:`Copy image reference`,"aria-label":`Copy image reference`,onClick:j},[d(o(te),{class:`w-3.5 h-3.5`})])):g(``,!0),k.value?(e(),l(`span`,Ye,`copied`)):g(``,!0)])])]),c(`section`,Xe,[c(`div`,null,[c(`h2`,Ze,[d(o(le),{class:`w-4 h-4 text-foreground-muted`}),a[8]||=p(` AI assistant `,-1)])]),d(Ne)]),c(`section`,Qe,[c(`div`,$e,[c(`div`,null,[c(`h2`,et,[d(o(be),{class:`w-4 h-4 text-foreground-muted`}),a[9]||=p(` Storage `,-1)]),a[10]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Data directory usage and database maintenance. `,-1)]),d(D,{variant:`secondary`,loading:H.value,disabled:!B.value||H.value,onClick:Me},{default:t(()=>[d(o(Te),{class:`w-4 h-4`}),a[11]||=p(` Compact database `,-1)]),_:1},8,[`loading`,`disabled`])]),!B.value&&!V.value?(e(),l(`div`,tt,` Loading storage stats… `)):g(``,!0),V.value?(e(),l(`div`,nt,[a[12]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load storage stats `,-1),c(`div`,rt,_(V.value),1)])):g(``,!0),B.value?(e(),l(`div`,it,[c(`div`,at,[G.value>0?(e(),l(`div`,{key:0,class:`bg-info h-full`,style:s({width:G.value+`%`}),title:`orva.db: ${K(B.value.db_bytes)}`},null,12,ot)):g(``,!0),Oe.value>0?(e(),l(`div`,{key:1,class:`bg-warning h-full`,style:s({width:Oe.value+`%`}),title:`WAL: ${K(B.value.wal_bytes)}`},null,12,st)):g(``,!0),ke.value>0?(e(),l(`div`,{key:2,class:`bg-success h-full`,style:s({width:ke.value+`%`}),title:`functions/: ${K(B.value.functions_bytes)}`},null,12,ct)):g(``,!0)]),c(`div`,lt,[c(`div`,ut,[a[13]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-info`}),p(` orva.db `)],-1),c(`span`,dt,_(K(B.value.db_bytes)),1)]),c(`div`,ft,[a[14]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-success`}),p(` functions/ `)],-1),c(`span`,pt,_(K(B.value.functions_bytes)),1)]),B.value.wal_bytes>0?(e(),l(`div`,mt,[a[15]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-warning`}),p(` orva.db-wal `)],-1),c(`span`,ht,_(K(B.value.wal_bytes)),1)])):g(``,!0),c(`div`,gt,[a[16]||=c(`span`,{class:`text-foreground-muted`},`total`,-1),c(`span`,_t,_(K(B.value.total_bytes)),1)])]),Ae.value>0?(e(),l(`div`,vt,_(K(Ae.value))+` reclaimable (`+_(B.value.db_free_pages)+` free SQLite pages) `,1)):g(``,!0)])):g(``,!0),W.value?(e(),l(`div`,yt,[p(` Compacted in `+_(W.value.duration_ms)+` ms and freed `,1),c(`span`,bt,_(K(W.value.freed_bytes)),1),p(` (`+_(K(W.value.before_bytes))+` → `+_(K(W.value.after_bytes))+`). `,1)])):g(``,!0),U.value?(e(),l(`div`,xt,[a[17]||=c(`div`,{class:`font-semibold mb-1`},` Compact failed `,-1),c(`div`,St,_(U.value),1)])):g(``,!0)]),c(`section`,Ct,[c(`div`,null,[c(`h2`,wt,[d(o(y),{class:`w-4 h-4 text-foreground-muted`}),a[18]||=p(` Account `,-1)]),a[19]||=c(`p`,{class:`text-xs text-foreground-muted mt-1`},` Update your password or end your session. `,-1)]),c(`form`,{class:`space-y-3 pt-2`,onSubmit:C(Ee,[`prevent`])},[a[24]||=c(`h3`,{class:`text-sm font-medium text-foreground`},` Change password `,-1),c(`div`,Tt,[c(`div`,Et,[a[20]||=c(`label`,{for:`settings-current-password`,class:`text-xs text-foreground-muted`},`Current password`,-1),r(c(`input`,{id:`settings-current-password`,"onUpdate:modelValue":a[0]||=e=>M.value.current=e,type:`password`,autocomplete:`current-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.current]])]),c(`div`,Dt,[a[21]||=c(`label`,{for:`settings-new-password`,class:`text-xs text-foreground-muted`},`New password`,-1),r(c(`input`,{id:`settings-new-password`,"onUpdate:modelValue":a[1]||=e=>M.value.next=e,type:`password`,autocomplete:`new-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.next]])]),c(`div`,Ot,[a[22]||=c(`label`,{for:`settings-confirm-password`,class:`text-xs text-foreground-muted`},`Confirm new password`,-1),r(c(`input`,{id:`settings-confirm-password`,"onUpdate:modelValue":a[2]||=e=>M.value.confirm=e,type:`password`,autocomplete:`new-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.confirm]])])]),P.value?(e(),l(`div`,kt,_(P.value),1)):g(``,!0),F.value?(e(),l(`div`,At,` Password updated successfully. `)):g(``,!0),d(D,{type:`submit`,variant:`primary`,loading:N.value,disabled:N.value},{default:t(()=>[d(o(y),{class:`w-4 h-4`}),a[23]||=p(` Update password `,-1)]),_:1},8,[`loading`,`disabled`])],32),c(`div`,jt,[d(D,{variant:`danger`,onClick:De},{default:t(()=>[d(o(Se),{class:`w-4 h-4`}),a[25]||=p(` Log out `,-1)]),_:1})])]),c(`section`,Mt,[c(`div`,Nt,[c(`div`,null,[c(`h2`,Pt,[d(o(w),{class:`w-4 h-4 text-foreground-muted`}),a[26]||=p(` Connected applications `,-1)]),c(`p`,Ft,[a[28]||=p(` OAuth clients with access to this instance. Add connectors from `,-1),d(o(fe),{to:`/docs#mcp`,class:`text-primary hover:underline`},{default:t(()=>[...a[27]||=[p(` Docs `,-1)]]),_:1})])]),q.value.length>0?(e(),l(`span`,It,_(q.value.length)+` active `,1)):g(``,!0)]),Y.value?(e(),l(`div`,Lt,[a[29]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load connected apps `,-1),c(`div`,Rt,_(Y.value),1)])):J.value?(e(),l(`div`,zt,` Loading… `)):q.value.length===0?(e(),l(`div`,Bt,[...a[30]||=[c(`p`,{class:`text-xs text-foreground-muted`},` No connected applications. `,-1)]])):(e(),l(`ul`,Vt,[(e(!0),l(m,null,f(q.value,t=>(e(),l(`li`,{key:t.id,class:`px-5 py-3 flex items-start gap-3`},[(e(),ee(i(o(Re)(t.client_name).icon),{class:u([`w-5 h-5 mt-0.5 shrink-0`,o(Re)(t.client_name).accent])},null,8,[`class`])),c(`div`,Ht,[c(`div`,Ut,_(t.client_name),1),c(`div`,Wt,[c(`span`,null,`Authorized `+_(o(A)(t.issued_at)),1),t.last_used_at?(e(),l(`span`,Gt,` · Last used `+_(o(A)(t.last_used_at)),1)):(e(),l(`span`,Kt,`· Never used`)),t.refresh_expires_at?(e(),l(`span`,qt,` · Re-consent `+_(o(A)(t.refresh_expires_at)),1)):g(``,!0)]),c(`div`,Jt,[(e(!0),l(m,null,f(Ie(t.scope),t=>(e(),l(`span`,{key:t,class:u([`text-xs px-1.5 py-0.5 rounded font-mono`,Le(t)])},_(t),3))),128))])]),c(`button`,{type:`button`,class:`text-xs text-foreground-muted hover:text-danger-fg transition-colors flex items-center gap-1 shrink-0 self-center`,disabled:X.value===t.id,onClick:e=>Fe(t)},[d(o(x),{class:`w-3.5 h-3.5`}),a[31]||=p(` Revoke `,-1)],8,Yt)]))),128))]))]),c(`section`,Xt,[c(`div`,Zt,[c(`div`,null,[c(`h2`,Qt,[d(o(Ce),{class:`w-4 h-4 text-foreground-muted`}),a[32]||=p(` Active sessions `,-1)]),a[33]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Browsers signed in to this instance. `,-1)]),Z.value.length>0?(e(),l(`span`,$t,_(Z.value.length)+` active `,1)):g(``,!0)]),Q.value?(e(),l(`div`,en,[a[34]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load sessions `,-1),c(`div`,tn,_(Q.value),1)])):(e(),l(`ul`,nn,[(e(!0),l(m,null,f(Z.value,t=>(e(),l(`li`,{key:t.prefix,class:`px-5 py-3 flex items-start gap-3`},[d(o(Ce),{class:u([`w-5 h-5 mt-0.5 shrink-0`,t.current?`text-success-fg`:`text-foreground-muted`])},null,8,[`class`]),c(`div`,rn,[c(`div`,an,[t.current?(e(),l(`span`,on,`This session`)):(e(),l(`span`,sn,_(bn(t.prefix)),1)),t.current?(e(),l(`span`,cn,` current `)):g(``,!0)]),c(`div`,ln,` Signed in `+_(o(A)(t.created_at))+` · expires `+_(o(A)(t.expires_at)),1)]),t.current?g(``,!0):(e(),l(`button`,{key:0,type:`button`,class:`text-xs text-foreground-muted hover:text-danger-fg transition-colors flex items-center gap-1 shrink-0 self-center`,disabled:$.value===t.prefix,onClick:e=>yn(t)},[d(o(x),{class:`w-3.5 h-3.5`}),a[35]||=p(` Revoke `,-1)],8,un))]))),128))]))]),c(`section`,dn,[c(`div`,fn,[c(`div`,null,[c(`h2`,pn,[d(o(ye),{class:`w-4 h-4 text-foreground-muted`}),a[36]||=p(` Backup & Restore `,-1)]),a[37]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Download or restore a complete instance snapshot. `,-1),a[38]||=c(`p`,{class:`text-xs text-warning-fg mt-2 max-w-prose`},` Backups contain secret keys. Store them securely. `,-1)])]),c(`div`,mn,[d(D,{variant:`primary`,onClick:xn},{default:t(()=>[d(o(ne),{class:`w-4 h-4`}),a[39]||=p(` Download backup `,-1)]),_:1}),d(D,{variant:`secondary`,loading:L.value,onClick:Sn},{default:t(()=>[d(o(we),{class:`w-4 h-4`}),a[40]||=p(` Restore from backup `,-1)]),_:1},8,[`loading`]),c(`input`,{ref_key:`fileInput`,ref:I,type:`file`,accept:`.tar.gz,.tgz,application/gzip`,class:`hidden`,onChange:Cn},null,544)]),R.value?(e(),l(`div`,hn,[a[41]||=c(`div`,{class:`font-semibold mb-1`},` Restore failed `,-1),c(`div`,gn,_(R.value),1)])):g(``,!0),z.value?(e(),l(`div`,_n,[a[42]||=p(` Restore complete. The server is restarting to load the new data. Reload in a few seconds. `,-1),c(`button`,{class:`underline ml-1`,onClick:wn},` Reload now `)])):g(``,!0)])]))}});export{$ as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,M as i,T as a,Z as o,_t as s,c,d as l,gt as u,h as d,k as f,l as ee,m as p,r as m,s as h,u as g,vt as _}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./copy-3UAsea5P.js";import{i as ne,r as re,t as v}from"./ModelMenu-D7Iysg0v.js";import{t as y}from"./key-round-D9wVuhgl.js";import{t as b}from"./terminal-Czs3Hy-Y.js";import{t as x}from"./trash-2-Cz9PSE2q.js";import{$ as S,Bt as C,Ct as w,D as ie,Ft as ae,G as oe,I as T,It as se,Lt as E,Q as ce,Tt as le,_t as D,ct as ue,dt as de,ft as fe,gt as pe,jt as O,mt as me,n as he,nt as ge,ut as k}from"./index-pE9wnfTb.js";import{t as _e}from"./clipboard-D_9N0yai.js";import{t as A}from"./time-D8OmbYzY.js";import{t as j}from"./Input-DQ-tWGkn.js";var ve=O(`code-xml`,[[`path`,{d:`m18 16 4-4-4-4`,key:`1inbqp`}],[`path`,{d:`m6 8-4 4 4 4`,key:`15zrgr`}],[`path`,{d:`m14.5 4-5 16`,key:`e7oirm`}]]),ye=O(`database-backup`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 12a9 3 0 0 0 5 2.69`,key:`1ui2ym`}],[`path`,{d:`M21 9.3V5`,key:`6k6cib`}],[`path`,{d:`M3 5v14a9 3 0 0 0 6.47 2.88`,key:`i62tjy`}],[`path`,{d:`M12 12v4h4`,key:`1bxaet`}],[`path`,{d:`M13 20a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L12 16`,key:`1f4ei9`}]]),be=O(`hard-drive`,[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]),xe=O(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),Se=O(`log-out`,[[`path`,{d:`m16 17 5-5-5-5`,key:`1bji2h`}],[`path`,{d:`M21 12H9`,key:`dn1m92`}],[`path`,{d:`M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4`,key:`1uf3rs`}]]),Ce=O(`monitor`,[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`,key:`48i651`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`,key:`1svkeh`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`,key:`vw1qmm`}]]),M=O(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),we=O(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]),Te=O(`wand-sparkles`,[[`path`,{d:`m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72`,key:`ul74o6`}],[`path`,{d:`m14 7 3 3`,key:`1r5n42`}],[`path`,{d:`M5 6v4`,key:`ilb8ba`}],[`path`,{d:`M19 14v4`,key:`blhpug`}],[`path`,{d:`M10 2v2`,key:`7u0qdc`}],[`path`,{d:`M7 8H3`,key:`zfb6yr`}],[`path`,{d:`M21 16h-4`,key:`1cnmox`}],[`path`,{d:`M11 3H9`,key:`1obp7u`}]]),N={class:`space-y-6`},P={class:`space-y-3`},F={key:0,class:`grid grid-cols-1 gap-3 sm:grid-cols-2 sm:items-start`},Ee=[`value`],De=[`value`],I={class:`mt-1.5`},L={key:0,class:`text-xs text-danger-fg sm:col-span-2`},R={class:`divide-y divide-border border-y border-border`},z={class:`flex items-center gap-2 px-3 py-2`},B={class:`font-mono text-sm text-foreground`},V={key:0,class:`text-xs text-foreground-muted`},H={key:1,class:`text-xs uppercase tracking-label rounded px-1.5 py-0.5 bg-primary/15 text-primary-hover`},U={key:0,class:`text-xs text-foreground-muted`},W={class:`group border-t border-border pt-4`},G={class:`mt-4 space-y-3`},Oe=[`value`],ke={key:0,class:`space-y-3 border-t border-border pt-5`},Ae={class:`space-y-2`},je=[`value`],Me={key:0,class:`h-2 w-2 rounded-full bg-primary`},K={class:`min-w-0`},q={class:`block text-sm font-medium text-foreground`},J={class:`mt-0.5 block text-xs text-foreground-muted leading-snug`},Ne={__name:`AISettingsPanel`,setup(i){let s=re(),ee=pe();async function te(e){await ee.ask({title:`Remove provider?`,message:`This permanently removes the provider and its encrypted API key.`,danger:!0,confirmLabel:`Remove`})&&s.deleteProvider(e)}let ne=[`openai`,`anthropic`,`groq`,`gemini`,`ollama`,`mistral`,`openrouter`,`xai`,`cohere`],y=[{value:`all_writes`,label:`Ask before changes (recommended)`,hint:`Confirm creates, updates, and deletes.`},{value:`destructive_only`,label:`Ask before deletes only`,hint:`Confirm deletes; run other changes automatically.`},{value:`auto`,label:`Bypass: allow everything`,hint:`Run every action without confirmation.`}],b=n({provider:`openai`,label:``,api_key:``,base_url:``}),x=[`ollama`],S=h(()=>x.includes(b.value.provider)),C=h(()=>S.value&&!b.value.base_url.trim()?`Base URL is required for Ollama.`:``),w=h(()=>!!b.value.provider&&!C.value),ie=h(()=>S.value?`http://192.168.1.50:11434 or http://ollama.lan:11434`:`https://api.openai.com/v1 or https://your-host/v1`),oe=h(()=>S.value?`Where your server is listening. A private LAN address works; Orva permits it when your egress blocklist does.`:`For custom / self-hosted endpoints. Either with or without /v1 works. A private LAN address works too.`),T=n(!1),E=n(!1);a(async()=>{await s.loadSettings(),await s.loadProviders()});async function ce(e){await s.selectProvider(e.target.value)}async function le(){if(w.value){T.value=!0;try{await s.saveProvider({provider:b.value.provider,label:b.value.label,api_key:b.value.api_key,base_url:b.value.base_url,enabled:!0}),b.value.api_key=``}finally{T.value=!1}}}async function ue(){E.value=!0;try{await s.saveSettings(s.settings)}finally{E.value=!1}}return(n,i)=>(e(),l(`div`,N,[c(`section`,P,[i[9]||=c(`div`,null,[c(`h3`,{class:`text-sm font-semibold text-foreground`},` Providers `),c(`p`,{class:`text-xs text-foreground-muted mt-1.5 max-w-prose leading-snug`},` Keys are encrypted at rest. Choose which provider and model Chat uses. `)],-1),o(s).providers.length?(e(),l(`div`,F,[c(`div`,null,[i[5]||=c(`label`,{for:`ai-active-provider`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Active provider`,-1),c(`select`,{id:`ai-active-provider`,value:o(s).selectedProviderId||``,class:`mt-1.5 h-10 w-full bg-background border border-border rounded-md text-sm px-3 text-foreground transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onChange:ce},[(e(!0),l(m,null,f(o(s).providers,t=>(e(),l(`option`,{key:t.id,value:t.id},_(t.label?`${t.provider} (${t.label})`:t.provider),9,De))),128))],40,Ee)]),c(`div`,null,[i[6]||=c(`label`,{for:`ai-active-model`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},` Active model `,-1),c(`div`,I,[d(v,{wide:``,"trigger-id":`ai-active-model`})])]),o(s).modelsError?(e(),l(`p`,L,` Models could not be loaded. Check the provider endpoint and credentials. `)):g(``,!0)])):g(``,!0),c(`div`,R,[(e(!0),l(m,null,f(o(s).providers,n=>(e(),l(`div`,{key:n.id,class:`py-1`},[c(`div`,z,[c(`span`,B,_(n.provider),1),n.label?(e(),l(`span`,V,_(n.label),1)):g(``,!0),o(s).selectedProviderId===n.id?(e(),l(`span`,H,`active`)):g(``,!0),c(`span`,{class:u([`text-xs uppercase tracking-label rounded px-1.5 py-0.5`,n.has_key?`bg-success-tint text-success-fg`:`bg-surface-hover text-foreground-muted`])},_(n.has_key?`key set`:`no key`),3),i[8]||=c(`span`,{class:`flex-1`},null,-1),d(D,{size:`xs`,variant:`ghost`,onClick:e=>te(n.id)},{default:t(()=>[...i[7]||=[p(` Remove `,-1)]]),_:1},8,[`onClick`])])]))),128)),o(s).providers.length?g(``,!0):(e(),l(`p`,U,` No providers configured yet. `))])]),c(`details`,W,[i[13]||=c(`summary`,{class:`flex cursor-pointer list-none items-center justify-between rounded-sm text-sm font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary`},[p(` Add provider `),c(`span`,{class:`text-foreground-muted transition-transform group-open:rotate-45`,"aria-hidden":`true`},`+`)],-1),c(`div`,G,[i[12]||=c(`p`,{class:`text-xs text-foreground-muted max-w-prose leading-snug`},[p(` For compatible endpoints, choose `),c(`span`,{class:`font-mono`},`openai`),p(` and add the Base URL. `)],-1),c(`div`,null,[i[10]||=c(`label`,{for:`ai-provider`,class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},`Provider`,-1),r(c(`select`,{id:`ai-provider`,"onUpdate:modelValue":i[0]||=e=>b.value.provider=e,class:`mt-1.5 w-full bg-background border border-border rounded-md text-sm px-3 py-2 text-foreground transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},[(e(),l(m,null,f(ne,e=>c(`option`,{key:e,value:e},_(e),9,Oe)),64))],512),[[se,b.value.provider]])]),d(j,{modelValue:b.value.label,"onUpdate:modelValue":i[1]||=e=>b.value.label=e,label:`Label`,placeholder:`e.g. personal, work (optional)`},null,8,[`modelValue`]),d(j,{modelValue:b.value.base_url,"onUpdate:modelValue":i[2]||=e=>b.value.base_url=e,label:S.value?`Base URL (required)`:`Base URL (optional)`,placeholder:ie.value,hint:oe.value,error:C.value,required:S.value},null,8,[`modelValue`,`label`,`placeholder`,`hint`,`error`,`required`]),d(j,{modelValue:b.value.api_key,"onUpdate:modelValue":i[3]||=e=>b.value.api_key=e,label:`API key`,type:`password`,placeholder:`sk-…`,hint:`Stored encrypted; never shown again. Leave blank when updating to keep the current key.`},null,8,[`modelValue`]),d(D,{variant:`primary`,loading:T.value,disabled:!w.value,onClick:le},{default:t(()=>[...i[11]||=[p(` Save provider `,-1)]]),_:1},8,[`loading`,`disabled`])])]),o(s).settings?(e(),l(`section`,ke,[i[17]||=c(`h3`,{class:`text-sm font-semibold text-foreground`},` Defaults `,-1),c(`fieldset`,Ae,[i[14]||=c(`legend`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide`},` Approval policy `,-1),i[15]||=c(`p`,{class:`text-xs text-foreground-muted leading-snug`},` Choose when changes require confirmation. `,-1),(e(),l(m,null,f(y,t=>c(`label`,{key:t.value,class:`flex cursor-pointer items-start gap-3 px-1 py-2 transition-colors hover:bg-surface-hover focus-within:outline-none focus-within:ring-2 focus-within:ring-inset focus-within:ring-primary`},[r(c(`input`,{"onUpdate:modelValue":i[4]||=e=>o(s).settings.approval_policy=e,type:`radio`,name:`approval-policy`,value:t.value,class:`sr-only`},null,8,je),[[ae,o(s).settings.approval_policy]]),c(`span`,{class:u([`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full border transition-colors`,o(s).settings.approval_policy===t.value?`border-primary`:`border-foreground-muted/50`])},[o(s).settings.approval_policy===t.value?(e(),l(`span`,Me)):g(``,!0)],2),c(`span`,K,[c(`span`,q,_(t.label),1),c(`span`,J,_(t.hint),1)])])),64))]),d(D,{variant:`primary`,loading:E.value,onClick:ue},{default:t(()=>[...i[16]||=[p(` Save defaults `,-1)]]),_:1},8,[`loading`])])):g(``,!0)]))}},Y={},X={xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 24 24`,fill:`currentColor`,"aria-hidden":`true`};function Pe(t,n){return e(),l(`svg`,X,[...n[0]||=[c(`path`,{d:`M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.4069-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z`},null,-1)]])}var Fe=k(Y,[[`render`,Pe]]),Ie={},Le={xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 24 24`,fill:`currentColor`,"aria-hidden":`true`};function Z(t,n){return e(),l(`svg`,Le,[...n[0]||=[c(`path`,{d:`M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.146-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.418 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.349-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.658-.851-.747-1.926-1.622h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z`},null,-1)]])}var Q=k(Ie,[[`render`,Z]]);function Re(e){let t=(e||``).toLowerCase();return t.includes(`claude code`)?{icon:b,accent:`text-orange-400`}:t.includes(`chatgpt`)||t.includes(`openai`)?{icon:Fe,accent:`text-emerald-400`}:t.includes(`claude`)||t.includes(`anthropic`)?{icon:Q,accent:`text-orange-400`}:t.includes(`cursor`)?{icon:M,accent:`text-blue-400`}:t.includes(`vscode`)||t.includes(`vs code`)||t.includes(`code`)?{icon:ve,accent:`text-blue-400`}:{icon:w,accent:`text-foreground-muted`}}var ze={class:`space-y-8`},Be={class:`group border-b border-border pb-6`},Ve={class:`flex cursor-pointer list-none items-center gap-2 text-sm font-semibold text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary [&::-webkit-details-marker]:hidden`},He={class:`ml-auto text-xs font-normal text-foreground-muted group-open:hidden`},Ue={class:`mt-4 grid grid-cols-[max-content,1fr] gap-x-6 gap-y-2 text-xs`},We={class:`font-mono text-white`},Ge={class:`font-mono text-white`},Ke={class:`font-mono text-white`},qe={class:`font-mono text-white flex items-center gap-2 min-w-0`},Je={class:`truncate`},Ye={key:1,class:`text-xs text-primary-hover shrink-0`},Xe={id:`ai`,class:`scroll-mt-6 space-y-4 border-b border-border pb-8`},Ze={class:`text-base font-semibold text-white flex items-center gap-2`},Qe={class:`space-y-4 border-b border-border pb-8`},$e={class:`flex items-start justify-between gap-4`},et={class:`text-base font-semibold text-white flex items-center gap-2`},tt={key:0,class:`text-xs text-foreground-muted italic`},nt={key:1,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},rt={class:`font-mono break-all`},it={key:2,class:`space-y-3`},at={class:`h-2 w-full rounded-full overflow-hidden bg-border/60 flex`},ot=[`title`],st=[`title`],ct=[`title`],lt={class:`grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-1.5 text-xs`},ut={class:`flex items-center justify-between`},dt={class:`font-mono text-white`},ft={class:`flex items-center justify-between`},pt={class:`font-mono text-white`},mt={key:0,class:`flex items-center justify-between`},ht={class:`font-mono text-white`},gt={class:`flex items-center justify-between`},_t={class:`font-mono text-white font-semibold`},vt={key:0,class:`text-xs text-foreground-muted pt-1 border-t border-border`},yt={key:3,class:`rounded-md border border-success-ring bg-success-tint p-3 text-xs text-success-fg`},bt={class:`font-mono`},xt={key:4,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},St={class:`font-mono break-all`},Ct={class:`space-y-4 border-b border-border pb-8`},wt={class:`text-base font-semibold text-white flex items-center gap-2`},Tt={class:`grid grid-cols-1 sm:grid-cols-3 gap-3`},Et={class:`flex flex-col gap-1`},Dt={class:`flex flex-col gap-1`},Ot={class:`flex flex-col gap-1`},kt={key:0,id:`pw-error`,class:`rounded-md border border-danger-ring bg-danger-tint p-2.5 text-xs text-danger-fg`},At={key:1,class:`rounded-md border border-success-ring bg-success-tint p-2.5 text-xs text-success-fg`},jt={class:`pt-2 border-t border-border`},Mt={class:`space-y-4 border-b border-border pb-8`},Nt={class:`flex items-start justify-between gap-4`},Pt={class:`text-base font-semibold text-white flex items-center gap-2`},Ft={class:`text-xs text-foreground-muted mt-1 max-w-prose`},It={key:0,class:`text-xs text-foreground-muted self-center`},Lt={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},Rt={class:`font-mono break-all`},zt={key:1,class:`text-xs text-foreground-muted italic`},Bt={key:2,class:`py-3`},Vt={key:3,class:`divide-y divide-border -mx-5`},Ht={class:`flex-1 min-w-0`},Ut={class:`text-sm font-medium text-white truncate`},Wt={class:`text-xs text-foreground-muted mt-0.5 flex flex-wrap gap-x-3 gap-y-0.5`},Gt={key:0},Kt={key:1,class:`italic opacity-70`},qt={key:2},Jt={class:`flex flex-wrap gap-1 mt-2`},Yt=[`disabled`,`onClick`],Xt={class:`space-y-4 border-b border-border pb-8`},Zt={class:`flex items-start justify-between gap-4`},Qt={class:`text-base font-semibold text-white flex items-center gap-2`},$t={key:0,class:`text-xs text-foreground-muted self-center`},en={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},tn={class:`font-mono break-all`},nn={key:1,class:`divide-y divide-border -mx-5`},rn={class:`flex-1 min-w-0`},an={class:`text-sm font-medium text-white flex items-center gap-2 flex-wrap`},on={key:0},sn={key:1,class:`font-mono text-xs`},cn={key:2,class:`text-xs px-1.5 py-0.5 rounded bg-success-tint text-success-fg font-medium`},ln={class:`text-xs text-foreground-muted mt-0.5`},un=[`disabled`,`onClick`],dn={class:`space-y-4`},fn={class:`flex items-start justify-between gap-4`},pn={class:`text-base font-semibold text-white flex items-center gap-2`},mn={class:`flex flex-col sm:flex-row gap-3 pt-2 border-t border-border`},hn={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},gn={class:`font-mono break-all`},_n={key:1,class:`rounded-md border border-success-ring bg-success-tint p-3 text-xs text-success-fg`},$=Object.assign({name:`SettingsView`},{__name:`Settings`,setup(re){let v=pe(),b=de(),ae=me(),se=he(),O=h(()=>se.buildInfo),k=n(!1),j=async()=>{O.value?.image&&await _e(O.value.image)&&(k.value=!0,setTimeout(()=>{k.value=!1},1500))},ve=e=>{if(!e||e===`unknown`)return`—`;try{return new Date(e).toISOString().replace(`T`,` `).replace(/\.\d+Z$/,` UTC`)}catch{return e}},M=n({current:``,next:``,confirm:``}),N=n(!1),P=n(``),F=n(!1),Ee=async()=>{if(P.value=``,F.value=!1,!M.value.current||!M.value.next||!M.value.confirm){P.value=`All three fields are required.`;return}if(M.value.next.length<8){P.value=`New password must be at least 8 characters.`;return}if(M.value.next!==M.value.confirm){P.value=`New password and confirmation do not match.`;return}N.value=!0;try{await b.changePassword(M.value.current,M.value.next),F.value=!0,M.value={current:``,next:``,confirm:``}}catch(e){P.value=e?.response?.data?.error?.message||`Failed to update password.`}finally{N.value=!1}},De=async()=>{await b.logout(),ae.push(`/login`)},I=n(null),L=n(!1),R=n(``),z=n(!1),B=n(null),V=n(``),H=n(!1),U=n(``),W=n(null),G=h(()=>B.value&&B.value.total_bytes>0?Math.max(.5,B.value.db_bytes/B.value.total_bytes*100):0),Oe=h(()=>B.value&&B.value.total_bytes>0&&B.value.wal_bytes>0?Math.max(.5,B.value.wal_bytes/B.value.total_bytes*100):0),ke=h(()=>B.value&&B.value.total_bytes>0?Math.max(.5,B.value.functions_bytes/B.value.total_bytes*100):0),Ae=h(()=>B.value?(B.value.db_free_pages||0)*(B.value.db_page_size||0):0),je=async()=>{try{V.value=``;let e=await ie();B.value=e.data}catch(e){V.value=e?.response?.data?.error?.message||e?.message||`unknown error`}},Me=async()=>{if(await v.ask({title:`Compact database?`,message:`VACUUM rewrites orva.db to drop the freelist and shrink the file. It holds an exclusive lock for the duration; every other writer (deploys, invocations recording executions, KV puts, job enqueues) blocks until it returns. Typical runtime is sub-second, but a heavily-loaded instance can stall for several seconds.`,confirmLabel:`Compact`,danger:!1})){H.value=!0,U.value=``,W.value=null;try{let e=await ge();W.value=e.data,await je()}catch(e){U.value=e?.response?.data?.error?.message||e?.message||`vacuum failed`}finally{H.value=!1}}},K=e=>{if(e==null||isNaN(e))return`—`;let t=1024;if(e=t&&i{window.location.hash===`#ai`&&window.requestAnimationFrame(()=>{document.getElementById(`ai`)?.scrollIntoView({behavior:`smooth`,block:`start`})})});let q=n([]),J=n(!1),Y=n(``),X=n(``),Pe=async()=>{J.value=!0,Y.value=``;try{let e=await T();q.value=e.data.apps||[]}catch(e){Y.value=e?.response?.data?.error?.message||e?.message||`unknown error`}finally{J.value=!1}},Fe=async e=>{if(await v.ask({title:`Revoke ${e.client_name}?`,message:`${e.client_name} will lose access immediately. Any in-flight request will fail with 401. The connector can be re-authorized at any time from the originating app.`,confirmLabel:`Revoke`,danger:!0})){X.value=e.id;try{await ce(e.id),await Pe()}catch(e){Y.value=e?.response?.data?.error?.message||e?.message||`failed to revoke`}finally{X.value=``}}},Ie=e=>(e||``).split(/\s+/).filter(Boolean),Le=e=>{switch(e){case`admin`:return`bg-danger-tint text-danger-fg`;case`write`:return`bg-warning-tint text-warning-fg`;case`invoke`:return`bg-info-tint text-info-fg`;case`read`:return`bg-foreground-muted/15 text-foreground-muted`;default:return`bg-foreground-muted/10 text-foreground-muted`}},Z=n([]),Q=n(``),$=n(``),vn=async()=>{Q.value=``;try{let e=await oe();Z.value=e.data.sessions||[]}catch(e){Q.value=e?.response?.data?.error?.message||e?.message||`unknown error`}},yn=async e=>{if(await v.ask({title:`Revoke this session?`,message:`The browser using this session will be logged out on its next request. Use this if you suspect a device was lost or to clean up old logins.`,confirmLabel:`Revoke`,danger:!0})){$.value=e.prefix;try{await S(e.prefix),await vn()}catch(e){Q.value=e?.response?.data?.error?.message||e?.message||`failed to revoke`}finally{$.value=``}}},bn=e=>!e||e.length<8?e:e.slice(0,1)+`••••••••`+e.slice(-4);a(Pe),a(vn);let xn=()=>{window.location.assign(`/api/v1/backup?ts=`+Date.now())},Sn=()=>{R.value=``,z.value=!1,I.value?.click()},Cn=async e=>{let t=e.target.files?.[0];if(e.target.value=``,t&&await v.ask({title:`Restore from backup?`,message:`This will replace the live database and function code with the contents of "${t.name}". The current orva.db is moved aside as orva.db.before-restore- in case rollback is needed. You will need to reload after restore completes.`,confirmLabel:`Restore`,danger:!0})){L.value=!0,R.value=``,z.value=!1;try{await ue(t),z.value=!0}catch(e){R.value=e?.response?.data?.error?.message||e?.message||`Restore failed`}finally{L.value=!1}}},wn=()=>{window.location.reload()};return(n,a)=>(e(),l(`div`,ze,[a[43]||=c(`div`,null,[c(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Settings `),c(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Instance, access, storage, backups, and AI. `)],-1),c(`details`,Be,[c(`summary`,Ve,[d(o(xe),{class:`w-4 h-4 text-foreground-muted`}),a[3]||=p(` Build info `,-1),c(`span`,He,_(O.value?.version||o(`—`)),1)]),c(`dl`,Ue,[a[4]||=c(`dt`,{class:`text-foreground-muted`},` Version `,-1),c(`dd`,We,_(O.value?.version||o(`—`)),1),a[5]||=c(`dt`,{class:`text-foreground-muted`},` Commit `,-1),c(`dd`,Ge,_(O.value?.commit&&O.value.commit!==`unknown`?O.value.commit:`dev build`),1),a[6]||=c(`dt`,{class:`text-foreground-muted`},` Built `,-1),c(`dd`,Ke,_(ve(O.value?.buildTime)),1),a[7]||=c(`dt`,{class:`text-foreground-muted`},` Image `,-1),c(`dd`,qe,[c(`span`,Je,_(O.value?.image||o(`—`)),1),O.value?.image?(e(),l(`button`,{key:0,class:`p-1 rounded hover:bg-surface text-foreground-muted hover:text-white transition-colors shrink-0`,title:`Copy image reference`,"aria-label":`Copy image reference`,onClick:j},[d(o(te),{class:`w-3.5 h-3.5`})])):g(``,!0),k.value?(e(),l(`span`,Ye,`copied`)):g(``,!0)])])]),c(`section`,Xe,[c(`div`,null,[c(`h2`,Ze,[d(o(le),{class:`w-4 h-4 text-foreground-muted`}),a[8]||=p(` AI assistant `,-1)])]),d(Ne)]),c(`section`,Qe,[c(`div`,$e,[c(`div`,null,[c(`h2`,et,[d(o(be),{class:`w-4 h-4 text-foreground-muted`}),a[9]||=p(` Storage `,-1)]),a[10]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Data directory usage and database maintenance. `,-1)]),d(D,{variant:`secondary`,loading:H.value,disabled:!B.value||H.value,onClick:Me},{default:t(()=>[d(o(Te),{class:`w-4 h-4`}),a[11]||=p(` Compact database `,-1)]),_:1},8,[`loading`,`disabled`])]),!B.value&&!V.value?(e(),l(`div`,tt,` Loading storage stats… `)):g(``,!0),V.value?(e(),l(`div`,nt,[a[12]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load storage stats `,-1),c(`div`,rt,_(V.value),1)])):g(``,!0),B.value?(e(),l(`div`,it,[c(`div`,at,[G.value>0?(e(),l(`div`,{key:0,class:`bg-info h-full`,style:s({width:G.value+`%`}),title:`orva.db: ${K(B.value.db_bytes)}`},null,12,ot)):g(``,!0),Oe.value>0?(e(),l(`div`,{key:1,class:`bg-warning h-full`,style:s({width:Oe.value+`%`}),title:`WAL: ${K(B.value.wal_bytes)}`},null,12,st)):g(``,!0),ke.value>0?(e(),l(`div`,{key:2,class:`bg-success h-full`,style:s({width:ke.value+`%`}),title:`functions/: ${K(B.value.functions_bytes)}`},null,12,ct)):g(``,!0)]),c(`div`,lt,[c(`div`,ut,[a[13]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-info`}),p(` orva.db `)],-1),c(`span`,dt,_(K(B.value.db_bytes)),1)]),c(`div`,ft,[a[14]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-success`}),p(` functions/ `)],-1),c(`span`,pt,_(K(B.value.functions_bytes)),1)]),B.value.wal_bytes>0?(e(),l(`div`,mt,[a[15]||=c(`span`,{class:`flex items-center gap-2 text-foreground-muted`},[c(`span`,{class:`w-2 h-2 rounded-sm bg-warning`}),p(` orva.db-wal `)],-1),c(`span`,ht,_(K(B.value.wal_bytes)),1)])):g(``,!0),c(`div`,gt,[a[16]||=c(`span`,{class:`text-foreground-muted`},`total`,-1),c(`span`,_t,_(K(B.value.total_bytes)),1)])]),Ae.value>0?(e(),l(`div`,vt,_(K(Ae.value))+` reclaimable (`+_(B.value.db_free_pages)+` free SQLite pages) `,1)):g(``,!0)])):g(``,!0),W.value?(e(),l(`div`,yt,[p(` Compacted in `+_(W.value.duration_ms)+` ms and freed `,1),c(`span`,bt,_(K(W.value.freed_bytes)),1),p(` (`+_(K(W.value.before_bytes))+` → `+_(K(W.value.after_bytes))+`). `,1)])):g(``,!0),U.value?(e(),l(`div`,xt,[a[17]||=c(`div`,{class:`font-semibold mb-1`},` Compact failed `,-1),c(`div`,St,_(U.value),1)])):g(``,!0)]),c(`section`,Ct,[c(`div`,null,[c(`h2`,wt,[d(o(y),{class:`w-4 h-4 text-foreground-muted`}),a[18]||=p(` Account `,-1)]),a[19]||=c(`p`,{class:`text-xs text-foreground-muted mt-1`},` Update your password or end your session. `,-1)]),c(`form`,{class:`space-y-3 pt-2`,onSubmit:C(Ee,[`prevent`])},[a[24]||=c(`h3`,{class:`text-sm font-medium text-foreground`},` Change password `,-1),c(`div`,Tt,[c(`div`,Et,[a[20]||=c(`label`,{for:`settings-current-password`,class:`text-xs text-foreground-muted`},`Current password`,-1),r(c(`input`,{id:`settings-current-password`,"onUpdate:modelValue":a[0]||=e=>M.value.current=e,type:`password`,autocomplete:`current-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.current]])]),c(`div`,Dt,[a[21]||=c(`label`,{for:`settings-new-password`,class:`text-xs text-foreground-muted`},`New password`,-1),r(c(`input`,{id:`settings-new-password`,"onUpdate:modelValue":a[1]||=e=>M.value.next=e,type:`password`,autocomplete:`new-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.next]])]),c(`div`,Ot,[a[22]||=c(`label`,{for:`settings-confirm-password`,class:`text-xs text-foreground-muted`},`Confirm new password`,-1),r(c(`input`,{id:`settings-confirm-password`,"onUpdate:modelValue":a[2]||=e=>M.value.confirm=e,type:`password`,autocomplete:`new-password`,"aria-describedby":`pw-error`,class:`bg-surface border border-border rounded-md px-3 py-2 text-sm text-white placeholder:text-foreground-muted focus:outline-none focus:ring-1 focus:ring-primary`,placeholder:`••••••••`},null,512),[[E,M.value.confirm]])])]),P.value?(e(),l(`div`,kt,_(P.value),1)):g(``,!0),F.value?(e(),l(`div`,At,` Password updated successfully. `)):g(``,!0),d(D,{type:`submit`,variant:`primary`,loading:N.value,disabled:N.value},{default:t(()=>[d(o(y),{class:`w-4 h-4`}),a[23]||=p(` Update password `,-1)]),_:1},8,[`loading`,`disabled`])],32),c(`div`,jt,[d(D,{variant:`danger`,onClick:De},{default:t(()=>[d(o(Se),{class:`w-4 h-4`}),a[25]||=p(` Log out `,-1)]),_:1})])]),c(`section`,Mt,[c(`div`,Nt,[c(`div`,null,[c(`h2`,Pt,[d(o(w),{class:`w-4 h-4 text-foreground-muted`}),a[26]||=p(` Connected applications `,-1)]),c(`p`,Ft,[a[28]||=p(` OAuth clients with access to this instance. Add connectors from `,-1),d(o(fe),{to:`/docs#mcp`,class:`text-primary hover:underline`},{default:t(()=>[...a[27]||=[p(` Docs `,-1)]]),_:1})])]),q.value.length>0?(e(),l(`span`,It,_(q.value.length)+` active `,1)):g(``,!0)]),Y.value?(e(),l(`div`,Lt,[a[29]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load connected apps `,-1),c(`div`,Rt,_(Y.value),1)])):J.value?(e(),l(`div`,zt,` Loading… `)):q.value.length===0?(e(),l(`div`,Bt,[...a[30]||=[c(`p`,{class:`text-xs text-foreground-muted`},` No connected applications. `,-1)]])):(e(),l(`ul`,Vt,[(e(!0),l(m,null,f(q.value,t=>(e(),l(`li`,{key:t.id,class:`px-5 py-3 flex items-start gap-3`},[(e(),ee(i(o(Re)(t.client_name).icon),{class:u([`w-5 h-5 mt-0.5 shrink-0`,o(Re)(t.client_name).accent])},null,8,[`class`])),c(`div`,Ht,[c(`div`,Ut,_(t.client_name),1),c(`div`,Wt,[c(`span`,null,`Authorized `+_(o(A)(t.issued_at)),1),t.last_used_at?(e(),l(`span`,Gt,` · Last used `+_(o(A)(t.last_used_at)),1)):(e(),l(`span`,Kt,`· Never used`)),t.refresh_expires_at?(e(),l(`span`,qt,` · Re-consent `+_(o(A)(t.refresh_expires_at)),1)):g(``,!0)]),c(`div`,Jt,[(e(!0),l(m,null,f(Ie(t.scope),t=>(e(),l(`span`,{key:t,class:u([`text-xs px-1.5 py-0.5 rounded font-mono`,Le(t)])},_(t),3))),128))])]),c(`button`,{type:`button`,class:`text-xs text-foreground-muted hover:text-danger-fg transition-colors flex items-center gap-1 shrink-0 self-center`,disabled:X.value===t.id,onClick:e=>Fe(t)},[d(o(x),{class:`w-3.5 h-3.5`}),a[31]||=p(` Revoke `,-1)],8,Yt)]))),128))]))]),c(`section`,Xt,[c(`div`,Zt,[c(`div`,null,[c(`h2`,Qt,[d(o(Ce),{class:`w-4 h-4 text-foreground-muted`}),a[32]||=p(` Active sessions `,-1)]),a[33]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Browsers signed in to this instance. `,-1)]),Z.value.length>0?(e(),l(`span`,$t,_(Z.value.length)+` active `,1)):g(``,!0)]),Q.value?(e(),l(`div`,en,[a[34]||=c(`div`,{class:`font-semibold mb-1`},` Failed to load sessions `,-1),c(`div`,tn,_(Q.value),1)])):(e(),l(`ul`,nn,[(e(!0),l(m,null,f(Z.value,t=>(e(),l(`li`,{key:t.prefix,class:`px-5 py-3 flex items-start gap-3`},[d(o(Ce),{class:u([`w-5 h-5 mt-0.5 shrink-0`,t.current?`text-success-fg`:`text-foreground-muted`])},null,8,[`class`]),c(`div`,rn,[c(`div`,an,[t.current?(e(),l(`span`,on,`This session`)):(e(),l(`span`,sn,_(bn(t.prefix)),1)),t.current?(e(),l(`span`,cn,` current `)):g(``,!0)]),c(`div`,ln,` Signed in `+_(o(A)(t.created_at))+` · expires `+_(o(A)(t.expires_at)),1)]),t.current?g(``,!0):(e(),l(`button`,{key:0,type:`button`,class:`text-xs text-foreground-muted hover:text-danger-fg transition-colors flex items-center gap-1 shrink-0 self-center`,disabled:$.value===t.prefix,onClick:e=>yn(t)},[d(o(x),{class:`w-3.5 h-3.5`}),a[35]||=p(` Revoke `,-1)],8,un))]))),128))]))]),c(`section`,dn,[c(`div`,fn,[c(`div`,null,[c(`h2`,pn,[d(o(ye),{class:`w-4 h-4 text-foreground-muted`}),a[36]||=p(` Backup & Restore `,-1)]),a[37]||=c(`p`,{class:`text-xs text-foreground-muted mt-1 max-w-prose`},` Download or restore a complete instance snapshot. `,-1),a[38]||=c(`p`,{class:`text-xs text-warning-fg mt-2 max-w-prose`},` Backups contain secret keys. Store them securely. `,-1)])]),c(`div`,mn,[d(D,{variant:`primary`,onClick:xn},{default:t(()=>[d(o(ne),{class:`w-4 h-4`}),a[39]||=p(` Download backup `,-1)]),_:1}),d(D,{variant:`secondary`,loading:L.value,onClick:Sn},{default:t(()=>[d(o(we),{class:`w-4 h-4`}),a[40]||=p(` Restore from backup `,-1)]),_:1},8,[`loading`]),c(`input`,{ref_key:`fileInput`,ref:I,type:`file`,accept:`.tar.gz,.tgz,application/gzip`,class:`hidden`,onChange:Cn},null,544)]),R.value?(e(),l(`div`,hn,[a[41]||=c(`div`,{class:`font-semibold mb-1`},` Restore failed `,-1),c(`div`,gn,_(R.value),1)])):g(``,!0),z.value?(e(),l(`div`,_n,[a[42]||=p(` Restore complete. The server is restarting to load the new data. Reload in a few seconds. `,-1),c(`button`,{class:`underline ml-1`,onClick:wn},` Reload now `)])):g(``,!0)])]))}});export{$ as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/StatusBadge-Baoe7YAb.js b/backend/internal/server/ui_dist/assets/StatusBadge-BpEw6z9Z.js similarity index 86% rename from backend/internal/server/ui_dist/assets/StatusBadge-Baoe7YAb.js rename to backend/internal/server/ui_dist/assets/StatusBadge-BpEw6z9Z.js index 15fc5535..d1c88db3 100644 --- a/backend/internal/server/ui_dist/assets/StatusBadge-Baoe7YAb.js +++ b/backend/internal/server/ui_dist/assets/StatusBadge-BpEw6z9Z.js @@ -1 +1 @@ -import{D as e,M as t,d as n,gt as r,l as i,m as a,s as o,vt as s}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as c,t as l}from"./clock-CiH8bQVI.js";import{n as u,t as d}from"./circle-NOse79gh.js";var f={__name:`StatusBadge`,props:{status:{type:String,required:!0}},setup(f){let p=f,m=o(()=>{switch(p.status){case`succeeded`:case`success`:case`active`:return{classes:`text-success-fg border-success-ring`,icon:c};case`failed`:case`error`:case`crashed`:return{classes:`text-danger-fg border-danger-ring`,icon:u};case`queued`:case`building`:case`pending`:case`timeout`:return{classes:`text-warning-fg border-warning-ring`,icon:l};default:return{classes:`text-foreground-muted border-border`,icon:d}}});return(o,c)=>(e(),n(`span`,{class:r([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs border bg-background font-mono`,m.value.classes])},[(e(),i(t(m.value.icon),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),a(` `+s(f.status),1)],2))}};export{f as t}; \ No newline at end of file +import{D as e,M as t,d as n,gt as r,l as i,m as a,s as o,vt as s}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as c,t as l}from"./clock-CIjbNepe.js";import{n as u,t as d}from"./circle-DhZmtdqu.js";var f={__name:`StatusBadge`,props:{status:{type:String,required:!0}},setup(f){let p=f,m=o(()=>{switch(p.status){case`succeeded`:case`success`:case`active`:return{classes:`text-success-fg border-success-ring`,icon:c};case`failed`:case`error`:case`crashed`:return{classes:`text-danger-fg border-danger-ring`,icon:u};case`queued`:case`building`:case`pending`:case`timeout`:return{classes:`text-warning-fg border-warning-ring`,icon:l};default:return{classes:`text-foreground-muted border-border`,icon:d}}});return(o,c)=>(e(),n(`span`,{class:r([`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs border bg-background font-mono`,m.value.classes])},[(e(),i(t(m.value.icon),{class:`h-3 w-3 shrink-0`,"aria-hidden":`true`})),a(` `+s(f.status),1)],2))}};export{f as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/TraceDetail-wVyyYiTv.js b/backend/internal/server/ui_dist/assets/TraceDetail-C28REiIi.js similarity index 97% rename from backend/internal/server/ui_dist/assets/TraceDetail-wVyyYiTv.js rename to backend/internal/server/ui_dist/assets/TraceDetail-C28REiIi.js index e83eafdc..33c5612f 100644 --- a/backend/internal/server/ui_dist/assets/TraceDetail-wVyyYiTv.js +++ b/backend/internal/server/ui_dist/assets/TraceDetail-C28REiIi.js @@ -1 +1 @@ -import{D as e,G as t,T as n,Z as r,_t as i,c as a,d as o,gt as s,h as c,k as l,l as u,m as d,r as f,s as ee,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./arrow-left-Ba3OArNt.js";import{t as ne}from"./circle-alert-BnUYYhGE.js";import{t as re}from"./copy-BqdwwcxC.js";import{t as h}from"./flag-CmjNKmxi.js";import{O as ie,mt as ae,pt as oe}from"./index-DTqMKlE1.js";import{t as g}from"./StatusBadge-Baoe7YAb.js";var se={class:`space-y-6`},_={class:`flex items-start justify-between gap-4`},v={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},y={key:1,class:`text-xs text-foreground-muted italic`},b={class:`bg-background border border-border rounded-lg p-5 space-y-4`},x={class:`flex items-center gap-3 flex-wrap text-xs`},S={class:`bg-surface text-white px-2 py-0.5 rounded font-mono`},C={class:`grid grid-cols-2 sm:grid-cols-4 gap-4 pt-3 border-t border-border text-xs`},w={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},T={class:`text-white font-mono`},E={class:`text-white`},D={class:`flex items-center gap-2`},O={key:0,class:`inline-flex items-center gap-1 text-[10px] uppercase tracking-wide text-warning-fg`},k={class:`bg-background border border-border rounded-lg p-5`},A={class:`space-y-1.5`},j=[`onClick`],M={class:`col-span-3 truncate flex items-center gap-1.5`},N={class:`text-white`},P={class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] border bg-background font-mono text-foreground-muted border-border lowercase`},F={class:`col-span-7 relative h-4`},I=[`title`],L={class:`col-span-2 text-right font-mono`},R={class:`text-white`},z={key:0,class:`block text-[10px] text-foreground-muted`},B={class:`col-span-3 truncate flex items-center gap-1.5 pl-5`},V={class:`text-foreground-muted`},H={key:0,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] bg-danger-tint text-danger-fg border border-danger-ring`},U={class:`col-span-7 relative h-3`},W=[`title`],G={class:`col-span-2 text-right font-mono text-foreground-muted`},K={key:0,class:`bg-background border border-border rounded-lg p-5`},ce={class:`text-xs text-foreground-muted uppercase tracking-wide mb-3`},le={class:`space-y-1 font-mono text-xs`},ue={class:`text-foreground-muted text-[10px] tabular-nums`},de={class:`text-white truncate`},fe={key:0,class:`text-[10px] text-foreground-muted truncate`},pe={class:`bg-background border border-border rounded-lg overflow-x-auto`},me={class:`w-full text-sm text-left`},he={class:`divide-y divide-border`},ge=[`onClick`],_e={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},ve={class:`px-4 py-2.5 text-white`},ye={class:`px-4 py-2.5 hidden md:table-cell`},be={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},xe={class:`px-4 py-2.5 text-right font-mono text-xs text-foreground-muted`},Se={class:`px-4 py-2.5 text-right font-mono text-xs text-white`},Ce={class:`px-4 py-2.5`},we={__name:`TraceDetail`,setup(we){let Te=oe(),q=ae(),J=t(null),Y=t(!1),X=t(``),Ee=async()=>{Y.value=!0,X.value=``;try{let e=await ie(Te.params.id);J.value=e.data}catch(e){e?.response?.status===404?X.value=`No spans found for that trace.`:X.value=e?.response?.data?.error?.message||e?.message||`failed to load trace`}finally{Y.value=!1}},Z=ee(()=>Math.max(1,J.value?.total_duration_ms||1)),De=e=>{let t=e.offset_ms/Z.value*100,n=Math.max(.5,e.duration_ms/Z.value*100);return{left:`${t}%`,width:`${n}%`}},Oe=e=>e.status===`error`?`bg-danger/70`:e.is_outlier?`bg-warning/80`:`bg-primary/80`,Q=e=>!J.value?.user_spans||!e?.span_id?[]:J.value.user_spans.filter(t=>t.parent_span_id===e.span_id).sort((e,t)=>(e.offset_ms||0)-(t.offset_ms||0)),ke=e=>{let t=(e.offset_ms||0)/Z.value*100,n=Math.max(.5,(e.duration_ms||0)/Z.value*100);return{left:`${t}%`,width:`${n}%`}},Ae=e=>{switch(e){case`error`:return`text-danger-fg`;case`warn`:return`text-warning-fg`;case`debug`:return`text-foreground-muted`;default:return`text-primary-light`}},je=e=>e.level===`error`?`bg-danger-tint`:``,Me=e=>{if(!e)return``;try{let t=new Date(e);return t.toLocaleTimeString(void 0,{hour12:!1})+`.`+String(t.getMilliseconds()).padStart(3,`0`)}catch{return e}},$=e=>{e.execution_id&&q.push({path:`/invocations`,query:{exec:e.execution_id}})},Ne=async()=>{if(J.value?.trace_id)try{await navigator.clipboard.writeText(J.value.trace_id)}catch{}};return n(Ee),(t,n)=>(e(),o(`div`,se,[a(`div`,_,[a(`div`,null,[a(`button`,{class:`inline-flex items-center gap-1 text-xs text-foreground-muted hover:text-white mb-1 transition-colors`,onClick:n[0]||=e=>r(q).push(`/traces`)},[c(r(te),{class:`w-3.5 h-3.5`}),n[1]||=d(` All traces `,-1)]),n[2]||=a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Trace `,-1),n[3]||=a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Spans in this invocation chain. `,-1)])]),X.value?(e(),o(`div`,v,m(X.value),1)):Y.value&&!J.value?(e(),o(`div`,y,` Loading trace… `)):J.value?(e(),o(f,{key:2},[a(`div`,b,[a(`div`,x,[n[4]||=a(`span`,{class:`text-foreground-muted uppercase tracking-wide`},` trace id `,-1),a(`code`,S,m(J.value.trace_id),1),a(`button`,{class:`p-1 rounded hover:bg-surface text-foreground-muted hover:text-white transition-colors`,title:`Copy trace id`,"aria-label":`Copy trace ID`,onClick:Ne},[c(r(re),{class:`w-3.5 h-3.5`})])]),a(`div`,C,[a(`div`,null,[n[5]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Trigger `,-1),a(`span`,w,m(J.value.trigger||r(`—`)),1)]),a(`div`,null,[n[6]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Total duration `,-1),a(`div`,T,m(J.value.total_duration_ms)+`ms `,1)]),a(`div`,null,[n[7]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Spans `,-1),a(`div`,E,m(J.value.span_count),1)]),a(`div`,null,[n[9]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Status `,-1),a(`div`,D,[c(g,{status:J.value.status},null,8,[`status`]),J.value.has_outlier?(e(),o(`span`,O,[c(r(h),{class:`w-3 h-3`}),n[8]||=d(` Outlier `,-1)])):p(``,!0)])])])]),a(`div`,k,[n[11]||=a(`div`,{class:`text-xs text-foreground-muted uppercase tracking-wide mb-4`},` Waterfall `,-1),a(`div`,A,[(e(!0),o(f,null,l(J.value.spans,(t,c)=>(e(),o(f,{key:t.span_id||`s${c}`},[a(`div`,{class:`grid grid-cols-12 gap-2 items-center text-xs hover:bg-surface/40 px-2 py-1.5 rounded cursor-pointer transition-colors`,onClick:e=>$(t)},[a(`div`,M,[a(`span`,N,m(t.function_name||t.function_id),1),a(`span`,P,m(t.trigger||r(`—`)),1),t.status===`error`?(e(),u(r(ne),{key:0,class:`w-3 h-3 shrink-0 text-danger-fg`,"aria-label":`error`})):p(``,!0),t.is_outlier?(e(),u(r(h),{key:1,class:`w-3 h-3 shrink-0 text-warning-fg`,"aria-label":`outlier`})):p(``,!0)]),a(`div`,F,[a(`div`,{class:s([`absolute h-2 top-1 rounded-sm`,Oe(t)]),style:i(De(t)),title:`+${t.offset_ms}ms · ${t.duration_ms}ms`},null,14,I)]),a(`div`,L,[a(`span`,R,m(t.duration_ms)+`ms`,1),t.baseline_p95_ms?(e(),o(`span`,z,` p95 `+m(t.baseline_p95_ms)+`ms `,1)):p(``,!0)])],8,j),(e(!0),o(f,null,l(Q(t),t=>(e(),o(`div`,{key:`us-${t.id}`,class:`grid grid-cols-12 gap-2 items-center text-xs hover:bg-surface/40 px-2 py-1 rounded transition-colors`},[a(`div`,B,[n[10]||=a(`span`,{class:`text-foreground-muted text-[10px]`},`└`,-1),a(`span`,V,m(t.name),1),t.status===`error`?(e(),o(`span`,H,` error `)):p(``,!0)]),a(`div`,U,[a(`div`,{class:`absolute h-1.5 top-1 rounded-sm bg-accent-muted/70`,style:i(ke(t)),title:`+${t.offset_ms}ms · ${t.duration_ms}ms`},null,12,W)]),a(`div`,G,m(t.duration_ms)+`ms `,1)]))),128))],64))),128))])]),J.value.log_entries&&J.value.log_entries.length?(e(),o(`div`,K,[a(`div`,ce,` Logs (`+m(J.value.log_entries.length)+`) `,1),a(`div`,le,[(e(!0),o(f,null,l(J.value.log_entries,t=>(e(),o(`div`,{key:`log-${t.id}`,class:s([`flex items-baseline gap-2 px-2 py-1 rounded hover:bg-surface/40 transition-colors`,je(t)])},[a(`span`,ue,m(Me(t.ts)),1),a(`span`,{class:s([`text-[10px] uppercase tracking-wide`,Ae(t.level)])},m(t.level),3),a(`span`,de,m(t.message),1),t.fields?(e(),o(`code`,fe,m(t.fields),1)):p(``,!0)],2))),128))])])):p(``,!0),a(`div`,pe,[a(`table`,me,[n[12]||=a(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[a(`tr`,null,[a(`th`,{class:`px-4 py-3 w-32`},` Span `),a(`th`,{class:`px-4 py-3`},` Function `),a(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Trigger `),a(`th`,{class:`px-4 py-3 w-24 text-right`},` Offset `),a(`th`,{class:`px-4 py-3 w-24 text-right`},` Duration `),a(`th`,{class:`px-4 py-3 w-24`},` Status `)])],-1),a(`tbody`,he,[(e(!0),o(f,null,l(J.value.spans,t=>(e(),o(`tr`,{key:`tbl-${t.span_id}`,class:`hover:bg-surface/40 cursor-pointer transition-colors`,onClick:e=>$(t)},[a(`td`,_e,m(t.span_id?.slice(0,11)||r(`—`)),1),a(`td`,ve,m(t.function_name||t.function_id),1),a(`td`,ye,[a(`span`,be,m(t.trigger||r(`—`)),1)]),a(`td`,xe,` +`+m(t.offset_ms)+`ms `,1),a(`td`,Se,m(t.duration_ms)+`ms `,1),a(`td`,Ce,[c(g,{status:t.status},null,8,[`status`])])],8,ge))),128))])])])],64)):p(``,!0)]))}};export{we as default}; \ No newline at end of file +import{D as e,G as t,T as n,Z as r,_t as i,c as a,d as o,gt as s,h as c,k as l,l as u,m as d,r as f,s as ee,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./arrow-left-DTH7GseC.js";import{t as ne}from"./circle-alert-CwieDBHo.js";import{t as re}from"./copy-3UAsea5P.js";import{t as h}from"./flag-C__IsWHC.js";import{O as ie,mt as ae,pt as oe}from"./index-pE9wnfTb.js";import{t as g}from"./StatusBadge-BpEw6z9Z.js";var se={class:`space-y-6`},_={class:`flex items-start justify-between gap-4`},v={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},y={key:1,class:`text-xs text-foreground-muted italic`},b={class:`bg-background border border-border rounded-lg p-5 space-y-4`},x={class:`flex items-center gap-3 flex-wrap text-xs`},S={class:`bg-surface text-white px-2 py-0.5 rounded font-mono`},C={class:`grid grid-cols-2 sm:grid-cols-4 gap-4 pt-3 border-t border-border text-xs`},w={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},T={class:`text-white font-mono`},E={class:`text-white`},D={class:`flex items-center gap-2`},O={key:0,class:`inline-flex items-center gap-1 text-[10px] uppercase tracking-wide text-warning-fg`},k={class:`bg-background border border-border rounded-lg p-5`},A={class:`space-y-1.5`},j=[`onClick`],M={class:`col-span-3 truncate flex items-center gap-1.5`},N={class:`text-white`},P={class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] border bg-background font-mono text-foreground-muted border-border lowercase`},F={class:`col-span-7 relative h-4`},I=[`title`],L={class:`col-span-2 text-right font-mono`},R={class:`text-white`},z={key:0,class:`block text-[10px] text-foreground-muted`},B={class:`col-span-3 truncate flex items-center gap-1.5 pl-5`},V={class:`text-foreground-muted`},H={key:0,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] bg-danger-tint text-danger-fg border border-danger-ring`},U={class:`col-span-7 relative h-3`},W=[`title`],G={class:`col-span-2 text-right font-mono text-foreground-muted`},K={key:0,class:`bg-background border border-border rounded-lg p-5`},ce={class:`text-xs text-foreground-muted uppercase tracking-wide mb-3`},le={class:`space-y-1 font-mono text-xs`},ue={class:`text-foreground-muted text-[10px] tabular-nums`},de={class:`text-white truncate`},fe={key:0,class:`text-[10px] text-foreground-muted truncate`},pe={class:`bg-background border border-border rounded-lg overflow-x-auto`},me={class:`w-full text-sm text-left`},he={class:`divide-y divide-border`},ge=[`onClick`],_e={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},ve={class:`px-4 py-2.5 text-white`},ye={class:`px-4 py-2.5 hidden md:table-cell`},be={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},xe={class:`px-4 py-2.5 text-right font-mono text-xs text-foreground-muted`},Se={class:`px-4 py-2.5 text-right font-mono text-xs text-white`},Ce={class:`px-4 py-2.5`},we={__name:`TraceDetail`,setup(we){let Te=oe(),q=ae(),J=t(null),Y=t(!1),X=t(``),Ee=async()=>{Y.value=!0,X.value=``;try{let e=await ie(Te.params.id);J.value=e.data}catch(e){e?.response?.status===404?X.value=`No spans found for that trace.`:X.value=e?.response?.data?.error?.message||e?.message||`failed to load trace`}finally{Y.value=!1}},Z=ee(()=>Math.max(1,J.value?.total_duration_ms||1)),De=e=>{let t=e.offset_ms/Z.value*100,n=Math.max(.5,e.duration_ms/Z.value*100);return{left:`${t}%`,width:`${n}%`}},Oe=e=>e.status===`error`?`bg-danger/70`:e.is_outlier?`bg-warning/80`:`bg-primary/80`,Q=e=>!J.value?.user_spans||!e?.span_id?[]:J.value.user_spans.filter(t=>t.parent_span_id===e.span_id).sort((e,t)=>(e.offset_ms||0)-(t.offset_ms||0)),ke=e=>{let t=(e.offset_ms||0)/Z.value*100,n=Math.max(.5,(e.duration_ms||0)/Z.value*100);return{left:`${t}%`,width:`${n}%`}},Ae=e=>{switch(e){case`error`:return`text-danger-fg`;case`warn`:return`text-warning-fg`;case`debug`:return`text-foreground-muted`;default:return`text-primary-light`}},je=e=>e.level===`error`?`bg-danger-tint`:``,Me=e=>{if(!e)return``;try{let t=new Date(e);return t.toLocaleTimeString(void 0,{hour12:!1})+`.`+String(t.getMilliseconds()).padStart(3,`0`)}catch{return e}},$=e=>{e.execution_id&&q.push({path:`/invocations`,query:{exec:e.execution_id}})},Ne=async()=>{if(J.value?.trace_id)try{await navigator.clipboard.writeText(J.value.trace_id)}catch{}};return n(Ee),(t,n)=>(e(),o(`div`,se,[a(`div`,_,[a(`div`,null,[a(`button`,{class:`inline-flex items-center gap-1 text-xs text-foreground-muted hover:text-white mb-1 transition-colors`,onClick:n[0]||=e=>r(q).push(`/traces`)},[c(r(te),{class:`w-3.5 h-3.5`}),n[1]||=d(` All traces `,-1)]),n[2]||=a(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Trace `,-1),n[3]||=a(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Spans in this invocation chain. `,-1)])]),X.value?(e(),o(`div`,v,m(X.value),1)):Y.value&&!J.value?(e(),o(`div`,y,` Loading trace… `)):J.value?(e(),o(f,{key:2},[a(`div`,b,[a(`div`,x,[n[4]||=a(`span`,{class:`text-foreground-muted uppercase tracking-wide`},` trace id `,-1),a(`code`,S,m(J.value.trace_id),1),a(`button`,{class:`p-1 rounded hover:bg-surface text-foreground-muted hover:text-white transition-colors`,title:`Copy trace id`,"aria-label":`Copy trace ID`,onClick:Ne},[c(r(re),{class:`w-3.5 h-3.5`})])]),a(`div`,C,[a(`div`,null,[n[5]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Trigger `,-1),a(`span`,w,m(J.value.trigger||r(`—`)),1)]),a(`div`,null,[n[6]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Total duration `,-1),a(`div`,T,m(J.value.total_duration_ms)+`ms `,1)]),a(`div`,null,[n[7]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Spans `,-1),a(`div`,E,m(J.value.span_count),1)]),a(`div`,null,[n[9]||=a(`div`,{class:`text-foreground-muted uppercase tracking-wide mb-1`},` Status `,-1),a(`div`,D,[c(g,{status:J.value.status},null,8,[`status`]),J.value.has_outlier?(e(),o(`span`,O,[c(r(h),{class:`w-3 h-3`}),n[8]||=d(` Outlier `,-1)])):p(``,!0)])])])]),a(`div`,k,[n[11]||=a(`div`,{class:`text-xs text-foreground-muted uppercase tracking-wide mb-4`},` Waterfall `,-1),a(`div`,A,[(e(!0),o(f,null,l(J.value.spans,(t,c)=>(e(),o(f,{key:t.span_id||`s${c}`},[a(`div`,{class:`grid grid-cols-12 gap-2 items-center text-xs hover:bg-surface/40 px-2 py-1.5 rounded cursor-pointer transition-colors`,onClick:e=>$(t)},[a(`div`,M,[a(`span`,N,m(t.function_name||t.function_id),1),a(`span`,P,m(t.trigger||r(`—`)),1),t.status===`error`?(e(),u(r(ne),{key:0,class:`w-3 h-3 shrink-0 text-danger-fg`,"aria-label":`error`})):p(``,!0),t.is_outlier?(e(),u(r(h),{key:1,class:`w-3 h-3 shrink-0 text-warning-fg`,"aria-label":`outlier`})):p(``,!0)]),a(`div`,F,[a(`div`,{class:s([`absolute h-2 top-1 rounded-sm`,Oe(t)]),style:i(De(t)),title:`+${t.offset_ms}ms · ${t.duration_ms}ms`},null,14,I)]),a(`div`,L,[a(`span`,R,m(t.duration_ms)+`ms`,1),t.baseline_p95_ms?(e(),o(`span`,z,` p95 `+m(t.baseline_p95_ms)+`ms `,1)):p(``,!0)])],8,j),(e(!0),o(f,null,l(Q(t),t=>(e(),o(`div`,{key:`us-${t.id}`,class:`grid grid-cols-12 gap-2 items-center text-xs hover:bg-surface/40 px-2 py-1 rounded transition-colors`},[a(`div`,B,[n[10]||=a(`span`,{class:`text-foreground-muted text-[10px]`},`└`,-1),a(`span`,V,m(t.name),1),t.status===`error`?(e(),o(`span`,H,` error `)):p(``,!0)]),a(`div`,U,[a(`div`,{class:`absolute h-1.5 top-1 rounded-sm bg-accent-muted/70`,style:i(ke(t)),title:`+${t.offset_ms}ms · ${t.duration_ms}ms`},null,12,W)]),a(`div`,G,m(t.duration_ms)+`ms `,1)]))),128))],64))),128))])]),J.value.log_entries&&J.value.log_entries.length?(e(),o(`div`,K,[a(`div`,ce,` Logs (`+m(J.value.log_entries.length)+`) `,1),a(`div`,le,[(e(!0),o(f,null,l(J.value.log_entries,t=>(e(),o(`div`,{key:`log-${t.id}`,class:s([`flex items-baseline gap-2 px-2 py-1 rounded hover:bg-surface/40 transition-colors`,je(t)])},[a(`span`,ue,m(Me(t.ts)),1),a(`span`,{class:s([`text-[10px] uppercase tracking-wide`,Ae(t.level)])},m(t.level),3),a(`span`,de,m(t.message),1),t.fields?(e(),o(`code`,fe,m(t.fields),1)):p(``,!0)],2))),128))])])):p(``,!0),a(`div`,pe,[a(`table`,me,[n[12]||=a(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[a(`tr`,null,[a(`th`,{class:`px-4 py-3 w-32`},` Span `),a(`th`,{class:`px-4 py-3`},` Function `),a(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Trigger `),a(`th`,{class:`px-4 py-3 w-24 text-right`},` Offset `),a(`th`,{class:`px-4 py-3 w-24 text-right`},` Duration `),a(`th`,{class:`px-4 py-3 w-24`},` Status `)])],-1),a(`tbody`,he,[(e(!0),o(f,null,l(J.value.spans,t=>(e(),o(`tr`,{key:`tbl-${t.span_id}`,class:`hover:bg-surface/40 cursor-pointer transition-colors`,onClick:e=>$(t)},[a(`td`,_e,m(t.span_id?.slice(0,11)||r(`—`)),1),a(`td`,ve,m(t.function_name||t.function_id),1),a(`td`,ye,[a(`span`,be,m(t.trigger||r(`—`)),1)]),a(`td`,xe,` +`+m(t.offset_ms)+`ms `,1),a(`td`,Se,m(t.duration_ms)+`ms `,1),a(`td`,Ce,[c(g,{status:t.status},null,8,[`status`])])],8,ge))),128))])])])],64)):p(``,!0)]))}};export{we as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Traces-BEuuXgIG.js b/backend/internal/server/ui_dist/assets/Traces-BoBh7dBt.js similarity index 95% rename from backend/internal/server/ui_dist/assets/Traces-BEuuXgIG.js rename to backend/internal/server/ui_dist/assets/Traces-BoBh7dBt.js index 6f3e4f46..68a2ddcd 100644 --- a/backend/internal/server/ui_dist/assets/Traces-BEuuXgIG.js +++ b/backend/internal/server/ui_dist/assets/Traces-BoBh7dBt.js @@ -1 +1 @@ -import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,k as l,l as u,m as d,r as f,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as h}from"./flag-CmjNKmxi.js";import{t as g}from"./refresh-cw-Cn8qkf-v.js";import{K as _,Lt as v,_t as y,mt as b,wt as x,xt as S,zt as C}from"./index-DTqMKlE1.js";import{t as ee}from"./StatusBadge-Baoe7YAb.js";var te={class:`space-y-6`},w={class:`flex items-start justify-between gap-4`},T={class:`flex flex-col sm:flex-row sm:items-center gap-2 sm:flex-wrap`},E={class:`relative w-full sm:flex-1 sm:min-w-[260px] sm:max-w-[420px]`},D={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0`},O={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},k={key:1,class:`bg-background border border-border rounded-lg p-8 text-center text-sm text-foreground-muted`},A={key:2,class:`bg-background border border-border rounded-lg overflow-x-auto`},j={class:`w-full text-sm text-left`},M={class:`divide-y divide-border`},N=[`onClick`],P={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted whitespace-nowrap`},F={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},I={class:`px-4 py-2.5 text-white`},L={class:`px-4 py-2.5 hidden md:table-cell`},R={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},z={class:`px-4 py-2.5 text-right font-mono text-xs text-foreground-muted hidden sm:table-cell`},ne={class:`px-4 py-2.5`},B={class:`px-4 py-2.5 text-right`},V={key:3,class:`flex justify-center`},H=Object.assign({name:`TracesView`},{__name:`Traces`,setup(H){let U=b(),W=n([]),G=n(!1),K=n(``),q=n(``),J=n(``),Y=n(``),X=n(!1),Z=[{value:``,label:`All`},{value:`success`,label:`Success`},{value:`error`,label:`Errors`}],Q=async({append:e=!1}={})=>{G.value=!0,K.value=``;try{let t={limit:50};J.value&&(t.function_id=J.value),Y.value&&(t.status=Y.value),X.value&&(t.outlier_only=`1`),e&&q.value&&(t.before=q.value);let n=await _(t),r=n.data?.traces||[];e?W.value.push(...r):W.value=r,q.value=n.data?.next_cursor||``}catch(e){K.value=e?.response?.data?.error?.message||e?.message||`failed to load traces`}finally{G.value=!1}},$=()=>{q.value=``,Q()},re=()=>Q({append:!0}),ie=e=>{Y.value=e,$()},ae=()=>{X.value=!X.value,$()},oe=e=>U.push(`/traces/${e}`),se=e=>e?new Date(e).toLocaleTimeString(void 0,{hour12:!1}):`—`;return i($),(n,i)=>(e(),s(`div`,te,[o(`div`,w,[i[2]||=o(`div`,null,[o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Traces `),o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Invocation chains across functions and triggers. `)],-1),c(y,{variant:`secondary`,size:`sm`,loading:G.value,onClick:$},{default:t(()=>[c(a(g),{class:`w-3.5 h-3.5`}),i[1]||=d(` Refresh `,-1)]),_:1},8,[`loading`])]),o(`div`,T,[o(`div`,E,[c(a(S),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),r(o(`input`,{"onUpdate:modelValue":i[0]||=e=>J.value=e,placeholder:`Filter by function id or name…`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-base sm:text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:border-white`,onKeydown:C($,[`enter`])},null,544),[[v,J.value]])]),o(`div`,D,[(e(),s(f,null,l(Z,e=>c(y,{key:e.value,variant:`chip`,size:`xs`,active:Y.value===e.value,class:`shrink-0 snap-start`,onClick:t=>ie(e.value)},{default:t(()=>[d(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64)),i[4]||=o(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),c(y,{variant:`chip`,size:`xs`,active:X.value,class:`shrink-0 snap-start`,onClick:ae},{default:t(()=>[c(a(h),{class:`w-3 h-3`}),i[3]||=d(` Outliers only `,-1)]),_:1},8,[`active`])])]),K.value?(e(),s(`div`,O,m(K.value),1)):!W.value.length&&!G.value?(e(),s(`div`,k,[c(a(x),{class:`w-6 h-6 mx-auto mb-3 text-foreground-muted/50`}),i[5]||=o(`p`,null,`No traces yet.`,-1),i[6]||=o(`p`,{class:`text-xs mt-1 text-foreground-muted/60`},` HTTP and scheduled invocations appear here. `,-1)])):(e(),s(`div`,A,[o(`table`,j,[i[7]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-4 py-3 w-32`},` Time `),o(`th`,{class:`px-4 py-3 w-40`},` Trace `),o(`th`,{class:`px-4 py-3`},` Root function `),o(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Trigger `),o(`th`,{class:`px-4 py-3 w-24 text-right hidden sm:table-cell`},` Duration `),o(`th`,{class:`px-4 py-3 w-24`},` Status `),o(`th`,{class:`px-4 py-3 w-10`})])],-1),o(`tbody`,M,[(e(!0),s(f,null,l(W.value,t=>(e(),s(`tr`,{key:t.trace_id,class:`hover:bg-surface/40 cursor-pointer transition-colors`,onClick:e=>oe(t.trace_id)},[o(`td`,P,m(se(t.started_at)),1),o(`td`,F,m(t.trace_id.slice(0,11)),1),o(`td`,I,m(t.function_name||t.root_function_id),1),o(`td`,L,[o(`span`,R,m(t.trigger||a(`—`)),1)]),o(`td`,z,m(t.duration_ms==null?a(`—`):`${t.duration_ms}ms`),1),o(`td`,ne,[c(ee,{status:t.status},null,8,[`status`])]),o(`td`,B,[t.is_outlier?(e(),u(a(h),{key:0,class:`w-3.5 h-3.5 text-amber-400 inline`,title:`Latency outlier vs P95 baseline`})):p(``,!0)])],8,N))),128))])])])),q.value?(e(),s(`div`,V,[c(y,{variant:`ghost`,size:`sm`,onClick:re},{default:t(()=>[...i[8]||=[d(` Load more `,-1)]]),_:1})])):p(``,!0)]))}});export{H as default}; \ No newline at end of file +import{D as e,F as t,G as n,I as r,T as i,Z as a,c as o,d as s,h as c,k as l,l as u,m as d,r as f,u as p,vt as m}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as h}from"./flag-C__IsWHC.js";import{t as g}from"./refresh-cw-CEfUzOcv.js";import{K as _,Lt as v,_t as y,mt as b,wt as x,xt as S,zt as C}from"./index-pE9wnfTb.js";import{t as ee}from"./StatusBadge-BpEw6z9Z.js";var te={class:`space-y-6`},w={class:`flex items-start justify-between gap-4`},T={class:`flex flex-col sm:flex-row sm:items-center gap-2 sm:flex-wrap`},E={class:`relative w-full sm:flex-1 sm:min-w-[260px] sm:max-w-[420px]`},D={class:`flex items-center gap-2 sm:flex-wrap overflow-x-auto sm:overflow-visible scrollable snap-x min-w-0`},O={key:0,class:`rounded-md border border-danger-ring bg-danger-tint p-3 text-xs text-danger-fg`},k={key:1,class:`bg-background border border-border rounded-lg p-8 text-center text-sm text-foreground-muted`},A={key:2,class:`bg-background border border-border rounded-lg overflow-x-auto`},j={class:`w-full text-sm text-left`},M={class:`divide-y divide-border`},N=[`onClick`],P={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted whitespace-nowrap`},F={class:`px-4 py-2.5 font-mono text-xs text-foreground-muted`},I={class:`px-4 py-2.5 text-white`},L={class:`px-4 py-2.5 hidden md:table-cell`},R={class:`inline-flex items-center px-2 py-0.5 rounded text-xs border bg-background font-mono text-foreground-muted border-border lowercase`},z={class:`px-4 py-2.5 text-right font-mono text-xs text-foreground-muted hidden sm:table-cell`},ne={class:`px-4 py-2.5`},B={class:`px-4 py-2.5 text-right`},V={key:3,class:`flex justify-center`},H=Object.assign({name:`TracesView`},{__name:`Traces`,setup(H){let U=b(),W=n([]),G=n(!1),K=n(``),q=n(``),J=n(``),Y=n(``),X=n(!1),Z=[{value:``,label:`All`},{value:`success`,label:`Success`},{value:`error`,label:`Errors`}],Q=async({append:e=!1}={})=>{G.value=!0,K.value=``;try{let t={limit:50};J.value&&(t.function_id=J.value),Y.value&&(t.status=Y.value),X.value&&(t.outlier_only=`1`),e&&q.value&&(t.before=q.value);let n=await _(t),r=n.data?.traces||[];e?W.value.push(...r):W.value=r,q.value=n.data?.next_cursor||``}catch(e){K.value=e?.response?.data?.error?.message||e?.message||`failed to load traces`}finally{G.value=!1}},$=()=>{q.value=``,Q()},re=()=>Q({append:!0}),ie=e=>{Y.value=e,$()},ae=()=>{X.value=!X.value,$()},oe=e=>U.push(`/traces/${e}`),se=e=>e?new Date(e).toLocaleTimeString(void 0,{hour12:!1}):`—`;return i($),(n,i)=>(e(),s(`div`,te,[o(`div`,w,[i[2]||=o(`div`,null,[o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Traces `),o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Invocation chains across functions and triggers. `)],-1),c(y,{variant:`secondary`,size:`sm`,loading:G.value,onClick:$},{default:t(()=>[c(a(g),{class:`w-3.5 h-3.5`}),i[1]||=d(` Refresh `,-1)]),_:1},8,[`loading`])]),o(`div`,T,[o(`div`,E,[c(a(S),{class:`w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-foreground-muted/60 pointer-events-none`}),r(o(`input`,{"onUpdate:modelValue":i[0]||=e=>J.value=e,placeholder:`Filter by function id or name…`,class:`w-full bg-background border border-border rounded-md pl-8 pr-3 py-1.5 text-base sm:text-xs text-foreground placeholder-foreground-muted/60 focus:outline-none focus:border-white`,onKeydown:C($,[`enter`])},null,544),[[v,J.value]])]),o(`div`,D,[(e(),s(f,null,l(Z,e=>c(y,{key:e.value,variant:`chip`,size:`xs`,active:Y.value===e.value,class:`shrink-0 snap-start`,onClick:t=>ie(e.value)},{default:t(()=>[d(m(e.label),1)]),_:2},1032,[`active`,`onClick`])),64)),i[4]||=o(`span`,{class:`text-foreground-muted/40 shrink-0`},`·`,-1),c(y,{variant:`chip`,size:`xs`,active:X.value,class:`shrink-0 snap-start`,onClick:ae},{default:t(()=>[c(a(h),{class:`w-3 h-3`}),i[3]||=d(` Outliers only `,-1)]),_:1},8,[`active`])])]),K.value?(e(),s(`div`,O,m(K.value),1)):!W.value.length&&!G.value?(e(),s(`div`,k,[c(a(x),{class:`w-6 h-6 mx-auto mb-3 text-foreground-muted/50`}),i[5]||=o(`p`,null,`No traces yet.`,-1),i[6]||=o(`p`,{class:`text-xs mt-1 text-foreground-muted/60`},` HTTP and scheduled invocations appear here. `,-1)])):(e(),s(`div`,A,[o(`table`,j,[i[7]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-4 py-3 w-32`},` Time `),o(`th`,{class:`px-4 py-3 w-40`},` Trace `),o(`th`,{class:`px-4 py-3`},` Root function `),o(`th`,{class:`px-4 py-3 w-28 hidden md:table-cell`},` Trigger `),o(`th`,{class:`px-4 py-3 w-24 text-right hidden sm:table-cell`},` Duration `),o(`th`,{class:`px-4 py-3 w-24`},` Status `),o(`th`,{class:`px-4 py-3 w-10`})])],-1),o(`tbody`,M,[(e(!0),s(f,null,l(W.value,t=>(e(),s(`tr`,{key:t.trace_id,class:`hover:bg-surface/40 cursor-pointer transition-colors`,onClick:e=>oe(t.trace_id)},[o(`td`,P,m(se(t.started_at)),1),o(`td`,F,m(t.trace_id.slice(0,11)),1),o(`td`,I,m(t.function_name||t.root_function_id),1),o(`td`,L,[o(`span`,R,m(t.trigger||a(`—`)),1)]),o(`td`,z,m(t.duration_ms==null?a(`—`):`${t.duration_ms}ms`),1),o(`td`,ne,[c(ee,{status:t.status},null,8,[`status`])]),o(`td`,B,[t.is_outlier?(e(),u(a(h),{key:0,class:`w-3.5 h-3.5 text-amber-400 inline`,title:`Latency outlier vs P95 baseline`})):p(``,!0)])],8,N))),128))])])])),q.value?(e(),s(`div`,V,[c(y,{variant:`ghost`,size:`sm`,onClick:re},{default:t(()=>[...i[8]||=[d(` Load more `,-1)]]),_:1})])):p(``,!0)]))}});export{H as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/Webhooks-D2CkyonR.js b/backend/internal/server/ui_dist/assets/Webhooks-BHh3seUT.js similarity index 97% rename from backend/internal/server/ui_dist/assets/Webhooks-D2CkyonR.js rename to backend/internal/server/ui_dist/assets/Webhooks-BHh3seUT.js index fa311c56..7ac7024a 100644 --- a/backend/internal/server/ui_dist/assets/Webhooks-D2CkyonR.js +++ b/backend/internal/server/ui_dist/assets/Webhooks-BHh3seUT.js @@ -1 +1 @@ -import{C as e,D as t,F as n,G as r,I as i,T as ee,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./check-BNre7JFR.js";import{t as ne}from"./copy-BqdwwcxC.js";import{t as re}from"./rotate-ccw-DWwjKCqh.js";import{t as ie}from"./square-pen-DCrjAsLy.js";import{t as ae}from"./trash-2-DaeYqnW_.js";import{t as oe}from"./zap-BXGoxm_a.js";import{Bt as _,J as se,Lt as v,Nt as ce,St as le,Z as ue,_t as y,gt as de,it as fe,jt as pe,q as me,st as he,u as ge,v as _e,vt as ve}from"./index-DTqMKlE1.js";import{t as b}from"./clipboard-D_9N0yai.js";import{t as x}from"./IconButton-CsCZOqWo.js";import{t as S}from"./Modal-BAoZams6.js";var C=pe(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]),w={class:`space-y-4`},T={class:`flex items-center justify-between gap-4 flex-wrap`},E={class:`bg-background border border-border rounded-lg overflow-x-auto`},D={class:`w-full text-sm text-left`},O={class:`divide-y divide-border`},k=[`onClick`],A={class:`px-4 py-3 font-medium text-white`},j={class:`flex flex-col`},M={class:`text-xs text-foreground-muted font-mono`},N={class:`px-4 py-3 text-xs text-foreground-muted truncate max-w-xs hidden md:table-cell`},P={class:`px-4 py-3 hidden sm:table-cell`},F={class:`flex flex-wrap gap-1`},ye={class:`px-4 py-3`},be={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},xe={class:`inline-flex items-center gap-1`},Se={key:0},Ce={key:0,class:`space-y-4`},we={class:`flex flex-wrap gap-1.5`},Te={class:`flex items-center gap-2 pt-1`},Ee={key:1,class:`space-y-3`},De={class:`flex items-center gap-2 text-success-fg`},Oe={class:`bg-background border border-border rounded p-3 font-mono text-xs break-all flex items-center gap-2`},ke={class:`flex-1 text-foreground`},Ae={class:`bg-background border-l border-border w-full max-w-2xl h-full overflow-y-auto`},je={class:`border-b border-border px-6 py-4 flex items-center justify-between bg-surface sticky top-0`},Me={class:`min-w-0`},Ne={class:`text-base font-semibold text-foreground truncate`},Pe={class:`text-xs text-foreground-muted font-mono truncate`},Fe={class:`p-4 space-y-2`},Ie={key:0,class:`text-center text-foreground-muted text-sm py-12`},I={class:`flex items-center justify-between gap-2 flex-wrap`},Le={class:`text-xs font-mono text-foreground`},Re={class:`flex items-center justify-between text-xs text-foreground-muted gap-2 flex-wrap`},ze={class:`font-mono`},Be={class:`flex items-center justify-between text-xs text-foreground-muted gap-2 flex-wrap`},Ve={key:0},He=[`title`],L=Object.assign({name:`WebhooksView`},{__name:`Webhooks`,setup(pe){let L=de(),Ue=[{value:`*`},{value:`deployment.succeeded`},{value:`deployment.failed`},{value:`function.created`},{value:`function.updated`},{value:`function.deleted`},{value:`execution.error`},{value:`cron.failed`},{value:`job.succeeded`},{value:`job.failed`}],R=r([]),z=r(!1),B=r(null),V=r(!1),H=r(``),U=r(!1),W=r({name:``,url:``,events:[`*`],enabled:!0}),G=r(null),K=r([]),q=null,J=m(()=>W.value.name.trim()&&W.value.url.trim()&&W.value.events.length>0),We=e=>!e.events||e.events.length===0?[`*`]:e.events.length>3?[...e.events.slice(0,2),`+${e.events.length-2}`]:e.events,Ge=e=>e.enabled?e.last_status===`failed`?`bg-danger-tint text-danger-fg border-danger-ring`:e.last_status===`ok`?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`:`bg-warning-tint text-warning-fg border-warning-ring`,Ke=e=>e.enabled?e.last_status===`failed`?`bg-danger-fg`:e.last_status===`ok`?`bg-success-fg`:`bg-warning-fg`:`bg-warning-fg`,qe=e=>e.enabled?e.last_status===`failed`?`failing`:e.last_status===`ok`?`healthy`:`pending first delivery`:`paused`,Je=e=>{switch(e){case`pending`:return`bg-warning-tint text-warning-fg border-warning-ring`;case`running`:return`bg-info-tint text-info-fg border-info-ring`;case`succeeded`:return`bg-success-tint text-success-fg border-success-ring`;case`failed`:return`bg-danger-tint text-danger-fg border-danger-ring`;default:return`bg-surface text-foreground-muted border-border`}},Y=e=>e?new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}):`—`,X=async()=>{try{let e=await se();R.value=e.data.subscriptions||[]}catch(e){console.error(`Failed to load webhooks`,e)}},Ye=()=>{B.value=null,W.value={name:``,url:``,events:[`*`],enabled:!0},H.value=``,U.value=!1,z.value=!0},Xe=e=>{B.value=e.id,W.value={name:e.name,url:e.url,events:[...e.events||[`*`]],enabled:e.enabled},H.value=``,z.value=!0},Z=()=>{z.value=!1,B.value=null,H.value=``},Ze=e=>{let t=W.value.events.indexOf(e);t>=0?W.value.events.splice(t,1):W.value.events.push(e)},Qe=async()=>{if(!(!J.value||V.value)){V.value=!0;try{if(B.value)await he(B.value,{name:W.value.name.trim(),url:W.value.url.trim(),events:W.value.events,enabled:W.value.enabled}),await X(),Z();else{let e=await ge({name:W.value.name.trim(),url:W.value.url.trim(),events:W.value.events,enabled:W.value.enabled});H.value=e.data.secret,await X()}}catch(e){L.notify({title:`Failed to save webhook`,message:e?.response?.data?.error?.message||e.message,danger:!0})}finally{V.value=!1}}},$e=async()=>{await b(H.value)&&(U.value=!0,setTimeout(()=>{U.value=!1},1500))},et=async e=>{if(await L.ask({title:`Delete "${e.name}"?`,message:`Future events will not fire to this URL. Existing deliveries will be removed too.`,confirmLabel:`Delete`,danger:!0}))try{await _e(e.id),await X()}catch(e){L.notify({title:`Delete failed`,message:e.message,danger:!0})}},tt=async e=>{try{await fe(e.id),L.notify({title:`Test event queued`,message:`Will deliver to ${e.url} within 5s. Open the row to watch the delivery.`})}catch(e){L.notify({title:`Test failed`,message:e.message,danger:!0})}},nt=async e=>{G.value=e,await Q(e.id),q=setInterval(()=>Q(e.id),4e3)},Q=async e=>{try{let t=await me(e);K.value=t.data.deliveries||[]}catch(e){console.error(`Failed to load deliveries`,e)}},$=()=>{G.value=null,K.value=[],q&&clearInterval(q),q=null},rt=async e=>{try{await ue(e.id),G.value&&await Q(G.value.id)}catch(e){L.notify({title:`Retry failed`,message:e.message,danger:!0})}};return ee(()=>X()),e(()=>{q&&clearInterval(q)}),(e,r)=>(t(),s(`div`,w,[o(`div`,T,[r[6]||=o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Webhooks `,-1),l(y,{onClick:Ye},{default:n(()=>[l(a(le),{class:`w-4 h-4`}),r[5]||=f(` New webhook `,-1)]),_:1})]),r[21]||=o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Send signed system events to external URLs. `,-1),o(`div`,E,[o(`table`,D,[r[8]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-4 py-3 font-medium`},` Name `),o(`th`,{class:`px-4 py-3 font-medium hidden md:table-cell`},` URL `),o(`th`,{class:`px-4 py-3 font-medium hidden sm:table-cell`},` Events `),o(`th`,{class:`px-4 py-3 font-medium`},` Status `),o(`th`,{class:`px-4 py-3 font-medium hidden lg:table-cell`},` Last delivery `),o(`th`,{class:`px-4 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,O,[(t(!0),s(p,null,u(R.value,e=>(t(),s(`tr`,{key:e.id,class:`hover:bg-surface/40 transition-colors cursor-pointer`,onClick:t=>nt(e)},[o(`td`,A,[o(`div`,j,[o(`span`,null,g(e.name),1),o(`span`,M,g(e.id),1)])]),o(`td`,N,g(e.url),1),o(`td`,P,[o(`div`,F,[(t(!0),s(p,null,u(We(e),e=>(t(),s(`span`,{key:e,class:`inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-surface border border-border text-foreground font-mono`},g(e),1))),128))])]),o(`td`,ye,[o(`span`,{class:c([`inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs font-medium border`,Ge(e)])},[o(`span`,{class:c([`w-1.5 h-1.5 rounded-full`,Ke(e)])},null,2),f(` `+g(qe(e)),1)],2)]),o(`td`,be,g(e.last_delivery_at?Y(e.last_delivery_at):a(`—`)),1),o(`td`,{class:`px-4 py-3 text-right`,onClick:r[0]||=_(()=>{},[`stop`])},[o(`div`,xe,[l(x,{icon:a(oe),title:`Send test event`,onClick:t=>tt(e)},null,8,[`icon`,`onClick`]),l(x,{icon:a(ie),title:`Edit`,onClick:t=>Xe(e)},null,8,[`icon`,`onClick`]),l(x,{icon:a(ae),variant:`danger`,title:`Delete`,onClick:t=>et(e)},null,8,[`icon`,`onClick`])])])],8,k))),128)),R.value.length===0?(t(),s(`tr`,Se,[...r[7]||=[o(`td`,{colspan:`6`,class:`px-4 py-12 text-center`},[o(`p`,{class:`text-foreground-muted text-sm`},` No webhooks yet. `),o(`p`,{class:`text-foreground-muted text-xs mt-1`},` Add an endpoint to receive signed system events. `)],-1)]])):h(``,!0)])])]),l(S,{"model-value":z.value,title:B.value?`Edit webhook`:`New webhook`,size:`lg`,"onUpdate:modelValue":r[4]||=e=>e?null:Z()},{footer:n(()=>[H.value?h(``,!0):(t(),d(y,{key:0,variant:`ghost`,onClick:Z},{default:n(()=>[...r[17]||=[f(` Cancel `,-1)]]),_:1})),H.value?(t(),d(y,{key:2,onClick:Z},{default:n(()=>[...r[18]||=[f(` Done `,-1)]]),_:1})):(t(),d(y,{key:1,disabled:!J.value||V.value,onClick:Qe},{default:n(()=>[f(g(V.value?`Saving…`:B.value?`Save`:`Create`),1)]),_:1},8,[`disabled`]))]),default:n(()=>[H.value?(t(),s(`div`,Ee,[o(`div`,De,[l(a(C),{class:`w-5 h-5`}),r[15]||=o(`span`,{class:`text-sm font-medium`},`Webhook created`,-1)]),r[16]||=o(`p`,{class:`text-xs text-foreground-muted`},[f(` Copy this secret `),o(`span`,{class:`text-foreground font-medium`},`now`),f(`. It won't be shown again. `)],-1),o(`div`,Oe,[o(`code`,ke,g(H.value),1),l(x,{icon:U.value?a(te):a(ne),title:U.value?`Copied`:`Copy secret`,onClick:$e},null,8,[`icon`,`title`])])])):(t(),s(`div`,Ce,[o(`div`,null,[r[9]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Name`,-1),i(o(`input`,{"onUpdate:modelValue":r[1]||=e=>W.value.name=e,placeholder:`ops-slack`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[v,W.value.name]])]),o(`div`,null,[r[10]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Receiver URL`,-1),i(o(`input`,{"onUpdate:modelValue":r[2]||=e=>W.value.url=e,placeholder:`https://hooks.slack.com/services/...`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[v,W.value.url]]),r[11]||=o(`p`,{class:`text-xs text-foreground-muted mt-1.5`},` The receiver must respond 2xx within 15s. Failed deliveries retry up to 5× with exponential backoff. `,-1)]),o(`div`,null,[r[12]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Events`,-1),o(`div`,we,[(t(),s(p,null,u(Ue,e=>l(y,{key:e.value,variant:`chip`,size:`xs`,active:W.value.events.includes(e.value),class:`font-mono`,onClick:t=>Ze(e.value)},{default:n(()=>[f(g(e.value),1)]),_:2},1032,[`active`,`onClick`])),64))]),r[13]||=o(`p`,{class:`text-xs text-foreground-muted mt-1.5`},[f(` Pick `),o(`code`,{class:`font-mono`},`*`),f(` to receive every event. Each badge above is one of the 8 system events that can fire today. `)],-1)]),o(`div`,Te,[i(o(`input`,{id:`enabled`,"onUpdate:modelValue":r[3]||=e=>W.value.enabled=e,type:`checkbox`,class:`w-4 h-4 rounded border-border bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`},null,512),[[ce,W.value.enabled]]),r[14]||=o(`label`,{for:`enabled`,class:`text-sm text-foreground`},`Enabled`,-1)])]))]),_:1},8,[`model-value`,`title`]),G.value?(t(),s(`div`,{key:0,class:`fixed inset-0 bg-black/60 backdrop-blur-sm flex justify-end z-50`,onClick:_($,[`self`])},[o(`div`,Ae,[o(`div`,je,[o(`div`,Me,[o(`h2`,Ne,` Deliveries · `+g(G.value.name),1),o(`p`,Pe,g(G.value.id),1)]),l(x,{icon:a(ve),title:`Close`,onClick:$},null,8,[`icon`])]),o(`div`,Fe,[K.value.length?h(``,!0):(t(),s(`div`,Ie,[...r[19]||=[f(` No deliveries yet. Trigger a system event or use `,-1),o(`span`,{class:`text-foreground`},`Send test event`,-1),f(` to seed one. `,-1)]])),(t(!0),s(p,null,u(K.value,e=>(t(),s(`div`,{key:e.id,class:`bg-surface border border-border rounded p-3 space-y-1.5`},[o(`div`,I,[o(`code`,Le,g(e.event_name),1),o(`span`,{class:c([`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border`,Je(e.status)])},g(e.status),3)]),o(`div`,Re,[o(`span`,ze,g(e.id),1),o(`span`,null,g(Y(e.created_at)),1)]),o(`div`,Be,[o(`span`,null,`attempts `+g(e.attempts)+` / `+g(e.max_attempts),1),e.response_status?(t(),s(`span`,Ve,`HTTP `+g(e.response_status),1)):h(``,!0)]),e.last_error?(t(),s(`p`,{key:0,class:`text-xs text-danger-fg truncate`,title:e.last_error},g(e.last_error),9,He)):h(``,!0),e.status===`failed`?(t(),d(y,{key:1,size:`xs`,variant:`ghost`,onClick:t=>rt(e)},{default:n(()=>[l(a(re),{class:`w-3.5 h-3.5`}),r[20]||=f(` Retry `,-1)]),_:1},8,[`onClick`])):h(``,!0)]))),128))])])])):h(``,!0)]))}});export{L as default}; \ No newline at end of file +import{C as e,D as t,F as n,G as r,I as i,T as ee,Z as a,c as o,d as s,gt as c,h as l,k as u,l as d,m as f,r as p,s as m,u as h,vt as g}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{t as te}from"./check-CZmR72iA.js";import{t as ne}from"./copy-3UAsea5P.js";import{t as re}from"./rotate-ccw-DgujV-4F.js";import{t as ie}from"./square-pen-Ctkj2Y_N.js";import{t as ae}from"./trash-2-Cz9PSE2q.js";import{t as oe}from"./zap-BF0H8u1s.js";import{Bt as _,J as se,Lt as v,Nt as ce,St as le,Z as ue,_t as y,gt as de,it as fe,jt as pe,q as me,st as he,u as ge,v as _e,vt as ve}from"./index-pE9wnfTb.js";import{t as b}from"./clipboard-D_9N0yai.js";import{t as x}from"./IconButton-CsCZOqWo.js";import{t as S}from"./Modal-C1IBLm0r.js";var C=pe(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]),w={class:`space-y-4`},T={class:`flex items-center justify-between gap-4 flex-wrap`},E={class:`bg-background border border-border rounded-lg overflow-x-auto`},D={class:`w-full text-sm text-left`},O={class:`divide-y divide-border`},k=[`onClick`],A={class:`px-4 py-3 font-medium text-white`},j={class:`flex flex-col`},M={class:`text-xs text-foreground-muted font-mono`},N={class:`px-4 py-3 text-xs text-foreground-muted truncate max-w-xs hidden md:table-cell`},P={class:`px-4 py-3 hidden sm:table-cell`},F={class:`flex flex-wrap gap-1`},ye={class:`px-4 py-3`},be={class:`px-4 py-3 text-foreground-muted text-xs hidden lg:table-cell`},xe={class:`inline-flex items-center gap-1`},Se={key:0},Ce={key:0,class:`space-y-4`},we={class:`flex flex-wrap gap-1.5`},Te={class:`flex items-center gap-2 pt-1`},Ee={key:1,class:`space-y-3`},De={class:`flex items-center gap-2 text-success-fg`},Oe={class:`bg-background border border-border rounded p-3 font-mono text-xs break-all flex items-center gap-2`},ke={class:`flex-1 text-foreground`},Ae={class:`bg-background border-l border-border w-full max-w-2xl h-full overflow-y-auto`},je={class:`border-b border-border px-6 py-4 flex items-center justify-between bg-surface sticky top-0`},Me={class:`min-w-0`},Ne={class:`text-base font-semibold text-foreground truncate`},Pe={class:`text-xs text-foreground-muted font-mono truncate`},Fe={class:`p-4 space-y-2`},Ie={key:0,class:`text-center text-foreground-muted text-sm py-12`},I={class:`flex items-center justify-between gap-2 flex-wrap`},Le={class:`text-xs font-mono text-foreground`},Re={class:`flex items-center justify-between text-xs text-foreground-muted gap-2 flex-wrap`},ze={class:`font-mono`},Be={class:`flex items-center justify-between text-xs text-foreground-muted gap-2 flex-wrap`},Ve={key:0},He=[`title`],L=Object.assign({name:`WebhooksView`},{__name:`Webhooks`,setup(pe){let L=de(),Ue=[{value:`*`},{value:`deployment.succeeded`},{value:`deployment.failed`},{value:`function.created`},{value:`function.updated`},{value:`function.deleted`},{value:`execution.error`},{value:`cron.failed`},{value:`job.succeeded`},{value:`job.failed`}],R=r([]),z=r(!1),B=r(null),V=r(!1),H=r(``),U=r(!1),W=r({name:``,url:``,events:[`*`],enabled:!0}),G=r(null),K=r([]),q=null,J=m(()=>W.value.name.trim()&&W.value.url.trim()&&W.value.events.length>0),We=e=>!e.events||e.events.length===0?[`*`]:e.events.length>3?[...e.events.slice(0,2),`+${e.events.length-2}`]:e.events,Ge=e=>e.enabled?e.last_status===`failed`?`bg-danger-tint text-danger-fg border-danger-ring`:e.last_status===`ok`?`bg-success-tint text-success-fg border-success-ring`:`bg-warning-tint text-warning-fg border-warning-ring`:`bg-warning-tint text-warning-fg border-warning-ring`,Ke=e=>e.enabled?e.last_status===`failed`?`bg-danger-fg`:e.last_status===`ok`?`bg-success-fg`:`bg-warning-fg`:`bg-warning-fg`,qe=e=>e.enabled?e.last_status===`failed`?`failing`:e.last_status===`ok`?`healthy`:`pending first delivery`:`paused`,Je=e=>{switch(e){case`pending`:return`bg-warning-tint text-warning-fg border-warning-ring`;case`running`:return`bg-info-tint text-info-fg border-info-ring`;case`succeeded`:return`bg-success-tint text-success-fg border-success-ring`;case`failed`:return`bg-danger-tint text-danger-fg border-danger-ring`;default:return`bg-surface text-foreground-muted border-border`}},Y=e=>e?new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}):`—`,X=async()=>{try{let e=await se();R.value=e.data.subscriptions||[]}catch(e){console.error(`Failed to load webhooks`,e)}},Ye=()=>{B.value=null,W.value={name:``,url:``,events:[`*`],enabled:!0},H.value=``,U.value=!1,z.value=!0},Xe=e=>{B.value=e.id,W.value={name:e.name,url:e.url,events:[...e.events||[`*`]],enabled:e.enabled},H.value=``,z.value=!0},Z=()=>{z.value=!1,B.value=null,H.value=``},Ze=e=>{let t=W.value.events.indexOf(e);t>=0?W.value.events.splice(t,1):W.value.events.push(e)},Qe=async()=>{if(!(!J.value||V.value)){V.value=!0;try{if(B.value)await he(B.value,{name:W.value.name.trim(),url:W.value.url.trim(),events:W.value.events,enabled:W.value.enabled}),await X(),Z();else{let e=await ge({name:W.value.name.trim(),url:W.value.url.trim(),events:W.value.events,enabled:W.value.enabled});H.value=e.data.secret,await X()}}catch(e){L.notify({title:`Failed to save webhook`,message:e?.response?.data?.error?.message||e.message,danger:!0})}finally{V.value=!1}}},$e=async()=>{await b(H.value)&&(U.value=!0,setTimeout(()=>{U.value=!1},1500))},et=async e=>{if(await L.ask({title:`Delete "${e.name}"?`,message:`Future events will not fire to this URL. Existing deliveries will be removed too.`,confirmLabel:`Delete`,danger:!0}))try{await _e(e.id),await X()}catch(e){L.notify({title:`Delete failed`,message:e.message,danger:!0})}},tt=async e=>{try{await fe(e.id),L.notify({title:`Test event queued`,message:`Will deliver to ${e.url} within 5s. Open the row to watch the delivery.`})}catch(e){L.notify({title:`Test failed`,message:e.message,danger:!0})}},nt=async e=>{G.value=e,await Q(e.id),q=setInterval(()=>Q(e.id),4e3)},Q=async e=>{try{let t=await me(e);K.value=t.data.deliveries||[]}catch(e){console.error(`Failed to load deliveries`,e)}},$=()=>{G.value=null,K.value=[],q&&clearInterval(q),q=null},rt=async e=>{try{await ue(e.id),G.value&&await Q(G.value.id)}catch(e){L.notify({title:`Retry failed`,message:e.message,danger:!0})}};return ee(()=>X()),e(()=>{q&&clearInterval(q)}),(e,r)=>(t(),s(`div`,w,[o(`div`,T,[r[6]||=o(`h1`,{class:`text-xl font-semibold text-white tracking-tight`},` Webhooks `,-1),l(y,{onClick:Ye},{default:n(()=>[l(a(le),{class:`w-4 h-4`}),r[5]||=f(` New webhook `,-1)]),_:1})]),r[21]||=o(`p`,{class:`text-sm text-foreground-muted mt-1.5 max-w-prose leading-body`},` Send signed system events to external URLs. `,-1),o(`div`,E,[o(`table`,D,[r[8]||=o(`thead`,{class:`text-xs text-foreground-muted uppercase bg-surface border-b border-border`},[o(`tr`,null,[o(`th`,{class:`px-4 py-3 font-medium`},` Name `),o(`th`,{class:`px-4 py-3 font-medium hidden md:table-cell`},` URL `),o(`th`,{class:`px-4 py-3 font-medium hidden sm:table-cell`},` Events `),o(`th`,{class:`px-4 py-3 font-medium`},` Status `),o(`th`,{class:`px-4 py-3 font-medium hidden lg:table-cell`},` Last delivery `),o(`th`,{class:`px-4 py-3 font-medium text-right`},` Actions `)])],-1),o(`tbody`,O,[(t(!0),s(p,null,u(R.value,e=>(t(),s(`tr`,{key:e.id,class:`hover:bg-surface/40 transition-colors cursor-pointer`,onClick:t=>nt(e)},[o(`td`,A,[o(`div`,j,[o(`span`,null,g(e.name),1),o(`span`,M,g(e.id),1)])]),o(`td`,N,g(e.url),1),o(`td`,P,[o(`div`,F,[(t(!0),s(p,null,u(We(e),e=>(t(),s(`span`,{key:e,class:`inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-surface border border-border text-foreground font-mono`},g(e),1))),128))])]),o(`td`,ye,[o(`span`,{class:c([`inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs font-medium border`,Ge(e)])},[o(`span`,{class:c([`w-1.5 h-1.5 rounded-full`,Ke(e)])},null,2),f(` `+g(qe(e)),1)],2)]),o(`td`,be,g(e.last_delivery_at?Y(e.last_delivery_at):a(`—`)),1),o(`td`,{class:`px-4 py-3 text-right`,onClick:r[0]||=_(()=>{},[`stop`])},[o(`div`,xe,[l(x,{icon:a(oe),title:`Send test event`,onClick:t=>tt(e)},null,8,[`icon`,`onClick`]),l(x,{icon:a(ie),title:`Edit`,onClick:t=>Xe(e)},null,8,[`icon`,`onClick`]),l(x,{icon:a(ae),variant:`danger`,title:`Delete`,onClick:t=>et(e)},null,8,[`icon`,`onClick`])])])],8,k))),128)),R.value.length===0?(t(),s(`tr`,Se,[...r[7]||=[o(`td`,{colspan:`6`,class:`px-4 py-12 text-center`},[o(`p`,{class:`text-foreground-muted text-sm`},` No webhooks yet. `),o(`p`,{class:`text-foreground-muted text-xs mt-1`},` Add an endpoint to receive signed system events. `)],-1)]])):h(``,!0)])])]),l(S,{"model-value":z.value,title:B.value?`Edit webhook`:`New webhook`,size:`lg`,"onUpdate:modelValue":r[4]||=e=>e?null:Z()},{footer:n(()=>[H.value?h(``,!0):(t(),d(y,{key:0,variant:`ghost`,onClick:Z},{default:n(()=>[...r[17]||=[f(` Cancel `,-1)]]),_:1})),H.value?(t(),d(y,{key:2,onClick:Z},{default:n(()=>[...r[18]||=[f(` Done `,-1)]]),_:1})):(t(),d(y,{key:1,disabled:!J.value||V.value,onClick:Qe},{default:n(()=>[f(g(V.value?`Saving…`:B.value?`Save`:`Create`),1)]),_:1},8,[`disabled`]))]),default:n(()=>[H.value?(t(),s(`div`,Ee,[o(`div`,De,[l(a(C),{class:`w-5 h-5`}),r[15]||=o(`span`,{class:`text-sm font-medium`},`Webhook created`,-1)]),r[16]||=o(`p`,{class:`text-xs text-foreground-muted`},[f(` Copy this secret `),o(`span`,{class:`text-foreground font-medium`},`now`),f(`. It won't be shown again. `)],-1),o(`div`,Oe,[o(`code`,ke,g(H.value),1),l(x,{icon:U.value?a(te):a(ne),title:U.value?`Copied`:`Copy secret`,onClick:$e},null,8,[`icon`,`title`])])])):(t(),s(`div`,Ce,[o(`div`,null,[r[9]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Name`,-1),i(o(`input`,{"onUpdate:modelValue":r[1]||=e=>W.value.name=e,placeholder:`ops-slack`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[v,W.value.name]])]),o(`div`,null,[r[10]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Receiver URL`,-1),i(o(`input`,{"onUpdate:modelValue":r[2]||=e=>W.value.url=e,placeholder:`https://hooks.slack.com/services/...`,class:`w-full bg-background border border-border rounded-md px-3 py-2 text-sm text-foreground font-mono focus:outline-none focus:ring-1 focus:ring-white focus:border-white`},null,512),[[v,W.value.url]]),r[11]||=o(`p`,{class:`text-xs text-foreground-muted mt-1.5`},` The receiver must respond 2xx within 15s. Failed deliveries retry up to 5× with exponential backoff. `,-1)]),o(`div`,null,[r[12]||=o(`label`,{class:`text-xs font-medium text-foreground-muted uppercase tracking-wide block mb-1.5`},`Events`,-1),o(`div`,we,[(t(),s(p,null,u(Ue,e=>l(y,{key:e.value,variant:`chip`,size:`xs`,active:W.value.events.includes(e.value),class:`font-mono`,onClick:t=>Ze(e.value)},{default:n(()=>[f(g(e.value),1)]),_:2},1032,[`active`,`onClick`])),64))]),r[13]||=o(`p`,{class:`text-xs text-foreground-muted mt-1.5`},[f(` Pick `),o(`code`,{class:`font-mono`},`*`),f(` to receive every event. Each badge above is one of the 8 system events that can fire today. `)],-1)]),o(`div`,Te,[i(o(`input`,{id:`enabled`,"onUpdate:modelValue":r[3]||=e=>W.value.enabled=e,type:`checkbox`,class:`w-4 h-4 rounded border-border bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background`},null,512),[[ce,W.value.enabled]]),r[14]||=o(`label`,{for:`enabled`,class:`text-sm text-foreground`},`Enabled`,-1)])]))]),_:1},8,[`model-value`,`title`]),G.value?(t(),s(`div`,{key:0,class:`fixed inset-0 bg-black/60 backdrop-blur-sm flex justify-end z-50`,onClick:_($,[`self`])},[o(`div`,Ae,[o(`div`,je,[o(`div`,Me,[o(`h2`,Ne,` Deliveries · `+g(G.value.name),1),o(`p`,Pe,g(G.value.id),1)]),l(x,{icon:a(ve),title:`Close`,onClick:$},null,8,[`icon`])]),o(`div`,Fe,[K.value.length?h(``,!0):(t(),s(`div`,Ie,[...r[19]||=[f(` No deliveries yet. Trigger a system event or use `,-1),o(`span`,{class:`text-foreground`},`Send test event`,-1),f(` to seed one. `,-1)]])),(t(!0),s(p,null,u(K.value,e=>(t(),s(`div`,{key:e.id,class:`bg-surface border border-border rounded p-3 space-y-1.5`},[o(`div`,I,[o(`code`,Le,g(e.event_name),1),o(`span`,{class:c([`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border`,Je(e.status)])},g(e.status),3)]),o(`div`,Re,[o(`span`,ze,g(e.id),1),o(`span`,null,g(Y(e.created_at)),1)]),o(`div`,Be,[o(`span`,null,`attempts `+g(e.attempts)+` / `+g(e.max_attempts),1),e.response_status?(t(),s(`span`,Ve,`HTTP `+g(e.response_status),1)):h(``,!0)]),e.last_error?(t(),s(`p`,{key:0,class:`text-xs text-danger-fg truncate`,title:e.last_error},g(e.last_error),9,He)):h(``,!0),e.status===`failed`?(t(),d(y,{key:1,size:`xs`,variant:`ghost`,onClick:t=>rt(e)},{default:n(()=>[l(a(re),{class:`w-3.5 h-3.5`}),r[20]||=f(` Retry `,-1)]),_:1},8,[`onClick`])):h(``,!0)]))),128))])])])):h(``,!0)]))}});export{L as default}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/arrow-left-Ba3OArNt.js b/backend/internal/server/ui_dist/assets/arrow-left-DTH7GseC.js similarity index 58% rename from backend/internal/server/ui_dist/assets/arrow-left-Ba3OArNt.js rename to backend/internal/server/ui_dist/assets/arrow-left-DTH7GseC.js index 24aa1139..08d16e6c 100644 --- a/backend/internal/server/ui_dist/assets/arrow-left-Ba3OArNt.js +++ b/backend/internal/server/ui_dist/assets/arrow-left-DTH7GseC.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/book-open-B7-cMpW6.js b/backend/internal/server/ui_dist/assets/book-open-DQ3Rz8Ui.js similarity index 77% rename from backend/internal/server/ui_dist/assets/book-open-B7-cMpW6.js rename to backend/internal/server/ui_dist/assets/book-open-DQ3Rz8Ui.js index 3d9e9c35..94504840 100644 --- a/backend/internal/server/ui_dist/assets/book-open-B7-cMpW6.js +++ b/backend/internal/server/ui_dist/assets/book-open-DQ3Rz8Ui.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`book-open`,[[`path`,{d:`M12 5v16`,key:`1f6ucr`}],[`path`,{d:`M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z`,key:`1fyvmf`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`book-open`,[[`path`,{d:`M12 5v16`,key:`1f6ucr`}],[`path`,{d:`M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z`,key:`1fyvmf`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/check-BNre7JFR.js b/backend/internal/server/ui_dist/assets/check-BNre7JFR.js deleted file mode 100644 index f8728d08..00000000 --- a/backend/internal/server/ui_dist/assets/check-BNre7JFR.js +++ /dev/null @@ -1 +0,0 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/check-CZmR72iA.js b/backend/internal/server/ui_dist/assets/check-CZmR72iA.js new file mode 100644 index 00000000..83122ed7 --- /dev/null +++ b/backend/internal/server/ui_dist/assets/check-CZmR72iA.js @@ -0,0 +1 @@ +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/chevron-right-CRxFsA9Y.js b/backend/internal/server/ui_dist/assets/chevron-right-CRxFsA9Y.js deleted file mode 100644 index 67dc0945..00000000 --- a/backend/internal/server/ui_dist/assets/chevron-right-CRxFsA9Y.js +++ /dev/null @@ -1 +0,0 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/chevron-right-D5C5fM5p.js b/backend/internal/server/ui_dist/assets/chevron-right-D5C5fM5p.js new file mode 100644 index 00000000..3167deab --- /dev/null +++ b/backend/internal/server/ui_dist/assets/chevron-right-D5C5fM5p.js @@ -0,0 +1 @@ +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/circle-NOse79gh.js b/backend/internal/server/ui_dist/assets/circle-DhZmtdqu.js similarity index 76% rename from backend/internal/server/ui_dist/assets/circle-NOse79gh.js rename to backend/internal/server/ui_dist/assets/circle-DhZmtdqu.js index d2d9343f..d0a14f42 100644 --- a/backend/internal/server/ui_dist/assets/circle-NOse79gh.js +++ b/backend/internal/server/ui_dist/assets/circle-DhZmtdqu.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),n=e(`circle`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]);export{t as n,n as t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),n=e(`circle`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]);export{t as n,n as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/circle-alert-BnUYYhGE.js b/backend/internal/server/ui_dist/assets/circle-alert-CwieDBHo.js similarity index 73% rename from backend/internal/server/ui_dist/assets/circle-alert-BnUYYhGE.js rename to backend/internal/server/ui_dist/assets/circle-alert-CwieDBHo.js index d3cff568..d6969cc5 100644 --- a/backend/internal/server/ui_dist/assets/circle-alert-BnUYYhGE.js +++ b/backend/internal/server/ui_dist/assets/circle-alert-CwieDBHo.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`circle-alert`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`circle-alert`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/clock-CiH8bQVI.js b/backend/internal/server/ui_dist/assets/clock-CIjbNepe.js similarity index 77% rename from backend/internal/server/ui_dist/assets/clock-CiH8bQVI.js rename to backend/internal/server/ui_dist/assets/clock-CIjbNepe.js index 02257288..d860b96c 100644 --- a/backend/internal/server/ui_dist/assets/clock-CiH8bQVI.js +++ b/backend/internal/server/ui_dist/assets/clock-CIjbNepe.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`circle-check`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),n=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]);export{t as n,n as t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`circle-check`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),n=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]);export{t as n,n as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/copy-BqdwwcxC.js b/backend/internal/server/ui_dist/assets/copy-3UAsea5P.js similarity index 71% rename from backend/internal/server/ui_dist/assets/copy-BqdwwcxC.js rename to backend/internal/server/ui_dist/assets/copy-3UAsea5P.js index b017db8e..ea9b61db 100644 --- a/backend/internal/server/ui_dist/assets/copy-BqdwwcxC.js +++ b/backend/internal/server/ui_dist/assets/copy-3UAsea5P.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`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`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`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`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/flag-CmjNKmxi.js b/backend/internal/server/ui_dist/assets/flag-C__IsWHC.js similarity index 73% rename from backend/internal/server/ui_dist/assets/flag-CmjNKmxi.js rename to backend/internal/server/ui_dist/assets/flag-C__IsWHC.js index ade93ef8..dc5dfd3d 100644 --- a/backend/internal/server/ui_dist/assets/flag-CmjNKmxi.js +++ b/backend/internal/server/ui_dist/assets/flag-C__IsWHC.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`flag`,[[`path`,{d:`M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528`,key:`1jaruq`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`flag`,[[`path`,{d:`M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528`,key:`1jaruq`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/git-compare-Co883xFS.js b/backend/internal/server/ui_dist/assets/git-compare-BnvFSVmQ.js similarity index 86% rename from backend/internal/server/ui_dist/assets/git-compare-Co883xFS.js rename to backend/internal/server/ui_dist/assets/git-compare-BnvFSVmQ.js index 0e35728a..081e918f 100644 --- a/backend/internal/server/ui_dist/assets/git-compare-Co883xFS.js +++ b/backend/internal/server/ui_dist/assets/git-compare-BnvFSVmQ.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`cloud-upload`,[[`path`,{d:`M12 13v8`,key:`1l5pq0`}],[`path`,{d:`M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242`,key:`1pljnt`}],[`path`,{d:`m8 17 4-4 4 4`,key:`1quai1`}]]),n=e(`git-compare`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M13 6h3a2 2 0 0 1 2 2v7`,key:`1yeb86`}],[`path`,{d:`M11 18H8a2 2 0 0 1-2-2V9`,key:`19pyzm`}]]);export{t as n,n as t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`cloud-upload`,[[`path`,{d:`M12 13v8`,key:`1l5pq0`}],[`path`,{d:`M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242`,key:`1pljnt`}],[`path`,{d:`m8 17 4-4 4 4`,key:`1quai1`}]]),n=e(`git-compare`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M13 6h3a2 2 0 0 1 2 2v7`,key:`1yeb86`}],[`path`,{d:`M11 18H8a2 2 0 0 1-2-2V9`,key:`19pyzm`}]]);export{t as n,n as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/globe-BnBar2lO.js b/backend/internal/server/ui_dist/assets/globe-DJC2u-h_.js similarity index 72% rename from backend/internal/server/ui_dist/assets/globe-BnBar2lO.js rename to backend/internal/server/ui_dist/assets/globe-DJC2u-h_.js index e97950fc..fd84486c 100644 --- a/backend/internal/server/ui_dist/assets/globe-BnBar2lO.js +++ b/backend/internal/server/ui_dist/assets/globe-DJC2u-h_.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/index-DTqMKlE1.js b/backend/internal/server/ui_dist/assets/index-pE9wnfTb.js similarity index 87% rename from backend/internal/server/ui_dist/assets/index-DTqMKlE1.js rename to backend/internal/server/ui_dist/assets/index-pE9wnfTb.js index 46916ad8..6133d6ce 100644 --- a/backend/internal/server/ui_dist/assets/index-DTqMKlE1.js +++ b/backend/internal/server/ui_dist/assets/index-pE9wnfTb.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Login-DscOTSMy.js","assets/runtime-core.esm-bundler-BMQPyJ_W.js","assets/circle-alert-BnUYYhGE.js","assets/Onboarding-CI9ktN7I.js","assets/copy-BqdwwcxC.js","assets/Dashboard-rKNyCP0W.js","assets/AI-De72Ye8u.js","assets/axios-DVDuIpRy.js","assets/check-BNre7JFR.js","assets/ModelMenu-BtMjUXcx.js","assets/pinia-B41TZNUX.js","assets/client-BF51V3uE.js","assets/Drawer-B98TBytl.js","assets/Drawer-9hPWZO7g.css","assets/pencil-Do2I7soU.js","assets/rotate-ccw-DWwjKCqh.js","assets/sparkles-DTHEIS5T.js","assets/trash-2-DaeYqnW_.js","assets/zap-BXGoxm_a.js","assets/github-dark-D7LxIVih.js","assets/github-dark-C8LL_u4z.css","assets/clipboard-D_9N0yai.js","assets/AI-DWprRWt2.css","assets/FunctionsList-CPOzZCfJ.js","assets/globe-BnBar2lO.js","assets/lock-CttMBTH5.js","assets/refresh-cw-Cn8qkf-v.js","assets/IconButton-CsCZOqWo.js","assets/Editor-C_JYWteY.js","assets/book-open-B7-cMpW6.js","assets/git-compare-Co883xFS.js","assets/settings-2-D5QtFfdZ.js","assets/key-round-BKXtbC85.js","assets/play-CmQifd74.js","assets/shield-check-piXkOtNv.js","assets/terminal-BQdlNiyt.js","assets/variable-DrK2KZuk.js","assets/Modal-BAoZams6.js","assets/rollbackDiff-DsaWcdbl.js","assets/aiPrompts-XrsFCpj_.js","assets/Input-DQ-tWGkn.js","assets/Editor-4XWCDeWw.css","assets/Deployments-CRPgafhC.js","assets/clock-CiH8bQVI.js","assets/StatusBadge-Baoe7YAb.js","assets/circle-NOse79gh.js","assets/FunctionDiff-DtVzmfsl.js","assets/dist-CR15Grce.js","assets/FunctionDiff-C-FH-cay.css","assets/KVStore-DzgumyT2.js","assets/InboundWebhooks-CFOyt9ev.js","assets/CronJobs-CDFaee6D.js","assets/square-pen-DCrjAsLy.js","assets/Jobs-CfHJpgrS.js","assets/Activity-6I8QCc07.js","assets/chevron-right-CRxFsA9Y.js","assets/InvocationsLog-Bz2zpa_f.js","assets/Traces-BEuuXgIG.js","assets/flag-CmjNKmxi.js","assets/TraceDetail-wVyyYiTv.js","assets/arrow-left-Ba3OArNt.js","assets/ApiKeys-B5PU7HpA.js","assets/time-D8OmbYzY.js","assets/Channels-fKQl2oE8.js","assets/Webhooks-D2CkyonR.js","assets/Firewall-Bpe5shll.js","assets/Firewall-Cdy796t2.css","assets/Settings-Bjj6gg_h.js","assets/Docs-BssSTQCS.js","assets/Docs-D8AUJ3IN.css","assets/NotFound-b7MSgvru.js"])))=>i.map(i=>d[i]); -import{t as e}from"./axios-DVDuIpRy.js";import{$ as t,A as n,D as r,E as i,F as a,G as o,I as s,K as c,M as l,O as u,P as d,Q as f,T as p,U as m,W as h,Z as g,_,a as v,at as y,b,c as x,ct as S,d as C,dt as w,et as T,f as E,ft as D,gt as O,h as k,ht as A,i as ee,it as j,j as te,k as M,l as N,lt as ne,m as re,mt as ie,n as ae,nt as oe,o as se,ot as ce,pt as P,q as le,r as F,rt as ue,s as I,st as de,t as fe,tt as pe,u as L,ut as me,v as he,vt as R,x as z,yt as ge}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as _e,t as ve}from"./pinia-B41TZNUX.js";import{n as ye,t as B}from"./client-BF51V3uE.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),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var be=void 0,xe=typeof window<`u`&&window.trustedTypes;if(xe)try{be=xe.createPolicy(`vue`,{createHTML:e=>e})}catch{}var Se=be?e=>be.createHTML(e):e=>e,Ce=`http://www.w3.org/2000/svg`,we=`http://www.w3.org/1998/Math/MathML`,V=typeof document<`u`?document:null,Te=V&&V.createElement(`template`),Ee={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{let t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{let i=t===`svg`?V.createElementNS(Ce,e):t===`mathml`?V.createElementNS(we,e):n?V.createElement(e,{is:n}):V.createElement(e);return e===`select`&&r&&r.multiple!=null&&i.setAttribute(`multiple`,r.multiple),i},createText:e=>V.createTextNode(e),createComment:e=>V.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>V.querySelector(e),setScopeId(e,t){e.setAttribute(t,``)},insertStaticContent(e,t,n,r,i,a){let o=n?n.previousSibling:t.lastChild;if(i&&(i===a||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),n),!(i===a||!(i=i.nextSibling)););else{Te.innerHTML=Se(r===`svg`?`${e}`:r===`mathml`?`${e}`:e);let i=Te.content;if(r===`svg`||r===`mathml`){let e=i.firstChild;for(;e.firstChild;)i.appendChild(e.firstChild);i.removeChild(e)}t.insertBefore(i,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},H=`transition`,De=`animation`,Oe=Symbol(`_vtc`),ke={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Ae=T({},ae,ke),je=(e=>(e.displayName=`Transition`,e.props=Ae,e))((e,{slots:t})=>he(fe,Pe(e),t)),Me=(e,t=[])=>{j(e)?e.forEach(e=>e(...t)):e&&e(...t)},Ne=e=>e?j(e)?e.some(e=>e.length>1):e.length>1:!1;function Pe(e){let t={};for(let n in e)n in ke||(t[n]=e[n]);if(e.css===!1)return t;let{name:n=`v`,type:r,duration:i,enterFromClass:a=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:s=`${n}-enter-to`,appearFromClass:c=a,appearActiveClass:l=o,appearToClass:u=s,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:f=`${n}-leave-active`,leaveToClass:p=`${n}-leave-to`}=e,m=Fe(i),h=m&&m[0],g=m&&m[1],{onBeforeEnter:_,onEnter:v,onEnterCancelled:y,onLeave:b,onLeaveCancelled:x,onBeforeAppear:S=_,onAppear:C=v,onAppearCancelled:w=y}=t,E=(e,t,n,r)=>{e._enterCancelled=r,Le(e,t?u:s),Le(e,t?l:o),n&&n()},D=(e,t)=>{e._isLeaving=!1,Le(e,d),Le(e,p),Le(e,f),t&&t()},O=e=>(t,n)=>{let i=e?C:v,o=()=>E(t,e,n);Me(i,[t,o]),Re(()=>{Le(t,e?c:a),U(t,e?u:s),Ne(i)||Be(t,r,h,o)})};return T(t,{onBeforeEnter(e){Me(_,[e]),U(e,a),U(e,o)},onBeforeAppear(e){Me(S,[e]),U(e,c),U(e,l)},onEnter:O(!1),onAppear:O(!0),onLeave(e,t){e._isLeaving=!0;let n=()=>D(e,t);U(e,d),e._enterCancelled?(U(e,f),We(e)):(We(e),U(e,f)),Re(()=>{e._isLeaving&&(Le(e,d),U(e,p),Ne(b)||Be(e,r,g,n))}),Me(b,[e,n])},onEnterCancelled(e){E(e,!1,void 0,!0),Me(y,[e])},onAppearCancelled(e){E(e,!0,void 0,!0),Me(w,[e])},onLeaveCancelled(e){D(e),Me(x,[e])}})}function Fe(e){if(e==null)return null;if(de(e))return[Ie(e.enter),Ie(e.leave)];{let t=Ie(e);return[t,t]}}function Ie(e){return ge(e)}function U(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.add(t)),(e[Oe]||(e[Oe]=new Set)).add(t)}function Le(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.remove(t));let n=e[Oe];n&&(n.delete(t),n.size||(e[Oe]=void 0))}function Re(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}var ze=0;function Be(e,t,n,r){let i=e._endId=++ze,a=()=>{i===e._endId&&r()};if(n!=null)return setTimeout(a,n);let{type:o,timeout:s,propCount:c}=Ve(e,t);if(!o)return r();let l=o+`end`,u=0,d=()=>{e.removeEventListener(l,f),a()},f=t=>{t.target===e&&++u>=c&&d()};setTimeout(()=>{u(n[e]||``).split(`, `),i=r(`${H}Delay`),a=r(`${H}Duration`),o=He(i,a),s=r(`${De}Delay`),c=r(`${De}Duration`),l=He(s,c),u=null,d=0,f=0;t===H?o>0&&(u=H,d=o,f=a.length):t===De?l>0&&(u=De,d=l,f=c.length):(d=Math.max(o,l),u=d>0?o>l?H:De:null,f=u?u===H?a.length:c.length:0);let p=u===H&&/\b(?:transform|all)(?:,|$)/.test(r(`${H}Property`).toString());return{type:u,timeout:d,propCount:f,hasTransform:p}}function He(e,t){for(;e.lengthUe(t)+Ue(e[n])))}function Ue(e){return e===`auto`?0:Number(e.slice(0,-1).replace(`,`,`.`))*1e3}function We(e){return(e?e.ownerDocument:document).body.offsetHeight}function Ge(e,t,n){let r=e[Oe];r&&(t=(t?[t,...r]:[...r]).join(` `)),t==null?e.removeAttribute(`class`):n?e.setAttribute(`class`,t):e.className=t}var Ke=Symbol(`_vod`),qe=Symbol(`_vsh`),Je={name:`show`,beforeMount(e,{value:t},{transition:n}){e[Ke]=e.style.display===`none`?``:e.style.display,n&&t?n.beforeEnter(e):Ye(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Ye(e,!0),r.enter(e)):r.leave(e,()=>{Ye(e,!1)}):Ye(e,t))},beforeUnmount(e,{value:t}){Ye(e,t)}};function Ye(e,t){e.style.display=t?e[Ke]:`none`,e[qe]=!t}var Xe=Symbol(``),Ze=/(?:^|;)\s*display\s*:/;function Qe(e,t,n){let r=e.style,i=w(n),a=!1;if(n&&!i){if(t)if(w(t))for(let e of t.split(`;`)){let t=e.slice(0,e.indexOf(`:`)).trim();n[t]??et(r,t,``)}else for(let e in t)n[e]??et(r,e,``);for(let i in n){i===`display`&&(a=!0);let o=n[i];o==null?et(r,i,``):it(e,i,!w(t)&&t?t[i]:void 0,o)||et(r,i,o)}}else if(i){if(t!==n){let e=r[Xe];e&&(n+=`;`+e),r.cssText=n,a=Ze.test(n)}}else t&&e.removeAttribute(`style`);Ke in e&&(e[Ke]=a?r.display:``,e[qe]&&(r.display=`none`))}var $e=/\s*!important$/;function et(e,t,n){if(j(n))n.forEach(n=>et(e,t,n));else if(n??=``,t.startsWith(`--`))e.setProperty(t,n);else{let r=rt(e,t);$e.test(n)?e.setProperty(pe(r),n.replace($e,``),`important`):e[r]=n}}var tt=[`Webkit`,`Moz`,`ms`],nt={};function rt(e,n){let r=nt[n];if(r)return r;let i=f(n);if(i!==`filter`&&i in e)return nt[n]=i;i=t(i);for(let t=0;tmt||=(ht.then(()=>mt=0),Date.now());function _t(e,t){let n=e=>{if(!e._vts)e._vts=Date.now();else if(e._vts<=n.attached)return;let r=n.value;if(j(r)){let n=e.stopImmediatePropagation;e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0};let i=r.slice(),a=[e];for(let n=0;ne.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,yt=(e,t,n,r,i,a)=>{let o=i===`svg`;t===`class`?Ge(e,r,o):t===`style`?Qe(e,n,r):S(t)?ce(t)||ut(e,t,n,r,a):(t[0]===`.`?(t=t.slice(1),!0):t[0]===`^`?(t=t.slice(1),!1):bt(e,t,r,o))?(st(e,t,r),!e.tagName.includes(`-`)&&(t===`value`||t===`checked`||t===`selected`)&&ot(e,t,r,o,a,t!==`value`)):e._isVueCE&&(xt(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!w(r)))?st(e,f(t),r,a,t):(t===`true-value`?e._trueValue=r:t===`false-value`&&(e._falseValue=r),ot(e,t,r,o))};function bt(e,t,n,r){if(r)return!!(t===`innerHTML`||t===`textContent`||t in e&&vt(t)&&y(n));if(t===`spellcheck`||t===`draggable`||t===`translate`||t===`autocorrect`||t===`sandbox`&&e.tagName===`IFRAME`||t===`form`||t===`list`&&e.tagName===`INPUT`||t===`type`&&e.tagName===`TEXTAREA`)return!1;if(t===`width`||t===`height`){let t=e.tagName;if(t===`IMG`||t===`VIDEO`||t===`CANVAS`||t===`SOURCE`)return!1}return vt(t)&&w(n)?!1:t in e}function xt(e,t){let n=e._def.props;if(!n)return!1;let r=f(t);return Array.isArray(n)?n.some(e=>f(e)===r):Object.keys(n).some(e=>f(e)===r)}var G=e=>{let t=e.props[`onUpdate:modelValue`]||!1;return j(t)?e=>ue(t,e):t};function St(e){e.target.composing=!0}function Ct(e){let t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event(`input`)))}var K=Symbol(`_assign`);function wt(e,t,n){return t&&(e=e.trim()),n&&(e=A(e)),e}var Tt={created(e,{modifiers:{lazy:t,trim:n,number:r}},i){e[K]=G(i);let a=r||i.props&&i.props.type===`number`;W(e,t?`change`:`input`,t=>{t.target.composing||e[K](wt(e.value,n,a))}),(n||a)&&W(e,`change`,()=>{e.value=wt(e.value,n,a)}),t||(W(e,`compositionstart`,St),W(e,`compositionend`,Ct),W(e,`change`,Ct))},mounted(e,{value:t}){e.value=t??``},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:i,number:a}},o){if(e[K]=G(o),e.composing)return;let s=(a||e.type===`number`)&&!/^0\d/.test(e.value)?A(e.value):e.value,c=t??``;if(s===c)return;let l=e.getRootNode();(l instanceof Document||l instanceof ShadowRoot)&&l.activeElement===e&&e.type!==`range`&&(r&&t===n||i&&e.value.trim()===c)||(e.value=c)}},Et={deep:!0,created(e,t,n){e[K]=G(n),W(e,`change`,()=>{let t=e._modelValue,n=jt(e),r=e.checked,i=e[K];if(j(t)){let e=ie(t,n),a=e!==-1;if(r&&!a)i(t.concat(n));else if(!r&&a){let n=[...t];n.splice(e,1),i(n)}}else if(ne(t)){let e=new Set(t);r?e.add(n):e.delete(n),i(e)}else i(Mt(e,r))})},mounted:Dt,beforeUpdate(e,t,n){e[K]=G(n),Dt(e,t,n)}};function Dt(e,{value:t,oldValue:n},r){e._modelValue=t;let i;if(j(t))i=ie(t,r.props.value)>-1;else if(ne(t))i=t.has(r.props.value);else{if(t===n)return;i=P(t,Mt(e,!0))}e.checked!==i&&(e.checked=i)}var Ot={created(e,{value:t},n){e.checked=P(t,n.props.value),e[K]=G(n),W(e,`change`,()=>{e[K](jt(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[K]=G(r),t!==n&&(e.checked=P(t,r.props.value))}},kt={deep:!0,created(e,{value:t,modifiers:{number:n}},r){e._modelValue=t,W(e,`change`,()=>{let t=Array.prototype.filter.call(e.options,e=>e.selected).map(e=>n?A(jt(e)):jt(e));e[K](e.multiple?ne(e._modelValue)?new Set(t):t:t[0]),e._assigning=!0,z(()=>{e._assigning=!1})}),e[K]=G(r)},mounted(e,{value:t}){At(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[K]=G(n)},updated(e,{value:t}){e._assigning||At(e,t)}};function At(e,t){let n=e.multiple,r=j(t);if(!(n&&!r&&!ne(t))){for(let i=0,a=e.options.length;iString(e)===String(o)):ie(t,o)>-1}else a.selected=t.has(o);else if(P(jt(a),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function jt(e){return`_value`in e?e._value:e.value}function Mt(e,t){let n=t?`_trueValue`:`_falseValue`;return n in e?e[n]:t}var Nt={created(e,t,n){Ft(e,t,n,null,`created`)},mounted(e,t,n){Ft(e,t,n,null,`mounted`)},beforeUpdate(e,t,n,r){Ft(e,t,n,r,`beforeUpdate`)},updated(e,t,n,r){Ft(e,t,n,r,`updated`)}};function Pt(e,t){switch(e){case`SELECT`:return kt;case`TEXTAREA`:return Tt;default:switch(t){case`checkbox`:return Et;case`radio`:return Ot;default:return Tt}}}function Ft(e,t,n,r,i){let a=Pt(e.tagName,n.props&&n.props.type)[i];a&&a(e,t,n,r)}var It=[`ctrl`,`shift`,`alt`,`meta`],Lt={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>`button`in e&&e.button!==0,middle:e=>`button`in e&&e.button!==1,right:e=>`button`in e&&e.button!==2,exact:(e,t)=>It.some(n=>e[`${n}Key`]&&!t.includes(n))},Rt=(e,t)=>{if(!e)return e;let n=e._withMods||={},r=t.join(`.`);return n[r]||(n[r]=((n,...r)=>{for(let e=0;e{let n=e._withKeys||={},r=t.join(`.`);return n[r]||(n[r]=(n=>{if(!(`key`in n))return;let r=pe(n.key);if(t.some(e=>e===r||zt[e]===r))return e(n)}))},Vt=T({patchProp:yt},Ee),Ht;function Ut(){return Ht||=E(Vt)}var Wt=((...e)=>{let t=Ut().createApp(...e),{mount:n}=t;return t.mount=e=>{let r=Kt(e);if(!r)return;let i=t._component;!y(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent=``);let a=n(r,!1,Gt(r));return r instanceof Element&&(r.removeAttribute(`v-cloak`),r.setAttribute(`data-v-app`,``)),a},t});function Gt(e){if(e instanceof SVGElement)return`svg`;if(typeof MathMLElement==`function`&&e instanceof MathMLElement)return`mathml`}function Kt(e){return w(e)?document.querySelector(e):e}var qt=e=>e===``,Jt=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),Yt=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),Xt=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),Zt=e=>{let t=Xt(e);return t.charAt(0).toUpperCase()+t.slice(1)},Qt={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":2,"stroke-linecap":`round`,"stroke-linejoin":`round`},$t=Symbol(`lucide-icons`);function en(){return b($t,{})}var tn=({name:e,iconNode:t,"icon-node":n,absoluteStrokeWidth:r,"absolute-stroke-width":i,strokeWidth:a,"stroke-width":o,size:s,color:c,...l},{slots:u})=>{let{size:d,color:f,strokeWidth:p=2,absoluteStrokeWidth:m=!1,class:h=``}=en(),g=I(()=>{let e=qt(r)||qt(i)||r===!0||i===!0||m===!0,t=a||o||p||Qt[`stroke-width`];return e?Number(t)*24/Number(s??d??Qt.width):t});return he(`svg`,{...Qt,...l,width:s??d??Qt.width,height:s??d??Qt.height,stroke:c??f??Qt.stroke,"stroke-width":g.value,class:Jt(`lucide`,h,...e?[`lucide-${Yt(Zt(e))}-icon`,`lucide-${Yt(e)}`]:[`lucide-icon`])},[...(t??n??[]).map(e=>he(...e)),...u.default?[u.default()]:[]])},q=(e,t)=>(n,{slots:r,attrs:i})=>he(tn,{...i,...n,iconNode:t,name:e},r.default?{default:r.default}:void 0),nn=q(`activity`,[[`path`,{d:`M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2`,key:`169zse`}]]),rn=q(`boxes`,[[`path`,{d:`M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z`,key:`lc1i9w`}],[`path`,{d:`m7 16.5-4.74-2.85`,key:`1o9zyk`}],[`path`,{d:`m7 16.5 5-3`,key:`va8pkn`}],[`path`,{d:`M7 16.5v5.17`,key:`jnp8gn`}],[`path`,{d:`M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z`,key:`8zsnat`}],[`path`,{d:`m17 16.5-5-3`,key:`8arw3v`}],[`path`,{d:`m17 16.5 4.74-2.85`,key:`8rfmw`}],[`path`,{d:`M17 16.5v5.17`,key:`k6z78m`}],[`path`,{d:`M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z`,key:`1xygjf`}],[`path`,{d:`M12 8 7.26 5.15`,key:`1vbdud`}],[`path`,{d:`m12 8 4.74-2.85`,key:`3rx089`}],[`path`,{d:`M12 13.5V8`,key:`1io7kd`}]]),an=q(`calendar-clock`,[[`path`,{d:`M16 14v2.2l1.6 1`,key:`fo4ql5`}],[`path`,{d:`M16 2v3`,key:`otl347`}],[`path`,{d:`M21 7.338V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h2.338`,key:`7hb8p4`}],[`path`,{d:`M3 9h5.859`,key:`numkqi`}],[`path`,{d:`M8 2v3`,key:`1ioesn`}],[`circle`,{cx:`16`,cy:`16`,r:`6`,key:`qoo3c4`}]]),on=q(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),sn=q(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),cn=q(`fingerprint-pattern`,[[`path`,{d:`M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4`,key:`1nerag`}],[`path`,{d:`M14 13.12c0 2.38 0 6.38-1 8.88`,key:`o46ks0`}],[`path`,{d:`M17.29 21.02c.12-.6.43-2.3.5-3.02`,key:`ptglia`}],[`path`,{d:`M2 12a10 10 0 0 1 18-6`,key:`ydlgp0`}],[`path`,{d:`M2 16h.01`,key:`1gqxmh`}],[`path`,{d:`M21.8 16c.2-2 .131-5.354 0-6`,key:`drycrb`}],[`path`,{d:`M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2`,key:`1tidbn`}],[`path`,{d:`M8.65 22c.21-.66.45-1.32.57-2`,key:`13wd9y`}],[`path`,{d:`M9 6.8a6 6 0 0 1 9 5.2v2`,key:`1fr1j5`}]]),ln=q(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]),un=q(`library-big`,[[`rect`,{width:`8`,height:`18`,x:`3`,y:`3`,rx:`1`,key:`oynpb5`}],[`path`,{d:`M7 3v18`,key:`bbkbws`}],[`path`,{d:`M20.4 18.9c.2.5-.1 1.1-.6 1.3l-1.9.7c-.5.2-1.1-.1-1.3-.6L11.1 5.1c-.2-.5.1-1.1.6-1.3l1.9-.7c.5-.2 1.1.1 1.3.6Z`,key:`1qboyk`}]]),dn=q(`list-checks`,[[`path`,{d:`M13 5h8`,key:`a7qcls`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`m3 17 2 2 4-4`,key:`1jhpwq`}],[`path`,{d:`m3 7 2 2 4-4`,key:`1obspn`}]]),fn=q(`list-tree`,[[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`M3 10a2 2 0 0 0 2 2h3`,key:`1npucw`}],[`path`,{d:`M3 5v12a2 2 0 0 0 2 2h3`,key:`x1gjn2`}]]),pn=q(`menu`,[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]),mn=q(`messages-square`,[[`path`,{d:`M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z`,key:`1n2ejm`}],[`path`,{d:`M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1`,key:`1qfcsi`}]]),hn=q(`network`,[[`rect`,{x:`16`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`4q2zg0`}],[`rect`,{x:`2`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`8cvhb9`}],[`rect`,{x:`9`,y:`2`,width:`6`,height:`6`,rx:`1`,key:`1egb70`}],[`path`,{d:`M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3`,key:`1jsf9p`}],[`path`,{d:`M12 12V8`,key:`2874zd`}]]),gn=q(`plug`,[[`path`,{d:`M12 22v-5`,key:`1ega77`}],[`path`,{d:`M15 8V2`,key:`18g5xt`}],[`path`,{d:`M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z`,key:`1xoxul`}],[`path`,{d:`M9 8V2`,key:`14iosj`}]]),_n=q(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),vn=q(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]),yn=q(`settings`,[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),bn=q(`shield-half`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 22V2`,key:`zs6s6o`}]]),xn=q(`triangle-alert`,[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),Sn=q(`webhook`,[[`path`,{d:`M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2`,key:`q3hayz`}],[`path`,{d:`m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06`,key:`1go1hn`}],[`path`,{d:`m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8`,key:`qlwsc0`}]]),Cn=q(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),wn=[`disabled`],Tn={key:0,class:`animate-spin -ml-1 mr-2 h-4 w-4`,xmlns:`http://www.w3.org/2000/svg`,fill:`none`,viewBox:`0 0 24 24`},En={__name:`Button`,props:{variant:{type:String,default:`primary`,validator:e=>[`primary`,`secondary`,`danger`,`ghost`,`chip`].includes(e)},size:{type:String,default:`md`,validator:e=>[`xs`,`sm`,`md`,`lg`].includes(e)},active:{type:Boolean,default:!1},disabled:Boolean,loading:Boolean},setup(e){let t=e,i=I(()=>{switch(t.size){case`xs`:return`h-7 px-2.5 text-xs touch-expand-xs`;case`sm`:return`h-8 px-3 text-xs touch-expand-sm`;case`lg`:return`h-12 px-6 text-base`;default:return`h-10 px-4 text-sm`}}),a=I(()=>{switch(t.variant){case`secondary`:return`bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border shadow-sm`;case`danger`:return`bg-danger text-foreground-strong border border-danger hover:bg-danger-fg focus-visible:ring-danger shadow-sm`;case`ghost`:return`bg-transparent text-foreground-muted hover:text-foreground hover:bg-surface-hover`;case`chip`:return t.active?`bg-primary text-primary-foreground border border-primary`:`bg-surface text-foreground-muted border border-border hover:text-white hover:border-foreground-muted`;default:return`bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary shadow-sm border border-transparent`}});return(t,o)=>(r(),C(`button`,{class:O([`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:opacity-50 disabled:cursor-not-allowed`,i.value,a.value]),disabled:e.disabled||e.loading},[e.loading?(r(),C(`svg`,Tn,[...o[0]||=[x(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`},null,-1),x(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`},null,-1)]])):L(``,!0),n(t.$slots,`default`)],10,wn))}},Dn=_e(`confirm`,()=>{let e=o(!1),t=o(``),n=o(``),r=o(`Confirm`),i=o(`Cancel`),a=o(!1),s=o(!1),c=o(!1),l=o(``),u=o(``),d=null;return{visible:e,title:t,message:n,confirmLabel:r,cancelLabel:i,danger:a,noticeOnly:s,promptMode:c,promptValue:l,promptPlaceholder:u,ask:(o={})=>(t.value=o.title||`Are you sure?`,n.value=o.message||``,r.value=o.confirmLabel||`Confirm`,i.value=o.cancelLabel||`Cancel`,a.value=!!o.danger,s.value=!1,c.value=!1,e.value=!0,new Promise(e=>{d=e})),notify:(i={})=>(t.value=i.title||`Notice`,n.value=i.message||``,r.value=i.confirmLabel||`OK`,a.value=!!i.danger,s.value=!0,c.value=!1,e.value=!0,new Promise(e=>{d=e})),prompt:(o={})=>(t.value=o.title||`Enter a value`,n.value=o.message||``,r.value=o.confirmLabel||`OK`,i.value=o.cancelLabel||`Cancel`,a.value=!!o.danger,s.value=!1,c.value=!0,l.value=o.defaultValue||``,u.value=o.placeholder||``,e.value=!0,new Promise(e=>{d=e})),settle:t=>{e.value=!1,d&&=(c.value?d(t?l.value:null):d(t),null),c.value=!1}}}),On=[`a[href]`,`button:not([disabled])`,`input:not([disabled]):not([type="hidden"])`,`textarea:not([disabled])`,`select:not([disabled])`,`[tabindex]:not([tabindex="-1"])`,`audio[controls]`,`video[controls]`,`details > summary`].join(`,`);function kn(e,t){let n=null,r=null,i=null,a=async()=>{n=document.activeElement instanceof HTMLElement?document.activeElement:null,i=document.getElementById(`app`),i&&i.setAttribute(`inert`,``),await z();let t=e.value;t&&((t.querySelector(`[autofocus]`)||t.querySelector(On))?.focus?.(),r=e=>{if(e.key!==`Tab`)return;let n=Array.from(t.querySelectorAll(On)).filter(e=>!e.hasAttribute(`inert`)&&e.offsetParent!==null);if(!n.length){e.preventDefault();return}let r=n[0],i=n[n.length-1],a=document.activeElement;e.shiftKey&&a===r?(e.preventDefault(),i.focus()):!e.shiftKey&&a===i&&(e.preventDefault(),r.focus())},document.addEventListener(`keydown`,r))},o=()=>{r&&=(document.removeEventListener(`keydown`,r),null),i&&=(i.removeAttribute(`inert`),null),n&&n.isConnected&&typeof n.focus==`function`&&n.focus(),n=null};d(t,e=>{e?a():o()},{immediate:!1})}var An={class:`flex items-start gap-3`},jn={class:`flex-1 min-w-0`},Mn={key:0,class:`text-sm text-foreground-muted mt-1 whitespace-pre-line break-words`},Nn=[`placeholder`],Pn={class:`flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2`},Fn=`confirm-dialog-title`,In={__name:`ConfirmDialog`,setup(e){let t=Dn(),n=o(null),c=o(null);kn(c,I(()=>t.visible)),d(()=>t.visible&&t.promptMode,e=>{e&&z(()=>{let e=n.value;e&&(e.focus(),window.innerWidth<640&&setTimeout(()=>{e.scrollIntoView({block:`center`,behavior:`smooth`})},50))})});let l=e=>{t.visible&&(e.key===`Escape`&&t.settle(!1),e.key===`Enter`&&!t.promptMode&&t.settle(!0))};return p(()=>window.addEventListener(`keydown`,l)),i(()=>window.removeEventListener(`keydown`,l)),(e,i)=>(r(),N(v,{to:`body`},[k(je,{name:`fade`},{default:a(()=>[g(t).visible?(r(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm pt-safe pb-safe pl-safe pr-safe p-2 sm:p-4`,onClick:i[4]||=Rt(e=>g(t).settle(!1),[`self`]),onKeydown:i[5]||=Bt(e=>g(t).settle(!1),[`esc`])},[x(`div`,{ref_key:`dialogRoot`,ref:c,class:`w-full sm:max-w-md bg-background border border-border rounded-t-lg sm:rounded-lg shadow-xl p-5 sm:p-6 space-y-4 max-h-[calc(100dvh-1rem)] overflow-y-auto scrollable`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Fn},[x(`div`,An,[g(t).promptMode?L(``,!0):(r(),C(`div`,{key:0,class:O([`shrink-0 w-9 h-9 rounded-full flex items-center justify-center`,g(t).danger?`bg-red-500/15 text-red-400`:`bg-primary/15 text-primary`])},[g(t).danger?(r(),N(g(xn),{key:0,class:`w-5 h-5`})):(r(),N(g(sn),{key:1,class:`w-5 h-5`}))],2)),x(`div`,jn,[x(`h3`,{id:Fn,class:`text-sm font-semibold text-white tracking-tight`},R(g(t).title),1),g(t).message?(r(),C(`p`,Mn,R(g(t).message),1)):L(``,!0),g(t).promptMode?s((r(),C(`input`,{key:1,ref_key:`promptInput`,ref:n,"onUpdate:modelValue":i[0]||=e=>g(t).promptValue=e,placeholder:g(t).promptPlaceholder,type:`text`,class:`mt-3 w-full bg-background border border-border rounded-md px-3 py-2 text-base sm:text-sm text-foreground placeholder-foreground-muted/50 transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onKeydown:i[1]||=Bt(Rt(e=>g(t).settle(!0),[`stop`,`prevent`]),[`enter`])},null,40,Nn)),[[Tt,g(t).promptValue]]):L(``,!0)])]),x(`div`,Pn,[g(t).noticeOnly?L(``,!0):(r(),N(En,{key:0,variant:`secondary`,class:`w-full sm:w-auto`,onClick:i[2]||=e=>g(t).settle(!1)},{default:a(()=>[re(R(g(t).cancelLabel),1)]),_:1})),k(En,{variant:g(t).danger?`danger`:`primary`,class:`w-full sm:w-auto`,onClick:i[3]||=e=>g(t).settle(!0)},{default:a(()=>[re(R(g(t).confirmLabel),1)]),_:1},8,[`variant`])])],512)],32)):L(``,!0)]),_:1})]))}},Ln={__name:`App`,setup(e){return(e,t)=>{let n=te(`router-view`);return r(),C(F,null,[k(n),k(In)],64)}}};function Rn(e){return typeof e==`object`||`displayName`in e||`props`in e||`__vccOpts`in e}function zn(e){return e.__esModule||e[Symbol.toStringTag]===`Module`||e.default&&Rn(e.default)}var J=Object.assign;function Bn(e,t){let n={};for(let r in t){let i=t[r];n[r]=Y(i)?i.map(e):e(i)}return n}var Vn=()=>{},Y=Array.isArray;function Hn(e,t){let n={};for(let r in e)n[r]=r in t?t[r]:e[r];return n}var Un=Symbol(``);function Wn(e,t){return J(Error(),{type:e,[Un]:!0},t)}function X(e,t){return e instanceof Error&&Un in e&&(t==null||!!(e.type&t))}var Gn=Symbol(``),Kn=Symbol(``),qn=Symbol(``),Jn=Symbol(``),Yn=Symbol(``);function Xn(){return b(qn)}function Zn(e){return b(Jn)}var Qn=typeof document<`u`,$n=/#/g,er=/&/g,tr=/\//g,nr=/=/g,rr=/\?/g,ir=/\+/g,ar=/%5B/g,or=/%5D/g,sr=/%5E/g,cr=/%60/g,lr=/%7B/g,ur=/%7C/g,dr=/%7D/g,fr=/%20/g;function pr(e){return e==null?``:encodeURI(``+e).replace(ur,`|`).replace(ar,`[`).replace(or,`]`)}function mr(e){return pr(e).replace(lr,`{`).replace(dr,`}`).replace(sr,`^`)}function hr(e){return pr(e).replace(ir,`%2B`).replace(fr,`+`).replace($n,`%23`).replace(er,`%26`).replace(cr,"`").replace(lr,`{`).replace(dr,`}`).replace(sr,`^`)}function gr(e){return hr(e).replace(nr,`%3D`)}function _r(e){return pr(e).replace($n,`%23`).replace(rr,`%3F`)}function vr(e){return _r(e).replace(tr,`%2F`)}function yr(e){if(e==null)return null;try{return decodeURIComponent(``+e)}catch{}return``+e}var br=/\/$/,xr=e=>e.replace(br,``);function Sr(e,t,n=`/`){let r,i={},a=``,o=``,s=t.indexOf(`#`),c=t.indexOf(`?`);return c=s>=0&&c>s?-1:c,c>=0&&(r=t.slice(0,c),a=t.slice(c,s>0?s:t.length),i=e(a.slice(1))),s>=0&&(r||=t.slice(0,s),o=t.slice(s,t.length)),r=Ar(r??t,n),{fullPath:r+a+o,path:r,query:i,hash:yr(o)}}function Cr(e,t){let n=t.query?e(t.query):``;return t.path+(n&&`?`)+n+(t.hash||``)}function wr(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||`/`}function Tr(e,t,n){let r=t.matched.length-1,i=n.matched.length-1;return r>-1&&r===i&&Er(t.matched[r],n.matched[i])&&Dr(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Er(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Dr(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(!Or(e[n],t[n]))return!1;return!0}function Or(e,t){return Y(e)?kr(e,t):Y(t)?kr(t,e):(e&&e.valueOf())===(t&&t.valueOf())}function kr(e,t){return Y(t)?e.length===t.length&&e.every((e,n)=>e===t[n]):e.length===1&&e[0]===t}function Ar(e,t){if(e.startsWith(`/`))return e;if(!e)return t;let n=t.split(`/`),r=e.split(`/`),i=r[r.length-1];(i===`..`||i===`.`)&&r.push(``);let a=n.length-1,o,s;for(o=0;o1&&a--;else break;return n.slice(0,a).join(`/`)+`/`+r.slice(o).join(`/`)}var Z={path:`/`,name:void 0,params:{},query:{},hash:``,fullPath:`/`,matched:[],meta:{},redirectedFrom:void 0};function jr(e){if(!e)if(Qn){let t=document.querySelector(`base`);e=t&&t.getAttribute(`href`)||`/`,e=e.replace(/^\w+:\/\/[^/]+/,``)}else e=`/`;return e[0]!==`/`&&e[0]!==`#`&&(e=`/`+e),xr(e)}var Mr=/^[^#]+#/;function Nr(e,t){return e.replace(Mr,`#`)+t}function Pr(e,t){let n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}var Fr=()=>({left:window.scrollX,top:window.scrollY});function Ir(e){let t;if(`el`in e){let n=e.el,r=typeof n==`string`&&n.startsWith(`#`),i=typeof n==`string`?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!i)return;t=Pr(i,e)}else t=e;`scrollBehavior`in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left==null?window.scrollX:t.left,t.top==null?window.scrollY:t.top)}function Lr(e,t){return(history.state?history.state.position-t:-1)+e}var Rr=new Map;function zr(e,t){Rr.set(e,t)}function Br(e){let t=Rr.get(e);return Rr.delete(e),t}function Vr(e){return typeof e==`string`||e&&typeof e==`object`}function Hr(e){return typeof e==`string`||typeof e==`symbol`}function Ur(e){let t={};if(e===``||e===`?`)return t;let n=(e[0]===`?`?e.slice(1):e).split(`&`);for(let e=0;ee&&hr(e)):[r&&hr(r)]).forEach(e=>{e!==void 0&&(t+=(t.length?`&`:``)+n,e!=null&&(t+=`=`+e))})}return t}function Gr(e){let t={};for(let n in e){let r=e[n];r!==void 0&&(t[n]=Y(r)?r.map(e=>e==null?null:``+e):r==null?r:``+r)}return t}function Kr(){let e=[];function t(t){return e.push(t),()=>{let n=e.indexOf(t);n>-1&&e.splice(n,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Q(e,t,n,r,i,a=e=>e()){let o=r&&(r.enterCallbacks[i]=r.enterCallbacks[i]||[]);return()=>new Promise((s,c)=>{let l=e=>{e===!1?c(Wn(4,{from:n,to:t})):e instanceof Error?c(e):Vr(e)?c(Wn(2,{from:t,to:e})):(o&&r.enterCallbacks[i]===o&&typeof e==`function`&&o.push(e),s())},u=a(()=>e.call(r&&r.instances[i],t,n,l)),d=Promise.resolve(u);e.length<3&&(d=d.then(l)),d.catch(e=>c(e))})}function qr(e,t,n,r,i=e=>e()){let a=[];for(let o of e)for(let e in o.components){let s=o.components[e];if(!(t!==`beforeRouteEnter`&&!o.instances[e]))if(Rn(s)){let c=(s.__vccOpts||s)[t];c&&a.push(Q(c,n,r,o,e,i))}else{let c=s();a.push(()=>c.then(a=>{if(!a)throw Error(`Couldn't resolve component "${e}" at "${o.path}"`);let s=zn(a)?a.default:a;o.mods[e]=a,o.components[e]=s;let c=(s.__vccOpts||s)[t];return c&&Q(c,n,r,o,e,i)()}))}}return a}function Jr(e,t){let n=[],r=[],i=[],a=Math.max(t.matched.length,e.matched.length);for(let o=0;oEr(e,a))?r.push(a):n.push(a));let s=e.matched[o];s&&(t.matched.find(e=>Er(e,s))||i.push(s))}return[n,r,i]}var Yr=()=>location.protocol+`//`+location.host;function Xr(e,t){let{pathname:n,search:r,hash:i}=t,a=e.indexOf(`#`);if(a>-1){let t=i.includes(e.slice(a))?e.slice(a).length:1,n=i.slice(t);return n[0]!==`/`&&(n=`/`+n),wr(n,``)}return wr(n,e)+r+i}function Zr(e,t,n,r){let i=[],a=[],o=null,s=({state:a})=>{let s=Xr(e,location),c=n.value,l=t.value,u=0;if(a){if(n.value=s,t.value=a,o&&o===c){o=null;return}u=l?a.position-l.position:0}else r(s);i.forEach(e=>{e(n.value,c,{delta:u,type:`pop`,direction:u?u>0?`forward`:`back`:``})})};function c(){o=n.value}function l(e){i.push(e);let t=()=>{let t=i.indexOf(e);t>-1&&i.splice(t,1)};return a.push(t),t}function u(){if(document.visibilityState===`hidden`){let{history:e}=window;if(!e.state)return;e.replaceState(J({},e.state,{scroll:Fr()}),``)}}function d(){for(let e of a)e();a=[],window.removeEventListener(`popstate`,s),window.removeEventListener(`pagehide`,u),document.removeEventListener(`visibilitychange`,u)}return window.addEventListener(`popstate`,s),window.addEventListener(`pagehide`,u),document.addEventListener(`visibilitychange`,u),{pauseListeners:c,listen:l,destroy:d}}function Qr(e,t,n,r=!1,i=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:i?Fr():null}}function $r(e){let{history:t,location:n}=window,r={value:Xr(e,n)},i={value:t.state};i.value||a(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function a(r,a,o){let s=e.indexOf(`#`),c=s>-1?(n.host&&document.querySelector(`base`)?e:e.slice(s))+r:Yr()+e+r;try{t[o?`replaceState`:`pushState`](a,``,c),i.value=a}catch(e){console.error(e),n[o?`replace`:`assign`](c)}}function o(e,n){a(e,J({},t.state,Qr(i.value.back,e,i.value.forward,!0),n,{position:i.value.position}),!0),r.value=e}function s(e,n){let o=J({},i.value,t.state,{forward:e,scroll:Fr()});a(o.current,o,!0),a(e,J({},Qr(r.value,e,null),{position:o.position+1},n),!1),r.value=e}return{location:r,state:i,push:s,replace:o}}function ei(e){e=jr(e);let t=$r(e),n=Zr(e,t.state,t.location,t.replace);function r(e,t=!0){t||n.pauseListeners(),history.go(e)}let i=J({location:``,base:e,go:r,createHref:Nr.bind(null,e)},t,n);return Object.defineProperty(i,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(i,"state",{enumerable:!0,get:()=>t.state.value}),i}var ti={type:0,value:``},ni=/[a-zA-Z0-9_]/;function ri(e){if(!e)return[[]];if(e===`/`)return[[ti]];if(!e.startsWith(`/`))throw Error(`Invalid path "${e}"`);function t(e){throw Error(`ERR (${n})/"${l}": ${e}`)}let n=0,r=n,i=[],a;function o(){a&&i.push(a),a=[]}let s=0,c,l=``,u=``;function d(){l&&=(n===0?a.push({type:0,value:l}):n===1||n===2||n===3?(a.length>1&&(c===`*`||c===`+`)&&t(`A repeatable param (${l}) must be alone in its segment. eg: '/:ids+.`),a.push({type:1,value:l,regexp:u,repeatable:c===`*`||c===`+`,optional:c===`*`||c===`?`})):t(`Invalid state to consume buffer`),``)}function f(){l+=c}for(;st.length?t.length===1&&t[0]===80?1:-1:0}function li(e,t){let n=0,r=e.score,i=t.score;for(;n0&&t[t.length-1]<0}var di={strict:!1,end:!0,sensitive:!1};function fi(e,t,n){let r=J(si(ri(e.path),n),{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function pi(e,t){let n=[],r=new Map;t=Hn(di,t);function i(e){return r.get(e)}function a(e,n,r){let i=!r,s=hi(e);s.aliasOf=r&&r.record;let l=Hn(t,e),u=[s];if(`alias`in e){let t=typeof e.alias==`string`?[e.alias]:e.alias;for(let e of t)u.push(hi(J({},s,{components:r?r.record.components:s.components,path:e,aliasOf:r?r.record:s})))}let d,f;for(let t of u){let{path:u}=t;if(n&&u[0]!==`/`){let e=n.record.path,r=e[e.length-1]===`/`?``:`/`;t.path=n.record.path+(u&&r+u)}if(d=fi(t,n,l),r?r.alias.push(d):(f||=d,f!==d&&f.alias.push(d),i&&e.name&&!_i(d)&&o(e.name)),xi(d)&&c(d),s.children){let e=s.children;for(let t=0;t{o(f)}:Vn}function o(e){if(Hr(e)){let t=r.get(e);t&&(r.delete(e),n.splice(n.indexOf(t),1),t.children.forEach(o),t.alias.forEach(o))}else{let t=n.indexOf(e);t>-1&&(n.splice(t,1),e.record.name&&r.delete(e.record.name),e.children.forEach(o),e.alias.forEach(o))}}function s(){return n}function c(e){let t=yi(e,n);n.splice(t,0,e),e.record.name&&!_i(e)&&r.set(e.record.name,e)}function l(e,t){let i,a={},o,s;if(`name`in e&&e.name){if(i=r.get(e.name),!i)throw Wn(1,{location:e});s=i.record.name,a=J(mi(t.params,i.keys.filter(e=>!e.optional).concat(i.parent?i.parent.keys.filter(e=>e.optional):[]).map(e=>e.name)),e.params&&mi(e.params,i.keys.map(e=>e.name))),o=i.stringify(a)}else if(e.path!=null)o=e.path,i=n.find(e=>e.re.test(o)),i&&(a=i.parse(o),s=i.record.name,i.keys.forEach(e=>{e.optional&&!a[e.name]&&delete a[e.name]}));else{if(i=t.name?r.get(t.name):n.find(e=>e.re.test(t.path)),!i)throw Wn(1,{location:e,currentLocation:t});s=i.record.name,a=J({},t.params,e.params),o=i.stringify(a)}let c=[],l=i;for(;l;)c.unshift(l.record),l=l.parent;return{name:s,path:o,params:a,matched:c,meta:vi(c)}}e.forEach(e=>a(e));function u(){n.length=0,r.clear()}return{addRoute:a,resolve:l,removeRoute:o,clearRoutes:u,getRoutes:s,getRecordMatcher:i}}function mi(e,t){let n={};for(let r of t)r in e&&(n[r]=e[r]);return n}function hi(e){let t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:gi(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:`components`in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function gi(e){let t={},n=e.props||!1;if(`component`in e)t.default=n;else for(let r in e.components)t[r]=typeof n==`object`?n[r]:n;return t}function _i(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function vi(e){return e.reduce((e,t)=>J(e,t.meta),{})}function yi(e,t){let n=0,r=t.length;for(;n!==r;){let i=n+r>>1;li(e,t[i])<0?r=i:n=i+1}let i=bi(e);return i&&(r=t.lastIndexOf(i,r-1)),r}function bi(e){let t=e;for(;t=t.parent;)if(xi(t)&&li(e,t)===0)return t}function xi({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function Si(e){let t=b(qn),n=b(Jn),r=I(()=>{let n=g(e.to);return t.resolve(n)}),i=I(()=>{let{matched:e}=r.value,{length:t}=e,i=e[t-1],a=n.matched;if(!i||!a.length)return-1;let o=a.findIndex(Er.bind(null,i));if(o>-1)return o;let s=Di(e[t-2]);return t>1&&Di(i)===s&&a[a.length-1].path!==s?a.findIndex(Er.bind(null,e[t-2])):o}),a=I(()=>i.value>-1&&Ei(n.params,r.value.params)),o=I(()=>i.value>-1&&i.value===n.matched.length-1&&Dr(n.params,r.value.params));function s(n={}){if(Ti(n)){let n=t[g(e.replace)?`replace`:`push`](g(e.to)).catch(Vn);return e.viewTransition&&typeof document<`u`&&`startViewTransition`in document&&document.startViewTransition(()=>n),n}return Promise.resolve()}return{route:r,href:I(()=>r.value.href),isActive:a,isExactActive:o,navigate:s}}function Ci(e){return e.length===1?e[0]:e}var wi=_({name:`RouterLink`,compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:`page`},viewTransition:Boolean},useLink:Si,setup(e,{slots:t}){let n=m(Si(e)),{options:r}=b(qn),i=I(()=>({[Oi(e.activeClass,r.linkActiveClass,`router-link-active`)]:n.isActive,[Oi(e.exactActiveClass,r.linkExactActiveClass,`router-link-exact-active`)]:n.isExactActive}));return()=>{let r=t.default&&Ci(t.default(n));return e.custom?r:he(`a`,{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:i.value},r)}}});function Ti(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(e.button===void 0||e.button===0)){if(e.currentTarget&&e.currentTarget.getAttribute){let t=e.currentTarget.getAttribute(`target`);if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Ei(e,t){for(let n in t){let r=t[n],i=e[n];if(typeof r==`string`){if(r!==i)return!1}else if(!Y(i)||i.length!==r.length||r.some((e,t)=>e.valueOf()!==i[t].valueOf()))return!1}return!0}function Di(e){return e?e.aliasOf?e.aliasOf.path:e.path:``}var Oi=(e,t,n)=>e??t??n,ki=_({name:`RouterView`,inheritAttrs:!1,props:{name:{type:String,default:`default`},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){let r=b(Yn),i=I(()=>e.route||r.value),a=b(Kn,0),s=I(()=>{let e=g(a),{matched:t}=i.value,n;for(;(n=t[e])&&!n.components;)e++;return e}),c=I(()=>i.value.matched[s.value]);u(Kn,I(()=>s.value+1)),u(Gn,c),u(Yn,i);let l=o();return d(()=>[l.value,c.value,e.name],([e,t,n],[r,i,a])=>{t&&(t.instances[n]=e,i&&i!==t&&e&&e===r&&(t.leaveGuards.size||(t.leaveGuards=i.leaveGuards),t.updateGuards.size||(t.updateGuards=i.updateGuards))),e&&t&&(!i||!Er(t,i)||!r)&&(t.enterCallbacks[n]||[]).forEach(t=>t(e))},{flush:`post`}),()=>{let r=i.value,a=e.name,o=c.value,s=o&&o.components[a];if(!s)return Ai(n.default,{Component:s,route:r});let u=o.props[a],d=u?u===!0?r.params:typeof u==`function`?u(r):u:null,f=he(s,J({},d,t,{onVnodeUnmounted:e=>{e.component.isUnmounted&&(o.instances[a]=null)},ref:l}));return Ai(n.default,{Component:f,route:r})||f}}});function Ai(e,t){if(!e)return null;let n=e(t);return n.length===1?n[0]:n}var ji=ki;function Mi(e){let t=pi(e.routes,e),n=e.parseQuery||Ur,r=e.stringifyQuery||Wr,i=e.history,a=Kr(),o=Kr(),s=Kr(),l=le(Z),u=Z;Qn&&e.scrollBehavior&&`scrollRestoration`in history&&(history.scrollRestoration=`manual`);let d=Bn.bind(null,e=>``+e),f=Bn.bind(null,vr),p=Bn.bind(null,yr);function m(e,n){let r,i;return Hr(e)?(r=t.getRecordMatcher(e),i=n):i=e,t.addRoute(i,r)}function h(e){let n=t.getRecordMatcher(e);n&&t.removeRoute(n)}function _(){return t.getRoutes().map(e=>e.record)}function v(e){return!!t.getRecordMatcher(e)}function y(e,a){if(a=J({},a||l.value),typeof e==`string`){let r=Sr(n,e,a.path),o=t.resolve({path:r.path},a),s=i.createHref(r.fullPath);return J(r,o,{params:p(o.params),redirectedFrom:void 0,href:s})}let o;if(e.path!=null)o=J({},e,{path:Sr(n,e.path,a.path).path});else{let t=J({},e.params);for(let e in t)t[e]??delete t[e];o=J({},e,{params:f(t)}),a.params=f(a.params)}let s=t.resolve(o,a),c=e.hash||``;s.params=d(p(s.params));let u=Cr(r,J({},e,{hash:mr(c),path:s.path})),m=i.createHref(u);return J({fullPath:u,hash:c,query:r===Wr?Gr(e.query):e.query||{}},s,{redirectedFrom:void 0,href:m})}function b(e){return typeof e==`string`?Sr(n,e,l.value.path):J({},e)}function x(e,t){if(u!==e)return Wn(8,{from:t,to:e})}function S(e){return T(e)}function C(e){return S(J(b(e),{replace:!0}))}function w(e,t){let n=e.matched[e.matched.length-1];if(n&&n.redirect){let{redirect:r}=n,i=typeof r==`function`?r(e,t):r;return typeof i==`string`&&(i=i.includes(`?`)||i.includes(`#`)?i=b(i):{path:i},i.params={}),J({query:e.query,hash:e.hash,params:i.path==null?e.params:{}},i)}}function T(e,t){let n=u=y(e),i=l.value,a=e.state,o=e.force,s=e.replace===!0,c=w(n,i);if(c)return T(J(b(c),{state:typeof c==`object`?J({},a,c.state):a,force:o,replace:s}),t||n);let d=n;d.redirectedFrom=t;let f;return!o&&Tr(r,i,n)&&(f=Wn(16,{to:d,from:i}),ae(i,i,!0,!1)),(f?Promise.resolve(f):O(d,i)).catch(e=>X(e)?X(e,2)?e:ie(e):ne(e,d,i)).then(e=>{if(e){if(X(e,2))return T(J({replace:s},b(e.to),{state:typeof e.to==`object`?J({},a,e.to.state):a,force:o}),t||d)}else e=A(d,i,!0,s,a);return k(d,i,e),e})}function E(e,t){let n=x(e,t);return n?Promise.reject(n):Promise.resolve()}function D(e){let t=ce.values().next().value;return t&&typeof t.runWithContext==`function`?t.runWithContext(e):e()}function O(e,t){let n,[r,i,s]=Jr(e,t);n=qr(r.reverse(),`beforeRouteLeave`,e,t);for(let i of r)i.leaveGuards.forEach(r=>{n.push(Q(r,e,t))});let c=E.bind(null,e,t);return n.push(c),F(n).then(()=>{n=[];for(let r of a.list())n.push(Q(r,e,t));return n.push(c),F(n)}).then(()=>{n=qr(i,`beforeRouteUpdate`,e,t);for(let r of i)r.updateGuards.forEach(r=>{n.push(Q(r,e,t))});return n.push(c),F(n)}).then(()=>{n=[];for(let r of s)if(r.beforeEnter)if(Y(r.beforeEnter))for(let i of r.beforeEnter)n.push(Q(i,e,t));else n.push(Q(r.beforeEnter,e,t));return n.push(c),F(n)}).then(()=>(e.matched.forEach(e=>e.enterCallbacks={}),n=qr(s,`beforeRouteEnter`,e,t,D),n.push(c),F(n))).then(()=>{n=[];for(let r of o.list())n.push(Q(r,e,t));return n.push(c),F(n)}).catch(e=>X(e,8)?e:Promise.reject(e))}function k(e,t,n){s.list().forEach(r=>D(()=>r(e,t,n)))}function A(e,t,n,r,a){let o=x(e,t);if(o)return o;let s=t===Z,c=Qn?history.state:{};n&&(r||s?i.replace(e.fullPath,J({scroll:s&&c&&c.scroll},a)):i.push(e.fullPath,a)),l.value=e,ae(e,t,n,s),ie()}let ee;function j(){ee||=i.listen((e,t,n)=>{if(!P.listening)return;let r=y(e),a=w(r,P.currentRoute.value);if(a){T(J(a,{replace:!0,force:!0}),r).catch(Vn);return}u=r;let o=l.value;Qn&&zr(Lr(o.fullPath,n.delta),Fr()),O(r,o).catch(e=>X(e,12)?e:X(e,2)?(T(J(b(e.to),{force:!0}),r).then(e=>{X(e,20)&&!n.delta&&n.type===`pop`&&i.go(-1,!1)}).catch(Vn),Promise.reject()):(n.delta&&i.go(-n.delta,!1),ne(e,r,o))).then(e=>{e||=A(r,o,!1),e&&(n.delta&&!X(e,8)?i.go(-n.delta,!1):n.type===`pop`&&X(e,20)&&i.go(-1,!1)),k(r,o,e)}).catch(Vn)})}let te=Kr(),M=Kr(),N;function ne(e,t,n){ie(e);let r=M.list();return r.length?r.forEach(r=>r(e,t,n)):console.error(e),Promise.reject(e)}function re(){return N&&l.value!==Z?Promise.resolve():new Promise((e,t)=>{te.add([e,t])})}function ie(e){return N||(N=!e,j(),te.list().forEach(([t,n])=>e?n(e):t()),te.reset()),e}function ae(t,n,r,i){let{scrollBehavior:a}=e;if(!Qn||!a)return Promise.resolve();let o=!r&&Br(Lr(t.fullPath,0))||(i||!r)&&history.state&&history.state.scroll||null;return z().then(()=>a(t,n,o)).then(e=>t===l.value&&e&&Ir(e)).catch(e=>t===l.value&&ne(e,t,n))}let oe=e=>i.go(e),se,ce=new Set,P={currentRoute:l,listening:!0,addRoute:m,removeRoute:h,clearRoutes:t.clearRoutes,hasRoute:v,getRoutes:_,resolve:y,options:e,push:S,replace:C,go:oe,back:()=>oe(-1),forward:()=>oe(1),beforeEach:a.add,beforeResolve:o.add,afterEach:s.add,onError:M.add,isReady:re,install(e){e.component(`RouterLink`,wi),e.component(`RouterView`,ji),e.config.globalProperties.$router=P,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>g(l)}),Qn&&!se&&l.value===Z&&(se=!0,S(i.location).catch(e=>{}));let t={};for(let e in Z)Object.defineProperty(t,e,{get:()=>l.value[e],enumerable:!0});e.provide(qn,P),e.provide(Jn,c(t)),e.provide(Yn,l);let n=e.unmount;ce.add(e),e.unmount=function(){ce.delete(e),ce.size<1&&(u=Z,ee&&ee(),ee=null,l.value=Z,se=!1,N=!1),n()}}};function F(e){return e.reduce((e,t)=>e.then(()=>D(t)),Promise.resolve())}return P}var Ni=e.create({baseURL:``,timeout:3e4,withCredentials:!0,headers:{"Content-Type":`application/json`}}),Pi=12;try{localStorage.removeItem(`orva.hasUser`)}catch{}var Fi=_e(`auth`,()=>{let e=o(null),t=o(!1),n=o(!1),r=o(null),i=o(null),a=o(!1),s=o(0),c=e=>{r.value=e},l=async(r,i)=>{n.value=!0;try{let n=await Ni.post(`/api/v1/auth/login`,{username:r,password:i});return e.value=n.data.user,t.value=!0,c(!0),{success:!0}}catch(e){return{success:!1,error:e.response?.data?.error?.message||`Login failed`}}finally{n.value=!1}},u=async(r,i)=>{n.value=!0;try{let n=await Ni.post(`/api/v1/auth/onboard`,{username:r,password:i});return e.value=n.data.user,t.value=!0,c(!0),{success:!0}}catch(e){return{success:!1,error:e.response?.data?.error?.message||`Setup failed`}}finally{n.value=!1}},d=async()=>{try{await Ni.post(`/api/v1/auth/logout`)}catch{}e.value=null,t.value=!1},f=async({force:e=!1}={})=>{if(!e&&r.value!==null)return r.value;try{let e=await Ni.get(`/api/v1/auth/status`);return c(!!e.data.has_user),r.value}catch{return r.value===null&&c(!0),r.value}},p=async()=>{try{let n=await Ni.get(`/api/v1/auth/me`);return e.value=n.data,t.value=!0,c(!0),i.value=n.data.expires_at||null,!0}catch{return e.value=null,t.value=!1,i.value=null,!1}},m=async()=>{a.value=!0;try{let e=await Ni.post(`/api/v1/auth/refresh`);return i.value=e.data.expires_at||null,{success:!0}}catch(e){return t.value=!1,i.value=null,{success:!1,error:e.response?.data?.error?.message||`Refresh failed`}}finally{a.value=!1}},h=I(()=>i.value?(new Date(i.value).getTime()-Date.now())/1e3:null);return{user:e,isAuthenticated:t,loading:n,hasUser:r,expiresAt:i,refreshing:a,secondsUntilExpiry:h,shouldShowExpiryToast:I(()=>{if(!t.value)return!1;let e=h.value;return e==null||e<=0||Date.now(){s.value=Date.now()+36e5},changePassword:async(e,t)=>{await Ni.post(`/api/v1/auth/change-password`,{old_password:e,new_password:t})}}}),Ii=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},Li={},Ri={viewBox:`0 0 32 32`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,class:`text-primary`};function zi(e,t){return r(),C(`svg`,Ri,[...t[0]||=[x(`rect`,{width:`32`,height:`32`,rx:`8`,fill:`currentColor`},null,-1),x(`text`,{x:`16`,y:`21`,"font-family":`'Inter', system-ui, sans-serif`,"font-size":`13`,"font-weight":`700`,fill:`white`,"text-anchor":`middle`,"letter-spacing":`-0.5`},` f(x) `,-1)]])}var Bi=Ii(Li,[[`render`,zi]]),Vi={class:`lg:hidden fixed top-0 inset-x-0 h-14 bg-background border-b border-border z-30 flex items-center justify-between px-4 pt-safe pl-safe pr-safe`},Hi={class:`flex items-center gap-2 text-white font-mono`},Ui=[`aria-label`,`aria-expanded`],Wi={class:`h-16 flex items-center px-6 border-b border-border`},Gi={class:`flex items-center gap-3 text-white font-mono tracking-tight text-lg`},Ki={class:`flex-1 p-3 space-y-1 overflow-y-auto scrollable`},qi=[`aria-expanded`,`aria-controls`,`onClick`],Ji={class:`flex-1 text-left`},Yi=[`id`],Xi={class:`mt-2 space-y-1 border-t border-border pt-2`},Zi={__name:`Sidebar`,setup(e){let t=Zn(),n=o(!1),i=o(null),c=o(null),u=e=>e===`/`?t.path===`/`:t.path.startsWith(e),f=[{path:`/`,label:`Overview`,icon:ln},{path:`/ai`,label:`Chat`,icon:mn},{path:`/functions`,label:`Functions`,icon:rn}],p=[{id:`automation`,label:`Automation`,icon:an,items:[{path:`/cron`,label:`Schedules`,icon:an},{path:`/jobs`,label:`Jobs`,icon:dn}]},{id:`observe`,label:`Observe`,icon:nn,items:[{path:`/activity`,label:`Activity`,icon:nn},{path:`/invocations`,label:`Invocations`,icon:fn},{path:`/traces`,label:`Traces`,icon:hn}]},{id:`connect`,label:`Connect`,icon:gn,items:[{path:`/api-keys`,label:`Keys`,icon:cn},{path:`/channels`,label:`Channels`,icon:gn},{path:`/webhooks`,label:`Webhooks`,icon:Sn},{path:`/firewall`,label:`Egress`,icon:bn}]}],m=[{path:`/settings`,label:`Settings`,icon:yn},{path:`/docs`,label:`Docs`,icon:un}],h=o(Object.fromEntries(p.map(e=>[e.id,!1]))),_=e=>e.items.some(e=>u(e.path)),v=()=>{let e=p.find(_);e&&(h.value[e.id]=!0)};v(),d(()=>t.fullPath,()=>{n.value=!1,v()}),d(n,async e=>{await z(),e?(i.value?.querySelector(`a[href]`))?.focus?.():i.value?.contains(document.activeElement)&&c.value?.focus?.()});let y=0,b=0,S=!1,w=e=>{if(window.innerWidth>=1024||!n.value)return;let t=e.touches[0];y=t.clientX,b=t.clientY,S=!0},T=e=>{if(!S)return;let t=e.touches[0],r=t.clientX-y,i=Math.abs(t.clientY-b);r<-60&&i<40&&(n.value=!1,S=!1)},E=()=>{S=!1};return(e,t)=>{let o=te(`router-link`);return r(),C(F,null,[x(`header`,Vi,[x(`div`,Hi,[k(Bi,{class:`w-6 h-6`}),t[5]||=x(`span`,{class:`font-bold tracking-tight`},`Orva`,-1)]),x(`button`,{ref_key:`toggleBtn`,ref:c,class:`p-2 rounded-md text-foreground-muted hover:text-white hover:bg-surface transition-colors touch-expand-iconbtn`,"aria-label":n.value?`Close menu`:`Open menu`,"aria-expanded":n.value,"aria-controls":`primary-navigation`,onClick:t[0]||=e=>n.value=!n.value},[n.value?(r(),N(g(Cn),{key:1,class:`w-5 h-5`})):(r(),N(g(pn),{key:0,class:`w-5 h-5`}))],8,Ui)]),k(je,{name:`fade`},{default:a(()=>[n.value?(r(),C(`div`,{key:0,class:`lg:hidden fixed inset-0 bg-black/50 z-30 backdrop-blur-sm`,onClick:t[1]||=e=>n.value=!1})):L(``,!0)]),_:1}),x(`aside`,{id:`primary-navigation`,ref_key:`drawerEl`,ref:i,class:O([`bg-background border-r border-border flex flex-col h-full shrink-0 z-40 w-64 lg:w-52 fixed inset-y-0 left-0 transform transition-transform duration-150 ease-out lg:static lg:translate-x-0 lg:transform-none lg:transition-none pt-safe pb-safe pl-safe`,n.value?`translate-x-0`:`-translate-x-full lg:translate-x-0`]),onTouchstart:w,onTouchmove:T,onTouchend:E},[x(`div`,Wi,[x(`div`,Gi,[k(Bi,{class:`w-8 h-8`}),t[6]||=x(`span`,{class:`font-bold tracking-tight text-white`},`Orva`,-1)])]),x(`nav`,Ki,[(r(),C(F,null,M(f,e=>k(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[2]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:O([`w-4 h-4 transition-colors`,u(e.path)?`text-white`:`text-foreground-muted group-hover:text-white`])},null,8,[`class`])),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`])),64)),(r(),C(F,null,M(p,e=>x(`div`,{key:e.id,class:`pt-1`},[x(`button`,{type:`button`,class:O([`flex w-full items-center gap-3 rounded-md px-3 py-2.5 text-sm font-medium text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,_(e)?`text-white`:``]),"aria-expanded":h.value[e.id],"aria-controls":`nav-group-${e.id}`,onClick:t=>h.value[e.id]=!h.value[e.id]},[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,Ji,R(e.label),1),k(g(on),{class:O([`h-3.5 w-3.5 transition-transform`,h.value[e.id]?`rotate-0`:`-rotate-90`])},null,8,[`class`])],10,qi),s(x(`div`,{id:`nav-group-${e.id}`,class:`ml-3 mt-1 space-y-0.5 border-l border-border pl-2`},[(r(!0),C(F,null,M(e.items,e=>(r(),N(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[3]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`]))),128))],8,Yi),[[Je,h.value[e.id]]])])),64)),x(`div`,Xi,[(r(),C(F,null,M(m,e=>k(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[4]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`])),64))])])],34)],64)}}},Qi={key:0,class:`fixed z-50 bg-background border border-border shadow-lg rounded-lg p-4 flex items-start gap-3 inset-x-2 bottom-2 max-w-sm mx-auto pb-safe sm:inset-x-auto sm:bottom-6 sm:right-6 sm:mx-0 sm:pb-4`},$i={class:`flex-1 min-w-0`},ea={key:0,class:`text-sm font-medium text-white mb-0.5`},ta={class:`text-xs text-foreground-muted`},na={class:`flex flex-col gap-2 shrink-0`},ra=[`disabled`],ia=Ii(Object.assign({name:`CommonToast`},{__name:`Toast`,props:{visible:{type:Boolean,default:!1},title:{type:String,default:``},actionLabel:{type:String,default:``},actionLoading:{type:Boolean,default:!1},dismissible:{type:Boolean,default:!0}},emits:[`action`,`dismiss`],setup(e){return(t,i)=>(r(),N(v,{to:`body`},[k(je,{name:`toast`},{default:a(()=>[e.visible?(r(),C(`div`,Qi,[x(`div`,$i,[e.title?(r(),C(`div`,ea,R(e.title),1)):L(``,!0),x(`div`,ta,[n(t.$slots,`default`,{},void 0,!0)])]),x(`div`,na,[e.actionLabel?(r(),C(`button`,{key:0,class:`px-3 py-1 rounded text-xs font-medium bg-white text-black hover:bg-foreground-muted transition-colors`,disabled:e.actionLoading,onClick:i[0]||=e=>t.$emit(`action`)},R(e.actionLoading?`…`:e.actionLabel),9,ra)):L(``,!0),e.dismissible?(r(),C(`button`,{key:1,class:`text-foreground-muted hover:text-white text-xs`,onClick:i[1]||=e=>t.$emit(`dismiss`)},` Dismiss `)):L(``,!0)])])):L(``,!0)]),_:3})]))}}),[[`__scopeId`,`data-v-1cbabcec`]]),aa={class:`flex items-center gap-2 px-4 py-3 border-b border-border`},oa=[`aria-selected`,`onClick`,`onMouseenter`],sa={class:`flex-1 truncate`},ca={key:0,class:`hidden sm:inline-flex items-center gap-1 text-[10px] font-mono text-foreground-muted`},la={key:0,class:`px-4 py-6 text-center text-sm text-foreground-muted`},ua=800,da={__name:`CommandPalette`,setup(e,{expose:t}){let n=Xn(),c=o(!1),u=o(``),f=o(0),m=o(null),h=o(null),_=o(null);kn(_,c);let y=[{id:`fn-new`,label:`New function`,icon:_n,action:()=>n.push(`/functions/new`),shortcut:[`c`,`n`]},{id:`go-fns`,label:`Functions`,icon:rn,action:()=>n.push(`/functions`),shortcut:[`g`,`f`]},{id:`go-inv`,label:`Invocations`,icon:fn,action:()=>n.push(`/invocations`),shortcut:[`g`,`i`]},{id:`go-jobs`,label:`Jobs`,icon:dn,action:()=>n.push(`/jobs`),shortcut:[`g`,`j`]},{id:`go-cron`,label:`Schedules`,icon:an,action:()=>n.push(`/cron`)},{id:`go-activity`,label:`Activity`,icon:nn,action:()=>n.push(`/activity`)},{id:`go-traces`,label:`Traces`,icon:hn,action:()=>n.push(`/traces`)},{id:`go-keys`,label:`API Keys`,icon:cn,action:()=>n.push(`/api-keys`)},{id:`go-channels`,label:`Channels`,icon:gn,action:()=>n.push(`/channels`)},{id:`go-hooks`,label:`Webhooks`,icon:Sn,action:()=>n.push(`/webhooks`)},{id:`go-fw`,label:`Egress`,icon:bn,action:()=>n.push(`/firewall`),keywords:`firewall blocklist dns`},{id:`go-settings`,label:`Settings`,icon:yn,action:()=>n.push(`/settings`)},{id:`go-docs`,label:`Docs`,icon:un,action:()=>n.push(`/docs`)},{id:`go-overview`,label:`Overview`,icon:ln,action:()=>n.push(`/`)}],b=I(()=>{let e=u.value.trim().toLowerCase();return e?y.filter(t=>t.label.toLowerCase().includes(e)||(t.keywords||``).includes(e)):y});d(b,()=>{f.value=0});let S=e=>{let t=b.value.length;t&&(f.value=(f.value+e+t)%t,z(()=>{(h.value?.querySelectorAll(`li[role="option"]`)[f.value])?.scrollIntoView?.({block:`nearest`})}))},w=e=>{e&&(T(),z(()=>e.action()))},T=()=>{c.value=!1,u.value=``,f.value=0},E=()=>{c.value=!0,z(()=>m.value?.focus())},D=``,A=null,ee=e=>{if(!e)return!1;let t=e.tagName;return!!(t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable)},j=e=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`){e.preventDefault(),c.value?T():E();return}if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`s`&&window.location.pathname.includes(`/functions/`)){e.preventDefault(),window.dispatchEvent(new CustomEvent(`orva:deploy`));return}if(e.metaKey||e.ctrlKey||e.altKey||ee(document.activeElement))return;if(!D){if(e.key===`g`||e.key===`c`){D=e.key,clearTimeout(A),A=setTimeout(()=>{D=``},ua);return}return}let t=D+e.key;D=``,clearTimeout(A);let n=y.find(e=>e.shortcut&&e.shortcut.join(``)===t);n&&(e.preventDefault(),n.action())};return p(()=>{window.addEventListener(`keydown`,j)}),i(()=>{window.removeEventListener(`keydown`,j),clearTimeout(A)}),t({show:E,close:T}),(e,t)=>(r(),N(v,{to:`body`},[k(je,{name:`fade`},{default:a(()=>[c.value?(r(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-start justify-center bg-black/60 backdrop-blur-sm pt-[10vh] sm:pt-[15vh] px-4`,onClick:Rt(T,[`self`])},[x(`div`,{ref_key:`dialogRoot`,ref:_,class:`w-full max-w-lg bg-background border border-border rounded-lg shadow-xl overflow-hidden`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`command-palette-label`},[x(`div`,aa,[k(g(vn),{class:`w-4 h-4 text-foreground-muted shrink-0`}),t[4]||=x(`span`,{id:`command-palette-label`,class:`sr-only`},`Command palette`,-1),s(x(`input`,{ref_key:`searchInput`,ref:m,"onUpdate:modelValue":t[0]||=e=>u.value=e,type:`text`,placeholder:`Search routes, actions…`,class:`flex-1 bg-transparent border-0 text-base sm:text-sm text-white placeholder-foreground-muted focus:outline-none`,onKeydown:[t[1]||=Bt(Rt(e=>S(1),[`prevent`]),[`down`]),t[2]||=Bt(Rt(e=>S(-1),[`prevent`]),[`up`]),t[3]||=Bt(Rt(e=>w(b.value[f.value]),[`prevent`]),[`enter`]),Bt(T,[`esc`])]},null,544),[[Tt,u.value]]),t[5]||=x(`kbd`,{class:`hidden sm:inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-mono text-foreground-muted bg-surface border border-border`},`esc`,-1)]),x(`ul`,{ref_key:`listRef`,ref:h,class:`max-h-[60dvh] overflow-y-auto scrollable py-1`,role:`listbox`},[(r(!0),C(F,null,M(b.value,(e,t)=>(r(),C(`li`,{key:e.id,role:`option`,"aria-selected":t===f.value,class:O([`flex items-center gap-3 px-4 py-2.5 min-h-[44px] text-base sm:text-sm cursor-pointer`,t===f.value?`bg-primary/15 text-white`:`text-foreground hover:bg-surface-hover`]),onClick:t=>w(e),onMouseenter:e=>f.value=t},[(r(),N(l(e.icon),{class:`w-4 h-4 shrink-0 text-foreground-muted`})),x(`span`,sa,R(e.label),1),e.shortcut?(r(),C(`span`,ca,[(r(!0),C(F,null,M(e.shortcut,e=>(r(),C(`kbd`,{key:e,class:`px-1.5 py-0.5 rounded bg-surface border border-border`},R(e),1))),128))])):L(``,!0)],42,oa))),128)),b.value.length?L(``,!0):(r(),C(`li`,la,` Nothing matches "`+R(u.value)+`". `,1))],512),t[6]||=x(`div`,{class:`px-4 py-2 border-t border-border bg-surface/40 flex items-center justify-between text-[10px] text-foreground-muted`},[x(`span`,{class:`flex items-center gap-2`},[x(`kbd`,{class:`px-1.5 py-0.5 rounded font-mono bg-surface border border-border`},`↑↓`),x(`span`,null,`navigate`)]),x(`span`,{class:`flex items-center gap-2`},[x(`kbd`,{class:`px-1.5 py-0.5 rounded font-mono bg-surface border border-border`},`↵`),x(`span`,null,`activate`)])],-1)],512)])):L(``,!0)]),_:1})]))}},fa=()=>B.get(`/system/health`),pa=e=>B.get(`/functions`,{params:e}),ma=e=>B.get(`/functions/${e}`),ha=e=>B.get(`/functions/${e}/source`),ga=()=>B.get(`/routes`),_a=(e,t,n=`*`)=>B.post(`/routes`,{path:e,function_id:t,methods:n}),va=e=>B.delete(`/routes`,{params:{path:e}}),ya=(e,{method:t=`POST`,path:n=`/`,headers:r={},body:i=``}={})=>{let a=`/${e.replace(/^fn_/,``)}`;n&&n!==`/`&&(a+=n.startsWith(`/`)?n:`/${n}`);let o={url:a,method:t,headers:{...r},responseType:`text`,transformRequest:[e=>e]},s=(t||`POST`).toUpperCase();return i&&s!==`GET`&&s!==`HEAD`&&(o.data=i),ye.request(o)},ba=e=>B.get(`/executions`,{params:e}),xa=e=>B.get(`/executions/${e}`),Sa=e=>B.get(`/executions/${e}/logs`),Ca=e=>B.get(`/executions/${e}/request`),wa=e=>B.post(`/executions/${e}/replay`,null,{responseType:`text`}),Ta=e=>B.get(`/activity`,{params:e}),Ea=(e,t)=>B.get(`/functions/${encodeURIComponent(e)}/kv`,{params:t}),Da=(e,t,n)=>B.put(`/functions/${encodeURIComponent(e)}/kv/${encodeURIComponent(t)}`,n),Oa=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/kv/${encodeURIComponent(t)}`),ka=e=>B.get(`/functions/${encodeURIComponent(e)}/fixtures`),Aa=(e,t,n)=>B.put(`/functions/${encodeURIComponent(e)}/fixtures/${encodeURIComponent(t)}`,n),ja=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/fixtures/${encodeURIComponent(t)}`),Ma=()=>B.get(`/keys`),Na=e=>B.post(`/keys`,e),Pa=e=>B.delete(`/keys/${e}`),Fa=()=>B.get(`/oauth/connected-apps`),Ia=e=>B.delete(`/oauth/connected-apps/${e}`),La=()=>B.get(`/auth/sessions`),Ra=e=>B.delete(`/auth/sessions/${e}`),za=()=>B.get(`/channels`),Ba=e=>B.post(`/channels`,e),Va=e=>B.post(`/channels/${e}/rotate`),Ha=e=>B.delete(`/channels/${e}`),Ua=()=>B.get(`/system/metrics.json`),Wa=e=>B.get(`/deployments/${e}`),Ga=(e,t=0,n=200)=>B.get(`/deployments/${e}/logs`,{params:{from:t,limit:n}}),Ka=(e,t=50)=>B.get(`/functions/${e}/deployments`,{params:{limit:t}}),qa=(e,t,n,r=`json`)=>B.get(`/functions/${encodeURIComponent(e)}/diff`,{params:{from:t,to:n,format:r},responseType:r===`unified`?`text`:`json`}),Ja=(e,t)=>B.post(`/functions/${e}/rollback`,t),Ya=async e=>{let t=((await B.get(`/functions`)).data.functions||[]).find(t=>t.name===e);if(!t)throw Error(`Function "${e}" not found`);return t.id},Xa=e=>({...e,cron_expression:e.cron_expr}),Za=async()=>({data:{schedules:((await B.get(`/cron`)).data.schedules||[]).map(Xa)}}),Qa=async(e,t)=>{let n=await Ya(e),r={cron_expr:t.cron,timezone:t.timezone||eo(),enabled:t.enabled!==!1,payload:t.payload??{}};return{data:Xa((await B.post(`/functions/${n}/cron`,r)).data)}},$a=async(e,t)=>{let n=t.function_id;if(!n)throw Error(`updateCronSchedule: function_id is required`);let r={};return t.cron!==void 0&&(r.cron_expr=t.cron),t.timezone!==void 0&&(r.timezone=t.timezone),t.enabled!==void 0&&(r.enabled=t.enabled),t.payload!==void 0&&(r.payload=t.payload),{data:Xa((await B.put(`/functions/${n}/cron/${e}`,r)).data)}},eo=()=>{try{return Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`}catch{return`UTC`}},to=async(e,t)=>{if(!t)throw Error(`deleteCronSchedule: functionId is required`);return B.delete(`/functions/${t}/cron/${e}`)},no=(e={})=>B.get(`/jobs`,{params:e}),ro=e=>B.post(`/jobs`,e),io=e=>B.post(`/jobs/${e}/retry`),ao=e=>B.delete(`/jobs/${e}`),oo=()=>B.get(`/system/storage`),so=()=>B.post(`/system/vacuum`),co=e=>{let t=new FormData;return t.append(`archive`,e),B.post(`/restore?confirm=1`,t,{headers:{"Content-Type":`multipart/form-data`},timeout:6e5})},lo=e=>B.get(`/traces/${e}`),uo=(e={})=>B.get(`/traces`,{params:e}),fo=()=>B.get(`/webhooks`),po=e=>B.post(`/webhooks`,e),mo=(e,t)=>B.put(`/webhooks/${e}`,t),ho=e=>B.delete(`/webhooks/${e}`),go=e=>B.post(`/webhooks/${e}/test`),_o=e=>B.get(`/webhooks/${e}/deliveries`),vo=e=>B.post(`/webhooks/deliveries/${e}/retry`),yo=e=>B.get(`/functions/${encodeURIComponent(e)}/inbound-webhooks`),bo=(e,t)=>B.post(`/functions/${encodeURIComponent(e)}/inbound-webhooks`,t),xo=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/inbound-webhooks/${t}`),So=[500,1e3,2e3,5e3,1e4],Co=_e(`events`,()=>{let e=o(!1),t=o(0),n=new Map,r=null,i=null,a=(e,t)=>{let r=n.get(e);if(r)for(let e of r)try{e(t)}catch(e){console.error(`events callback error`,e)}},s=n=>{n.onopen=()=>{e.value=!0,t.value=0};for(let e of[`metrics`,`execution`,`deployment`,`function`,`activity`])n.addEventListener(e,t=>{try{let n=JSON.parse(t.data);a(e,n)}catch(e){console.warn(`failed to parse SSE payload`,e,t.data)}});n.onerror=()=>{if(e.value=!1,r){try{r.close()}catch{}r=null}let n=So[Math.min(t.value,So.length-1)];t.value+=1,clearTimeout(i),i=setTimeout(()=>c(),n)}},c=()=>{if(!r)try{r=new EventSource(`/api/v1/events`,{withCredentials:!0}),s(r)}catch(t){console.error(`failed to open /api/v1/events`,t),e.value=!1}};return{connected:h(e),reconnectAttempt:h(t),connect:c,disconnect:()=>{if(clearTimeout(i),i=null,r){try{r.close()}catch{}r=null}e.value=!1,t.value=0},subscribe:(e,t)=>(n.has(e)||n.set(e,new Set),n.get(e).add(t),()=>{let r=n.get(e);r&&r.delete(t)})}}),wo=60,To=_e(`system`,()=>{let e=o(!1),t=o(null),n=o(0),r=o([]),i=o({}),a=o(null),s=null,c=null,l=null,u=e=>{t.value=e;let n=new Set;for(let t of e.pools||[]){n.add(t.function_id);let e=i.value[t.function_id]||[];e.push(t.rate_ewma),e.length>wo&&e.splice(0,e.length-wo),i.value[t.function_id]=e}for(let e of Object.keys(i.value))n.has(e)||delete i.value[e]},d=async()=>{try{let[t,i,o,s]=await Promise.all([Ua(),pa().catch(()=>({data:{functions:[],total:0}})),ba({limit:20}).catch(()=>({data:{executions:[]}})),fa().catch(()=>({data:null}))]);u(t.data),n.value=i.data.total??(i.data.functions||[]).length,r.value=o.data.executions||[],s.data&&(a.value={version:s.data.version,commit:s.data.commit,buildTime:s.data.build_time,image:s.data.image,uptimeSeconds:s.data.uptime_seconds}),e.value=!0}catch(t){console.error(`seed fetch error:`,t),e.value=!1}};return{isConnected:e,metrics:t,functionsCount:n,recentInvocations:r,poolHistory:i,buildInfo:a,connect:()=>{let t=Co();d(),s=t.subscribe(`metrics`,t=>{u(t),e.value=!0}),c=t.subscribe(`execution`,e=>{r.value=[e,...r.value].slice(0,20)}),l=t.subscribe(`function`,e=>{e.action===`deleted`?n.value=Math.max(0,n.value-1):e.action===`created`&&(n.value+=1)})},disconnect:()=>{s&&=(s(),null),c&&=(c(),null),l&&=(l(),null),e.value=!1}}}),Eo={class:`flex h-screen w-full bg-background overflow-hidden font-sans antialiased text-foreground`},Do={class:`flex-1 flex flex-col min-w-0 overflow-hidden relative pt-14 lg:pt-0`},Oo={__name:`Layout`,setup(e){let t=To(),n=Co(),s=Fi(),c=o(0),u=null,d=I(()=>{c.value;let e=s.secondsUntilExpiry;return e==null||e<=0?`—`:e<60?`${Math.floor(e)}s`:e<3600?`${Math.floor(e/60)} min`:`${Math.floor(e/3600)} h`}),f=async()=>{(await s.refreshSession()).success||(window.location.href=`/login`)};return p(async()=>{await s.checkAuth(),n.connect(),t.connect(),u=setInterval(()=>{c.value++},3e4)}),i(()=>{t.disconnect(),n.disconnect(),u&&clearInterval(u)}),(e,t)=>{let n=te(`router-view`);return r(),C(`div`,Eo,[k(Zi),x(`main`,Do,[k(n,null,{default:a(({Component:e})=>[(r(),N(ee,{max:10},[(r(),N(l(e),{class:`flex-1 overflow-auto scrollable p-page`}))],1024))]),_:1})]),k(da),k(ia,{visible:g(s).shouldShowExpiryToast,"action-loading":g(s).refreshing,title:`Session expiring soon`,"action-label":`Stay signed in`,onAction:f,onDismiss:g(s).dismissExpiryToast},{default:a(()=>[re(` Your session expires in `+R(d.value)+`. Click to extend it for another 7 days. `,1)]),_:1},8,[`visible`,`action-loading`,`onDismiss`])])}}},ko=`modulepreload`,Ao=function(e){return`/web/`+e},jo={},$=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}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Ao(t,n),t=s(t),t in jo)return;jo[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:ko,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.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)})},Mo=Mi({history:ei(`/web/`),routes:[{path:`/login`,name:`login`,component:()=>$(()=>import(`./Login-DscOTSMy.js`),__vite__mapDeps([0,1,2])),meta:{requiresAuth:!1}},{path:`/onboarding`,name:`onboarding`,component:()=>$(()=>import(`./Onboarding-CI9ktN7I.js`),__vite__mapDeps([3,1,2,4])),meta:{requiresAuth:!1}},{path:`/`,component:Oo,meta:{requiresAuth:!0},children:[{path:``,name:`dashboard`,component:()=>$(()=>import(`./Dashboard-rKNyCP0W.js`),__vite__mapDeps([5,1]))},{path:`ai`,name:`ai`,component:()=>$(()=>import(`./AI-De72Ye8u.js`),__vite__mapDeps([6,7,1,8,4,9,10,11,12,13,14,15,16,17,18,19,20,21,22]))},{path:`functions`,name:`functions`,component:()=>$(()=>import(`./FunctionsList-CPOzZCfJ.js`),__vite__mapDeps([23,1,8,4,24,25,14,26,17,11,7,21,27]))},{path:`functions/:name`,name:`function-detail`,component:()=>$(()=>import(`./Editor-C_JYWteY.js`),__vite__mapDeps([28,1,29,8,30,4,31,24,32,25,33,15,34,16,35,17,36,11,7,21,37,38,39,40,41]))},{path:`functions/:name/deployments`,name:`function-deployments`,component:()=>$(()=>import(`./Deployments-CRPgafhC.js`),__vite__mapDeps([42,1,43,30,26,15,12,13,44,45,38]))},{path:`functions/:name/diff`,name:`function-diff`,component:()=>$(()=>import(`./FunctionDiff-DtVzmfsl.js`),__vite__mapDeps([46,1,4,31,15,18,47,21,38,48]))},{path:`functions/:name/kv`,name:`function-kv`,component:()=>$(()=>import(`./KVStore-DzgumyT2.js`),__vite__mapDeps([49,1,26,17,12,13,27]))},{path:`functions/:name/inbound-webhooks`,name:`function-inbound-webhooks`,component:()=>$(()=>import(`./InboundWebhooks-CFOyt9ev.js`),__vite__mapDeps([50,1,26,17,12,13,27]))},{path:`functions/new`,name:`function-new`,component:()=>$(()=>import(`./Editor-C_JYWteY.js`),__vite__mapDeps([28,1,29,8,30,4,31,24,32,25,33,15,34,16,35,17,36,11,7,21,37,38,39,40,41]))},{path:`deploy`,redirect:{name:`function-new`}},{path:`cron`,name:`cron`,component:()=>$(()=>import(`./CronJobs-CDFaee6D.js`),__vite__mapDeps([51,1,43,33,52,17,27,37]))},{path:`jobs`,name:`jobs`,component:()=>$(()=>import(`./Jobs-CfHJpgrS.js`),__vite__mapDeps([53,1,43,45,15,17,12,13,27]))},{path:`activity`,name:`activity`,component:()=>$(()=>import(`./Activity-6I8QCc07.js`),__vite__mapDeps([54,1,55,12,13,44,43,45]))},{path:`invocations`,name:`invocations`,component:()=>$(()=>import(`./InvocationsLog-Bz2zpa_f.js`),__vite__mapDeps([56,1,8,2,33,26,15,16,17,11,7,12,13,21,44,43,45,39]))},{path:`traces`,name:`traces`,component:()=>$(()=>import(`./Traces-BEuuXgIG.js`),__vite__mapDeps([57,1,58,26,44,43,45]))},{path:`traces/:id`,name:`trace-detail`,component:()=>$(()=>import(`./TraceDetail-wVyyYiTv.js`),__vite__mapDeps([59,1,60,2,4,58,44,43,45]))},{path:`api-keys`,name:`api-keys`,component:()=>$(()=>import(`./ApiKeys-B5PU7HpA.js`),__vite__mapDeps([61,1,8,4,32,17,21,27,62]))},{path:`channels`,name:`channels`,component:()=>$(()=>import(`./Channels-fKQl2oE8.js`),__vite__mapDeps([63,1,8,2,4,15,17,21,27,62]))},{path:`webhooks`,name:`webhooks`,component:()=>$(()=>import(`./Webhooks-D2CkyonR.js`),__vite__mapDeps([64,1,8,4,15,52,17,18,21,27,37]))},{path:`firewall`,name:`firewall`,component:()=>$(()=>import(`./Firewall-Bpe5shll.js`),__vite__mapDeps([65,1,24,26,34,17,11,7,37,40,66]))},{path:`settings`,name:`settings`,component:()=>$(()=>import(`./Settings-Bjj6gg_h.js`),__vite__mapDeps([67,1,4,9,10,8,11,7,12,13,32,35,17,21,62,40]))},{path:`docs`,name:`docs`,component:()=>$(()=>import(`./Docs-BssSTQCS.js`),__vite__mapDeps([68,1,8,55,4,24,32,25,36,11,7,19,20,21,39,69]))}]},{path:`/:pathMatch(.*)*`,name:`not-found`,component:()=>$(()=>import(`./NotFound-b7MSgvru.js`),__vite__mapDeps([70,1,60,29])),meta:{requiresAuth:!1}}]});Mo.beforeEach((e,t,n)=>{if(t.fullPath===e.fullPath&&t.name)return n(!1);n()}),Mo.beforeEach(async(e,t,n)=>{let r=Fi();if(!await r.fetchAuthStatus())return e.name===`onboarding`?n():n({name:`onboarding`,replace:!0});if(r.isAuthenticated===!1&&await r.checkAuth(),r.isAuthenticated)return e.name===`onboarding`||e.name===`login`?n({name:`dashboard`}):n();if(e.name===`login`)return n();if(e.name===`onboarding`)return n({name:`login`,replace:!0});n({name:`login`,query:{redirect:e.fullPath}})});var No=Wt(Ln),Po=ve();No.use(Po),No.use(Mo),No.mount(`#app`);export{Ra as $,Oa as A,nn as At,pa as B,Rt as Bt,ma as C,gn as Ct,oo as D,on as Dt,Sa as E,ln as Et,za as F,Ot as Ft,La as G,ba as H,Fa as I,kt as It,fo as J,uo as K,Za as L,Tt as Lt,Da as M,je as Mt,Ta as N,Et as Nt,lo as O,an as Ot,Ma as P,Nt as Pt,Ia as Q,Ka as R,Je as Rt,Ca as S,_n as St,xa as T,mn as Tt,no as U,yo as V,ga as W,io as X,wa as Y,vo as Z,va as _,En as _t,qa as a,$a as at,Wa as b,xn as bt,Qa as c,co as ct,Pa as d,Fi as dt,Ja as et,Ha as f,wi as ft,ao as g,Dn as gt,xo as h,kn as ht,eo as i,go as it,Ea as j,q as jt,ya as k,rn as kt,bo as l,Bi as lt,ja as m,Xn as mt,To as n,so as nt,Na as o,Aa as ot,to as p,Zn as pt,_o as q,Co as r,_a as rt,Ba as s,mo as st,$ as t,Va as tt,po as u,Ii as ut,ho as v,Cn as vt,ha as w,hn as wt,Ga as x,vn as xt,ro as y,Sn as yt,ka as z,Bt as zt}; \ No newline at end of file +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Login-yy2M_6WN.js","assets/runtime-core.esm-bundler-BMQPyJ_W.js","assets/circle-alert-CwieDBHo.js","assets/Onboarding-CEzpQ2g5.js","assets/copy-3UAsea5P.js","assets/Dashboard-DdzpeDBo.js","assets/AI-5L2rM3_1.js","assets/axios-DVDuIpRy.js","assets/check-CZmR72iA.js","assets/ModelMenu-D7Iysg0v.js","assets/pinia-B41TZNUX.js","assets/client-BF51V3uE.js","assets/Drawer-CSwYBfhJ.js","assets/Drawer-9hPWZO7g.css","assets/pencil-BmuCVcyO.js","assets/rotate-ccw-DgujV-4F.js","assets/sparkles-BZcVxan3.js","assets/trash-2-Cz9PSE2q.js","assets/zap-BF0H8u1s.js","assets/github-dark-D7LxIVih.js","assets/github-dark-C8LL_u4z.css","assets/clipboard-D_9N0yai.js","assets/AI-DWprRWt2.css","assets/FunctionsList-CqkUOCmN.js","assets/globe-DJC2u-h_.js","assets/lock-n1lM5kKa.js","assets/refresh-cw-CEfUzOcv.js","assets/IconButton-CsCZOqWo.js","assets/Editor--ZYS7LkE.js","assets/book-open-DQ3Rz8Ui.js","assets/git-compare-BnvFSVmQ.js","assets/settings-2-C0pnmjU4.js","assets/key-round-D9wVuhgl.js","assets/play-CnkMURxf.js","assets/shield-check-CowI6J3x.js","assets/terminal-Czs3Hy-Y.js","assets/variable-DFVSR15i.js","assets/Modal-C1IBLm0r.js","assets/rollbackDiff-DsaWcdbl.js","assets/aiPrompts-XrsFCpj_.js","assets/Input-DQ-tWGkn.js","assets/Editor-4XWCDeWw.css","assets/Deployments-BvLjnxyG.js","assets/clock-CIjbNepe.js","assets/StatusBadge-BpEw6z9Z.js","assets/circle-DhZmtdqu.js","assets/FunctionDiff-CpSHReET.js","assets/dist-CR15Grce.js","assets/FunctionDiff-C-FH-cay.css","assets/KVStore-B42u_-WY.js","assets/InboundWebhooks-DlQkZ2lf.js","assets/CronJobs-Ches-sRR.js","assets/square-pen-Ctkj2Y_N.js","assets/Jobs-DuQCYFLA.js","assets/Activity-BCmI00tZ.js","assets/chevron-right-D5C5fM5p.js","assets/InvocationsLog-DEPmQG0y.js","assets/Traces-BoBh7dBt.js","assets/flag-C__IsWHC.js","assets/TraceDetail-C28REiIi.js","assets/arrow-left-DTH7GseC.js","assets/ApiKeys-B1jjrPlM.js","assets/time-D8OmbYzY.js","assets/Channels-B3r_Mr9x.js","assets/Webhooks-BHh3seUT.js","assets/Firewall-qk4ey7XG.js","assets/Firewall-Cdy796t2.css","assets/Settings-CTZtncIj.js","assets/Docs-CMWnQ8Ew.js","assets/Docs-D8AUJ3IN.css","assets/NotFound-PtAc3nsW.js"])))=>i.map(i=>d[i]); +import{t as e}from"./axios-DVDuIpRy.js";import{$ as t,A as n,D as r,E as i,F as a,G as o,I as s,K as c,M as l,O as u,P as d,Q as f,T as p,U as m,W as h,Z as g,_,a as v,at as y,b,c as x,ct as S,d as C,dt as w,et as T,f as E,ft as D,gt as O,h as k,ht as A,i as ee,it as j,j as te,k as M,l as N,lt as ne,m as re,mt as ie,n as ae,nt as oe,o as se,ot as ce,pt as P,q as le,r as F,rt as ue,s as I,st as de,t as fe,tt as pe,u as L,ut as me,v as he,vt as R,x as z,yt as ge}from"./runtime-core.esm-bundler-BMQPyJ_W.js";import{n as _e,t as ve}from"./pinia-B41TZNUX.js";import{n as ye,t as B}from"./client-BF51V3uE.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),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var be=void 0,xe=typeof window<`u`&&window.trustedTypes;if(xe)try{be=xe.createPolicy(`vue`,{createHTML:e=>e})}catch{}var Se=be?e=>be.createHTML(e):e=>e,Ce=`http://www.w3.org/2000/svg`,we=`http://www.w3.org/1998/Math/MathML`,V=typeof document<`u`?document:null,Te=V&&V.createElement(`template`),Ee={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{let t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{let i=t===`svg`?V.createElementNS(Ce,e):t===`mathml`?V.createElementNS(we,e):n?V.createElement(e,{is:n}):V.createElement(e);return e===`select`&&r&&r.multiple!=null&&i.setAttribute(`multiple`,r.multiple),i},createText:e=>V.createTextNode(e),createComment:e=>V.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>V.querySelector(e),setScopeId(e,t){e.setAttribute(t,``)},insertStaticContent(e,t,n,r,i,a){let o=n?n.previousSibling:t.lastChild;if(i&&(i===a||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),n),!(i===a||!(i=i.nextSibling)););else{Te.innerHTML=Se(r===`svg`?`${e}`:r===`mathml`?`${e}`:e);let i=Te.content;if(r===`svg`||r===`mathml`){let e=i.firstChild;for(;e.firstChild;)i.appendChild(e.firstChild);i.removeChild(e)}t.insertBefore(i,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},H=`transition`,De=`animation`,Oe=Symbol(`_vtc`),ke={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Ae=T({},ae,ke),je=(e=>(e.displayName=`Transition`,e.props=Ae,e))((e,{slots:t})=>he(fe,Pe(e),t)),Me=(e,t=[])=>{j(e)?e.forEach(e=>e(...t)):e&&e(...t)},Ne=e=>e?j(e)?e.some(e=>e.length>1):e.length>1:!1;function Pe(e){let t={};for(let n in e)n in ke||(t[n]=e[n]);if(e.css===!1)return t;let{name:n=`v`,type:r,duration:i,enterFromClass:a=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:s=`${n}-enter-to`,appearFromClass:c=a,appearActiveClass:l=o,appearToClass:u=s,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:f=`${n}-leave-active`,leaveToClass:p=`${n}-leave-to`}=e,m=Fe(i),h=m&&m[0],g=m&&m[1],{onBeforeEnter:_,onEnter:v,onEnterCancelled:y,onLeave:b,onLeaveCancelled:x,onBeforeAppear:S=_,onAppear:C=v,onAppearCancelled:w=y}=t,E=(e,t,n,r)=>{e._enterCancelled=r,Le(e,t?u:s),Le(e,t?l:o),n&&n()},D=(e,t)=>{e._isLeaving=!1,Le(e,d),Le(e,p),Le(e,f),t&&t()},O=e=>(t,n)=>{let i=e?C:v,o=()=>E(t,e,n);Me(i,[t,o]),Re(()=>{Le(t,e?c:a),U(t,e?u:s),Ne(i)||Be(t,r,h,o)})};return T(t,{onBeforeEnter(e){Me(_,[e]),U(e,a),U(e,o)},onBeforeAppear(e){Me(S,[e]),U(e,c),U(e,l)},onEnter:O(!1),onAppear:O(!0),onLeave(e,t){e._isLeaving=!0;let n=()=>D(e,t);U(e,d),e._enterCancelled?(U(e,f),We(e)):(We(e),U(e,f)),Re(()=>{e._isLeaving&&(Le(e,d),U(e,p),Ne(b)||Be(e,r,g,n))}),Me(b,[e,n])},onEnterCancelled(e){E(e,!1,void 0,!0),Me(y,[e])},onAppearCancelled(e){E(e,!0,void 0,!0),Me(w,[e])},onLeaveCancelled(e){D(e),Me(x,[e])}})}function Fe(e){if(e==null)return null;if(de(e))return[Ie(e.enter),Ie(e.leave)];{let t=Ie(e);return[t,t]}}function Ie(e){return ge(e)}function U(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.add(t)),(e[Oe]||(e[Oe]=new Set)).add(t)}function Le(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.remove(t));let n=e[Oe];n&&(n.delete(t),n.size||(e[Oe]=void 0))}function Re(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}var ze=0;function Be(e,t,n,r){let i=e._endId=++ze,a=()=>{i===e._endId&&r()};if(n!=null)return setTimeout(a,n);let{type:o,timeout:s,propCount:c}=Ve(e,t);if(!o)return r();let l=o+`end`,u=0,d=()=>{e.removeEventListener(l,f),a()},f=t=>{t.target===e&&++u>=c&&d()};setTimeout(()=>{u(n[e]||``).split(`, `),i=r(`${H}Delay`),a=r(`${H}Duration`),o=He(i,a),s=r(`${De}Delay`),c=r(`${De}Duration`),l=He(s,c),u=null,d=0,f=0;t===H?o>0&&(u=H,d=o,f=a.length):t===De?l>0&&(u=De,d=l,f=c.length):(d=Math.max(o,l),u=d>0?o>l?H:De:null,f=u?u===H?a.length:c.length:0);let p=u===H&&/\b(?:transform|all)(?:,|$)/.test(r(`${H}Property`).toString());return{type:u,timeout:d,propCount:f,hasTransform:p}}function He(e,t){for(;e.lengthUe(t)+Ue(e[n])))}function Ue(e){return e===`auto`?0:Number(e.slice(0,-1).replace(`,`,`.`))*1e3}function We(e){return(e?e.ownerDocument:document).body.offsetHeight}function Ge(e,t,n){let r=e[Oe];r&&(t=(t?[t,...r]:[...r]).join(` `)),t==null?e.removeAttribute(`class`):n?e.setAttribute(`class`,t):e.className=t}var Ke=Symbol(`_vod`),qe=Symbol(`_vsh`),Je={name:`show`,beforeMount(e,{value:t},{transition:n}){e[Ke]=e.style.display===`none`?``:e.style.display,n&&t?n.beforeEnter(e):Ye(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Ye(e,!0),r.enter(e)):r.leave(e,()=>{Ye(e,!1)}):Ye(e,t))},beforeUnmount(e,{value:t}){Ye(e,t)}};function Ye(e,t){e.style.display=t?e[Ke]:`none`,e[qe]=!t}var Xe=Symbol(``),Ze=/(?:^|;)\s*display\s*:/;function Qe(e,t,n){let r=e.style,i=w(n),a=!1;if(n&&!i){if(t)if(w(t))for(let e of t.split(`;`)){let t=e.slice(0,e.indexOf(`:`)).trim();n[t]??et(r,t,``)}else for(let e in t)n[e]??et(r,e,``);for(let i in n){i===`display`&&(a=!0);let o=n[i];o==null?et(r,i,``):it(e,i,!w(t)&&t?t[i]:void 0,o)||et(r,i,o)}}else if(i){if(t!==n){let e=r[Xe];e&&(n+=`;`+e),r.cssText=n,a=Ze.test(n)}}else t&&e.removeAttribute(`style`);Ke in e&&(e[Ke]=a?r.display:``,e[qe]&&(r.display=`none`))}var $e=/\s*!important$/;function et(e,t,n){if(j(n))n.forEach(n=>et(e,t,n));else if(n??=``,t.startsWith(`--`))e.setProperty(t,n);else{let r=rt(e,t);$e.test(n)?e.setProperty(pe(r),n.replace($e,``),`important`):e[r]=n}}var tt=[`Webkit`,`Moz`,`ms`],nt={};function rt(e,n){let r=nt[n];if(r)return r;let i=f(n);if(i!==`filter`&&i in e)return nt[n]=i;i=t(i);for(let t=0;tmt||=(ht.then(()=>mt=0),Date.now());function _t(e,t){let n=e=>{if(!e._vts)e._vts=Date.now();else if(e._vts<=n.attached)return;let r=n.value;if(j(r)){let n=e.stopImmediatePropagation;e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0};let i=r.slice(),a=[e];for(let n=0;ne.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,yt=(e,t,n,r,i,a)=>{let o=i===`svg`;t===`class`?Ge(e,r,o):t===`style`?Qe(e,n,r):S(t)?ce(t)||ut(e,t,n,r,a):(t[0]===`.`?(t=t.slice(1),!0):t[0]===`^`?(t=t.slice(1),!1):bt(e,t,r,o))?(st(e,t,r),!e.tagName.includes(`-`)&&(t===`value`||t===`checked`||t===`selected`)&&ot(e,t,r,o,a,t!==`value`)):e._isVueCE&&(xt(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!w(r)))?st(e,f(t),r,a,t):(t===`true-value`?e._trueValue=r:t===`false-value`&&(e._falseValue=r),ot(e,t,r,o))};function bt(e,t,n,r){if(r)return!!(t===`innerHTML`||t===`textContent`||t in e&&vt(t)&&y(n));if(t===`spellcheck`||t===`draggable`||t===`translate`||t===`autocorrect`||t===`sandbox`&&e.tagName===`IFRAME`||t===`form`||t===`list`&&e.tagName===`INPUT`||t===`type`&&e.tagName===`TEXTAREA`)return!1;if(t===`width`||t===`height`){let t=e.tagName;if(t===`IMG`||t===`VIDEO`||t===`CANVAS`||t===`SOURCE`)return!1}return vt(t)&&w(n)?!1:t in e}function xt(e,t){let n=e._def.props;if(!n)return!1;let r=f(t);return Array.isArray(n)?n.some(e=>f(e)===r):Object.keys(n).some(e=>f(e)===r)}var G=e=>{let t=e.props[`onUpdate:modelValue`]||!1;return j(t)?e=>ue(t,e):t};function St(e){e.target.composing=!0}function Ct(e){let t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event(`input`)))}var K=Symbol(`_assign`);function wt(e,t,n){return t&&(e=e.trim()),n&&(e=A(e)),e}var Tt={created(e,{modifiers:{lazy:t,trim:n,number:r}},i){e[K]=G(i);let a=r||i.props&&i.props.type===`number`;W(e,t?`change`:`input`,t=>{t.target.composing||e[K](wt(e.value,n,a))}),(n||a)&&W(e,`change`,()=>{e.value=wt(e.value,n,a)}),t||(W(e,`compositionstart`,St),W(e,`compositionend`,Ct),W(e,`change`,Ct))},mounted(e,{value:t}){e.value=t??``},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:i,number:a}},o){if(e[K]=G(o),e.composing)return;let s=(a||e.type===`number`)&&!/^0\d/.test(e.value)?A(e.value):e.value,c=t??``;if(s===c)return;let l=e.getRootNode();(l instanceof Document||l instanceof ShadowRoot)&&l.activeElement===e&&e.type!==`range`&&(r&&t===n||i&&e.value.trim()===c)||(e.value=c)}},Et={deep:!0,created(e,t,n){e[K]=G(n),W(e,`change`,()=>{let t=e._modelValue,n=jt(e),r=e.checked,i=e[K];if(j(t)){let e=ie(t,n),a=e!==-1;if(r&&!a)i(t.concat(n));else if(!r&&a){let n=[...t];n.splice(e,1),i(n)}}else if(ne(t)){let e=new Set(t);r?e.add(n):e.delete(n),i(e)}else i(Mt(e,r))})},mounted:Dt,beforeUpdate(e,t,n){e[K]=G(n),Dt(e,t,n)}};function Dt(e,{value:t,oldValue:n},r){e._modelValue=t;let i;if(j(t))i=ie(t,r.props.value)>-1;else if(ne(t))i=t.has(r.props.value);else{if(t===n)return;i=P(t,Mt(e,!0))}e.checked!==i&&(e.checked=i)}var Ot={created(e,{value:t},n){e.checked=P(t,n.props.value),e[K]=G(n),W(e,`change`,()=>{e[K](jt(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[K]=G(r),t!==n&&(e.checked=P(t,r.props.value))}},kt={deep:!0,created(e,{value:t,modifiers:{number:n}},r){e._modelValue=t,W(e,`change`,()=>{let t=Array.prototype.filter.call(e.options,e=>e.selected).map(e=>n?A(jt(e)):jt(e));e[K](e.multiple?ne(e._modelValue)?new Set(t):t:t[0]),e._assigning=!0,z(()=>{e._assigning=!1})}),e[K]=G(r)},mounted(e,{value:t}){At(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[K]=G(n)},updated(e,{value:t}){e._assigning||At(e,t)}};function At(e,t){let n=e.multiple,r=j(t);if(!(n&&!r&&!ne(t))){for(let i=0,a=e.options.length;iString(e)===String(o)):ie(t,o)>-1}else a.selected=t.has(o);else if(P(jt(a),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function jt(e){return`_value`in e?e._value:e.value}function Mt(e,t){let n=t?`_trueValue`:`_falseValue`;return n in e?e[n]:t}var Nt={created(e,t,n){Ft(e,t,n,null,`created`)},mounted(e,t,n){Ft(e,t,n,null,`mounted`)},beforeUpdate(e,t,n,r){Ft(e,t,n,r,`beforeUpdate`)},updated(e,t,n,r){Ft(e,t,n,r,`updated`)}};function Pt(e,t){switch(e){case`SELECT`:return kt;case`TEXTAREA`:return Tt;default:switch(t){case`checkbox`:return Et;case`radio`:return Ot;default:return Tt}}}function Ft(e,t,n,r,i){let a=Pt(e.tagName,n.props&&n.props.type)[i];a&&a(e,t,n,r)}var It=[`ctrl`,`shift`,`alt`,`meta`],Lt={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>`button`in e&&e.button!==0,middle:e=>`button`in e&&e.button!==1,right:e=>`button`in e&&e.button!==2,exact:(e,t)=>It.some(n=>e[`${n}Key`]&&!t.includes(n))},Rt=(e,t)=>{if(!e)return e;let n=e._withMods||={},r=t.join(`.`);return n[r]||(n[r]=((n,...r)=>{for(let e=0;e{let n=e._withKeys||={},r=t.join(`.`);return n[r]||(n[r]=(n=>{if(!(`key`in n))return;let r=pe(n.key);if(t.some(e=>e===r||zt[e]===r))return e(n)}))},Vt=T({patchProp:yt},Ee),Ht;function Ut(){return Ht||=E(Vt)}var Wt=((...e)=>{let t=Ut().createApp(...e),{mount:n}=t;return t.mount=e=>{let r=Kt(e);if(!r)return;let i=t._component;!y(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent=``);let a=n(r,!1,Gt(r));return r instanceof Element&&(r.removeAttribute(`v-cloak`),r.setAttribute(`data-v-app`,``)),a},t});function Gt(e){if(e instanceof SVGElement)return`svg`;if(typeof MathMLElement==`function`&&e instanceof MathMLElement)return`mathml`}function Kt(e){return w(e)?document.querySelector(e):e}var qt=e=>e===``,Jt=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),Yt=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),Xt=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),Zt=e=>{let t=Xt(e);return t.charAt(0).toUpperCase()+t.slice(1)},Qt={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":2,"stroke-linecap":`round`,"stroke-linejoin":`round`},$t=Symbol(`lucide-icons`);function en(){return b($t,{})}var tn=({name:e,iconNode:t,"icon-node":n,absoluteStrokeWidth:r,"absolute-stroke-width":i,strokeWidth:a,"stroke-width":o,size:s,color:c,...l},{slots:u})=>{let{size:d,color:f,strokeWidth:p=2,absoluteStrokeWidth:m=!1,class:h=``}=en(),g=I(()=>{let e=qt(r)||qt(i)||r===!0||i===!0||m===!0,t=a||o||p||Qt[`stroke-width`];return e?Number(t)*24/Number(s??d??Qt.width):t});return he(`svg`,{...Qt,...l,width:s??d??Qt.width,height:s??d??Qt.height,stroke:c??f??Qt.stroke,"stroke-width":g.value,class:Jt(`lucide`,h,...e?[`lucide-${Yt(Zt(e))}-icon`,`lucide-${Yt(e)}`]:[`lucide-icon`])},[...(t??n??[]).map(e=>he(...e)),...u.default?[u.default()]:[]])},q=(e,t)=>(n,{slots:r,attrs:i})=>he(tn,{...i,...n,iconNode:t,name:e},r.default?{default:r.default}:void 0),nn=q(`activity`,[[`path`,{d:`M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2`,key:`169zse`}]]),rn=q(`boxes`,[[`path`,{d:`M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z`,key:`lc1i9w`}],[`path`,{d:`m7 16.5-4.74-2.85`,key:`1o9zyk`}],[`path`,{d:`m7 16.5 5-3`,key:`va8pkn`}],[`path`,{d:`M7 16.5v5.17`,key:`jnp8gn`}],[`path`,{d:`M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z`,key:`8zsnat`}],[`path`,{d:`m17 16.5-5-3`,key:`8arw3v`}],[`path`,{d:`m17 16.5 4.74-2.85`,key:`8rfmw`}],[`path`,{d:`M17 16.5v5.17`,key:`k6z78m`}],[`path`,{d:`M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z`,key:`1xygjf`}],[`path`,{d:`M12 8 7.26 5.15`,key:`1vbdud`}],[`path`,{d:`m12 8 4.74-2.85`,key:`3rx089`}],[`path`,{d:`M12 13.5V8`,key:`1io7kd`}]]),an=q(`calendar-clock`,[[`path`,{d:`M16 14v2.2l1.6 1`,key:`fo4ql5`}],[`path`,{d:`M16 2v3`,key:`otl347`}],[`path`,{d:`M21 7.338V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h2.338`,key:`7hb8p4`}],[`path`,{d:`M3 9h5.859`,key:`numkqi`}],[`path`,{d:`M8 2v3`,key:`1ioesn`}],[`circle`,{cx:`16`,cy:`16`,r:`6`,key:`qoo3c4`}]]),on=q(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),sn=q(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),cn=q(`fingerprint-pattern`,[[`path`,{d:`M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4`,key:`1nerag`}],[`path`,{d:`M14 13.12c0 2.38 0 6.38-1 8.88`,key:`o46ks0`}],[`path`,{d:`M17.29 21.02c.12-.6.43-2.3.5-3.02`,key:`ptglia`}],[`path`,{d:`M2 12a10 10 0 0 1 18-6`,key:`ydlgp0`}],[`path`,{d:`M2 16h.01`,key:`1gqxmh`}],[`path`,{d:`M21.8 16c.2-2 .131-5.354 0-6`,key:`drycrb`}],[`path`,{d:`M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2`,key:`1tidbn`}],[`path`,{d:`M8.65 22c.21-.66.45-1.32.57-2`,key:`13wd9y`}],[`path`,{d:`M9 6.8a6 6 0 0 1 9 5.2v2`,key:`1fr1j5`}]]),ln=q(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]),un=q(`library-big`,[[`rect`,{width:`8`,height:`18`,x:`3`,y:`3`,rx:`1`,key:`oynpb5`}],[`path`,{d:`M7 3v18`,key:`bbkbws`}],[`path`,{d:`M20.4 18.9c.2.5-.1 1.1-.6 1.3l-1.9.7c-.5.2-1.1-.1-1.3-.6L11.1 5.1c-.2-.5.1-1.1.6-1.3l1.9-.7c.5-.2 1.1.1 1.3.6Z`,key:`1qboyk`}]]),dn=q(`list-checks`,[[`path`,{d:`M13 5h8`,key:`a7qcls`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`m3 17 2 2 4-4`,key:`1jhpwq`}],[`path`,{d:`m3 7 2 2 4-4`,key:`1obspn`}]]),fn=q(`list-tree`,[[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`M3 10a2 2 0 0 0 2 2h3`,key:`1npucw`}],[`path`,{d:`M3 5v12a2 2 0 0 0 2 2h3`,key:`x1gjn2`}]]),pn=q(`menu`,[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]),mn=q(`messages-square`,[[`path`,{d:`M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z`,key:`1n2ejm`}],[`path`,{d:`M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1`,key:`1qfcsi`}]]),hn=q(`network`,[[`rect`,{x:`16`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`4q2zg0`}],[`rect`,{x:`2`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`8cvhb9`}],[`rect`,{x:`9`,y:`2`,width:`6`,height:`6`,rx:`1`,key:`1egb70`}],[`path`,{d:`M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3`,key:`1jsf9p`}],[`path`,{d:`M12 12V8`,key:`2874zd`}]]),gn=q(`plug`,[[`path`,{d:`M12 22v-5`,key:`1ega77`}],[`path`,{d:`M15 8V2`,key:`18g5xt`}],[`path`,{d:`M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z`,key:`1xoxul`}],[`path`,{d:`M9 8V2`,key:`14iosj`}]]),_n=q(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),vn=q(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]),yn=q(`settings`,[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),bn=q(`shield-half`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 22V2`,key:`zs6s6o`}]]),xn=q(`triangle-alert`,[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),Sn=q(`webhook`,[[`path`,{d:`M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2`,key:`q3hayz`}],[`path`,{d:`m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06`,key:`1go1hn`}],[`path`,{d:`m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8`,key:`qlwsc0`}]]),Cn=q(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),wn=[`disabled`],Tn={key:0,class:`animate-spin -ml-1 mr-2 h-4 w-4`,xmlns:`http://www.w3.org/2000/svg`,fill:`none`,viewBox:`0 0 24 24`},En={__name:`Button`,props:{variant:{type:String,default:`primary`,validator:e=>[`primary`,`secondary`,`danger`,`ghost`,`chip`].includes(e)},size:{type:String,default:`md`,validator:e=>[`xs`,`sm`,`md`,`lg`].includes(e)},active:{type:Boolean,default:!1},disabled:Boolean,loading:Boolean},setup(e){let t=e,i=I(()=>{switch(t.size){case`xs`:return`h-7 px-2.5 text-xs touch-expand-xs`;case`sm`:return`h-8 px-3 text-xs touch-expand-sm`;case`lg`:return`h-12 px-6 text-base`;default:return`h-10 px-4 text-sm`}}),a=I(()=>{switch(t.variant){case`secondary`:return`bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border shadow-sm`;case`danger`:return`bg-danger text-foreground-strong border border-danger hover:bg-danger-fg focus-visible:ring-danger shadow-sm`;case`ghost`:return`bg-transparent text-foreground-muted hover:text-foreground hover:bg-surface-hover`;case`chip`:return t.active?`bg-primary text-primary-foreground border border-primary`:`bg-surface text-foreground-muted border border-border hover:text-white hover:border-foreground-muted`;default:return`bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary shadow-sm border border-transparent`}});return(t,o)=>(r(),C(`button`,{class:O([`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:opacity-50 disabled:cursor-not-allowed`,i.value,a.value]),disabled:e.disabled||e.loading},[e.loading?(r(),C(`svg`,Tn,[...o[0]||=[x(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`},null,-1),x(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`},null,-1)]])):L(``,!0),n(t.$slots,`default`)],10,wn))}},Dn=_e(`confirm`,()=>{let e=o(!1),t=o(``),n=o(``),r=o(`Confirm`),i=o(`Cancel`),a=o(!1),s=o(!1),c=o(!1),l=o(``),u=o(``),d=null;return{visible:e,title:t,message:n,confirmLabel:r,cancelLabel:i,danger:a,noticeOnly:s,promptMode:c,promptValue:l,promptPlaceholder:u,ask:(o={})=>(t.value=o.title||`Are you sure?`,n.value=o.message||``,r.value=o.confirmLabel||`Confirm`,i.value=o.cancelLabel||`Cancel`,a.value=!!o.danger,s.value=!1,c.value=!1,e.value=!0,new Promise(e=>{d=e})),notify:(i={})=>(t.value=i.title||`Notice`,n.value=i.message||``,r.value=i.confirmLabel||`OK`,a.value=!!i.danger,s.value=!0,c.value=!1,e.value=!0,new Promise(e=>{d=e})),prompt:(o={})=>(t.value=o.title||`Enter a value`,n.value=o.message||``,r.value=o.confirmLabel||`OK`,i.value=o.cancelLabel||`Cancel`,a.value=!!o.danger,s.value=!1,c.value=!0,l.value=o.defaultValue||``,u.value=o.placeholder||``,e.value=!0,new Promise(e=>{d=e})),settle:t=>{e.value=!1,d&&=(c.value?d(t?l.value:null):d(t),null),c.value=!1}}}),On=[`a[href]`,`button:not([disabled])`,`input:not([disabled]):not([type="hidden"])`,`textarea:not([disabled])`,`select:not([disabled])`,`[tabindex]:not([tabindex="-1"])`,`audio[controls]`,`video[controls]`,`details > summary`].join(`,`);function kn(e,t){let n=null,r=null,i=null,a=async()=>{n=document.activeElement instanceof HTMLElement?document.activeElement:null,i=document.getElementById(`app`),i&&i.setAttribute(`inert`,``),await z();let t=e.value;t&&((t.querySelector(`[autofocus]`)||t.querySelector(On))?.focus?.(),r=e=>{if(e.key!==`Tab`)return;let n=Array.from(t.querySelectorAll(On)).filter(e=>!e.hasAttribute(`inert`)&&e.offsetParent!==null);if(!n.length){e.preventDefault();return}let r=n[0],i=n[n.length-1],a=document.activeElement;e.shiftKey&&a===r?(e.preventDefault(),i.focus()):!e.shiftKey&&a===i&&(e.preventDefault(),r.focus())},document.addEventListener(`keydown`,r))},o=()=>{r&&=(document.removeEventListener(`keydown`,r),null),i&&=(i.removeAttribute(`inert`),null),n&&n.isConnected&&typeof n.focus==`function`&&n.focus(),n=null};d(t,e=>{e?a():o()},{immediate:!1})}var An={class:`flex items-start gap-3`},jn={class:`flex-1 min-w-0`},Mn={key:0,class:`text-sm text-foreground-muted mt-1 whitespace-pre-line break-words`},Nn=[`placeholder`],Pn={class:`flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2`},Fn=`confirm-dialog-title`,In={__name:`ConfirmDialog`,setup(e){let t=Dn(),n=o(null),c=o(null);kn(c,I(()=>t.visible)),d(()=>t.visible&&t.promptMode,e=>{e&&z(()=>{let e=n.value;e&&(e.focus(),window.innerWidth<640&&setTimeout(()=>{e.scrollIntoView({block:`center`,behavior:`smooth`})},50))})});let l=e=>{t.visible&&(e.key===`Escape`&&t.settle(!1),e.key===`Enter`&&!t.promptMode&&t.settle(!0))};return p(()=>window.addEventListener(`keydown`,l)),i(()=>window.removeEventListener(`keydown`,l)),(e,i)=>(r(),N(v,{to:`body`},[k(je,{name:`fade`},{default:a(()=>[g(t).visible?(r(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm pt-safe pb-safe pl-safe pr-safe p-2 sm:p-4`,onClick:i[4]||=Rt(e=>g(t).settle(!1),[`self`]),onKeydown:i[5]||=Bt(e=>g(t).settle(!1),[`esc`])},[x(`div`,{ref_key:`dialogRoot`,ref:c,class:`w-full sm:max-w-md bg-background border border-border rounded-t-lg sm:rounded-lg shadow-xl p-5 sm:p-6 space-y-4 max-h-[calc(100dvh-1rem)] overflow-y-auto scrollable`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Fn},[x(`div`,An,[g(t).promptMode?L(``,!0):(r(),C(`div`,{key:0,class:O([`shrink-0 w-9 h-9 rounded-full flex items-center justify-center`,g(t).danger?`bg-red-500/15 text-red-400`:`bg-primary/15 text-primary`])},[g(t).danger?(r(),N(g(xn),{key:0,class:`w-5 h-5`})):(r(),N(g(sn),{key:1,class:`w-5 h-5`}))],2)),x(`div`,jn,[x(`h3`,{id:Fn,class:`text-sm font-semibold text-white tracking-tight`},R(g(t).title),1),g(t).message?(r(),C(`p`,Mn,R(g(t).message),1)):L(``,!0),g(t).promptMode?s((r(),C(`input`,{key:1,ref_key:`promptInput`,ref:n,"onUpdate:modelValue":i[0]||=e=>g(t).promptValue=e,placeholder:g(t).promptPlaceholder,type:`text`,class:`mt-3 w-full bg-background border border-border rounded-md px-3 py-2 text-base sm:text-sm text-foreground placeholder-foreground-muted/50 transition-colors duration-200 focus:outline-none focus:ring-1 focus:ring-white focus:border-white`,onKeydown:i[1]||=Bt(Rt(e=>g(t).settle(!0),[`stop`,`prevent`]),[`enter`])},null,40,Nn)),[[Tt,g(t).promptValue]]):L(``,!0)])]),x(`div`,Pn,[g(t).noticeOnly?L(``,!0):(r(),N(En,{key:0,variant:`secondary`,class:`w-full sm:w-auto`,onClick:i[2]||=e=>g(t).settle(!1)},{default:a(()=>[re(R(g(t).cancelLabel),1)]),_:1})),k(En,{variant:g(t).danger?`danger`:`primary`,class:`w-full sm:w-auto`,onClick:i[3]||=e=>g(t).settle(!0)},{default:a(()=>[re(R(g(t).confirmLabel),1)]),_:1},8,[`variant`])])],512)],32)):L(``,!0)]),_:1})]))}},Ln={__name:`App`,setup(e){return(e,t)=>{let n=te(`router-view`);return r(),C(F,null,[k(n),k(In)],64)}}};function Rn(e){return typeof e==`object`||`displayName`in e||`props`in e||`__vccOpts`in e}function zn(e){return e.__esModule||e[Symbol.toStringTag]===`Module`||e.default&&Rn(e.default)}var J=Object.assign;function Bn(e,t){let n={};for(let r in t){let i=t[r];n[r]=Y(i)?i.map(e):e(i)}return n}var Vn=()=>{},Y=Array.isArray;function Hn(e,t){let n={};for(let r in e)n[r]=r in t?t[r]:e[r];return n}var Un=Symbol(``);function Wn(e,t){return J(Error(),{type:e,[Un]:!0},t)}function X(e,t){return e instanceof Error&&Un in e&&(t==null||!!(e.type&t))}var Gn=Symbol(``),Kn=Symbol(``),qn=Symbol(``),Jn=Symbol(``),Yn=Symbol(``);function Xn(){return b(qn)}function Zn(e){return b(Jn)}var Qn=typeof document<`u`,$n=/#/g,er=/&/g,tr=/\//g,nr=/=/g,rr=/\?/g,ir=/\+/g,ar=/%5B/g,or=/%5D/g,sr=/%5E/g,cr=/%60/g,lr=/%7B/g,ur=/%7C/g,dr=/%7D/g,fr=/%20/g;function pr(e){return e==null?``:encodeURI(``+e).replace(ur,`|`).replace(ar,`[`).replace(or,`]`)}function mr(e){return pr(e).replace(lr,`{`).replace(dr,`}`).replace(sr,`^`)}function hr(e){return pr(e).replace(ir,`%2B`).replace(fr,`+`).replace($n,`%23`).replace(er,`%26`).replace(cr,"`").replace(lr,`{`).replace(dr,`}`).replace(sr,`^`)}function gr(e){return hr(e).replace(nr,`%3D`)}function _r(e){return pr(e).replace($n,`%23`).replace(rr,`%3F`)}function vr(e){return _r(e).replace(tr,`%2F`)}function yr(e){if(e==null)return null;try{return decodeURIComponent(``+e)}catch{}return``+e}var br=/\/$/,xr=e=>e.replace(br,``);function Sr(e,t,n=`/`){let r,i={},a=``,o=``,s=t.indexOf(`#`),c=t.indexOf(`?`);return c=s>=0&&c>s?-1:c,c>=0&&(r=t.slice(0,c),a=t.slice(c,s>0?s:t.length),i=e(a.slice(1))),s>=0&&(r||=t.slice(0,s),o=t.slice(s,t.length)),r=Ar(r??t,n),{fullPath:r+a+o,path:r,query:i,hash:yr(o)}}function Cr(e,t){let n=t.query?e(t.query):``;return t.path+(n&&`?`)+n+(t.hash||``)}function wr(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||`/`}function Tr(e,t,n){let r=t.matched.length-1,i=n.matched.length-1;return r>-1&&r===i&&Er(t.matched[r],n.matched[i])&&Dr(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Er(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Dr(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(!Or(e[n],t[n]))return!1;return!0}function Or(e,t){return Y(e)?kr(e,t):Y(t)?kr(t,e):(e&&e.valueOf())===(t&&t.valueOf())}function kr(e,t){return Y(t)?e.length===t.length&&e.every((e,n)=>e===t[n]):e.length===1&&e[0]===t}function Ar(e,t){if(e.startsWith(`/`))return e;if(!e)return t;let n=t.split(`/`),r=e.split(`/`),i=r[r.length-1];(i===`..`||i===`.`)&&r.push(``);let a=n.length-1,o,s;for(o=0;o1&&a--;else break;return n.slice(0,a).join(`/`)+`/`+r.slice(o).join(`/`)}var Z={path:`/`,name:void 0,params:{},query:{},hash:``,fullPath:`/`,matched:[],meta:{},redirectedFrom:void 0};function jr(e){if(!e)if(Qn){let t=document.querySelector(`base`);e=t&&t.getAttribute(`href`)||`/`,e=e.replace(/^\w+:\/\/[^/]+/,``)}else e=`/`;return e[0]!==`/`&&e[0]!==`#`&&(e=`/`+e),xr(e)}var Mr=/^[^#]+#/;function Nr(e,t){return e.replace(Mr,`#`)+t}function Pr(e,t){let n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}var Fr=()=>({left:window.scrollX,top:window.scrollY});function Ir(e){let t;if(`el`in e){let n=e.el,r=typeof n==`string`&&n.startsWith(`#`),i=typeof n==`string`?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!i)return;t=Pr(i,e)}else t=e;`scrollBehavior`in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left==null?window.scrollX:t.left,t.top==null?window.scrollY:t.top)}function Lr(e,t){return(history.state?history.state.position-t:-1)+e}var Rr=new Map;function zr(e,t){Rr.set(e,t)}function Br(e){let t=Rr.get(e);return Rr.delete(e),t}function Vr(e){return typeof e==`string`||e&&typeof e==`object`}function Hr(e){return typeof e==`string`||typeof e==`symbol`}function Ur(e){let t={};if(e===``||e===`?`)return t;let n=(e[0]===`?`?e.slice(1):e).split(`&`);for(let e=0;ee&&hr(e)):[r&&hr(r)]).forEach(e=>{e!==void 0&&(t+=(t.length?`&`:``)+n,e!=null&&(t+=`=`+e))})}return t}function Gr(e){let t={};for(let n in e){let r=e[n];r!==void 0&&(t[n]=Y(r)?r.map(e=>e==null?null:``+e):r==null?r:``+r)}return t}function Kr(){let e=[];function t(t){return e.push(t),()=>{let n=e.indexOf(t);n>-1&&e.splice(n,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Q(e,t,n,r,i,a=e=>e()){let o=r&&(r.enterCallbacks[i]=r.enterCallbacks[i]||[]);return()=>new Promise((s,c)=>{let l=e=>{e===!1?c(Wn(4,{from:n,to:t})):e instanceof Error?c(e):Vr(e)?c(Wn(2,{from:t,to:e})):(o&&r.enterCallbacks[i]===o&&typeof e==`function`&&o.push(e),s())},u=a(()=>e.call(r&&r.instances[i],t,n,l)),d=Promise.resolve(u);e.length<3&&(d=d.then(l)),d.catch(e=>c(e))})}function qr(e,t,n,r,i=e=>e()){let a=[];for(let o of e)for(let e in o.components){let s=o.components[e];if(!(t!==`beforeRouteEnter`&&!o.instances[e]))if(Rn(s)){let c=(s.__vccOpts||s)[t];c&&a.push(Q(c,n,r,o,e,i))}else{let c=s();a.push(()=>c.then(a=>{if(!a)throw Error(`Couldn't resolve component "${e}" at "${o.path}"`);let s=zn(a)?a.default:a;o.mods[e]=a,o.components[e]=s;let c=(s.__vccOpts||s)[t];return c&&Q(c,n,r,o,e,i)()}))}}return a}function Jr(e,t){let n=[],r=[],i=[],a=Math.max(t.matched.length,e.matched.length);for(let o=0;oEr(e,a))?r.push(a):n.push(a));let s=e.matched[o];s&&(t.matched.find(e=>Er(e,s))||i.push(s))}return[n,r,i]}var Yr=()=>location.protocol+`//`+location.host;function Xr(e,t){let{pathname:n,search:r,hash:i}=t,a=e.indexOf(`#`);if(a>-1){let t=i.includes(e.slice(a))?e.slice(a).length:1,n=i.slice(t);return n[0]!==`/`&&(n=`/`+n),wr(n,``)}return wr(n,e)+r+i}function Zr(e,t,n,r){let i=[],a=[],o=null,s=({state:a})=>{let s=Xr(e,location),c=n.value,l=t.value,u=0;if(a){if(n.value=s,t.value=a,o&&o===c){o=null;return}u=l?a.position-l.position:0}else r(s);i.forEach(e=>{e(n.value,c,{delta:u,type:`pop`,direction:u?u>0?`forward`:`back`:``})})};function c(){o=n.value}function l(e){i.push(e);let t=()=>{let t=i.indexOf(e);t>-1&&i.splice(t,1)};return a.push(t),t}function u(){if(document.visibilityState===`hidden`){let{history:e}=window;if(!e.state)return;e.replaceState(J({},e.state,{scroll:Fr()}),``)}}function d(){for(let e of a)e();a=[],window.removeEventListener(`popstate`,s),window.removeEventListener(`pagehide`,u),document.removeEventListener(`visibilitychange`,u)}return window.addEventListener(`popstate`,s),window.addEventListener(`pagehide`,u),document.addEventListener(`visibilitychange`,u),{pauseListeners:c,listen:l,destroy:d}}function Qr(e,t,n,r=!1,i=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:i?Fr():null}}function $r(e){let{history:t,location:n}=window,r={value:Xr(e,n)},i={value:t.state};i.value||a(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function a(r,a,o){let s=e.indexOf(`#`),c=s>-1?(n.host&&document.querySelector(`base`)?e:e.slice(s))+r:Yr()+e+r;try{t[o?`replaceState`:`pushState`](a,``,c),i.value=a}catch(e){console.error(e),n[o?`replace`:`assign`](c)}}function o(e,n){a(e,J({},t.state,Qr(i.value.back,e,i.value.forward,!0),n,{position:i.value.position}),!0),r.value=e}function s(e,n){let o=J({},i.value,t.state,{forward:e,scroll:Fr()});a(o.current,o,!0),a(e,J({},Qr(r.value,e,null),{position:o.position+1},n),!1),r.value=e}return{location:r,state:i,push:s,replace:o}}function ei(e){e=jr(e);let t=$r(e),n=Zr(e,t.state,t.location,t.replace);function r(e,t=!0){t||n.pauseListeners(),history.go(e)}let i=J({location:``,base:e,go:r,createHref:Nr.bind(null,e)},t,n);return Object.defineProperty(i,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(i,"state",{enumerable:!0,get:()=>t.state.value}),i}var ti={type:0,value:``},ni=/[a-zA-Z0-9_]/;function ri(e){if(!e)return[[]];if(e===`/`)return[[ti]];if(!e.startsWith(`/`))throw Error(`Invalid path "${e}"`);function t(e){throw Error(`ERR (${n})/"${l}": ${e}`)}let n=0,r=n,i=[],a;function o(){a&&i.push(a),a=[]}let s=0,c,l=``,u=``;function d(){l&&=(n===0?a.push({type:0,value:l}):n===1||n===2||n===3?(a.length>1&&(c===`*`||c===`+`)&&t(`A repeatable param (${l}) must be alone in its segment. eg: '/:ids+.`),a.push({type:1,value:l,regexp:u,repeatable:c===`*`||c===`+`,optional:c===`*`||c===`?`})):t(`Invalid state to consume buffer`),``)}function f(){l+=c}for(;st.length?t.length===1&&t[0]===80?1:-1:0}function li(e,t){let n=0,r=e.score,i=t.score;for(;n0&&t[t.length-1]<0}var di={strict:!1,end:!0,sensitive:!1};function fi(e,t,n){let r=J(si(ri(e.path),n),{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function pi(e,t){let n=[],r=new Map;t=Hn(di,t);function i(e){return r.get(e)}function a(e,n,r){let i=!r,s=hi(e);s.aliasOf=r&&r.record;let l=Hn(t,e),u=[s];if(`alias`in e){let t=typeof e.alias==`string`?[e.alias]:e.alias;for(let e of t)u.push(hi(J({},s,{components:r?r.record.components:s.components,path:e,aliasOf:r?r.record:s})))}let d,f;for(let t of u){let{path:u}=t;if(n&&u[0]!==`/`){let e=n.record.path,r=e[e.length-1]===`/`?``:`/`;t.path=n.record.path+(u&&r+u)}if(d=fi(t,n,l),r?r.alias.push(d):(f||=d,f!==d&&f.alias.push(d),i&&e.name&&!_i(d)&&o(e.name)),xi(d)&&c(d),s.children){let e=s.children;for(let t=0;t{o(f)}:Vn}function o(e){if(Hr(e)){let t=r.get(e);t&&(r.delete(e),n.splice(n.indexOf(t),1),t.children.forEach(o),t.alias.forEach(o))}else{let t=n.indexOf(e);t>-1&&(n.splice(t,1),e.record.name&&r.delete(e.record.name),e.children.forEach(o),e.alias.forEach(o))}}function s(){return n}function c(e){let t=yi(e,n);n.splice(t,0,e),e.record.name&&!_i(e)&&r.set(e.record.name,e)}function l(e,t){let i,a={},o,s;if(`name`in e&&e.name){if(i=r.get(e.name),!i)throw Wn(1,{location:e});s=i.record.name,a=J(mi(t.params,i.keys.filter(e=>!e.optional).concat(i.parent?i.parent.keys.filter(e=>e.optional):[]).map(e=>e.name)),e.params&&mi(e.params,i.keys.map(e=>e.name))),o=i.stringify(a)}else if(e.path!=null)o=e.path,i=n.find(e=>e.re.test(o)),i&&(a=i.parse(o),s=i.record.name,i.keys.forEach(e=>{e.optional&&!a[e.name]&&delete a[e.name]}));else{if(i=t.name?r.get(t.name):n.find(e=>e.re.test(t.path)),!i)throw Wn(1,{location:e,currentLocation:t});s=i.record.name,a=J({},t.params,e.params),o=i.stringify(a)}let c=[],l=i;for(;l;)c.unshift(l.record),l=l.parent;return{name:s,path:o,params:a,matched:c,meta:vi(c)}}e.forEach(e=>a(e));function u(){n.length=0,r.clear()}return{addRoute:a,resolve:l,removeRoute:o,clearRoutes:u,getRoutes:s,getRecordMatcher:i}}function mi(e,t){let n={};for(let r of t)r in e&&(n[r]=e[r]);return n}function hi(e){let t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:gi(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:`components`in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function gi(e){let t={},n=e.props||!1;if(`component`in e)t.default=n;else for(let r in e.components)t[r]=typeof n==`object`?n[r]:n;return t}function _i(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function vi(e){return e.reduce((e,t)=>J(e,t.meta),{})}function yi(e,t){let n=0,r=t.length;for(;n!==r;){let i=n+r>>1;li(e,t[i])<0?r=i:n=i+1}let i=bi(e);return i&&(r=t.lastIndexOf(i,r-1)),r}function bi(e){let t=e;for(;t=t.parent;)if(xi(t)&&li(e,t)===0)return t}function xi({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function Si(e){let t=b(qn),n=b(Jn),r=I(()=>{let n=g(e.to);return t.resolve(n)}),i=I(()=>{let{matched:e}=r.value,{length:t}=e,i=e[t-1],a=n.matched;if(!i||!a.length)return-1;let o=a.findIndex(Er.bind(null,i));if(o>-1)return o;let s=Di(e[t-2]);return t>1&&Di(i)===s&&a[a.length-1].path!==s?a.findIndex(Er.bind(null,e[t-2])):o}),a=I(()=>i.value>-1&&Ei(n.params,r.value.params)),o=I(()=>i.value>-1&&i.value===n.matched.length-1&&Dr(n.params,r.value.params));function s(n={}){if(Ti(n)){let n=t[g(e.replace)?`replace`:`push`](g(e.to)).catch(Vn);return e.viewTransition&&typeof document<`u`&&`startViewTransition`in document&&document.startViewTransition(()=>n),n}return Promise.resolve()}return{route:r,href:I(()=>r.value.href),isActive:a,isExactActive:o,navigate:s}}function Ci(e){return e.length===1?e[0]:e}var wi=_({name:`RouterLink`,compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:`page`},viewTransition:Boolean},useLink:Si,setup(e,{slots:t}){let n=m(Si(e)),{options:r}=b(qn),i=I(()=>({[Oi(e.activeClass,r.linkActiveClass,`router-link-active`)]:n.isActive,[Oi(e.exactActiveClass,r.linkExactActiveClass,`router-link-exact-active`)]:n.isExactActive}));return()=>{let r=t.default&&Ci(t.default(n));return e.custom?r:he(`a`,{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:i.value},r)}}});function Ti(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(e.button===void 0||e.button===0)){if(e.currentTarget&&e.currentTarget.getAttribute){let t=e.currentTarget.getAttribute(`target`);if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Ei(e,t){for(let n in t){let r=t[n],i=e[n];if(typeof r==`string`){if(r!==i)return!1}else if(!Y(i)||i.length!==r.length||r.some((e,t)=>e.valueOf()!==i[t].valueOf()))return!1}return!0}function Di(e){return e?e.aliasOf?e.aliasOf.path:e.path:``}var Oi=(e,t,n)=>e??t??n,ki=_({name:`RouterView`,inheritAttrs:!1,props:{name:{type:String,default:`default`},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){let r=b(Yn),i=I(()=>e.route||r.value),a=b(Kn,0),s=I(()=>{let e=g(a),{matched:t}=i.value,n;for(;(n=t[e])&&!n.components;)e++;return e}),c=I(()=>i.value.matched[s.value]);u(Kn,I(()=>s.value+1)),u(Gn,c),u(Yn,i);let l=o();return d(()=>[l.value,c.value,e.name],([e,t,n],[r,i,a])=>{t&&(t.instances[n]=e,i&&i!==t&&e&&e===r&&(t.leaveGuards.size||(t.leaveGuards=i.leaveGuards),t.updateGuards.size||(t.updateGuards=i.updateGuards))),e&&t&&(!i||!Er(t,i)||!r)&&(t.enterCallbacks[n]||[]).forEach(t=>t(e))},{flush:`post`}),()=>{let r=i.value,a=e.name,o=c.value,s=o&&o.components[a];if(!s)return Ai(n.default,{Component:s,route:r});let u=o.props[a],d=u?u===!0?r.params:typeof u==`function`?u(r):u:null,f=he(s,J({},d,t,{onVnodeUnmounted:e=>{e.component.isUnmounted&&(o.instances[a]=null)},ref:l}));return Ai(n.default,{Component:f,route:r})||f}}});function Ai(e,t){if(!e)return null;let n=e(t);return n.length===1?n[0]:n}var ji=ki;function Mi(e){let t=pi(e.routes,e),n=e.parseQuery||Ur,r=e.stringifyQuery||Wr,i=e.history,a=Kr(),o=Kr(),s=Kr(),l=le(Z),u=Z;Qn&&e.scrollBehavior&&`scrollRestoration`in history&&(history.scrollRestoration=`manual`);let d=Bn.bind(null,e=>``+e),f=Bn.bind(null,vr),p=Bn.bind(null,yr);function m(e,n){let r,i;return Hr(e)?(r=t.getRecordMatcher(e),i=n):i=e,t.addRoute(i,r)}function h(e){let n=t.getRecordMatcher(e);n&&t.removeRoute(n)}function _(){return t.getRoutes().map(e=>e.record)}function v(e){return!!t.getRecordMatcher(e)}function y(e,a){if(a=J({},a||l.value),typeof e==`string`){let r=Sr(n,e,a.path),o=t.resolve({path:r.path},a),s=i.createHref(r.fullPath);return J(r,o,{params:p(o.params),redirectedFrom:void 0,href:s})}let o;if(e.path!=null)o=J({},e,{path:Sr(n,e.path,a.path).path});else{let t=J({},e.params);for(let e in t)t[e]??delete t[e];o=J({},e,{params:f(t)}),a.params=f(a.params)}let s=t.resolve(o,a),c=e.hash||``;s.params=d(p(s.params));let u=Cr(r,J({},e,{hash:mr(c),path:s.path})),m=i.createHref(u);return J({fullPath:u,hash:c,query:r===Wr?Gr(e.query):e.query||{}},s,{redirectedFrom:void 0,href:m})}function b(e){return typeof e==`string`?Sr(n,e,l.value.path):J({},e)}function x(e,t){if(u!==e)return Wn(8,{from:t,to:e})}function S(e){return T(e)}function C(e){return S(J(b(e),{replace:!0}))}function w(e,t){let n=e.matched[e.matched.length-1];if(n&&n.redirect){let{redirect:r}=n,i=typeof r==`function`?r(e,t):r;return typeof i==`string`&&(i=i.includes(`?`)||i.includes(`#`)?i=b(i):{path:i},i.params={}),J({query:e.query,hash:e.hash,params:i.path==null?e.params:{}},i)}}function T(e,t){let n=u=y(e),i=l.value,a=e.state,o=e.force,s=e.replace===!0,c=w(n,i);if(c)return T(J(b(c),{state:typeof c==`object`?J({},a,c.state):a,force:o,replace:s}),t||n);let d=n;d.redirectedFrom=t;let f;return!o&&Tr(r,i,n)&&(f=Wn(16,{to:d,from:i}),ae(i,i,!0,!1)),(f?Promise.resolve(f):O(d,i)).catch(e=>X(e)?X(e,2)?e:ie(e):ne(e,d,i)).then(e=>{if(e){if(X(e,2))return T(J({replace:s},b(e.to),{state:typeof e.to==`object`?J({},a,e.to.state):a,force:o}),t||d)}else e=A(d,i,!0,s,a);return k(d,i,e),e})}function E(e,t){let n=x(e,t);return n?Promise.reject(n):Promise.resolve()}function D(e){let t=ce.values().next().value;return t&&typeof t.runWithContext==`function`?t.runWithContext(e):e()}function O(e,t){let n,[r,i,s]=Jr(e,t);n=qr(r.reverse(),`beforeRouteLeave`,e,t);for(let i of r)i.leaveGuards.forEach(r=>{n.push(Q(r,e,t))});let c=E.bind(null,e,t);return n.push(c),F(n).then(()=>{n=[];for(let r of a.list())n.push(Q(r,e,t));return n.push(c),F(n)}).then(()=>{n=qr(i,`beforeRouteUpdate`,e,t);for(let r of i)r.updateGuards.forEach(r=>{n.push(Q(r,e,t))});return n.push(c),F(n)}).then(()=>{n=[];for(let r of s)if(r.beforeEnter)if(Y(r.beforeEnter))for(let i of r.beforeEnter)n.push(Q(i,e,t));else n.push(Q(r.beforeEnter,e,t));return n.push(c),F(n)}).then(()=>(e.matched.forEach(e=>e.enterCallbacks={}),n=qr(s,`beforeRouteEnter`,e,t,D),n.push(c),F(n))).then(()=>{n=[];for(let r of o.list())n.push(Q(r,e,t));return n.push(c),F(n)}).catch(e=>X(e,8)?e:Promise.reject(e))}function k(e,t,n){s.list().forEach(r=>D(()=>r(e,t,n)))}function A(e,t,n,r,a){let o=x(e,t);if(o)return o;let s=t===Z,c=Qn?history.state:{};n&&(r||s?i.replace(e.fullPath,J({scroll:s&&c&&c.scroll},a)):i.push(e.fullPath,a)),l.value=e,ae(e,t,n,s),ie()}let ee;function j(){ee||=i.listen((e,t,n)=>{if(!P.listening)return;let r=y(e),a=w(r,P.currentRoute.value);if(a){T(J(a,{replace:!0,force:!0}),r).catch(Vn);return}u=r;let o=l.value;Qn&&zr(Lr(o.fullPath,n.delta),Fr()),O(r,o).catch(e=>X(e,12)?e:X(e,2)?(T(J(b(e.to),{force:!0}),r).then(e=>{X(e,20)&&!n.delta&&n.type===`pop`&&i.go(-1,!1)}).catch(Vn),Promise.reject()):(n.delta&&i.go(-n.delta,!1),ne(e,r,o))).then(e=>{e||=A(r,o,!1),e&&(n.delta&&!X(e,8)?i.go(-n.delta,!1):n.type===`pop`&&X(e,20)&&i.go(-1,!1)),k(r,o,e)}).catch(Vn)})}let te=Kr(),M=Kr(),N;function ne(e,t,n){ie(e);let r=M.list();return r.length?r.forEach(r=>r(e,t,n)):console.error(e),Promise.reject(e)}function re(){return N&&l.value!==Z?Promise.resolve():new Promise((e,t)=>{te.add([e,t])})}function ie(e){return N||(N=!e,j(),te.list().forEach(([t,n])=>e?n(e):t()),te.reset()),e}function ae(t,n,r,i){let{scrollBehavior:a}=e;if(!Qn||!a)return Promise.resolve();let o=!r&&Br(Lr(t.fullPath,0))||(i||!r)&&history.state&&history.state.scroll||null;return z().then(()=>a(t,n,o)).then(e=>t===l.value&&e&&Ir(e)).catch(e=>t===l.value&&ne(e,t,n))}let oe=e=>i.go(e),se,ce=new Set,P={currentRoute:l,listening:!0,addRoute:m,removeRoute:h,clearRoutes:t.clearRoutes,hasRoute:v,getRoutes:_,resolve:y,options:e,push:S,replace:C,go:oe,back:()=>oe(-1),forward:()=>oe(1),beforeEach:a.add,beforeResolve:o.add,afterEach:s.add,onError:M.add,isReady:re,install(e){e.component(`RouterLink`,wi),e.component(`RouterView`,ji),e.config.globalProperties.$router=P,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>g(l)}),Qn&&!se&&l.value===Z&&(se=!0,S(i.location).catch(e=>{}));let t={};for(let e in Z)Object.defineProperty(t,e,{get:()=>l.value[e],enumerable:!0});e.provide(qn,P),e.provide(Jn,c(t)),e.provide(Yn,l);let n=e.unmount;ce.add(e),e.unmount=function(){ce.delete(e),ce.size<1&&(u=Z,ee&&ee(),ee=null,l.value=Z,se=!1,N=!1),n()}}};function F(e){return e.reduce((e,t)=>e.then(()=>D(t)),Promise.resolve())}return P}var Ni=e.create({baseURL:``,timeout:3e4,withCredentials:!0,headers:{"Content-Type":`application/json`}}),Pi=12;try{localStorage.removeItem(`orva.hasUser`)}catch{}var Fi=_e(`auth`,()=>{let e=o(null),t=o(!1),n=o(!1),r=o(null),i=o(null),a=o(!1),s=o(0),c=e=>{r.value=e},l=async(r,i)=>{n.value=!0;try{let n=await Ni.post(`/api/v1/auth/login`,{username:r,password:i});return e.value=n.data.user,t.value=!0,c(!0),{success:!0}}catch(e){return{success:!1,error:e.response?.data?.error?.message||`Login failed`}}finally{n.value=!1}},u=async(r,i)=>{n.value=!0;try{let n=await Ni.post(`/api/v1/auth/onboard`,{username:r,password:i});return e.value=n.data.user,t.value=!0,c(!0),{success:!0}}catch(e){return{success:!1,error:e.response?.data?.error?.message||`Setup failed`}}finally{n.value=!1}},d=async()=>{try{await Ni.post(`/api/v1/auth/logout`)}catch{}e.value=null,t.value=!1},f=async({force:e=!1}={})=>{if(!e&&r.value!==null)return r.value;try{let e=await Ni.get(`/api/v1/auth/status`);return c(!!e.data.has_user),r.value}catch{return r.value===null&&c(!0),r.value}},p=async()=>{try{let n=await Ni.get(`/api/v1/auth/me`);return e.value=n.data,t.value=!0,c(!0),i.value=n.data.expires_at||null,!0}catch{return e.value=null,t.value=!1,i.value=null,!1}},m=async()=>{a.value=!0;try{let e=await Ni.post(`/api/v1/auth/refresh`);return i.value=e.data.expires_at||null,{success:!0}}catch(e){return t.value=!1,i.value=null,{success:!1,error:e.response?.data?.error?.message||`Refresh failed`}}finally{a.value=!1}},h=I(()=>i.value?(new Date(i.value).getTime()-Date.now())/1e3:null);return{user:e,isAuthenticated:t,loading:n,hasUser:r,expiresAt:i,refreshing:a,secondsUntilExpiry:h,shouldShowExpiryToast:I(()=>{if(!t.value)return!1;let e=h.value;return e==null||e<=0||Date.now(){s.value=Date.now()+36e5},changePassword:async(e,t)=>{await Ni.post(`/api/v1/auth/change-password`,{old_password:e,new_password:t})}}}),Ii=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},Li={},Ri={viewBox:`0 0 32 32`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,class:`text-primary`};function zi(e,t){return r(),C(`svg`,Ri,[...t[0]||=[x(`rect`,{width:`32`,height:`32`,rx:`8`,fill:`currentColor`},null,-1),x(`text`,{x:`16`,y:`21`,"font-family":`'Inter', system-ui, sans-serif`,"font-size":`13`,"font-weight":`700`,fill:`white`,"text-anchor":`middle`,"letter-spacing":`-0.5`},` f(x) `,-1)]])}var Bi=Ii(Li,[[`render`,zi]]),Vi={class:`lg:hidden fixed top-0 inset-x-0 h-14 bg-background border-b border-border z-30 flex items-center justify-between px-4 pt-safe pl-safe pr-safe`},Hi={class:`flex items-center gap-2 text-white font-mono`},Ui=[`aria-label`,`aria-expanded`],Wi={class:`h-16 flex items-center px-6 border-b border-border`},Gi={class:`flex items-center gap-3 text-white font-mono tracking-tight text-lg`},Ki={class:`flex-1 p-3 space-y-1 overflow-y-auto scrollable`},qi=[`aria-expanded`,`aria-controls`,`onClick`],Ji={class:`flex-1 text-left`},Yi=[`id`],Xi={class:`mt-2 space-y-1 border-t border-border pt-2`},Zi={__name:`Sidebar`,setup(e){let t=Zn(),n=o(!1),i=o(null),c=o(null),u=e=>e===`/`?t.path===`/`:t.path.startsWith(e),f=[{path:`/`,label:`Overview`,icon:ln},{path:`/ai`,label:`Chat`,icon:mn},{path:`/functions`,label:`Functions`,icon:rn}],p=[{id:`automation`,label:`Automation`,icon:an,items:[{path:`/cron`,label:`Schedules`,icon:an},{path:`/jobs`,label:`Jobs`,icon:dn}]},{id:`observe`,label:`Observe`,icon:nn,items:[{path:`/activity`,label:`Activity`,icon:nn},{path:`/invocations`,label:`Invocations`,icon:fn},{path:`/traces`,label:`Traces`,icon:hn}]},{id:`connect`,label:`Connect`,icon:gn,items:[{path:`/api-keys`,label:`Keys`,icon:cn},{path:`/channels`,label:`Channels`,icon:gn},{path:`/webhooks`,label:`Webhooks`,icon:Sn},{path:`/firewall`,label:`Egress`,icon:bn}]}],m=[{path:`/settings`,label:`Settings`,icon:yn},{path:`/docs`,label:`Docs`,icon:un}],h=o(Object.fromEntries(p.map(e=>[e.id,!1]))),_=e=>e.items.some(e=>u(e.path)),v=()=>{let e=p.find(_);e&&(h.value[e.id]=!0)};v(),d(()=>t.fullPath,()=>{n.value=!1,v()}),d(n,async e=>{await z(),e?(i.value?.querySelector(`a[href]`))?.focus?.():i.value?.contains(document.activeElement)&&c.value?.focus?.()});let y=0,b=0,S=!1,w=e=>{if(window.innerWidth>=1024||!n.value)return;let t=e.touches[0];y=t.clientX,b=t.clientY,S=!0},T=e=>{if(!S)return;let t=e.touches[0],r=t.clientX-y,i=Math.abs(t.clientY-b);r<-60&&i<40&&(n.value=!1,S=!1)},E=()=>{S=!1};return(e,t)=>{let o=te(`router-link`);return r(),C(F,null,[x(`header`,Vi,[x(`div`,Hi,[k(Bi,{class:`w-6 h-6`}),t[5]||=x(`span`,{class:`font-bold tracking-tight`},`Orva`,-1)]),x(`button`,{ref_key:`toggleBtn`,ref:c,class:`p-2 rounded-md text-foreground-muted hover:text-white hover:bg-surface transition-colors touch-expand-iconbtn`,"aria-label":n.value?`Close menu`:`Open menu`,"aria-expanded":n.value,"aria-controls":`primary-navigation`,onClick:t[0]||=e=>n.value=!n.value},[n.value?(r(),N(g(Cn),{key:1,class:`w-5 h-5`})):(r(),N(g(pn),{key:0,class:`w-5 h-5`}))],8,Ui)]),k(je,{name:`fade`},{default:a(()=>[n.value?(r(),C(`div`,{key:0,class:`lg:hidden fixed inset-0 bg-black/50 z-30 backdrop-blur-sm`,onClick:t[1]||=e=>n.value=!1})):L(``,!0)]),_:1}),x(`aside`,{id:`primary-navigation`,ref_key:`drawerEl`,ref:i,class:O([`bg-background border-r border-border flex flex-col h-full shrink-0 z-40 w-64 lg:w-52 fixed inset-y-0 left-0 transform transition-transform duration-150 ease-out lg:static lg:translate-x-0 lg:transform-none lg:transition-none pt-safe pb-safe pl-safe`,n.value?`translate-x-0`:`-translate-x-full lg:translate-x-0`]),onTouchstart:w,onTouchmove:T,onTouchend:E},[x(`div`,Wi,[x(`div`,Gi,[k(Bi,{class:`w-8 h-8`}),t[6]||=x(`span`,{class:`font-bold tracking-tight text-white`},`Orva`,-1)])]),x(`nav`,Ki,[(r(),C(F,null,M(f,e=>k(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[2]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:O([`w-4 h-4 transition-colors`,u(e.path)?`text-white`:`text-foreground-muted group-hover:text-white`])},null,8,[`class`])),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`])),64)),(r(),C(F,null,M(p,e=>x(`div`,{key:e.id,class:`pt-1`},[x(`button`,{type:`button`,class:O([`flex w-full items-center gap-3 rounded-md px-3 py-2.5 text-sm font-medium text-foreground-muted transition-colors hover:bg-surface-hover hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,_(e)?`text-white`:``]),"aria-expanded":h.value[e.id],"aria-controls":`nav-group-${e.id}`,onClick:t=>h.value[e.id]=!h.value[e.id]},[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,Ji,R(e.label),1),k(g(on),{class:O([`h-3.5 w-3.5 transition-transform`,h.value[e.id]?`rotate-0`:`-rotate-90`])},null,8,[`class`])],10,qi),s(x(`div`,{id:`nav-group-${e.id}`,class:`ml-3 mt-1 space-y-0.5 border-l border-border pl-2`},[(r(!0),C(F,null,M(e.items,e=>(r(),N(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[3]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`]))),128))],8,Yi),[[Je,h.value[e.id]]])])),64)),x(`div`,Xi,[(r(),C(F,null,M(m,e=>k(o,{key:e.path,to:e.path,class:O([`flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors duration-150 group font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary`,u(e.path)?`text-white bg-primary/15`:`text-foreground-muted hover:text-white hover:bg-surface-hover`]),onClick:t[4]||=e=>n.value=!1},{default:a(()=>[(r(),N(l(e.icon),{class:`h-4 w-4`})),x(`span`,null,R(e.label),1)]),_:2},1032,[`to`,`class`])),64))])])],34)],64)}}},Qi={key:0,class:`fixed z-50 bg-background border border-border shadow-lg rounded-lg p-4 flex items-start gap-3 inset-x-2 bottom-2 max-w-sm mx-auto pb-safe sm:inset-x-auto sm:bottom-6 sm:right-6 sm:mx-0 sm:pb-4`},$i={class:`flex-1 min-w-0`},ea={key:0,class:`text-sm font-medium text-white mb-0.5`},ta={class:`text-xs text-foreground-muted`},na={class:`flex flex-col gap-2 shrink-0`},ra=[`disabled`],ia=Ii(Object.assign({name:`CommonToast`},{__name:`Toast`,props:{visible:{type:Boolean,default:!1},title:{type:String,default:``},actionLabel:{type:String,default:``},actionLoading:{type:Boolean,default:!1},dismissible:{type:Boolean,default:!0}},emits:[`action`,`dismiss`],setup(e){return(t,i)=>(r(),N(v,{to:`body`},[k(je,{name:`toast`},{default:a(()=>[e.visible?(r(),C(`div`,Qi,[x(`div`,$i,[e.title?(r(),C(`div`,ea,R(e.title),1)):L(``,!0),x(`div`,ta,[n(t.$slots,`default`,{},void 0,!0)])]),x(`div`,na,[e.actionLabel?(r(),C(`button`,{key:0,class:`px-3 py-1 rounded text-xs font-medium bg-white text-black hover:bg-foreground-muted transition-colors`,disabled:e.actionLoading,onClick:i[0]||=e=>t.$emit(`action`)},R(e.actionLoading?`…`:e.actionLabel),9,ra)):L(``,!0),e.dismissible?(r(),C(`button`,{key:1,class:`text-foreground-muted hover:text-white text-xs`,onClick:i[1]||=e=>t.$emit(`dismiss`)},` Dismiss `)):L(``,!0)])])):L(``,!0)]),_:3})]))}}),[[`__scopeId`,`data-v-1cbabcec`]]),aa={class:`flex items-center gap-2 px-4 py-3 border-b border-border`},oa=[`aria-selected`,`onClick`,`onMouseenter`],sa={class:`flex-1 truncate`},ca={key:0,class:`hidden sm:inline-flex items-center gap-1 text-[10px] font-mono text-foreground-muted`},la={key:0,class:`px-4 py-6 text-center text-sm text-foreground-muted`},ua=800,da={__name:`CommandPalette`,setup(e,{expose:t}){let n=Xn(),c=o(!1),u=o(``),f=o(0),m=o(null),h=o(null),_=o(null);kn(_,c);let y=[{id:`fn-new`,label:`New function`,icon:_n,action:()=>n.push(`/functions/new`),shortcut:[`c`,`n`]},{id:`go-fns`,label:`Functions`,icon:rn,action:()=>n.push(`/functions`),shortcut:[`g`,`f`]},{id:`go-inv`,label:`Invocations`,icon:fn,action:()=>n.push(`/invocations`),shortcut:[`g`,`i`]},{id:`go-jobs`,label:`Jobs`,icon:dn,action:()=>n.push(`/jobs`),shortcut:[`g`,`j`]},{id:`go-cron`,label:`Schedules`,icon:an,action:()=>n.push(`/cron`)},{id:`go-activity`,label:`Activity`,icon:nn,action:()=>n.push(`/activity`)},{id:`go-traces`,label:`Traces`,icon:hn,action:()=>n.push(`/traces`)},{id:`go-keys`,label:`API Keys`,icon:cn,action:()=>n.push(`/api-keys`)},{id:`go-channels`,label:`Channels`,icon:gn,action:()=>n.push(`/channels`)},{id:`go-hooks`,label:`Webhooks`,icon:Sn,action:()=>n.push(`/webhooks`)},{id:`go-fw`,label:`Egress`,icon:bn,action:()=>n.push(`/firewall`),keywords:`firewall blocklist dns`},{id:`go-settings`,label:`Settings`,icon:yn,action:()=>n.push(`/settings`)},{id:`go-docs`,label:`Docs`,icon:un,action:()=>n.push(`/docs`)},{id:`go-overview`,label:`Overview`,icon:ln,action:()=>n.push(`/`)}],b=I(()=>{let e=u.value.trim().toLowerCase();return e?y.filter(t=>t.label.toLowerCase().includes(e)||(t.keywords||``).includes(e)):y});d(b,()=>{f.value=0});let S=e=>{let t=b.value.length;t&&(f.value=(f.value+e+t)%t,z(()=>{(h.value?.querySelectorAll(`li[role="option"]`)[f.value])?.scrollIntoView?.({block:`nearest`})}))},w=e=>{e&&(T(),z(()=>e.action()))},T=()=>{c.value=!1,u.value=``,f.value=0},E=()=>{c.value=!0,z(()=>m.value?.focus())},D=``,A=null,ee=e=>{if(!e)return!1;let t=e.tagName;return!!(t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable)},j=e=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`){e.preventDefault(),c.value?T():E();return}if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`s`&&window.location.pathname.includes(`/functions/`)){e.preventDefault(),window.dispatchEvent(new CustomEvent(`orva:deploy`));return}if(e.metaKey||e.ctrlKey||e.altKey||ee(document.activeElement))return;if(!D){if(e.key===`g`||e.key===`c`){D=e.key,clearTimeout(A),A=setTimeout(()=>{D=``},ua);return}return}let t=D+e.key;D=``,clearTimeout(A);let n=y.find(e=>e.shortcut&&e.shortcut.join(``)===t);n&&(e.preventDefault(),n.action())};return p(()=>{window.addEventListener(`keydown`,j)}),i(()=>{window.removeEventListener(`keydown`,j),clearTimeout(A)}),t({show:E,close:T}),(e,t)=>(r(),N(v,{to:`body`},[k(je,{name:`fade`},{default:a(()=>[c.value?(r(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-start justify-center bg-black/60 backdrop-blur-sm pt-[10vh] sm:pt-[15vh] px-4`,onClick:Rt(T,[`self`])},[x(`div`,{ref_key:`dialogRoot`,ref:_,class:`w-full max-w-lg bg-background border border-border rounded-lg shadow-xl overflow-hidden`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`command-palette-label`},[x(`div`,aa,[k(g(vn),{class:`w-4 h-4 text-foreground-muted shrink-0`}),t[4]||=x(`span`,{id:`command-palette-label`,class:`sr-only`},`Command palette`,-1),s(x(`input`,{ref_key:`searchInput`,ref:m,"onUpdate:modelValue":t[0]||=e=>u.value=e,type:`text`,placeholder:`Search routes, actions…`,class:`flex-1 bg-transparent border-0 text-base sm:text-sm text-white placeholder-foreground-muted focus:outline-none`,onKeydown:[t[1]||=Bt(Rt(e=>S(1),[`prevent`]),[`down`]),t[2]||=Bt(Rt(e=>S(-1),[`prevent`]),[`up`]),t[3]||=Bt(Rt(e=>w(b.value[f.value]),[`prevent`]),[`enter`]),Bt(T,[`esc`])]},null,544),[[Tt,u.value]]),t[5]||=x(`kbd`,{class:`hidden sm:inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-mono text-foreground-muted bg-surface border border-border`},`esc`,-1)]),x(`ul`,{ref_key:`listRef`,ref:h,class:`max-h-[60dvh] overflow-y-auto scrollable py-1`,role:`listbox`},[(r(!0),C(F,null,M(b.value,(e,t)=>(r(),C(`li`,{key:e.id,role:`option`,"aria-selected":t===f.value,class:O([`flex items-center gap-3 px-4 py-2.5 min-h-[44px] text-base sm:text-sm cursor-pointer`,t===f.value?`bg-primary/15 text-white`:`text-foreground hover:bg-surface-hover`]),onClick:t=>w(e),onMouseenter:e=>f.value=t},[(r(),N(l(e.icon),{class:`w-4 h-4 shrink-0 text-foreground-muted`})),x(`span`,sa,R(e.label),1),e.shortcut?(r(),C(`span`,ca,[(r(!0),C(F,null,M(e.shortcut,e=>(r(),C(`kbd`,{key:e,class:`px-1.5 py-0.5 rounded bg-surface border border-border`},R(e),1))),128))])):L(``,!0)],42,oa))),128)),b.value.length?L(``,!0):(r(),C(`li`,la,` Nothing matches "`+R(u.value)+`". `,1))],512),t[6]||=x(`div`,{class:`px-4 py-2 border-t border-border bg-surface/40 flex items-center justify-between text-[10px] text-foreground-muted`},[x(`span`,{class:`flex items-center gap-2`},[x(`kbd`,{class:`px-1.5 py-0.5 rounded font-mono bg-surface border border-border`},`↑↓`),x(`span`,null,`navigate`)]),x(`span`,{class:`flex items-center gap-2`},[x(`kbd`,{class:`px-1.5 py-0.5 rounded font-mono bg-surface border border-border`},`↵`),x(`span`,null,`activate`)])],-1)],512)])):L(``,!0)]),_:1})]))}},fa=()=>B.get(`/system/health`),pa=e=>B.get(`/functions`,{params:e}),ma=e=>B.get(`/functions/${e}`),ha=e=>B.get(`/functions/${e}/source`),ga=()=>B.get(`/routes`),_a=(e,t,n=`*`)=>B.post(`/routes`,{path:e,function_id:t,methods:n}),va=e=>B.delete(`/routes`,{params:{path:e}}),ya=(e,{method:t=`POST`,path:n=`/`,headers:r={},body:i=``}={})=>{let a=`/${e.replace(/^fn_/,``)}`;n&&n!==`/`&&(a+=n.startsWith(`/`)?n:`/${n}`);let o={url:a,method:t,headers:{...r},responseType:`text`,transformRequest:[e=>e]},s=(t||`POST`).toUpperCase();return i&&s!==`GET`&&s!==`HEAD`&&(o.data=i),ye.request(o)},ba=e=>B.get(`/executions`,{params:e}),xa=e=>B.get(`/executions/${e}`),Sa=e=>B.get(`/executions/${e}/logs`),Ca=e=>B.get(`/executions/${e}/request`),wa=e=>B.post(`/executions/${e}/replay`,null,{responseType:`text`}),Ta=e=>B.get(`/activity`,{params:e}),Ea=(e,t)=>B.get(`/functions/${encodeURIComponent(e)}/kv`,{params:t}),Da=(e,t,n)=>B.put(`/functions/${encodeURIComponent(e)}/kv/${encodeURIComponent(t)}`,n),Oa=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/kv/${encodeURIComponent(t)}`),ka=e=>B.get(`/functions/${encodeURIComponent(e)}/fixtures`),Aa=(e,t,n)=>B.put(`/functions/${encodeURIComponent(e)}/fixtures/${encodeURIComponent(t)}`,n),ja=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/fixtures/${encodeURIComponent(t)}`),Ma=()=>B.get(`/keys`),Na=e=>B.post(`/keys`,e),Pa=e=>B.delete(`/keys/${e}`),Fa=()=>B.get(`/oauth/connected-apps`),Ia=e=>B.delete(`/oauth/connected-apps/${e}`),La=()=>B.get(`/auth/sessions`),Ra=e=>B.delete(`/auth/sessions/${e}`),za=()=>B.get(`/channels`),Ba=e=>B.post(`/channels`,e),Va=e=>B.post(`/channels/${e}/rotate`),Ha=e=>B.delete(`/channels/${e}`),Ua=()=>B.get(`/system/metrics.json`),Wa=e=>B.get(`/deployments/${e}`),Ga=(e,t=0,n=200)=>B.get(`/deployments/${e}/logs`,{params:{from:t,limit:n}}),Ka=(e,t=50)=>B.get(`/functions/${e}/deployments`,{params:{limit:t}}),qa=(e,t,n,r=`json`)=>B.get(`/functions/${encodeURIComponent(e)}/diff`,{params:{from:t,to:n,format:r},responseType:r===`unified`?`text`:`json`}),Ja=(e,t)=>B.post(`/functions/${e}/rollback`,t),Ya=async e=>{let t=((await B.get(`/functions`)).data.functions||[]).find(t=>t.name===e);if(!t)throw Error(`Function "${e}" not found`);return t.id},Xa=e=>({...e,cron_expression:e.cron_expr}),Za=async()=>({data:{schedules:((await B.get(`/cron`)).data.schedules||[]).map(Xa)}}),Qa=async(e,t)=>{let n=await Ya(e),r={cron_expr:t.cron,timezone:t.timezone||eo(),enabled:t.enabled!==!1,payload:t.payload??{}};return{data:Xa((await B.post(`/functions/${n}/cron`,r)).data)}},$a=async(e,t)=>{let n=t.function_id;if(!n)throw Error(`updateCronSchedule: function_id is required`);let r={};return t.cron!==void 0&&(r.cron_expr=t.cron),t.timezone!==void 0&&(r.timezone=t.timezone),t.enabled!==void 0&&(r.enabled=t.enabled),t.payload!==void 0&&(r.payload=t.payload),{data:Xa((await B.put(`/functions/${n}/cron/${e}`,r)).data)}},eo=()=>{try{return Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`}catch{return`UTC`}},to=async(e,t)=>{if(!t)throw Error(`deleteCronSchedule: functionId is required`);return B.delete(`/functions/${t}/cron/${e}`)},no=(e={})=>B.get(`/jobs`,{params:e}),ro=e=>B.post(`/jobs`,e),io=e=>B.post(`/jobs/${e}/retry`),ao=e=>B.delete(`/jobs/${e}`),oo=()=>B.get(`/system/storage`),so=()=>B.post(`/system/vacuum`),co=e=>{let t=new FormData;return t.append(`archive`,e),B.post(`/restore?confirm=1`,t,{headers:{"Content-Type":`multipart/form-data`},timeout:6e5})},lo=e=>B.get(`/traces/${e}`),uo=(e={})=>B.get(`/traces`,{params:e}),fo=()=>B.get(`/webhooks`),po=e=>B.post(`/webhooks`,e),mo=(e,t)=>B.put(`/webhooks/${e}`,t),ho=e=>B.delete(`/webhooks/${e}`),go=e=>B.post(`/webhooks/${e}/test`),_o=e=>B.get(`/webhooks/${e}/deliveries`),vo=e=>B.post(`/webhooks/deliveries/${e}/retry`),yo=e=>B.get(`/functions/${encodeURIComponent(e)}/inbound-webhooks`),bo=(e,t)=>B.post(`/functions/${encodeURIComponent(e)}/inbound-webhooks`,t),xo=(e,t)=>B.delete(`/functions/${encodeURIComponent(e)}/inbound-webhooks/${t}`),So=[500,1e3,2e3,5e3,1e4],Co=_e(`events`,()=>{let e=o(!1),t=o(0),n=new Map,r=null,i=null,a=(e,t)=>{let r=n.get(e);if(r)for(let e of r)try{e(t)}catch(e){console.error(`events callback error`,e)}},s=n=>{n.onopen=()=>{e.value=!0,t.value=0};for(let e of[`metrics`,`execution`,`deployment`,`function`,`activity`])n.addEventListener(e,t=>{try{let n=JSON.parse(t.data);a(e,n)}catch(e){console.warn(`failed to parse SSE payload`,e,t.data)}});n.onerror=()=>{if(e.value=!1,r){try{r.close()}catch{}r=null}let n=So[Math.min(t.value,So.length-1)];t.value+=1,clearTimeout(i),i=setTimeout(()=>c(),n)}},c=()=>{if(!r)try{r=new EventSource(`/api/v1/events`,{withCredentials:!0}),s(r)}catch(t){console.error(`failed to open /api/v1/events`,t),e.value=!1}};return{connected:h(e),reconnectAttempt:h(t),connect:c,disconnect:()=>{if(clearTimeout(i),i=null,r){try{r.close()}catch{}r=null}e.value=!1,t.value=0},subscribe:(e,t)=>(n.has(e)||n.set(e,new Set),n.get(e).add(t),()=>{let r=n.get(e);r&&r.delete(t)})}}),wo=60,To=_e(`system`,()=>{let e=o(!1),t=o(null),n=o(0),r=o([]),i=o({}),a=o(null),s=null,c=null,l=null,u=e=>{t.value=e;let n=new Set;for(let t of e.pools||[]){n.add(t.function_id);let e=i.value[t.function_id]||[];e.push(t.stable_rate),e.length>wo&&e.splice(0,e.length-wo),i.value[t.function_id]=e}for(let e of Object.keys(i.value))n.has(e)||delete i.value[e]},d=async()=>{try{let[t,i,o,s]=await Promise.all([Ua(),pa().catch(()=>({data:{functions:[],total:0}})),ba({limit:20}).catch(()=>({data:{executions:[]}})),fa().catch(()=>({data:null}))]);u(t.data),n.value=i.data.total??(i.data.functions||[]).length,r.value=o.data.executions||[],s.data&&(a.value={version:s.data.version,commit:s.data.commit,buildTime:s.data.build_time,image:s.data.image,uptimeSeconds:s.data.uptime_seconds}),e.value=!0}catch(t){console.error(`seed fetch error:`,t),e.value=!1}};return{isConnected:e,metrics:t,functionsCount:n,recentInvocations:r,poolHistory:i,buildInfo:a,connect:()=>{let t=Co();d(),s=t.subscribe(`metrics`,t=>{u(t),e.value=!0}),c=t.subscribe(`execution`,e=>{r.value=[e,...r.value].slice(0,20)}),l=t.subscribe(`function`,e=>{e.action===`deleted`?n.value=Math.max(0,n.value-1):e.action===`created`&&(n.value+=1)})},disconnect:()=>{s&&=(s(),null),c&&=(c(),null),l&&=(l(),null),e.value=!1}}}),Eo={class:`flex h-screen w-full bg-background overflow-hidden font-sans antialiased text-foreground`},Do={class:`flex-1 flex flex-col min-w-0 overflow-hidden relative pt-14 lg:pt-0`},Oo={__name:`Layout`,setup(e){let t=To(),n=Co(),s=Fi(),c=o(0),u=null,d=I(()=>{c.value;let e=s.secondsUntilExpiry;return e==null||e<=0?`—`:e<60?`${Math.floor(e)}s`:e<3600?`${Math.floor(e/60)} min`:`${Math.floor(e/3600)} h`}),f=async()=>{(await s.refreshSession()).success||(window.location.href=`/login`)};return p(async()=>{await s.checkAuth(),n.connect(),t.connect(),u=setInterval(()=>{c.value++},3e4)}),i(()=>{t.disconnect(),n.disconnect(),u&&clearInterval(u)}),(e,t)=>{let n=te(`router-view`);return r(),C(`div`,Eo,[k(Zi),x(`main`,Do,[k(n,null,{default:a(({Component:e})=>[(r(),N(ee,{max:10},[(r(),N(l(e),{class:`flex-1 overflow-auto scrollable p-page`}))],1024))]),_:1})]),k(da),k(ia,{visible:g(s).shouldShowExpiryToast,"action-loading":g(s).refreshing,title:`Session expiring soon`,"action-label":`Stay signed in`,onAction:f,onDismiss:g(s).dismissExpiryToast},{default:a(()=>[re(` Your session expires in `+R(d.value)+`. Click to extend it for another 7 days. `,1)]),_:1},8,[`visible`,`action-loading`,`onDismiss`])])}}},ko=`modulepreload`,Ao=function(e){return`/web/`+e},jo={},$=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}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Ao(t,n),t=s(t),t in jo)return;jo[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:ko,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.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)})},Mo=Mi({history:ei(`/web/`),routes:[{path:`/login`,name:`login`,component:()=>$(()=>import(`./Login-yy2M_6WN.js`),__vite__mapDeps([0,1,2])),meta:{requiresAuth:!1}},{path:`/onboarding`,name:`onboarding`,component:()=>$(()=>import(`./Onboarding-CEzpQ2g5.js`),__vite__mapDeps([3,1,2,4])),meta:{requiresAuth:!1}},{path:`/`,component:Oo,meta:{requiresAuth:!0},children:[{path:``,name:`dashboard`,component:()=>$(()=>import(`./Dashboard-DdzpeDBo.js`),__vite__mapDeps([5,1]))},{path:`ai`,name:`ai`,component:()=>$(()=>import(`./AI-5L2rM3_1.js`),__vite__mapDeps([6,7,1,8,4,9,10,11,12,13,14,15,16,17,18,19,20,21,22]))},{path:`functions`,name:`functions`,component:()=>$(()=>import(`./FunctionsList-CqkUOCmN.js`),__vite__mapDeps([23,1,8,4,24,25,14,26,17,11,7,21,27]))},{path:`functions/:name`,name:`function-detail`,component:()=>$(()=>import(`./Editor--ZYS7LkE.js`),__vite__mapDeps([28,1,29,8,30,4,31,24,32,25,33,15,34,16,35,17,36,11,7,21,37,38,39,40,41]))},{path:`functions/:name/deployments`,name:`function-deployments`,component:()=>$(()=>import(`./Deployments-BvLjnxyG.js`),__vite__mapDeps([42,1,43,30,26,15,12,13,44,45,38]))},{path:`functions/:name/diff`,name:`function-diff`,component:()=>$(()=>import(`./FunctionDiff-CpSHReET.js`),__vite__mapDeps([46,1,4,31,15,18,47,21,38,48]))},{path:`functions/:name/kv`,name:`function-kv`,component:()=>$(()=>import(`./KVStore-B42u_-WY.js`),__vite__mapDeps([49,1,26,17,12,13,27]))},{path:`functions/:name/inbound-webhooks`,name:`function-inbound-webhooks`,component:()=>$(()=>import(`./InboundWebhooks-DlQkZ2lf.js`),__vite__mapDeps([50,1,26,17,12,13,27]))},{path:`functions/new`,name:`function-new`,component:()=>$(()=>import(`./Editor--ZYS7LkE.js`),__vite__mapDeps([28,1,29,8,30,4,31,24,32,25,33,15,34,16,35,17,36,11,7,21,37,38,39,40,41]))},{path:`deploy`,redirect:{name:`function-new`}},{path:`cron`,name:`cron`,component:()=>$(()=>import(`./CronJobs-Ches-sRR.js`),__vite__mapDeps([51,1,43,33,52,17,27,37]))},{path:`jobs`,name:`jobs`,component:()=>$(()=>import(`./Jobs-DuQCYFLA.js`),__vite__mapDeps([53,1,43,45,15,17,12,13,27]))},{path:`activity`,name:`activity`,component:()=>$(()=>import(`./Activity-BCmI00tZ.js`),__vite__mapDeps([54,1,55,12,13,44,43,45]))},{path:`invocations`,name:`invocations`,component:()=>$(()=>import(`./InvocationsLog-DEPmQG0y.js`),__vite__mapDeps([56,1,8,2,33,26,15,16,17,11,7,12,13,21,44,43,45,39]))},{path:`traces`,name:`traces`,component:()=>$(()=>import(`./Traces-BoBh7dBt.js`),__vite__mapDeps([57,1,58,26,44,43,45]))},{path:`traces/:id`,name:`trace-detail`,component:()=>$(()=>import(`./TraceDetail-C28REiIi.js`),__vite__mapDeps([59,1,60,2,4,58,44,43,45]))},{path:`api-keys`,name:`api-keys`,component:()=>$(()=>import(`./ApiKeys-B1jjrPlM.js`),__vite__mapDeps([61,1,8,4,32,17,21,27,62]))},{path:`channels`,name:`channels`,component:()=>$(()=>import(`./Channels-B3r_Mr9x.js`),__vite__mapDeps([63,1,8,2,4,15,17,21,27,62]))},{path:`webhooks`,name:`webhooks`,component:()=>$(()=>import(`./Webhooks-BHh3seUT.js`),__vite__mapDeps([64,1,8,4,15,52,17,18,21,27,37]))},{path:`firewall`,name:`firewall`,component:()=>$(()=>import(`./Firewall-qk4ey7XG.js`),__vite__mapDeps([65,1,24,26,34,17,11,7,37,40,66]))},{path:`settings`,name:`settings`,component:()=>$(()=>import(`./Settings-CTZtncIj.js`),__vite__mapDeps([67,1,4,9,10,8,11,7,12,13,32,35,17,21,62,40]))},{path:`docs`,name:`docs`,component:()=>$(()=>import(`./Docs-CMWnQ8Ew.js`),__vite__mapDeps([68,1,8,55,4,24,32,25,36,11,7,19,20,21,39,69]))}]},{path:`/:pathMatch(.*)*`,name:`not-found`,component:()=>$(()=>import(`./NotFound-PtAc3nsW.js`),__vite__mapDeps([70,1,60,29])),meta:{requiresAuth:!1}}]});Mo.beforeEach((e,t,n)=>{if(t.fullPath===e.fullPath&&t.name)return n(!1);n()}),Mo.beforeEach(async(e,t,n)=>{let r=Fi();if(!await r.fetchAuthStatus())return e.name===`onboarding`?n():n({name:`onboarding`,replace:!0});if(r.isAuthenticated===!1&&await r.checkAuth(),r.isAuthenticated)return e.name===`onboarding`||e.name===`login`?n({name:`dashboard`}):n();if(e.name===`login`)return n();if(e.name===`onboarding`)return n({name:`login`,replace:!0});n({name:`login`,query:{redirect:e.fullPath}})});var No=Wt(Ln),Po=ve();No.use(Po),No.use(Mo),No.mount(`#app`);export{Ra as $,Oa as A,nn as At,pa as B,Rt as Bt,ma as C,gn as Ct,oo as D,on as Dt,Sa as E,ln as Et,za as F,Ot as Ft,La as G,ba as H,Fa as I,kt as It,fo as J,uo as K,Za as L,Tt as Lt,Da as M,je as Mt,Ta as N,Et as Nt,lo as O,an as Ot,Ma as P,Nt as Pt,Ia as Q,Ka as R,Je as Rt,Ca as S,_n as St,xa as T,mn as Tt,no as U,yo as V,ga as W,io as X,wa as Y,vo as Z,va as _,En as _t,qa as a,$a as at,Wa as b,xn as bt,Qa as c,co as ct,Pa as d,Fi as dt,Ja as et,Ha as f,wi as ft,ao as g,Dn as gt,xo as h,kn as ht,eo as i,go as it,Ea as j,q as jt,ya as k,rn as kt,bo as l,Bi as lt,ja as m,Xn as mt,To as n,so as nt,Na as o,Aa as ot,to as p,Zn as pt,_o as q,Co as r,_a as rt,Ba as s,mo as st,$ as t,Va as tt,po as u,Ii as ut,ho as v,Cn as vt,ha as w,hn as wt,Ga as x,vn as xt,ro as y,Sn as yt,ka as z,Bt as zt}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/key-round-BKXtbC85.js b/backend/internal/server/ui_dist/assets/key-round-D9wVuhgl.js similarity index 81% rename from backend/internal/server/ui_dist/assets/key-round-BKXtbC85.js rename to backend/internal/server/ui_dist/assets/key-round-D9wVuhgl.js index 1009b9be..953959fd 100644 --- a/backend/internal/server/ui_dist/assets/key-round-BKXtbC85.js +++ b/backend/internal/server/ui_dist/assets/key-round-D9wVuhgl.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`key-round`,[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`key-round`,[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/lock-CttMBTH5.js b/backend/internal/server/ui_dist/assets/lock-n1lM5kKa.js similarity index 67% rename from backend/internal/server/ui_dist/assets/lock-CttMBTH5.js rename to backend/internal/server/ui_dist/assets/lock-n1lM5kKa.js index c05fe8a0..ff1979dc 100644 --- a/backend/internal/server/ui_dist/assets/lock-CttMBTH5.js +++ b/backend/internal/server/ui_dist/assets/lock-n1lM5kKa.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`lock`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`lock`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/pencil-Do2I7soU.js b/backend/internal/server/ui_dist/assets/pencil-BmuCVcyO.js similarity index 75% rename from backend/internal/server/ui_dist/assets/pencil-Do2I7soU.js rename to backend/internal/server/ui_dist/assets/pencil-BmuCVcyO.js index 559fa270..ef941884 100644 --- a/backend/internal/server/ui_dist/assets/pencil-Do2I7soU.js +++ b/backend/internal/server/ui_dist/assets/pencil-BmuCVcyO.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`pencil`,[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}],[`path`,{d:`m15 5 4 4`,key:`1mk7zo`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`pencil`,[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}],[`path`,{d:`m15 5 4 4`,key:`1mk7zo`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/play-CmQifd74.js b/backend/internal/server/ui_dist/assets/play-CnkMURxf.js similarity index 64% rename from backend/internal/server/ui_dist/assets/play-CmQifd74.js rename to backend/internal/server/ui_dist/assets/play-CnkMURxf.js index 52d0b570..8f294ebd 100644 --- a/backend/internal/server/ui_dist/assets/play-CmQifd74.js +++ b/backend/internal/server/ui_dist/assets/play-CnkMURxf.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`play`,[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`play`,[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/refresh-cw-Cn8qkf-v.js b/backend/internal/server/ui_dist/assets/refresh-cw-CEfUzOcv.js similarity index 79% rename from backend/internal/server/ui_dist/assets/refresh-cw-Cn8qkf-v.js rename to backend/internal/server/ui_dist/assets/refresh-cw-CEfUzOcv.js index d50b3078..e8cbbbf0 100644 --- a/backend/internal/server/ui_dist/assets/refresh-cw-Cn8qkf-v.js +++ b/backend/internal/server/ui_dist/assets/refresh-cw-CEfUzOcv.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/rotate-ccw-DWwjKCqh.js b/backend/internal/server/ui_dist/assets/rotate-ccw-DgujV-4F.js similarity index 66% rename from backend/internal/server/ui_dist/assets/rotate-ccw-DWwjKCqh.js rename to backend/internal/server/ui_dist/assets/rotate-ccw-DgujV-4F.js index d26172e9..f145de16 100644 --- a/backend/internal/server/ui_dist/assets/rotate-ccw-DWwjKCqh.js +++ b/backend/internal/server/ui_dist/assets/rotate-ccw-DgujV-4F.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/settings-2-D5QtFfdZ.js b/backend/internal/server/ui_dist/assets/settings-2-C0pnmjU4.js similarity index 92% rename from backend/internal/server/ui_dist/assets/settings-2-D5QtFfdZ.js rename to backend/internal/server/ui_dist/assets/settings-2-C0pnmjU4.js index b16b818e..d4ab2d22 100644 --- a/backend/internal/server/ui_dist/assets/settings-2-D5QtFfdZ.js +++ b/backend/internal/server/ui_dist/assets/settings-2-C0pnmjU4.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`file-code`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 12.5 8 15l2 2.5`,key:`1tg20x`}],[`path`,{d:`m14 12.5 2 2.5-2 2.5`,key:`yinavb`}]]),n=e(`package`,[[`path`,{d:`M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z`,key:`1a0edw`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}],[`polyline`,{points:`3.29 7 12 12 20.71 7`,key:`ousv84`}],[`path`,{d:`m7.5 4.27 9 5.15`,key:`1c824w`}]]),r=e(`settings-2`,[[`path`,{d:`M14 17H5`,key:`gfn3mx`}],[`path`,{d:`M19 7h-9`,key:`6i9tg`}],[`circle`,{cx:`17`,cy:`17`,r:`3`,key:`18b49y`}],[`circle`,{cx:`7`,cy:`7`,r:`3`,key:`dfmy0x`}]]);export{n,t as r,r as t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`file-code`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 12.5 8 15l2 2.5`,key:`1tg20x`}],[`path`,{d:`m14 12.5 2 2.5-2 2.5`,key:`yinavb`}]]),n=e(`package`,[[`path`,{d:`M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z`,key:`1a0edw`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}],[`polyline`,{points:`3.29 7 12 12 20.71 7`,key:`ousv84`}],[`path`,{d:`m7.5 4.27 9 5.15`,key:`1c824w`}]]),r=e(`settings-2`,[[`path`,{d:`M14 17H5`,key:`gfn3mx`}],[`path`,{d:`M19 7h-9`,key:`6i9tg`}],[`circle`,{cx:`17`,cy:`17`,r:`3`,key:`18b49y`}],[`circle`,{cx:`7`,cy:`7`,r:`3`,key:`dfmy0x`}]]);export{n,t as r,r as t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/shield-check-piXkOtNv.js b/backend/internal/server/ui_dist/assets/shield-check-CowI6J3x.js similarity index 79% rename from backend/internal/server/ui_dist/assets/shield-check-piXkOtNv.js rename to backend/internal/server/ui_dist/assets/shield-check-CowI6J3x.js index ef3eecb0..522419b2 100644 --- a/backend/internal/server/ui_dist/assets/shield-check-piXkOtNv.js +++ b/backend/internal/server/ui_dist/assets/shield-check-CowI6J3x.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`shield-check`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`shield-check`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/sparkles-DTHEIS5T.js b/backend/internal/server/ui_dist/assets/sparkles-BZcVxan3.js similarity index 86% rename from backend/internal/server/ui_dist/assets/sparkles-DTHEIS5T.js rename to backend/internal/server/ui_dist/assets/sparkles-BZcVxan3.js index fb2df9e5..0f9ecf54 100644 --- a/backend/internal/server/ui_dist/assets/sparkles-DTHEIS5T.js +++ b/backend/internal/server/ui_dist/assets/sparkles-BZcVxan3.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/square-pen-DCrjAsLy.js b/backend/internal/server/ui_dist/assets/square-pen-Ctkj2Y_N.js similarity index 79% rename from backend/internal/server/ui_dist/assets/square-pen-DCrjAsLy.js rename to backend/internal/server/ui_dist/assets/square-pen-Ctkj2Y_N.js index 1e372903..2537a422 100644 --- a/backend/internal/server/ui_dist/assets/square-pen-DCrjAsLy.js +++ b/backend/internal/server/ui_dist/assets/square-pen-Ctkj2Y_N.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`square-pen`,[[`path`,{d:`M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`,key:`1m0v6g`}],[`path`,{d:`M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z`,key:`ohrbg2`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`square-pen`,[[`path`,{d:`M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`,key:`1m0v6g`}],[`path`,{d:`M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z`,key:`ohrbg2`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/terminal-BQdlNiyt.js b/backend/internal/server/ui_dist/assets/terminal-Czs3Hy-Y.js similarity index 57% rename from backend/internal/server/ui_dist/assets/terminal-BQdlNiyt.js rename to backend/internal/server/ui_dist/assets/terminal-Czs3Hy-Y.js index 6902b41c..b95562de 100644 --- a/backend/internal/server/ui_dist/assets/terminal-BQdlNiyt.js +++ b/backend/internal/server/ui_dist/assets/terminal-Czs3Hy-Y.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`terminal`,[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`terminal`,[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/trash-2-DaeYqnW_.js b/backend/internal/server/ui_dist/assets/trash-2-Cz9PSE2q.js similarity index 79% rename from backend/internal/server/ui_dist/assets/trash-2-DaeYqnW_.js rename to backend/internal/server/ui_dist/assets/trash-2-Cz9PSE2q.js index 2fe35548..1bdabaee 100644 --- a/backend/internal/server/ui_dist/assets/trash-2-DaeYqnW_.js +++ b/backend/internal/server/ui_dist/assets/trash-2-Cz9PSE2q.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/variable-DrK2KZuk.js b/backend/internal/server/ui_dist/assets/variable-DFVSR15i.js similarity index 77% rename from backend/internal/server/ui_dist/assets/variable-DrK2KZuk.js rename to backend/internal/server/ui_dist/assets/variable-DFVSR15i.js index 62a94564..ddab2fa4 100644 --- a/backend/internal/server/ui_dist/assets/variable-DrK2KZuk.js +++ b/backend/internal/server/ui_dist/assets/variable-DFVSR15i.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`variable`,[[`path`,{d:`M8 21s-4-3-4-9 4-9 4-9`,key:`uto9ud`}],[`path`,{d:`M16 3s4 3 4 9-4 9-4 9`,key:`4w2vsq`}],[`line`,{x1:`15`,x2:`9`,y1:`9`,y2:`15`,key:`f7djnv`}],[`line`,{x1:`9`,x2:`15`,y1:`9`,y2:`15`,key:`1shsy8`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`variable`,[[`path`,{d:`M8 21s-4-3-4-9 4-9 4-9`,key:`uto9ud`}],[`path`,{d:`M16 3s4 3 4 9-4 9-4 9`,key:`4w2vsq`}],[`line`,{x1:`15`,x2:`9`,y1:`9`,y2:`15`,key:`f7djnv`}],[`line`,{x1:`9`,x2:`15`,y1:`9`,y2:`15`,key:`1shsy8`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/assets/zap-BXGoxm_a.js b/backend/internal/server/ui_dist/assets/zap-BF0H8u1s.js similarity index 75% rename from backend/internal/server/ui_dist/assets/zap-BXGoxm_a.js rename to backend/internal/server/ui_dist/assets/zap-BF0H8u1s.js index 0216f3a6..0d14e991 100644 --- a/backend/internal/server/ui_dist/assets/zap-BXGoxm_a.js +++ b/backend/internal/server/ui_dist/assets/zap-BF0H8u1s.js @@ -1 +1 @@ -import{jt as e}from"./index-DTqMKlE1.js";var t=e(`zap`,[[`path`,{d:`M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z`,key:`1v7up4`}]]);export{t}; \ No newline at end of file +import{jt as e}from"./index-pE9wnfTb.js";var t=e(`zap`,[[`path`,{d:`M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z`,key:`1v7up4`}]]);export{t}; \ No newline at end of file diff --git a/backend/internal/server/ui_dist/docs.md b/backend/internal/server/ui_dist/docs.md index abf7d458..216455ad 100644 --- a/backend/internal/server/ui_dist/docs.md +++ b/backend/internal/server/ui_dist/docs.md @@ -1243,7 +1243,7 @@ Failed deliveries (non-2xx, timeout, network) retry up to 5× with exponential b - Network is OFF by default — sandbox has only loopback (no DNS, no outbound TCP). The user must flip "Allow outbound network" in the editor's Settings modal to call external HTTPS APIs (Stripe, OpenAI, a remote DB). Tell the user to do this whenever your code makes outbound calls. - orva.kv / orva.invoke / orva.jobs ALSO require egress — the SDK reaches orvad over the bridge network via HTTP, so a function with `network_mode: "none"` will see every SDK call fail with ENETUNREACH / OrvaUnavailableError. If the handler imports the orva module, set `network_mode: "egress"` at create time (or update later) — the editor's deploy step will warn you when the import meets `none`. - When egress IS enabled, the operator can still block specific destinations with the egress policy, and can pin resolvers / host overrides with the sandbox DNS settings (both on the dashboard's Egress controls page). A destination blocked by policy fails with ECONNREFUSED — distinct from the ENETUNREACH you get with `network_mode: "none"`. Handle both. -- Concurrency: each warm worker handles one request at a time. The pool autoscales workers up to the function's max_concurrent setting. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. +- Concurrency: each warm worker handles one request at a time. Pool Controller v2 sizes workers from arrival rate, queue pressure, service time, and cold-start time, bounded by the function's pool ceiling and effective host CPU/memory capacity. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. diff --git a/backend/internal/server/ui_dist/index.html b/backend/internal/server/ui_dist/index.html index 0fc047bd..03d24fdd 100644 --- a/backend/internal/server/ui_dist/index.html +++ b/backend/internal/server/ui_dist/index.html @@ -8,7 +8,7 @@ - + diff --git a/cli/commands/pool.go b/cli/commands/pool.go index d4e6d289..df8f5da2 100644 --- a/cli/commands/pool.go +++ b/cli/commands/pool.go @@ -12,16 +12,16 @@ import ( // poolCmd exposes the per-function warm-pool autoscaler config to the // terminal. It hits the same /api/v1/pool/config endpoints the dashboard's // function settings use. The pool keeps min_warm sandboxes hot, scales up -// toward max_warm under load (one new worker per target_concurrency -// in-flight requests), and recycles workers idle longer than idle_ttl. +// toward max_warm from measured demand, and recycles workers idle longer +// than idle_ttl. var poolCmd = &cobra.Command{ Use: "pool", Short: "View or tune warm-pool autoscaler config", Long: `View or tune the warm-sandbox autoscaler for a function. The autoscaler keeps min_warm sandboxes hot at all times, scales up toward -max_warm under load (adding a worker per target_concurrency in-flight -requests), recycles workers idle longer than idle_ttl seconds, and — when +max_warm from measured arrival, queue, service, and cold-start signals, +recycles workers idle longer than idle_ttl seconds, and — when scale_to_zero is on — drops to zero warm workers when fully idle (trading a cold start on the next request for zero idle cost). @@ -40,7 +40,7 @@ var poolGetCmd = &cobra.Command{ Use: "get", Short: "Show a function's warm-pool config", Long: `Show the autoscaler config for a function: min_warm, max_warm, idle_ttl, -target_concurrency, and scale_to_zero. +and scale_to_zero. If the function has no explicit override, the server reports it as unconfigured (running on built-in defaults).`, @@ -59,7 +59,6 @@ Only the flags you actually pass are sent; every omitted field keeps its current value (the server treats this as a partial update). Changes apply to new sandbox spawns; existing warm workers keep their behavior until recycled.`, Example: ` orva pool set --fn greeter --min-warm 1 --max-warm 10 - orva pool set --fn greeter --target-concurrency 5 orva pool set --fn greeter --scale-to-zero orva pool set --fn greeter --scale-to-zero=false`, Args: cobra.NoArgs, @@ -74,7 +73,6 @@ func init() { poolSetCmd.Flags().Int("min-warm", 0, "minimum warm sandboxes kept hot") poolSetCmd.Flags().Int("max-warm", 0, "maximum warm sandboxes under load") poolSetCmd.Flags().Int("idle-ttl", 0, "seconds a worker may sit idle before recycling") - poolSetCmd.Flags().Int("target-concurrency", 0, "in-flight requests per worker before scaling up") poolSetCmd.Flags().Bool("scale-to-zero", false, "drop to zero warm workers when fully idle") _ = poolSetCmd.MarkFlagRequired("fn") @@ -149,16 +147,12 @@ func runPoolSet(cmd *cobra.Command, _ []string) error { v, _ := cmd.Flags().GetInt("idle-ttl") body["idle_ttl_seconds"] = v } - if cmd.Flags().Changed("target-concurrency") { - v, _ := cmd.Flags().GetInt("target-concurrency") - body["target_concurrency"] = v - } if cmd.Flags().Changed("scale-to-zero") { v, _ := cmd.Flags().GetBool("scale-to-zero") body["scale_to_zero"] = v } if len(body) == 1 { - return fmt.Errorf("nothing to set — pass at least one of --min-warm, --max-warm, --idle-ttl, --target-concurrency, --scale-to-zero") + return fmt.Errorf("nothing to set — pass at least one of --min-warm, --max-warm, --idle-ttl, --scale-to-zero") } resp, err := client.Put("/api/v1/pool/config", body) @@ -185,12 +179,11 @@ func runPoolSet(cmd *cobra.Command, _ []string) error { // poolConfigView mirrors database.PoolConfig's JSON shape. type poolConfigView struct { - FunctionID string `json:"function_id"` - MinWarm int `json:"min_warm"` - MaxWarm int `json:"max_warm"` - IdleTTLSeconds int `json:"idle_ttl_seconds"` - TargetConcurrency int `json:"target_concurrency"` - ScaleToZero bool `json:"scale_to_zero"` + FunctionID string `json:"function_id"` + MinWarm int `json:"min_warm"` + MaxWarm int `json:"max_warm"` + IdleTTLSeconds int `json:"idle_ttl_seconds"` + ScaleToZero bool `json:"scale_to_zero"` } func printPoolConfig(cfg poolConfigView) { @@ -198,7 +191,6 @@ func printPoolConfig(cfg poolConfigView) { t.row("min_warm", cfg.MinWarm) t.row("max_warm", cfg.MaxWarm) t.row("idle_ttl_seconds", cfg.IdleTTLSeconds) - t.row("target_concurrency", cfg.TargetConcurrency) t.row("scale_to_zero", cfg.ScaleToZero) t.flush() } diff --git a/cli/commands/reference.md b/cli/commands/reference.md index abf7d458..216455ad 100644 --- a/cli/commands/reference.md +++ b/cli/commands/reference.md @@ -1243,7 +1243,7 @@ Failed deliveries (non-2xx, timeout, network) retry up to 5× with exponential b - Network is OFF by default — sandbox has only loopback (no DNS, no outbound TCP). The user must flip "Allow outbound network" in the editor's Settings modal to call external HTTPS APIs (Stripe, OpenAI, a remote DB). Tell the user to do this whenever your code makes outbound calls. - orva.kv / orva.invoke / orva.jobs ALSO require egress — the SDK reaches orvad over the bridge network via HTTP, so a function with `network_mode: "none"` will see every SDK call fail with ENETUNREACH / OrvaUnavailableError. If the handler imports the orva module, set `network_mode: "egress"` at create time (or update later) — the editor's deploy step will warn you when the import meets `none`. - When egress IS enabled, the operator can still block specific destinations with the egress policy, and can pin resolvers / host overrides with the sandbox DNS settings (both on the dashboard's Egress controls page). A destination blocked by policy fails with ECONNREFUSED — distinct from the ENETUNREACH you get with `network_mode: "none"`. Handle both. -- Concurrency: each warm worker handles one request at a time. The pool autoscales workers up to the function's max_concurrent setting. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. +- Concurrency: each warm worker handles one request at a time. Pool Controller v2 sizes workers from arrival rate, queue pressure, service time, and cold-start time, bounded by the function's pool ceiling and effective host CPU/memory capacity. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. diff --git a/docs/API.md b/docs/API.md index 1e6e25be..b36f0bd2 100644 --- a/docs/API.md +++ b/docs/API.md @@ -20,7 +20,7 @@ Error envelope (every 4xx/5xx): "code": "POOL_AT_CAPACITY", "message": "function pool at capacity for 019df200-7b00-7e00-9c00-aab1cd2e3f40", "request_id": "req_abc", - "hint": "raise pool_config.max_warm via PUT /api/v1/pool/config", + "hint": "inspect pool limiting_reason; raise max_warm only for operator_max", "retry_after_s": 5, "details": {"function_id": "019df200-7b00-7e00-9c00-aab1cd2e3f40", "current": 16, "limit": 16} } @@ -323,14 +323,15 @@ Read the row. "function_id": "019df200-7b00-7e00-9c00-aab1cd2e3f40", "min_warm": 2, "max_warm": 32, - "idle_ttl_seconds": 120, - "target_concurrency": 10, + "idle_ttl_seconds": 600, "scale_to_zero": false } ``` Fields are partial — unspecified ones keep the prior value (or default -for new rows). +for new rows). Defaults are min 1, max 50, idle TTL 600 seconds, and +scale-to-zero off. Pool Controller v2 derives desired capacity from demand; +the removed `target_concurrency` field returns `400 VALIDATION`. ## API keys diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 7cc0d12d..d695bf74 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -204,7 +204,7 @@ One SQLite file, grouped by subsystem. Core tables: | `build_logs` | stdout/stderr from `npm install` / `pip install` | | `function_secrets` | per-function encrypted env vars (AES-256-GCM) | | `routes` | custom URL → function-id mappings (`/webhooks/stripe`) | -| `pool_config` | per-fn autoscaler tuning (min_warm, max_warm, target_concurrency) | +| `pool_config` | per-fn pool policy (min_warm, max_warm, idle TTL, scale-to-zero) | | `system_config` | global tuning knobs (versions_to_keep, gc_interval_seconds, etc.) | Feature tables added since v0.2: diff --git a/docs/CAPACITY.md b/docs/CAPACITY.md index 750a551b..7ac5aae7 100644 --- a/docs/CAPACITY.md +++ b/docs/CAPACITY.md @@ -1,149 +1,114 @@ -# Capacity — honest numbers +# Pool Controller v2 capacity validation -This doc reports what was measured, not what was hoped for. +This document records reproducible measurements, not estimated capacity. +Numbers are a comparison aid for this host; they are not a universal sizing +promise. ## Test rig -- Host: 2 CPU / 12 GB RAM (`mem_total_mb=11961` reported by `/proc/meminfo`) -- Image: `orva:ui-mature` (built from this tree, nsjail compiled from source, two rootfs trees: node + python) -- Container flags: `--pid host --cgroupns host --cap-add SYS_ADMIN --security-opt seccomp=unconfined,apparmor=unconfined,systempaths=unconfined --device /dev/net/tun` -- Test: `bash test/atscale.sh` against a clean container (volume `orva-test-data`) -## What was deployed - -20 functions, mixed runtime: - -| runtime | count | shape | -|----------|-------|------------------------------| -| node | 10 | trivial echo handler | -| python | 10 | trivial dict-return handler | - -All 20 inline-deployed (no requirements.txt / package.json — those exercise the longer build path; covered separately in plan §B). - -**Build pipeline result:** all 20 deployments transitioned `queued → building → succeeded` in **2 seconds wall-clock** with `runtime.NumCPU()=2` build workers. No errors. - -## Idle capacity - -Right after deploy, before any traffic: - -| metric | value | -|-------------------------|---------------------------| -| pools created | **0** | -| host RSS (orva alloc) | 12 MB | -| memory reserved by pools | 0 MB | -| memory available | 9285 MB | - -Pools are created **lazily on first invoke**. With `EagerWarmup=true`, prewarm fires on startup for each function in the registry — but the autoscaler hasn't seen traffic, so it doesn't aggressively spawn before signals say it should. This is correct behavior and what the user asked for: *"you can't keep the pool always active when there are no requests."* - -**Idle capacity claim:** 20 functions deployed, sub-13 MB Orva heap, ~9.2 GB RAM still available. The platform itself takes negligible memory; real cost arrives only when traffic does. - -## Concurrent active capacity - -5 functions hammered concurrently (3 Node, 2 Python) at `c=25` each for 30 s: - -| metric | value | -|---------------------------------|---------------------------| -| total invocations | **13,476** | -| cold starts | 205 (1.5%) | -| warm hits | 13,271 (98.5%) | -| build errors | 0 | -| memory reserved (peak) | 5376 MB / 11961 MB (44.9%) | -| memory available (after) | 7871 MB | -| sandbox concurrent (peak) | 125 | -| sandbox total | 13,476 | - -Roughly **450 req/s aggregate** across 5 fns × 2 CPUs = ~90 req/s/fn — consistent with our single-fn ceiling (962 req/s on one fn) once divided five ways and accounting for the autoscaler tick latency. - -## Cross-function isolation — confirmed - -Per-pool snapshot at end of run: - -| function | idle | busy | scale_ups | scale_downs | -|-------------------|-----:|-----:|----------:|------------:| -| ascale-node-1 | 25 | 0 | 0 | 10 | -| ascale-node-3 | 25 | 0 | 0 | 11 | -| ascale-node-5 | 25 | 0 | 0 | 9 | -| ascale-py-1 | 14 | 0 | 14 | 0 | -| ascale-py-2 | 14 | 0 | 14 | 0 | -| (15 idle fns) | – | – | – | – | - -**Only 5 pools exist.** The 15 untouched functions never spawned a worker — confirming pool isolation under the per-function `functionPool` design. A function under heavy load cannot starve another function's resources. - -(Note: the `scale_ups=0` for the Node pools reflects that the autoscaler grew them via the request-path lazy spawn rather than the autoscaler's predictive `scaleUp`. Both code paths increment `spawned` but only the autoscaler increments `scale_ups`. This is a metrics-attribution nuance, not a behavior issue.) - -## Process leaks - -``` -nsjail processes: 104 -expected (Σ idle + Σ busy) = 25+25+25+14+14 + 0 = 103 -``` - -Off-by-one is the sampling race between `metrics.json` snapshot and the `ps`-equivalent walk. **No process leaks.** - -## Honest answers to the user's questions - -> *How many functions can we run smoothly?* - -- **Idle:** essentially unlimited up to disk space. Each function at `min_warm=1` reserves one ~50 MB worker only when it actually receives traffic. 20 idle functions cost `12 MB` of Orva-heap + zero pool memory. -- **Concurrent active:** 5 functions all hot, sharing 2 CPUs, sustains ~450 req/s aggregate before CPU is the wall. More functions can be active simultaneously, just at lower per-fn req/s. -- **Memory wall:** ~80 functions could each hold one 128 MB worker (`memory.max = 192 MB` × 1.5 factor) before hitting the 80% RAM-reservation gate. In practice the autoscaler shrinks idle pools, so this is the worst case. - -> *Did everything work end-to-end?* - -| component | tested | result | -|----------------------------------------|--------|--------------------------------| -| 20 deploys via async build pipeline | ✓ | 0 failures, 2s aggregate | -| Per-fn pool isolation | ✓ | 15 idle fns untouched | -| Autoscaler scale-up | ✓ | 5 hot pools spawned to ~25 | -| Autoscaler scale-down | ✓ | scale_downs counter increments | -| Memory accounting | ✓ | mem_reserved tracks workers | -| Process leak | ✓ | nsjail count matches pool size | -| Bootstrap admin key persistence | ✓ | survives `docker rm` + `run` | -| `/api/v1/auth/status` route guard correctness | ✓ | doesn't bounce to onboarding | -| Latency unit (ns→ms fix) | ✓ | `latency_ms` is now ms in JSON | -| New `/system/metrics.json` endpoint | ✓ | UI reads this directly | - -## Known soft issues (not blockers) - -1. The autoscaler's lazy spawn-on-Acquire bumps `spawned` but not `scale_ups` — fix is to attribute spawns by source. -2. `mem_reserved` momentarily reads 0 during the very first tick of a hot pool because Acquire-path spawns bypass `hostMem.reserve()`. Reserved memory is correctly tracked once the autoscaler ticks (within 2 s). Acceptable for now. -3. Bash test's phase 5 awk parser failed on empty `hey` percentile fields — the data we needed (cross-fn isolation, process leak check, total invocations) was already captured. - ---- - -## Round E retrospective (2026-04-25) - -All three soft issues above are **resolved**: -- **E.1.1** — `internal/pool/function_pool.go` lazy spawn now bumps `scaleUps` alongside `spawned`; verified live, hot pools reported 8/13/13/15/18 scale events vs the prior 0. -- **E.1.2** — `functionPool.hostMem` back-reference added; `acquire()` reserves memory before spawn and `killWorker` releases on every termination path. `mem_reserved_mb` now reflects accurate occupancy from sample 1 (was 0 for 4 ticks). -- **E.1.3** — `test/atscale.sh` phase 5 uses `awk -v` defaults; no more SIGPIPE on empty hey fields. - -Plus one **architectural fix** uncovered while writing E.4 tests: -- **Secrets injection.** Pre-round-E, secrets were built into a per-request env map by `proxy.Forward` but never plumbed to `pool.Acquire`. Warm workers kept their original env and never saw new secrets. Fix: `pool.SandboxTemplate.SecretsLookup` is consulted at every spawn, and secret upsert/delete triggers `Manager.RefreshForDeploy` so the next worker picks up the change. Verified by `test/secrets-test.sh` (8/8 pass). - -## Verified flows (`bash test/run-all.sh`, 2026-04-25) - -| flow | tests | result | artifact | -|---|---|---|---| -| Multi-fn deploy + isolation | atscale.sh | ✓ 20 fns deployed in 4s; 5-fn concurrent load; cross-fn isolation; ~705 req/s aggregate | `test/atscale-results.tsv` | -| Secrets injection | secrets-test.sh | ✓ 8/8: STRIPE_* env injected, delete propagates via pool refresh, value_encrypted opaque, c=20 invokes consistent | `test/run-all-results.tsv` | -| Custom routes | routes-test.sh | ✓ 7/7: exact + prefix matching, reserved-prefix rejected (400), method restriction (405/200), direct invoke coexists, c=25 load | `test/run-all-results.tsv` | -| Heavy-dep async deploy | heavy-deploy-test.sh | ✓ 12/12: POST 202 in <500 ms, terminal status, requests==2.31.0 imported in sandbox, failure path keeps prior version active | `test/heavy-deploy-stream.log` | -| Onboarding curl-sim | onboarding-flow.sh | ✓ 13/13: status flips, cookie 7d, /api/v1/auth/me returns expires_at, /api/v1/auth/refresh rotates token, logout invalidates | `test/run-all-results.tsv` | -| Error code coverage | errors-test.sh (Round F) | ✓ 5/5: PAYLOAD_TOO_LARGE 413, WORKER_CRASHED 502, TIMEOUT 504, NOT_FOUND 404, METHOD_NOT_ALLOWED 405 (POOL_AT_CAPACITY needs sqlite3 in image — skipped gracefully) | `docs/ERRORS.md` | -| Onboarding (browser) | manual checklist | pending — operator runs through Onboarding → Login → Dashboard → Editor flow once after deploying a release | append a dated checklist below | - -### Browser pass checklist (manual, run once per release) - -``` -[ ] Visit http://localhost:18443 → routes to /onboarding -[ ] Submit onboarding form → routes to / -[ ] Dashboard renders with all sections (host card, latency cards, build pipeline, sandbox, pool grid) -[ ] /api/v1/system/metrics.json values match Dashboard cards (no client-side recompute drift) -[ ] Click an invocation row in /invocations → drawer opens with stderr, status, duration -[ ] Deploy a fn with deps → Editor shows live SSE log drawer, Test button gated until succeeded -[ ] Click "Deploy history →" link in Editor → /functions//deployments table -[ ] Click a deployment row → drawer opens with build log -[ ] Wait for session to enter the last 12h (or set cookie expiry via devtools) → toast appears -[ ] Click "Stay signed in" → toast clears, navigate, no re-prompt -[ ] /api/v1/auth/logout → bounces to /login -``` +- Date: 2026-08-11 +- Host: 4 logical CPUs, 15,999 MiB RAM +- Baseline: `a1c7ac7d` (the KV reliability merge, before Pool Controller v2) +- Candidate: `codex/pool-controller-v2` +- Runtime: native Orva, nsjail, production Node rootfs, isolated ports and + temporary databases +- Logging: `ORVA_LOG_LEVEL=error` for both measured runs +- Handler: 10 ms async Node response, 128 MiB declared memory, 1 CPU +- Load: 15 seconds, concurrency 32, persistent HTTP connections + +The host did not delegate writable cgroup controllers to this development +process, so per-worker `memory.current` sampling was unavailable. Admission +therefore correctly stayed on the declared cgroup hard bound. Cgroup parsing +and constrained-capacity arithmetic are covered by deterministic tests and +the required provisioned-Linux CI lane. + +## Before and after + +| Metric | Baseline | Controller v2 | Change | +|---|---:|---:|---:| +| Successful requests | 17,183 | 15,978 | — | +| Failed requests | 0 | 0 | — | +| Throughput | 1,144.24 req/s | 1,063.80 req/s | **-7.03%** | +| Client latency p95 | 49.77 ms | 52.23 ms | +2.46 ms | +| Server service p95 | 37 ms | 39 ms | +2 ms | +| Queue-wait p95 | not exposed | **0.006 ms** | new signal | +| Cold-start rate | 0.402% | **0.200%** | -50.2% | +| Workers spawned | 69 | **32** | -53.6% | +| Workers killed during measured load | 37 | **0** | eliminated | +| Effective ceiling | 32 | 32 | unchanged | +| Capacity timeouts | not exposed | **0** | new signal | + +The throughput gate allows at most a 10% regression; the measured 7.03% +decrease passes. The controller trades that bounded difference for half the +cold-start rate and removes the baseline's spawn/kill churn under the same +load. No worker exceeded the 32-worker effective CPU ceiling. + +After correcting the unobserved-memory fallback, a separate 5-second +concurrency-32 check produced 1,205.28 req/s with zero failures. It reserved +6,144 MiB for 32 workers (32 × the 192 MiB declared cgroup hard bound), with +`queued=0`, `spawning=0`, and zero capacity timeouts after the run. Once +`memory.current` samples exist, admission uses observed worker memory p95, +clamped to the declared bound. + +## KV control measurement + +The same isolated candidate instance processed 1,000 concurrent atomic KV +increments: + +| Metric | Result | +|---|---:| +| Final value | 1,000 | +| KV errors | 0 | +| KV timeouts | 0 | +| Cumulative increment latency | 2,338.098 ms | +| Mean database increment latency | 2.338 ms | + +This confirms the pool changes did not disturb the KV reliability contract or +SQLite atomic-increment path. + +## Controller invariants validated + +Automated tests cover: + +- exact stable, burst, and immediate-pressure formulas at 70% utilization; +- scale-to-zero only after the configured no-demand TTL; +- `spawning` publication before launch and at most four concurrent starts per + function, including repeated evaluations; +- 30 seconds continuously below desired capacity before scale-down; +- no more than 20% shrink per evaluation and idle workers only; +- cgroup memory headroom and pending-reservation admission; +- declared memory as the safe fallback before an observed p95 exists; +- migration of legacy pool rows, removal of `target_concurrency`, preservation + of values and foreign-key cascade behavior; +- rejection of stale configuration with `400 VALIDATION` migration guidance; +- scale-to-zero configuration normalization in the database and REST surface; +- deployment/policy generation retirement without crossing workers between + generations. + +The global scheduler rotates its starting function each evaluation. When +memory or CPU admission fails, it first reclaims an idle worker above the +configured minimum from the largest borrowing pool. Busy workers and active +configured minimums are never reclamation candidates. CPU admission is global +across pools, weighted by each function's declared CPU limit, and bounded to +eight I/O-overlap worker slots per effective cgroup CPU. + +## Operational interpretation + +Use these Pool Controller v2 signals together: + +- `queued` and `queue_wait_p95_ms` show user-visible pressure. +- `spawning` distinguishes cold-start work from a stuck queue. +- `desired_workers` is the demand result; `effective_max` is the actual + host/operator ceiling. +- `host.effective_memory_capacity_mb` is the live admission budget after + cgroup headroom and worker reservations; `host.effective_cpu_workers` is + the ceiling derived from the active CPU quota. +- `limiting_reason` says whether the active bound is stable demand, burst + demand, immediate pressure, configured minimum, idle TTL, operator maximum, + function concurrency, CPU capacity, or memory capacity. +- `cold_start_p95_ms` and `service_p95_ms` explain why two functions with the + same request rate can require different worker counts. + +Raise `max_warm` only when `limiting_reason=operator_max`. CPU or memory +limits require host capacity or smaller function limits; increasing the +operator ceiling cannot override the effective host maximum. diff --git a/docs/CLI.md b/docs/CLI.md index 1af75987..0602d045 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -578,7 +578,7 @@ specify change; the rest keep their current values. ```bash orva pool get --fn greeter orva pool set --fn greeter --min-warm 2 --max-warm 20 --scale-to-zero -orva pool set --fn greeter --idle-ttl 300 --target-concurrency 4 +orva pool set --fn greeter --idle-ttl 300 ``` ### Background jobs + webhook deliveries diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 42a10dd6..56e70530 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -91,14 +91,26 @@ Edited via `PUT /api/v1/pool/config` — no restart needed. |-------|---------|------| | `min_warm` | 1 | Idle workers floor — pool never shrinks below this | | `max_warm` | 50 | Hard ceiling on warm pool size | -| `idle_ttl_seconds` | 120 | Worker idle this long gets reaped | -| `target_concurrency` | 10 | Requests per worker before scale-up triggers | +| `idle_ttl_seconds` | 600 | No-demand interval before an opted-in pool scales to zero | | `scale_to_zero` | `false` | `true` = pool can drain to 0 (cold-start on next request) | +Pool Controller v2 chooses capacity automatically from 60-second arrival +rate × service p95, 6-second arrival rate × (service p95 + spawn p95), and +immediate busy + queued pressure, with a 70% internal utilization target. +`target_concurrency` was removed; stale requests receive `400 VALIDATION` +with migration guidance. + +Admission is global across functions: the host CPU quota supplies eight +I/O-overlap worker slots per CPU, weighted by each function's declared `cpus`, +and memory uses cgroup v2 headroom plus per-worker reservations. + +`scale_to_zero=true` owns `min_warm=0`. Turning it off restores a minimum of +at least one. Sending both fields with an incompatible pair is rejected. + ```bash curl -X PUT -H "X-Orva-API-Key: $KEY" -H 'Content-Type: application/json' \ http://localhost:8443/api/v1/pool/config \ - -d '{"function_id":"019df200-7b00-7e00-9c00-aab1cd2e3f40","min_warm":2,"max_warm":32,"idle_ttl_seconds":60}' + -d '{"function_id":"019df200-7b00-7e00-9c00-aab1cd2e3f40","min_warm":2,"max_warm":32,"idle_ttl_seconds":600}' ``` --- diff --git a/docs/ERRORS.md b/docs/ERRORS.md index 25b84339..0fc8edb2 100644 --- a/docs/ERRORS.md +++ b/docs/ERRORS.md @@ -8,7 +8,7 @@ Every API error returns the same envelope: "code": "POOL_AT_CAPACITY", "message": "function pool at capacity for 019df200-7b00-7e00-9c00-aab1cd2e3f40", "request_id": "req_abc...", - "hint": "raise pool_config.max_warm via PUT /api/v1/pool/config", + "hint": "inspect pool limiting_reason; raise max_warm only for operator_max", "retry_after_s": 5, "details": { "function_id": "019df200-7b00-7e00-9c00-aab1cd2e3f40", @@ -65,7 +65,7 @@ Fields beyond `code` and `message` are optional and may be absent. Transient err Every transient error includes a `hint` field telling the operator what to change. Examples: -- `POOL_AT_CAPACITY`: "raise pool_config.max_warm via PUT /api/v1/pool/config or reduce client concurrency" +- `POOL_AT_CAPACITY`: "inspect pool limiting_reason; raise max_warm only for operator_max, otherwise add host capacity or reduce worker limits" - `MEMORY_EXHAUSTED`: "deploy fewer concurrent functions or increase host RAM; see /api/v1/system/metrics.json host.mem_*" - `BUILD_QUEUE_FULL`: "wait for current builds to drain; consider raising NumCPU or staggering deploys" - `WORKER_CRASHED`: "check stderr in the latest execution log; common causes: process.exit, OOM, syntax error in handler" diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index 5949854d..d0b179fc 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -21,9 +21,11 @@ Five fields to look at first: |---|---| | `host.num_goroutines` | 50–500 idle, scales with active invokes | | `host.mem_reserved_mb` / `host.mem_total_mb` | should stay under 80% | +| `host.effective_memory_capacity_mb` | current memory available for one or more additional worker admissions | +| `host.effective_cpu_workers` | worker ceiling derived from the active cgroup CPU quota | | `sandbox.active` | <= `cfg.Sandbox.MaxConcurrent` (derived: `NumCPU × 64`, floor 200) | | `latency_ms.p99` | <= 5 × `latency_ms.p50`. If p99 is 10× p50 the pool is saturated | -| `pools[].idle` for each pool | <= `pools[].dynamic_max`. If exceeded, the pool stability fix didn't deploy | +| `pools[].idle + busy + spawning` | <= `pools[].effective_max`; queued should drain after a burst | ## Common errors and what they mean @@ -32,7 +34,7 @@ Full catalog in [ERRORS.md](ERRORS.md). The ones operators see most: | code | what's happening | what to do | |---|---|---| | `429 TOO_MANY_REQUESTS` | host-wide concurrency cap hit | client should back off + retry. The ceiling is derived from CPU count (`NumCPU × 64`, floor 200) and is not operator-tunable today — add CPUs to raise it | -| `503 POOL_AT_CAPACITY` | this function's pool at `dynamic_max` and ctx fired waiting | raise `pool_config.max_warm` for that fn, or accept the backpressure | +| `503 POOL_AT_CAPACITY` | this function reached its effective host/operator ceiling and the queue deadline expired | inspect `limiting_reason`; raise `max_warm` only when it says `operator_max`, otherwise add host capacity or reduce worker limits | | `503 MEMORY_EXHAUSTED` | host RAM at 80% reservation | scale-down idle pools, increase host RAM, or reduce per-fn `memory_mb` | | `502 WORKER_CRASHED` | function process exited mid-request (panic, OOM kill, syntax error) | check the execution's stderr in the dashboard or `execution_logs` table | | `504 TIMEOUT` | exceeded fn `timeout_ms` | raise it (`PUT /api/v1/functions/{id}` with `{"timeout_ms": 60000}`) or optimize the handler | @@ -50,12 +52,13 @@ docker stats orva --no-stream docker exec orva ps -ef | wc -l # nsjail process count ``` -If PIDs are >300 and idle is >dynamic_max, the pool over-spawned past -its cap. This was a real bug fixed in early Round-G builds — if you're -on `v2026.04.28` or later it shouldn't recur. +If total workers (`idle + busy + spawning`) exceeds `effective_max`, capture +the metrics snapshot and logs: Pool Controller v2 publishes spawning before +launch specifically to prevent overlapping evaluations from over-spawning. -**Recovery.** The autoscaler will catch up within ~30 s of load -ending. If it doesn't: +**Recovery.** The controller waits 30 seconds below desired capacity, then removes no +more than 20% of workers per evaluation. It should converge without dropping +busy work. If it doesn't: ```bash docker restart orva diff --git a/docs/RUNTIMES.md b/docs/RUNTIMES.md index b625d63c..59ccb237 100644 --- a/docs/RUNTIMES.md +++ b/docs/RUNTIMES.md @@ -168,8 +168,9 @@ The first invocation after deploy or after a long idle period spawns a fresh worker (~50–500 ms depending on runtime size and deps). Subsequent invocations land on idle workers from the pool (~2–15 ms). -Per-function pool sizing is autoscaled based on EWMA request rate + -in-flight concurrency. You can tune the floor/ceiling via +Per-function pool sizing uses 60-second stable demand, 6-second burst demand, +queue pressure, service p95, and cold-start p95. You tune only the policy +floor/ceiling via `PUT /api/v1/pool/config`: ```json @@ -177,8 +178,8 @@ in-flight concurrency. You can tune the floor/ceiling via "function_id": "019df200-7b00-7e00-9c00-aab1cd2e3f40", "min_warm": 2, "max_warm": 32, - "idle_ttl_seconds": 120, - "target_concurrency": 10 + "idle_ttl_seconds": 600, + "scale_to_zero": false } ``` diff --git a/docs/reference.md b/docs/reference.md index abf7d458..216455ad 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -1243,7 +1243,7 @@ Failed deliveries (non-2xx, timeout, network) retry up to 5× with exponential b - Network is OFF by default — sandbox has only loopback (no DNS, no outbound TCP). The user must flip "Allow outbound network" in the editor's Settings modal to call external HTTPS APIs (Stripe, OpenAI, a remote DB). Tell the user to do this whenever your code makes outbound calls. - orva.kv / orva.invoke / orva.jobs ALSO require egress — the SDK reaches orvad over the bridge network via HTTP, so a function with `network_mode: "none"` will see every SDK call fail with ENETUNREACH / OrvaUnavailableError. If the handler imports the orva module, set `network_mode: "egress"` at create time (or update later) — the editor's deploy step will warn you when the import meets `none`. - When egress IS enabled, the operator can still block specific destinations with the egress policy, and can pin resolvers / host overrides with the sandbox DNS settings (both on the dashboard's Egress controls page). A destination blocked by policy fails with ECONNREFUSED — distinct from the ENETUNREACH you get with `network_mode: "none"`. Handle both. -- Concurrency: each warm worker handles one request at a time. The pool autoscales workers up to the function's max_concurrent setting. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. +- Concurrency: each warm worker handles one request at a time. Pool Controller v2 sizes workers from arrival rate, queue pressure, service time, and cold-start time, bounded by the function's pool ceiling and effective host CPU/memory capacity. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. diff --git a/frontend/public/docs.md b/frontend/public/docs.md index abf7d458..216455ad 100644 --- a/frontend/public/docs.md +++ b/frontend/public/docs.md @@ -1243,7 +1243,7 @@ Failed deliveries (non-2xx, timeout, network) retry up to 5× with exponential b - Network is OFF by default — sandbox has only loopback (no DNS, no outbound TCP). The user must flip "Allow outbound network" in the editor's Settings modal to call external HTTPS APIs (Stripe, OpenAI, a remote DB). Tell the user to do this whenever your code makes outbound calls. - orva.kv / orva.invoke / orva.jobs ALSO require egress — the SDK reaches orvad over the bridge network via HTTP, so a function with `network_mode: "none"` will see every SDK call fail with ENETUNREACH / OrvaUnavailableError. If the handler imports the orva module, set `network_mode: "egress"` at create time (or update later) — the editor's deploy step will warn you when the import meets `none`. - When egress IS enabled, the operator can still block specific destinations with the egress policy, and can pin resolvers / host overrides with the sandbox DNS settings (both on the dashboard's Egress controls page). A destination blocked by policy fails with ECONNREFUSED — distinct from the ENETUNREACH you get with `network_mode: "none"`. Handle both. -- Concurrency: each warm worker handles one request at a time. The pool autoscales workers up to the function's max_concurrent setting. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. +- Concurrency: each warm worker handles one request at a time. Pool Controller v2 sizes workers from arrival rate, queue pressure, service time, and cold-start time, bounded by the function's pool ceiling and effective host CPU/memory capacity. Don't rely on in-process module-level state surviving across requests beyond best-effort caching. diff --git a/frontend/src/stores/system.js b/frontend/src/stores/system.js index 9721717a..50287c96 100644 --- a/frontend/src/stores/system.js +++ b/frontend/src/stores/system.js @@ -3,7 +3,7 @@ import { ref } from 'vue' import { listFunctions, listInvocations, getMetricsJSON, getHealth } from '@/api/endpoints' import { useEventsStore } from '@/stores/events' -// poolHistorySize is how many ticks of per-pool rate_ewma we retain for +// poolHistorySize is how many ticks of per-pool stable_rate we retain for // the dashboard sparkline. 60 ticks × 5s/tick = 5 min of context. const poolHistorySize = 60 @@ -19,7 +19,7 @@ export const useSystemStore = defineStore('system', () => { const functionsCount = ref(0) const recentInvocations = ref([]) - // poolHistory[fn_id] = ring of recent rate_ewma values for sparkline. + // poolHistory[fn_id] = ring of recent stable-rate values for sparkline. const poolHistory = ref({}) // buildInfo: one-shot snapshot of /api/v1/system/health's build identity @@ -41,7 +41,7 @@ export const useSystemStore = defineStore('system', () => { for (const p of snap.pools || []) { seen.add(p.function_id) const ring = poolHistory.value[p.function_id] || [] - ring.push(p.rate_ewma) + ring.push(p.stable_rate) if (ring.length > poolHistorySize) ring.splice(0, ring.length - poolHistorySize) poolHistory.value[p.function_id] = ring } diff --git a/frontend/src/views/Dashboard.vue b/frontend/src/views/Dashboard.vue index 07ab90be..cb6bd163 100644 --- a/frontend/src/views/Dashboard.vue +++ b/frontend/src/views/Dashboard.vue @@ -66,10 +66,10 @@
- CPU cores + CPU / worker slots
- {{ m.host?.num_cpu ?? '?' }} + {{ m.host?.num_cpu ?? '?' }} / {{ m.host?.effective_cpu_workers ?? '?' }}
@@ -80,7 +80,7 @@ {{ formatMB(memUsed) }} / {{ formatMB(memTotal) }}
- {{ memUsedPct.toFixed(1) }}% used · {{ formatMB(memReserved) }} reserved by warm pools + {{ memUsedPct.toFixed(1) }}% used · {{ formatMB(memEffective) }} allocatable
@@ -215,23 +215,26 @@ Capacity
- {{ p.dynamic_max }} max + {{ p.effective_max }} max +
+
+ {{ formatLimit(p.limiting_reason) }}
@@ -245,19 +248,19 @@
- Avg latency + Service p95
- {{ p.latency_ewma_ms?.toFixed?.(1) ?? 0 }} ms + {{ p.service_p95_ms?.toFixed?.(1) ?? 0 }} ms
- Avg memory / limit + Queue / cold p95
- {{ p.mem_used_avg_mb > 0 ? '~' + Math.round(p.mem_used_avg_mb) : EMPTY }} - / {{ p.mem_limit_mb }} MB + {{ p.queue_wait_p95_ms?.toFixed?.(1) ?? 0 }} + / {{ p.cold_start_p95_ms?.toFixed?.(1) ?? 0 }} ms
@@ -308,6 +311,7 @@ const poolHistoryFor = (fnId) => system.poolHistory[fnId] || [] const formatPct = (v) => (v == null ? EMPTY : `${v.toFixed(1)}%`) const formatRate = (v) => (v == null ? '0' : v.toFixed(1)) +const formatLimit = (v) => (v ? v.replaceAll('_', ' ') : 'calculating') // Compact human-readable byte sizes. Server reports memory in MB; we show // GB once we cross 1 GB so the host card doesn't overflow with five-digit @@ -335,6 +339,7 @@ const memReserved = computed(() => m.value.host?.mem_reserved_mb ?? 0) // `docker stats`/`free` show. Idle warm sandboxes use a fraction of their // reservation, so memUsed is typically far below memReserved. const memAvailable = computed(() => m.value.host?.mem_available_mb ?? 0) +const memEffective = computed(() => m.value.host?.effective_memory_capacity_mb ?? 0) const memUsed = computed(() => Math.max(0, memTotal.value - memAvailable.value)) const memFree = computed(() => Math.max(0, memTotal.value - memUsed.value)) const memUsedPct = computed(() => (memTotal.value > 0 ? (memUsed.value / memTotal.value) * 100 : 0)) diff --git a/test/atscale.sh b/test/atscale.sh index b6bdc67a..647d16a1 100755 --- a/test/atscale.sh +++ b/test/atscale.sh @@ -8,7 +8,8 @@ # idle-capacity baseline. # 3. Hammer 5 fns concurrently with hey; assert cross-fn isolation # (untouched fns stay at min_warm) and no 503 BUILDING. -# 4. Capture autoscaler-driven scale-up/scale-down counts per fn. +# 4. Capture Controller v2 demand/capacity signals and assert no pool +# exceeds its effective host/operator ceiling. # # Output: tab-separated rows on stdout. Save to test/atscale-results.tsv. # @@ -174,8 +175,12 @@ wait "${PIDS[@]}" || true # ── Phase 4: Per-fn pool snapshot after load ──────────────────────────── echo "# phase 4: post-load per-pool snapshot" >&2 metrics=$("${CURL[@]}" "$BASE/api/v1/system/metrics.json") -echo "# function_id function_name idle busy dynamic_max scale_ups scale_downs rate_ewma" -echo "$metrics" | jq -r '.pools[] | [.function_id, .function_name, .idle, .busy, .dynamic_max, .scale_ups, .scale_downs, .rate_ewma] | @tsv' +echo "# function_id function_name idle busy queued spawning desired effective_max queue_p95_ms service_p95_ms cold_p95_ms limiting_reason" +echo "$metrics" | jq -r '.pools[] | [.function_id, .function_name, .idle, .busy, .queued, .spawning, .desired_workers, .effective_max, .queue_wait_p95_ms, .service_p95_ms, .cold_start_p95_ms, .limiting_reason] | @tsv' +if echo "$metrics" | jq -e 'any(.pools[]; (.idle + .busy + .spawning) > .effective_max)' >/dev/null; then + echo "pool exceeded effective capacity" >&2 + exit 1 +fi # ── Phase 5: Throughput per hammered fn ───────────────────────────────── echo "# phase 5: hammered-fn throughput" >&2 @@ -195,11 +200,11 @@ for name in "${LOAD_FNS[@]}"; do done # ── Phase 6: Process leak check ───────────────────────────────────────── -echo "# phase 6: nsjail process count (should match sum(idle+busy)) " >&2 +echo "# phase 6: nsjail process count (should match sum(idle+busy+spawning)) " >&2 container=$(docker ps --filter "publish=${BASE##*:}" --format '{{.Names}}' | head -1) if [ -n "$container" ]; then nsjail_count=$(docker exec "$container" sh -c 'ls /proc/[0-9]*/cmdline 2>/dev/null | xargs -I{} sh -c "tr \"\\000\" \" \" < {}; echo" 2>/dev/null | grep -c nsjail || true') - expected=$(echo "$metrics" | jq -r '[.pools[] | .idle + .busy] | add // 0') + expected=$(echo "$metrics" | jq -r '[.pools[] | .idle + .busy + .spawning] | add // 0') echo "process_check nsjail_running=$nsjail_count expected=$expected" fi diff --git a/test/errors-test.sh b/test/errors-test.sh index a0e3c30f..22a3ce09 100755 --- a/test/errors-test.sh +++ b/test/errors-test.sh @@ -25,7 +25,7 @@ http_status() { printf '%s' "$1" | head -n1 | awk '{print $2}' | tr -d '\r'; } # Extract a header value (case-insensitive) from a curl -i response. http_header() { local name="$1" resp="$2" - printf '%s' "$resp" | awk -v n="$(echo "$name" | tr 'A-Z' 'a-z')" ' + printf '%s' "$resp" | awk -v n="$(echo "$name" | tr '[:upper:]' '[:lower:]')" ' BEGIN{IGNORECASE=1} /^\r?$/ {exit} { @@ -158,9 +158,19 @@ done # Pin pool max_warm=1 via the public API. PoolRefresh tears down the running # pool so the next acquire picks up the new bounds without a server restart. +legacy_pool_body="/tmp/orva-legacy-pool-$$.json" +legacy_pool_status=$(curl -s -o "$legacy_pool_body" -w '%{http_code}' \ + -X PUT "$BASE/api/v1/pool/config" -H "X-Orva-API-Key: $KEY" \ + -H "Content-Type: application/json" \ + -d "{\"function_id\":\"$fid\",\"target_concurrency\":1}") +legacy_pool_code=$(jq -r '.error.code // empty' "$legacy_pool_body") +rm -f "$legacy_pool_body" +legacy_pool_ok=$([ "$legacy_pool_status" = 400 ] && [ "$legacy_pool_code" = VALIDATION ] && echo ok || echo fail) +check "removed target_concurrency returns 400 VALIDATION" "$legacy_pool_ok" \ + "status=$legacy_pool_status code=$legacy_pool_code" pool_resp=$("${CURL[@]}" -X PUT "$BASE/api/v1/pool/config" \ -H "Content-Type: application/json" \ - -d "{\"function_id\":\"$fid\",\"min_warm\":1,\"max_warm\":1,\"idle_ttl_seconds\":600,\"target_concurrency\":1}") + -d "{\"function_id\":\"$fid\",\"min_warm\":1,\"max_warm\":1,\"idle_ttl_seconds\":600}") if echo "$pool_resp" | jq -e '.max_warm == 1' >/dev/null 2>&1; then sleep 1 # let the pool refresh settle