diff --git a/CHANGELOG.md b/CHANGELOG.md index a98079f..9be1e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,68 @@ All notable changes to Vestige will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.5] - 2026-04-14 — "Intentional Amnesia" + +Every AI memory system stores too much. Vestige now treats forgetting as a first-class, neuroscientifically-grounded primitive. This release adds **active forgetting** — top-down inhibitory control over memory retrieval, based on two 2025 papers that no other AI memory system has implemented. + +### Scientific grounding + +- **Anderson, M. C., Hanslmayr, S., & Quaegebeur, L. (2025).** *"Brain mechanisms underlying the inhibitory control of thought."* Nature Reviews Neuroscience. DOI: [10.1038/s41583-025-00929-y](https://www.nature.com/articles/s41583-025-00929-y). Establishes the right lateral PFC as the domain-general inhibitory controller, and Suppression-Induced Forgetting (SIF) as compounding with each stopping attempt. +- **Cervantes-Sandoval, I., Chakraborty, M., MacMullen, C., & Davis, R. L. (2020).** *"Rac1 Impairs Forgetting-Induced Cellular Plasticity in Mushroom Body Output Neurons."* Front Cell Neurosci. [PMC7477079](https://pmc.ncbi.nlm.nih.gov/articles/PMC7477079/). Establishes Rac1 GTPase as the active synaptic destabilization mechanism — forgetting is a biological PROCESS, not passive decay. + +### Added + +#### `suppress` MCP Tool (NEW — Tool #24) +- **Top-down memory suppression.** Distinct from `memory.delete` (which removes) and `memory.demote` (which is a one-shot hit). Each `suppress` call compounds: `suppression_count` increments, and a `k × suppression_count` penalty (saturating at 80%) is subtracted from retrieval scores during hybrid search. +- **Rac1 cascade.** Background worker piggybacks the existing consolidation loop, walks `memory_connections` edges from recently-suppressed seeds, and applies attenuated FSRS decay to co-activated neighbors. You don't just forget "Jake" — you fade the café, the roommate, the birthday. +- **Reversible 24h labile window** — matches Nader reconsolidation semantics on a 24-hour axis. Pass `reverse: true` within 24h to undo. After that, it locks in. +- **Never deletes** — the memory persists and is still accessible via `memory.get(id)`. It's INHIBITED, not erased. + +#### `active_forgetting` Cognitive Module (NEW — #30) +- `crates/vestige-core/src/neuroscience/active_forgetting.rs` — stateless helper for SIF penalty computation, labile window tracking, and Rac1 cascade factors. +- 7 unit tests + 9 integration tests = 16 new tests. + +#### Migration V10 +- `ALTER TABLE knowledge_nodes ADD COLUMN suppression_count INTEGER DEFAULT 0` +- `ALTER TABLE knowledge_nodes ADD COLUMN suppressed_at TEXT` +- Partial indices on both columns for efficient sweep queries. +- Additive-only — backward compatible with all existing v2.0.x databases. + +#### Dashboard +- `ForgettingIndicator.svelte` — new status pill that pulses when suppressed memories exist. +- 3D graph nodes dim to 20% opacity and lose emissive glow when suppressed. +- New WebSocket events: `MemorySuppressed`, `MemoryUnsuppressed`, `Rac1CascadeSwept`. +- `Heartbeat` event now carries `suppressed_count` for live dashboard display. + +### Changed + +- `search` scoring pipeline now includes an SIF penalty applied after the accessibility filter. +- Consolidation worker (`VESTIGE_CONSOLIDATION_INTERVAL_HOURS`, default 6h) now runs `run_rac1_cascade_sweep` after each `run_consolidation` call. +- Tool count assertion bumped from 23 → 24. +- Workspace version bumped 2.0.4 → 2.0.5. + +### Tests + +- Rust: 1,284 passing (up from 1,237). Net +47 new tests for active forgetting, Rac1 cascade, migration V10. +- Dashboard (Vitest): 171 passing (up from 150). +21 regression tests locking in the issue #31 UI fix. +- Zero warnings, clippy clean across all targets. + +### Fixed + +- **Dashboard graph view rendered glowing squares instead of round halos** ([#31](https://github.com/samvallad33/vestige/issues/31)). Root cause: the node glow `THREE.SpriteMaterial` had no `map` set, so `Sprite` rendered as a solid-coloured 1×1 plane; additive blending plus `UnrealBloomPass(strength=0.8, radius=0.4, threshold=0.85)` then amplified the square edges into hard-edged glowing cubes. The aggressive `FogExp2(..., 0.008)` swallowed edges at depth and dark-navy `0x4a4a7a` lines were invisible against the fog. Fix bundled: + - Generated a shared 128×128 radial-gradient `CanvasTexture` (module-level singleton) and assigned it as `SpriteMaterial.map`. Gradient stops: `rgba(255,255,255,1.0) → rgba(255,255,255,0.7) → rgba(255,255,255,0.2) → rgba(255,255,255,0.0)`. Sprite now reads as a soft round halo; bloom diffuses cleanly. + - Retuned `UnrealBloomPass` to `(strength=0.55, radius=0.6, threshold=0.2)` — gentler, allows mid-tones to bloom instead of only blown-out highlights. + - Halved fog density `FogExp2(0x050510, 0.008) → FogExp2(0x0a0a1a, 0.0035)` so distant memories stay visible. + - Bumped edge color `0x4a4a7a → 0x8b5cf6` (brand violet). Opacity `0.1 + weight*0.5 → 0.25 + weight*0.5`, cap `0.6 → 0.8`. Added `depthWrite: false` so edges blend cleanly through fog. + - Added explicit `scene.background = 0x05050f` and a 2000-point starfield distributed on a spherical shell at radius 600–1000, additive-blended with subtle cool-white/violet vertex colors. + - Glow sprite scale bumped `size × 4 → size × 6` so the gradient has visible screen footprint. + - All node glow sprites share a single `CanvasTexture` instance (singleton cache — memory leak guard for large graphs). + - 21 regression tests added in `apps/dashboard/src/lib/graph/__tests__/ui-fixes.test.ts`. Hybrid strategy: runtime unit tests via the existing `three-mock.ts` (extended to propagate `map`/`color`/`depthWrite`/`blending` params and added `createRadialGradient` to the canvas context mock), plus source-level regex assertions on `scene.ts` and `nodes.ts` magic numbers so any accidental revert of fog/bloom/color/helper fails the suite immediately. +- `apps/dashboard/package.json` version stale at 2.0.3 — bumped to 2.0.5 to match the workspace. +- `packages/vestige-mcp-npm/.gitignore` missing `bin/vestige-restore` and `bin/vestige-restore.exe` entries — the other three binaries were already ignored as postinstall downloads. + +--- + ## [2.0.4] - 2026-04-09 — "Deep Reference" Context windows hit 1M tokens. Memory matters more than ever. This release removes artificial limits, adds contradiction detection, and hardens security. diff --git a/Cargo.lock b/Cargo.lock index 416a6f6..410e4d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4531,7 +4531,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vestige-core" -version = "2.0.4" +version = "2.0.5" dependencies = [ "chrono", "criterion", @@ -4566,7 +4566,7 @@ dependencies = [ [[package]] name = "vestige-mcp" -version = "2.0.4" +version = "2.0.5" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index 89761ac..b3008f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ exclude = [ ] [workspace.package] -version = "2.0.4" +version = "2.0.5" edition = "2024" license = "AGPL-3.0-only" repository = "https://github.com/samvallad33/vestige" diff --git a/README.md b/README.md index 9c7819a..f0aff79 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![GitHub stars](https://img.shields.io/github/stars/samvallad33/vestige?style=social)](https://github.com/samvallad33/vestige) [![Release](https://img.shields.io/github/v/release/samvallad33/vestige)](https://github.com/samvallad33/vestige/releases/latest) -[![Tests](https://img.shields.io/badge/tests-758%20passing-brightgreen)](https://github.com/samvallad33/vestige/actions) +[![Tests](https://img.shields.io/badge/tests-1284%20passing-brightgreen)](https://github.com/samvallad33/vestige/actions) [![License](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE) [![MCP Compatible](https://img.shields.io/badge/MCP-compatible-green)](https://modelcontextprotocol.io) @@ -14,21 +14,30 @@ Built on 130 years of memory research — FSRS-6 spaced repetition, prediction error gating, synaptic tagging, spreading activation, memory dreaming — all running in a single Rust binary with a 3D neural visualization dashboard. 100% local. Zero cloud. -[Quick Start](#quick-start) | [Dashboard](#-3d-memory-dashboard) | [How It Works](#-the-cognitive-science-stack) | [Tools](#-23-mcp-tools) | [Docs](docs/) +[Quick Start](#quick-start) | [Dashboard](#-3d-memory-dashboard) | [How It Works](#-the-cognitive-science-stack) | [Tools](#-24-mcp-tools) | [Docs](docs/) --- -## What's New in v2.0 "Cognitive Leap" +## What's New in v2.0.5 "Intentional Amnesia" -- **3D Memory Dashboard** — SvelteKit + Three.js neural visualization with real-time WebSocket events, bloom post-processing, force-directed graph layout. Watch your AI's mind in real-time. -- **WebSocket Event Bus** — Every cognitive operation broadcasts events: memory creation, search, dreaming, consolidation, retention decay -- **HyDE Query Expansion** — Template-based Hypothetical Document Embeddings for dramatically improved search quality on conceptual queries -- **Nomic v2 MoE (experimental)** — fastembed 5.11 with optional Nomic Embed Text v2 MoE (475M params, 8 experts) + Metal GPU acceleration. Default: v1.5 (8192 token context) -- **Command Palette** — `Cmd+K` navigation, keyboard shortcuts, responsive mobile layout, PWA installable -- **FSRS Decay Visualization** — SVG retention curves with predicted decay at 1d/7d/30d, endangered memory alerts -- **29 cognitive modules** — 1,238 tests, 79,600+ LOC +The first AI memory system that can actively forget. New **`suppress`** tool applies top-down inhibitory control over retrieval — each call compounds a penalty (up to 80%), a background Rac1 worker fades co-activated neighbors over 72h, and it's reversible within a 24h labile window. **Never deletes** — the memory is inhibited, not erased. + +Based on [Anderson et al. 2025](https://www.nature.com/articles/s41583-025-00929-y) (Suppression-Induced Forgetting) and [Cervantes-Sandoval et al. 2020](https://pmc.ncbi.nlm.nih.gov/articles/PMC7477079/) (Rac1 synaptic cascade). **24 tools · 30 cognitive modules · 1,284 tests.** + +
+Earlier releases (v2.0 "Cognitive Leap" → v2.0.4 "Deep Reference") + +- **v2.0.4 — `deep_reference` Tool** — 8-stage cognitive reasoning pipeline with FSRS-6 trust scoring, intent classification, spreading activation, contradiction analysis, and pre-built reasoning chains. Token budgets raised 10K → 100K. CORS tightened. +- **v2.0 — 3D Memory Dashboard** — SvelteKit + Three.js neural visualization with real-time WebSocket events, bloom post-processing, force-directed graph layout. +- **v2.0 — WebSocket Event Bus** — Every cognitive operation broadcasts events: memory creation, search, dreaming, consolidation, retention decay. +- **v2.0 — HyDE Query Expansion** — Template-based Hypothetical Document Embeddings for dramatically improved search quality on conceptual queries. +- **v2.0 — Nomic v2 MoE (experimental)** — fastembed 5.11 with optional Nomic Embed Text v2 MoE (475M params, 8 experts) + Metal GPU acceleration. +- **v2.0 — Command Palette** — `Cmd+K` navigation, keyboard shortcuts, responsive mobile layout, PWA installable. +- **v2.0 — FSRS Decay Visualization** — SVG retention curves with predicted decay at 1d/7d/30d. + +
--- @@ -132,7 +141,7 @@ The dashboard runs automatically at `http://localhost:3927/dashboard` when the M │ 15 REST endpoints · WS event broadcast │ ├─────────────────────────────────────────────────────┤ │ MCP Server (stdio JSON-RPC) │ -│ 23 tools · 29 cognitive modules │ +│ 24 tools · 30 cognitive modules │ ├─────────────────────────────────────────────────────┤ │ Cognitive Engine │ │ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │ @@ -192,11 +201,13 @@ This isn't a key-value store with an embedding model bolted on. Vestige implemen **Autonomic Regulation** — Self-regulating memory health. Auto-promotes frequently accessed memories. Auto-GCs low-retention memories. Consolidation triggers on 6h staleness or 2h active use. +**Active Forgetting** *(v2.0.5)* — Top-down inhibitory control via the `suppress` tool, distinct from passive FSRS decay and from bottom-up retrieval-induced forgetting. Each call compounds (Suppression-Induced Forgetting), a background Rac1 cascade worker fades co-activated neighbors, and a 24-hour labile window allows reversal. The memory persists — it's **inhibited, not erased**. Based on [Anderson et al., 2025](https://www.nature.com/articles/s41583-025-00929-y) and [Cervantes-Sandoval et al., 2020](https://pmc.ncbi.nlm.nih.gov/articles/PMC7477079/). First AI memory system to implement this. + [Full science documentation ->](docs/SCIENCE.md) --- -## 🛠 23 MCP Tools +## 🛠 24 MCP Tools ### Context Packets | Tool | What It Does | @@ -247,6 +258,11 @@ This isn't a key-value store with an embedding model bolted on. Vestige implemen | `deep_reference` | **Cognitive reasoning across memories.** 8-stage pipeline: FSRS-6 trust scoring, intent classification, spreading activation, temporal supersession, contradiction analysis, relation assessment, dream insight integration, and algorithmic reasoning chain generation. Returns trust-scored evidence with a pre-built reasoning scaffold. | | `cross_reference` | Backward-compatible alias for `deep_reference`. | +### Active Forgetting (v2.0.5) +| Tool | What It Does | +|------|-------------| +| `suppress` | **Top-down active forgetting** — neuroscience-grounded inhibitory control over retrieval. Distinct from `memory.delete` (destroys the row) and `memory.demote` (one-shot ranking hit). Each call **compounds** a retrieval-score penalty (Anderson 2025 SIF), and a background Rac1 cascade worker fades co-activated neighbors over 72h (Davis 2020). Reversible within a 24-hour labile window via `reverse: true`. **The memory persists** — it is inhibited, not erased. | + --- ## Make Your AI Use Vestige Automatically @@ -278,7 +294,7 @@ At the start of every session: | Metric | Value | |--------|-------| | **Language** | Rust 2024 edition (MSRV 1.91) | -| **Codebase** | 79,600+ lines, 1,238 tests | +| **Codebase** | 80,000+ lines, 1,284 tests (364 core + 419 mcp + 497 e2e + 4 doctests) | | **Binary size** | ~20MB | | **Embeddings** | Nomic Embed Text v1.5 (768d → 256d Matryoshka, 8192 context) | | **Vector search** | USearch HNSW (20x faster than FAISS) | @@ -286,7 +302,7 @@ At the start of every session: | **Storage** | SQLite + FTS5 (optional SQLCipher encryption) | | **Dashboard** | SvelteKit 2 + Svelte 5 + Three.js + Tailwind CSS 4 | | **Transport** | MCP stdio (JSON-RPC 2.0) + WebSocket | -| **Cognitive modules** | 29 stateful (16 neuroscience, 11 advanced, 2 search) | +| **Cognitive modules** | 30 stateful (17 neuroscience, 11 advanced, 2 search) | | **First run** | Downloads embedding model (~130MB), then fully offline | | **Platforms** | macOS (ARM/Intel), Linux (x86_64), Windows | @@ -386,5 +402,5 @@ AGPL-3.0 — free to use, modify, and self-host. If you offer Vestige as a netwo

Built by @samvallad33
- 79,600+ lines of Rust · 29 cognitive modules · 130 years of memory research · one 22MB binary + 80,000+ lines of Rust · 30 cognitive modules · 130 years of memory research · one 22MB binary

diff --git a/apps/dashboard/build/_app/env.js.gz b/apps/dashboard/build/_app/env.js.gz index e9f837d..e95cbd5 100644 Binary files a/apps/dashboard/build/_app/env.js.gz and b/apps/dashboard/build/_app/env.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css b/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css deleted file mode 100644 index cb69f97..0000000 --- a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css +++ /dev/null @@ -1 +0,0 @@ -/*! tailwindcss v4.2.0 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:"JetBrains Mono", "Fira Code", "SF Mono", monospace;--color-amber-400:oklch(82.8% .189 84.429);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-void:#050510;--color-deep:#10102a;--color-subtle:#2a2a5e;--color-muted:#4a4a7a;--color-dim:#7a7aaa;--color-text:#e0e0ff;--color-bright:#fff;--color-synapse:#6366f1;--color-synapse-glow:#818cf8;--color-dream:#a855f7;--color-dream-glow:#c084fc;--color-memory:#3b82f6;--color-recall:#10b981;--color-decay:#ef4444;--color-warning:#f59e0b}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.end\!{inset-inline-end:var(--spacing)!important}.top-0{top:calc(var(--spacing) * 0)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.right-0{right:calc(var(--spacing) * 0)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-4{bottom:calc(var(--spacing) * 4)}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing) * 4)}.left-6{left:calc(var(--spacing) * 6)}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-\[-12px\]{margin-top:-12px}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-12{height:calc(var(--spacing) * 12)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-32{height:calc(var(--spacing) * 32)}.h-40{height:calc(var(--spacing) * 40)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-96{width:calc(var(--spacing) * 96)}.w-\[90\%\]{width:90%}.w-full{width:100%}.w-px{width:1px}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-64{min-width:calc(var(--spacing) * 64)}.min-w-\[2rem\]{min-width:2rem}.min-w-\[3\.5rem\]{min-width:3.5rem}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.scale-125{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\!border-decay\/20{border-color:#ef444433!important}@supports (color:color-mix(in lab,red,red)){.\!border-decay\/20{border-color:color-mix(in oklab,var(--color-decay) 20%,transparent)!important}}.\!border-dream\/20{border-color:#a855f733!important}@supports (color:color-mix(in lab,red,red)){.\!border-dream\/20{border-color:color-mix(in oklab,var(--color-dream) 20%,transparent)!important}}.\!border-synapse\/20{border-color:#6366f133!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/20{border-color:color-mix(in oklab,var(--color-synapse) 20%,transparent)!important}}.\!border-synapse\/30{border-color:#6366f14d!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/30{border-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)!important}}.\!border-synapse\/40{border-color:#6366f166!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/40{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)!important}}.border-dream\/10{border-color:#a855f71a}@supports (color:color-mix(in lab,red,red)){.border-dream\/10{border-color:color-mix(in oklab,var(--color-dream) 10%,transparent)}}.border-dream\/20{border-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.border-dream\/20{border-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.border-dream\/30{border-color:#a855f74d}@supports (color:color-mix(in lab,red,red)){.border-dream\/30{border-color:color-mix(in oklab,var(--color-dream) 30%,transparent)}}.border-dream\/40{border-color:#a855f766}@supports (color:color-mix(in lab,red,red)){.border-dream\/40{border-color:color-mix(in oklab,var(--color-dream) 40%,transparent)}}.border-dream\/50{border-color:#a855f780}@supports (color:color-mix(in lab,red,red)){.border-dream\/50{border-color:color-mix(in oklab,var(--color-dream) 50%,transparent)}}.border-recall\/30{border-color:#10b9814d}@supports (color:color-mix(in lab,red,red)){.border-recall\/30{border-color:color-mix(in oklab,var(--color-recall) 30%,transparent)}}.border-subtle\/15{border-color:#2a2a5e26}@supports (color:color-mix(in lab,red,red)){.border-subtle\/15{border-color:color-mix(in oklab,var(--color-subtle) 15%,transparent)}}.border-subtle\/20{border-color:#2a2a5e33}@supports (color:color-mix(in lab,red,red)){.border-subtle\/20{border-color:color-mix(in oklab,var(--color-subtle) 20%,transparent)}}.border-synapse{border-color:var(--color-synapse)}.border-synapse\/10{border-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.border-synapse\/10{border-color:color-mix(in oklab,var(--color-synapse) 10%,transparent)}}.border-synapse\/30{border-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.border-synapse\/30{border-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)}}.border-synapse\/40{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.border-synapse\/40{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)}}.border-transparent{border-color:#0000}.border-warning\/40{border-color:#f59e0b66}@supports (color:color-mix(in lab,red,red)){.border-warning\/40{border-color:color-mix(in oklab,var(--color-warning) 40%,transparent)}}.border-warning\/50{border-color:#f59e0b80}@supports (color:color-mix(in lab,red,red)){.border-warning\/50{border-color:color-mix(in oklab,var(--color-warning) 50%,transparent)}}.border-t-dream{border-top-color:var(--color-dream)}.border-t-synapse{border-top-color:var(--color-synapse)}.border-t-warning{border-top-color:var(--color-warning)}.bg-amber-400{background-color:var(--color-amber-400)}.bg-decay{background-color:var(--color-decay)}.bg-decay\/10{background-color:#ef44441a}@supports (color:color-mix(in lab,red,red)){.bg-decay\/10{background-color:color-mix(in oklab,var(--color-decay) 10%,transparent)}}.bg-decay\/20{background-color:#ef444433}@supports (color:color-mix(in lab,red,red)){.bg-decay\/20{background-color:color-mix(in oklab,var(--color-decay) 20%,transparent)}}.bg-deep{background-color:var(--color-deep)}.bg-dream{background-color:var(--color-dream)}.bg-dream\/5{background-color:#a855f70d}@supports (color:color-mix(in lab,red,red)){.bg-dream\/5{background-color:color-mix(in oklab,var(--color-dream) 5%,transparent)}}.bg-dream\/10{background-color:#a855f71a}@supports (color:color-mix(in lab,red,red)){.bg-dream\/10{background-color:color-mix(in oklab,var(--color-dream) 10%,transparent)}}.bg-dream\/20{background-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.bg-dream\/20{background-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.bg-recall{background-color:var(--color-recall)}.bg-recall\/10{background-color:#10b9811a}@supports (color:color-mix(in lab,red,red)){.bg-recall\/10{background-color:color-mix(in oklab,var(--color-recall) 10%,transparent)}}.bg-recall\/20{background-color:#10b98133}@supports (color:color-mix(in lab,red,red)){.bg-recall\/20{background-color:color-mix(in oklab,var(--color-recall) 20%,transparent)}}.bg-synapse{background-color:var(--color-synapse)}.bg-synapse\/10{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/10{background-color:color-mix(in oklab,var(--color-synapse) 10%,transparent)}}.bg-synapse\/15{background-color:#6366f126}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/15{background-color:color-mix(in oklab,var(--color-synapse) 15%,transparent)}}.bg-synapse\/20{background-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/20{background-color:color-mix(in oklab,var(--color-synapse) 20%,transparent)}}.bg-transparent{background-color:#0000}.bg-void{background-color:var(--color-void)}.bg-void\/60{background-color:#05051099}@supports (color:color-mix(in lab,red,red)){.bg-void\/60{background-color:color-mix(in oklab,var(--color-void) 60%,transparent)}}.bg-warning\/20{background-color:#f59e0b33}@supports (color:color-mix(in lab,red,red)){.bg-warning\/20{background-color:color-mix(in oklab,var(--color-warning) 20%,transparent)}}.bg-white\/\[0\.02\]{background-color:#ffffff05}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.02\]{background-color:color-mix(in oklab,var(--color-white) 2%,transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab,var(--color-white) 3%,transparent)}}.bg-white\/\[0\.04\]{background-color:#ffffff0a}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.04\]{background-color:color-mix(in oklab,var(--color-white) 4%,transparent)}}.bg-white\/\[0\.06\]{background-color:#ffffff0f}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.06\]{background-color:color-mix(in oklab,var(--color-white) 6%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-dream{--tw-gradient-from:var(--color-dream);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-synapse{--tw-gradient-to:var(--color-synapse);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-20{padding-block:calc(var(--spacing) * 20)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-\[10vh\]{padding-top:10vh}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-14{padding-left:calc(var(--spacing) * 14)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-bright{color:var(--color-bright)}.text-decay{color:var(--color-decay)}.text-decay\/60{color:#ef444499}@supports (color:color-mix(in lab,red,red)){.text-decay\/60{color:color-mix(in oklab,var(--color-decay) 60%,transparent)}}.text-dim{color:var(--color-dim)}.text-dream{color:var(--color-dream)}.text-dream-glow{color:var(--color-dream-glow)}.text-memory{color:var(--color-memory)}.text-muted{color:var(--color-muted)}.text-muted\/50{color:#4a4a7a80}@supports (color:color-mix(in lab,red,red)){.text-muted\/50{color:color-mix(in oklab,var(--color-muted) 50%,transparent)}}.text-recall{color:var(--color-recall)}.text-subtle{color:var(--color-subtle)}.text-synapse{color:var(--color-synapse)}.text-synapse-glow{color:var(--color-synapse-glow)}.text-text{color:var(--color-text)}.text-warning{color:var(--color-warning)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.accent-synapse{accent-color:var(--color-synapse)}.opacity-20{opacity:.2}.opacity-30{opacity:.3}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow\!{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a)!important;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)!important}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(99\,102\,241\,0\.15\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#6366f126);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-synapse\/10{--tw-shadow-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.shadow-synapse\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-synapse) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-synapse\/20{--tw-shadow-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.shadow-synapse\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-synapse) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-muted::placeholder{color:var(--color-muted)}@media(hover:hover){.hover\:bg-decay\/20:hover{background-color:#ef444433}@supports (color:color-mix(in lab,red,red)){.hover\:bg-decay\/20:hover{background-color:color-mix(in oklab,var(--color-decay) 20%,transparent)}}.hover\:bg-decay\/30:hover{background-color:#ef44444d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-decay\/30:hover{background-color:color-mix(in oklab,var(--color-decay) 30%,transparent)}}.hover\:bg-dream\/20:hover{background-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.hover\:bg-dream\/20:hover{background-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.hover\:bg-dream\/30:hover{background-color:#a855f74d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-dream\/30:hover{background-color:color-mix(in oklab,var(--color-dream) 30%,transparent)}}.hover\:bg-recall\/30:hover{background-color:#10b9814d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-recall\/30:hover{background-color:color-mix(in oklab,var(--color-recall) 30%,transparent)}}.hover\:bg-synapse\/30:hover{background-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-synapse\/30:hover{background-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)}}.hover\:bg-warning\/30:hover{background-color:#f59e0b4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-warning\/30:hover{background-color:color-mix(in oklab,var(--color-warning) 30%,transparent)}}.hover\:bg-white\/\[0\.03\]:hover{background-color:#ffffff08}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/\[0\.03\]:hover{background-color:color-mix(in oklab,var(--color-white) 3%,transparent)}}.hover\:bg-white\/\[0\.04\]:hover{background-color:#ffffff0a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/\[0\.04\]:hover{background-color:color-mix(in oklab,var(--color-white) 4%,transparent)}}.hover\:text-dim:hover{color:var(--color-dim)}.hover\:text-text:hover{color:var(--color-text)}}.focus\:\!border-synapse\/40:focus{border-color:#6366f166!important}@supports (color:color-mix(in lab,red,red)){.focus\:\!border-synapse\/40:focus{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)!important}}.focus\:border-dream\/40:focus{border-color:#a855f766}@supports (color:color-mix(in lab,red,red)){.focus\:border-dream\/40:focus{border-color:color-mix(in oklab,var(--color-dream) 40%,transparent)}}.focus\:border-synapse\/40:focus{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.focus\:border-synapse\/40:focus{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)}}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-synapse\/20:focus{--tw-ring-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.focus\:ring-synapse\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-synapse) 20%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:pt-\[15vh\]{padding-top:15vh}.md\:pb-0{padding-bottom:calc(var(--spacing) * 0)}}@media(min-width:64rem){.lg\:block{display:block}.lg\:w-56{width:calc(var(--spacing) * 56)}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.\[\&\:\:-webkit-slider-thumb\]\:h-3::-webkit-slider-thumb{height:calc(var(--spacing) * 3)}.\[\&\:\:-webkit-slider-thumb\]\:w-3::-webkit-slider-thumb{width:calc(var(--spacing) * 3)}.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb{border-radius:3.40282e38px}.\[\&\:\:-webkit-slider-thumb\]\:bg-synapse-glow::-webkit-slider-thumb{background-color:var(--color-synapse-glow)}.\[\&\:\:-webkit-slider-thumb\]\:shadow-\[0_0_8px_rgba\(129\,140\,248\,0\.4\)\]::-webkit-slider-thumb{--tw-shadow:0 0 8px var(--tw-shadow-color,#818cf866);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}html{background:var(--color-void);color:var(--color-text);font-family:var(--font-mono)}body{min-height:100vh;margin:0;overflow:hidden}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-subtle);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-muted)}.glass{-webkit-backdrop-filter:blur(20px)saturate(180%);background:#16163873;border:1px solid #6366f114;box-shadow:inset 0 1px #ffffff08,0 4px 24px #0000004d}.glass-subtle{-webkit-backdrop-filter:blur(12px)saturate(150%);background:#10102a66;border:1px solid #6366f10f;box-shadow:inset 0 1px #ffffff05,0 2px 12px #0003}.glass-sidebar{-webkit-backdrop-filter:blur(24px)saturate(180%);background:#0a0a1a99;border-right:1px solid #6366f11a;box-shadow:inset -1px 0 #ffffff05,4px 0 24px #0000004d}.glass-panel{-webkit-backdrop-filter:blur(24px)saturate(180%);background:#0a0a1acc;border:1px solid #6366f11a;box-shadow:inset 0 1px #ffffff08,0 8px 32px #0006}.glow-synapse{box-shadow:0 0 20px #6366f14d,0 0 60px #6366f11a}.glow-dream{box-shadow:0 0 20px #a855f74d,0 0 60px #a855f71a}.glow-memory{box-shadow:0 0 20px #3b82f64d,0 0 60px #3b82f61a}@keyframes pulse-glow{0%,to{opacity:1}50%{opacity:.5}}.animate-pulse-glow{animation:2s ease-in-out infinite pulse-glow}@keyframes orb-float-1{0%,to{transform:translate(0)scale(1)}25%{transform:translate(60px,-40px)scale(1.1)}50%{transform:translate(-30px,-80px)scale(.95)}75%{transform:translate(-60px,-20px)scale(1.05)}}@keyframes orb-float-2{0%,to{transform:translate(0)scale(1)}25%{transform:translate(-50px,30px)scale(1.08)}50%{transform:translate(40px,60px)scale(.92)}75%{transform:translate(20px,-40px)scale(1.03)}}@keyframes orb-float-3{0%,to{transform:translate(0)scale(1)}25%{transform:translate(30px,50px)scale(1.05)}50%{transform:translate(-60px,20px)scale(.98)}75%{transform:translate(40px,-30px)scale(1.1)}}.ambient-orb{filter:blur(80px);pointer-events:none;z-index:0;opacity:.35;border-radius:50%;position:fixed}.ambient-orb-1{background:radial-gradient(circle,#a855f766,#0000 70%);width:400px;height:400px;animation:20s ease-in-out infinite orb-float-1;top:-10%;right:-5%}.ambient-orb-2{background:radial-gradient(circle,#6366f159,#0000 70%);width:350px;height:350px;animation:25s ease-in-out infinite orb-float-2;bottom:-15%;left:-5%}.ambient-orb-3{background:radial-gradient(circle,#f59e0b33,#0000 70%);width:300px;height:300px;animation:22s ease-in-out infinite orb-float-3;top:40%;left:40%}.nav-active-border{position:relative}.nav-active-border:before{content:"";background:linear-gradient(180deg,var(--color-synapse),var(--color-dream),var(--color-synapse));background-size:100% 200%;border-radius:1px;width:2px;animation:3s ease-in-out infinite gradient-shift;position:absolute;top:4px;bottom:4px;left:0}@keyframes gradient-shift{0%,to{background-position:0 0}50%{background-position:0 100%}}@keyframes float{0%,to{transform:translateY(0)translate(0)}25%{transform:translateY(-10px)translate(5px)}50%{transform:translateY(-5px)translate(-5px)}75%{transform:translateY(-15px)translate(3px)}}.retention-critical{color:var(--color-decay)}.retention-low{color:var(--color-warning)}.retention-good{color:var(--color-recall)}.retention-strong{color:var(--color-synapse)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}.safe-bottom.svelte-12qhfyh{padding-bottom:env(safe-area-inset-bottom,0px)}@keyframes svelte-12qhfyh-page-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.animate-page-in.svelte-12qhfyh{animation:svelte-12qhfyh-page-in .2s ease-out} diff --git a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.br b/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.br deleted file mode 100644 index 6f955a0..0000000 Binary files a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.gz b/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.gz deleted file mode 100644 index abec51e..0000000 Binary files a/apps/dashboard/build/_app/immutable/assets/0.BChctYiF.css.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css new file mode 100644 index 0000000..778c3e9 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css @@ -0,0 +1 @@ +/*! tailwindcss v4.2.0 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:"JetBrains Mono", "Fira Code", "SF Mono", monospace;--color-amber-400:oklch(82.8% .189 84.429);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-void:#050510;--color-deep:#10102a;--color-subtle:#2a2a5e;--color-muted:#4a4a7a;--color-dim:#7a7aaa;--color-text:#e0e0ff;--color-bright:#fff;--color-synapse:#6366f1;--color-synapse-glow:#818cf8;--color-dream:#a855f7;--color-dream-glow:#c084fc;--color-memory:#3b82f6;--color-recall:#10b981;--color-decay:#ef4444;--color-warning:#f59e0b}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.end\!{inset-inline-end:var(--spacing)!important}.top-0{top:calc(var(--spacing) * 0)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.right-0{right:calc(var(--spacing) * 0)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-4{bottom:calc(var(--spacing) * 4)}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing) * 4)}.left-6{left:calc(var(--spacing) * 6)}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-\[-12px\]{margin-top:-12px}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-12{height:calc(var(--spacing) * 12)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-32{height:calc(var(--spacing) * 32)}.h-40{height:calc(var(--spacing) * 40)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-96{width:calc(var(--spacing) * 96)}.w-\[90\%\]{width:90%}.w-full{width:100%}.w-px{width:1px}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-64{min-width:calc(var(--spacing) * 64)}.min-w-\[2rem\]{min-width:2rem}.min-w-\[3\.5rem\]{min-width:3.5rem}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.scale-125{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\!border-decay\/20{border-color:#ef444433!important}@supports (color:color-mix(in lab,red,red)){.\!border-decay\/20{border-color:color-mix(in oklab,var(--color-decay) 20%,transparent)!important}}.\!border-dream\/20{border-color:#a855f733!important}@supports (color:color-mix(in lab,red,red)){.\!border-dream\/20{border-color:color-mix(in oklab,var(--color-dream) 20%,transparent)!important}}.\!border-synapse\/20{border-color:#6366f133!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/20{border-color:color-mix(in oklab,var(--color-synapse) 20%,transparent)!important}}.\!border-synapse\/30{border-color:#6366f14d!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/30{border-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)!important}}.\!border-synapse\/40{border-color:#6366f166!important}@supports (color:color-mix(in lab,red,red)){.\!border-synapse\/40{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)!important}}.border-\[\#A33FFF\]\/40{border-color:#a33fff66}.border-dream\/10{border-color:#a855f71a}@supports (color:color-mix(in lab,red,red)){.border-dream\/10{border-color:color-mix(in oklab,var(--color-dream) 10%,transparent)}}.border-dream\/20{border-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.border-dream\/20{border-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.border-dream\/30{border-color:#a855f74d}@supports (color:color-mix(in lab,red,red)){.border-dream\/30{border-color:color-mix(in oklab,var(--color-dream) 30%,transparent)}}.border-dream\/40{border-color:#a855f766}@supports (color:color-mix(in lab,red,red)){.border-dream\/40{border-color:color-mix(in oklab,var(--color-dream) 40%,transparent)}}.border-dream\/50{border-color:#a855f780}@supports (color:color-mix(in lab,red,red)){.border-dream\/50{border-color:color-mix(in oklab,var(--color-dream) 50%,transparent)}}.border-recall\/30{border-color:#10b9814d}@supports (color:color-mix(in lab,red,red)){.border-recall\/30{border-color:color-mix(in oklab,var(--color-recall) 30%,transparent)}}.border-subtle\/15{border-color:#2a2a5e26}@supports (color:color-mix(in lab,red,red)){.border-subtle\/15{border-color:color-mix(in oklab,var(--color-subtle) 15%,transparent)}}.border-subtle\/20{border-color:#2a2a5e33}@supports (color:color-mix(in lab,red,red)){.border-subtle\/20{border-color:color-mix(in oklab,var(--color-subtle) 20%,transparent)}}.border-synapse{border-color:var(--color-synapse)}.border-synapse\/10{border-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.border-synapse\/10{border-color:color-mix(in oklab,var(--color-synapse) 10%,transparent)}}.border-synapse\/30{border-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.border-synapse\/30{border-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)}}.border-synapse\/40{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.border-synapse\/40{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)}}.border-transparent{border-color:#0000}.border-warning\/40{border-color:#f59e0b66}@supports (color:color-mix(in lab,red,red)){.border-warning\/40{border-color:color-mix(in oklab,var(--color-warning) 40%,transparent)}}.border-warning\/50{border-color:#f59e0b80}@supports (color:color-mix(in lab,red,red)){.border-warning\/50{border-color:color-mix(in oklab,var(--color-warning) 50%,transparent)}}.border-t-dream{border-top-color:var(--color-dream)}.border-t-synapse{border-top-color:var(--color-synapse)}.border-t-warning{border-top-color:var(--color-warning)}.bg-\[\#A33FFF\]{background-color:#a33fff}.bg-\[\#A33FFF\]\/10{background-color:#a33fff1a}.bg-amber-400{background-color:var(--color-amber-400)}.bg-decay{background-color:var(--color-decay)}.bg-decay\/10{background-color:#ef44441a}@supports (color:color-mix(in lab,red,red)){.bg-decay\/10{background-color:color-mix(in oklab,var(--color-decay) 10%,transparent)}}.bg-decay\/20{background-color:#ef444433}@supports (color:color-mix(in lab,red,red)){.bg-decay\/20{background-color:color-mix(in oklab,var(--color-decay) 20%,transparent)}}.bg-deep{background-color:var(--color-deep)}.bg-dream{background-color:var(--color-dream)}.bg-dream\/5{background-color:#a855f70d}@supports (color:color-mix(in lab,red,red)){.bg-dream\/5{background-color:color-mix(in oklab,var(--color-dream) 5%,transparent)}}.bg-dream\/10{background-color:#a855f71a}@supports (color:color-mix(in lab,red,red)){.bg-dream\/10{background-color:color-mix(in oklab,var(--color-dream) 10%,transparent)}}.bg-dream\/20{background-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.bg-dream\/20{background-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.bg-recall{background-color:var(--color-recall)}.bg-recall\/10{background-color:#10b9811a}@supports (color:color-mix(in lab,red,red)){.bg-recall\/10{background-color:color-mix(in oklab,var(--color-recall) 10%,transparent)}}.bg-recall\/20{background-color:#10b98133}@supports (color:color-mix(in lab,red,red)){.bg-recall\/20{background-color:color-mix(in oklab,var(--color-recall) 20%,transparent)}}.bg-synapse{background-color:var(--color-synapse)}.bg-synapse\/10{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/10{background-color:color-mix(in oklab,var(--color-synapse) 10%,transparent)}}.bg-synapse\/15{background-color:#6366f126}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/15{background-color:color-mix(in oklab,var(--color-synapse) 15%,transparent)}}.bg-synapse\/20{background-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.bg-synapse\/20{background-color:color-mix(in oklab,var(--color-synapse) 20%,transparent)}}.bg-transparent{background-color:#0000}.bg-void{background-color:var(--color-void)}.bg-void\/60{background-color:#05051099}@supports (color:color-mix(in lab,red,red)){.bg-void\/60{background-color:color-mix(in oklab,var(--color-void) 60%,transparent)}}.bg-warning\/20{background-color:#f59e0b33}@supports (color:color-mix(in lab,red,red)){.bg-warning\/20{background-color:color-mix(in oklab,var(--color-warning) 20%,transparent)}}.bg-white\/\[0\.02\]{background-color:#ffffff05}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.02\]{background-color:color-mix(in oklab,var(--color-white) 2%,transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab,var(--color-white) 3%,transparent)}}.bg-white\/\[0\.04\]{background-color:#ffffff0a}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.04\]{background-color:color-mix(in oklab,var(--color-white) 4%,transparent)}}.bg-white\/\[0\.06\]{background-color:#ffffff0f}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.06\]{background-color:color-mix(in oklab,var(--color-white) 6%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-dream{--tw-gradient-from:var(--color-dream);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-synapse{--tw-gradient-to:var(--color-synapse);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-20{padding-block:calc(var(--spacing) * 20)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-\[10vh\]{padding-top:10vh}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-14{padding-left:calc(var(--spacing) * 14)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#E4C8FF\]{color:#e4c8ff}.text-amber-400{color:var(--color-amber-400)}.text-bright{color:var(--color-bright)}.text-decay{color:var(--color-decay)}.text-decay\/60{color:#ef444499}@supports (color:color-mix(in lab,red,red)){.text-decay\/60{color:color-mix(in oklab,var(--color-decay) 60%,transparent)}}.text-dim{color:var(--color-dim)}.text-dream{color:var(--color-dream)}.text-dream-glow{color:var(--color-dream-glow)}.text-memory{color:var(--color-memory)}.text-muted{color:var(--color-muted)}.text-muted\/50{color:#4a4a7a80}@supports (color:color-mix(in lab,red,red)){.text-muted\/50{color:color-mix(in oklab,var(--color-muted) 50%,transparent)}}.text-recall{color:var(--color-recall)}.text-subtle{color:var(--color-subtle)}.text-synapse{color:var(--color-synapse)}.text-synapse-glow{color:var(--color-synapse-glow)}.text-text{color:var(--color-text)}.text-warning{color:var(--color-warning)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.accent-synapse{accent-color:var(--color-synapse)}.opacity-20{opacity:.2}.opacity-30{opacity:.3}.opacity-75{opacity:.75}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow\!{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a)!important;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)!important}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(99\,102\,241\,0\.15\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#6366f126);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(163\,63\,255\,0\.15\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#a33fff26);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-synapse\/10{--tw-shadow-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.shadow-synapse\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-synapse) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-synapse\/20{--tw-shadow-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.shadow-synapse\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-synapse) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-muted::placeholder{color:var(--color-muted)}@media(hover:hover){.hover\:bg-decay\/20:hover{background-color:#ef444433}@supports (color:color-mix(in lab,red,red)){.hover\:bg-decay\/20:hover{background-color:color-mix(in oklab,var(--color-decay) 20%,transparent)}}.hover\:bg-decay\/30:hover{background-color:#ef44444d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-decay\/30:hover{background-color:color-mix(in oklab,var(--color-decay) 30%,transparent)}}.hover\:bg-dream\/20:hover{background-color:#a855f733}@supports (color:color-mix(in lab,red,red)){.hover\:bg-dream\/20:hover{background-color:color-mix(in oklab,var(--color-dream) 20%,transparent)}}.hover\:bg-dream\/30:hover{background-color:#a855f74d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-dream\/30:hover{background-color:color-mix(in oklab,var(--color-dream) 30%,transparent)}}.hover\:bg-recall\/30:hover{background-color:#10b9814d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-recall\/30:hover{background-color:color-mix(in oklab,var(--color-recall) 30%,transparent)}}.hover\:bg-synapse\/30:hover{background-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-synapse\/30:hover{background-color:color-mix(in oklab,var(--color-synapse) 30%,transparent)}}.hover\:bg-warning\/30:hover{background-color:#f59e0b4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-warning\/30:hover{background-color:color-mix(in oklab,var(--color-warning) 30%,transparent)}}.hover\:bg-white\/\[0\.03\]:hover{background-color:#ffffff08}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/\[0\.03\]:hover{background-color:color-mix(in oklab,var(--color-white) 3%,transparent)}}.hover\:bg-white\/\[0\.04\]:hover{background-color:#ffffff0a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/\[0\.04\]:hover{background-color:color-mix(in oklab,var(--color-white) 4%,transparent)}}.hover\:text-dim:hover{color:var(--color-dim)}.hover\:text-text:hover{color:var(--color-text)}}.focus\:\!border-synapse\/40:focus{border-color:#6366f166!important}@supports (color:color-mix(in lab,red,red)){.focus\:\!border-synapse\/40:focus{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)!important}}.focus\:border-dream\/40:focus{border-color:#a855f766}@supports (color:color-mix(in lab,red,red)){.focus\:border-dream\/40:focus{border-color:color-mix(in oklab,var(--color-dream) 40%,transparent)}}.focus\:border-synapse\/40:focus{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.focus\:border-synapse\/40:focus{border-color:color-mix(in oklab,var(--color-synapse) 40%,transparent)}}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-synapse\/20:focus{--tw-ring-color:#6366f133}@supports (color:color-mix(in lab,red,red)){.focus\:ring-synapse\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-synapse) 20%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:pt-\[15vh\]{padding-top:15vh}.md\:pb-0{padding-bottom:calc(var(--spacing) * 0)}}@media(min-width:64rem){.lg\:block{display:block}.lg\:w-56{width:calc(var(--spacing) * 56)}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.\[\&\:\:-webkit-slider-thumb\]\:h-3::-webkit-slider-thumb{height:calc(var(--spacing) * 3)}.\[\&\:\:-webkit-slider-thumb\]\:w-3::-webkit-slider-thumb{width:calc(var(--spacing) * 3)}.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb{border-radius:3.40282e38px}.\[\&\:\:-webkit-slider-thumb\]\:bg-synapse-glow::-webkit-slider-thumb{background-color:var(--color-synapse-glow)}.\[\&\:\:-webkit-slider-thumb\]\:shadow-\[0_0_8px_rgba\(129\,140\,248\,0\.4\)\]::-webkit-slider-thumb{--tw-shadow:0 0 8px var(--tw-shadow-color,#818cf866);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}html{background:var(--color-void);color:var(--color-text);font-family:var(--font-mono)}body{min-height:100vh;margin:0;overflow:hidden}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-subtle);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-muted)}.glass{-webkit-backdrop-filter:blur(20px)saturate(180%);background:#16163873;border:1px solid #6366f114;box-shadow:inset 0 1px #ffffff08,0 4px 24px #0000004d}.glass-subtle{-webkit-backdrop-filter:blur(12px)saturate(150%);background:#10102a66;border:1px solid #6366f10f;box-shadow:inset 0 1px #ffffff05,0 2px 12px #0003}.glass-sidebar{-webkit-backdrop-filter:blur(24px)saturate(180%);background:#0a0a1a99;border-right:1px solid #6366f11a;box-shadow:inset -1px 0 #ffffff05,4px 0 24px #0000004d}.glass-panel{-webkit-backdrop-filter:blur(24px)saturate(180%);background:#0a0a1acc;border:1px solid #6366f11a;box-shadow:inset 0 1px #ffffff08,0 8px 32px #0006}.glow-synapse{box-shadow:0 0 20px #6366f14d,0 0 60px #6366f11a}.glow-dream{box-shadow:0 0 20px #a855f74d,0 0 60px #a855f71a}.glow-memory{box-shadow:0 0 20px #3b82f64d,0 0 60px #3b82f61a}@keyframes pulse-glow{0%,to{opacity:1}50%{opacity:.5}}.animate-pulse-glow{animation:2s ease-in-out infinite pulse-glow}@keyframes orb-float-1{0%,to{transform:translate(0)scale(1)}25%{transform:translate(60px,-40px)scale(1.1)}50%{transform:translate(-30px,-80px)scale(.95)}75%{transform:translate(-60px,-20px)scale(1.05)}}@keyframes orb-float-2{0%,to{transform:translate(0)scale(1)}25%{transform:translate(-50px,30px)scale(1.08)}50%{transform:translate(40px,60px)scale(.92)}75%{transform:translate(20px,-40px)scale(1.03)}}@keyframes orb-float-3{0%,to{transform:translate(0)scale(1)}25%{transform:translate(30px,50px)scale(1.05)}50%{transform:translate(-60px,20px)scale(.98)}75%{transform:translate(40px,-30px)scale(1.1)}}.ambient-orb{filter:blur(80px);pointer-events:none;z-index:0;opacity:.35;border-radius:50%;position:fixed}.ambient-orb-1{background:radial-gradient(circle,#a855f766,#0000 70%);width:400px;height:400px;animation:20s ease-in-out infinite orb-float-1;top:-10%;right:-5%}.ambient-orb-2{background:radial-gradient(circle,#6366f159,#0000 70%);width:350px;height:350px;animation:25s ease-in-out infinite orb-float-2;bottom:-15%;left:-5%}.ambient-orb-3{background:radial-gradient(circle,#f59e0b33,#0000 70%);width:300px;height:300px;animation:22s ease-in-out infinite orb-float-3;top:40%;left:40%}.nav-active-border{position:relative}.nav-active-border:before{content:"";background:linear-gradient(180deg,var(--color-synapse),var(--color-dream),var(--color-synapse));background-size:100% 200%;border-radius:1px;width:2px;animation:3s ease-in-out infinite gradient-shift;position:absolute;top:4px;bottom:4px;left:0}@keyframes gradient-shift{0%,to{background-position:0 0}50%{background-position:0 100%}}@keyframes float{0%,to{transform:translateY(0)translate(0)}25%{transform:translateY(-10px)translate(5px)}50%{transform:translateY(-5px)translate(-5px)}75%{transform:translateY(-15px)translate(3px)}}.retention-critical{color:var(--color-decay)}.retention-low{color:var(--color-warning)}.retention-good{color:var(--color-recall)}.retention-strong{color:var(--color-synapse)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}.safe-bottom.svelte-12qhfyh{padding-bottom:env(safe-area-inset-bottom,0px)}@keyframes svelte-12qhfyh-page-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.animate-page-in.svelte-12qhfyh{animation:svelte-12qhfyh-page-in .2s ease-out} diff --git a/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.br b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.br new file mode 100644 index 0000000..6878b3c Binary files /dev/null and b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.br differ diff --git a/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.gz b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.gz new file mode 100644 index 0000000..c1bba2f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/assets/0.D08DCOSm.css.gz differ diff --git a/apps/dashboard/build/_app/immutable/assets/5.BBx09UGv.css.gz b/apps/dashboard/build/_app/immutable/assets/5.BBx09UGv.css.gz index 1e76ad0..8719f65 100644 Binary files a/apps/dashboard/build/_app/immutable/assets/5.BBx09UGv.css.gz and b/apps/dashboard/build/_app/immutable/assets/5.BBx09UGv.css.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js new file mode 100644 index 0000000..aade4a4 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js @@ -0,0 +1 @@ +import{aE as h,ah as d,ao as l,aF as p,F as _,aG as E,aH as g,T as u,aj as s,aI as y,a7 as M,aJ as N,ac as x,aK as A}from"./nyjtQ1Ok.js";var f;const i=((f=globalThis==null?void 0:globalThis.window)==null?void 0:f.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function b(t){return(i==null?void 0:i.createHTML(t))??t}function L(t){var r=h("template");return r.innerHTML=b(t.replaceAll("","")),r.content}function a(t,r){var e=_;e.nodes===null&&(e.nodes={start:t,end:r,a:null,t:null})}function F(t,r){var e=(r&E)!==0,c=(r&g)!==0,n,m=!t.startsWith("");return()=>{if(u)return a(s,null),s;n===void 0&&(n=L(m?t:""+t),e||(n=l(n)));var o=c||p?document.importNode(n,!0):n.cloneNode(!0);if(e){var T=l(o),v=o.lastChild;a(T,v)}else a(o,o);return o}}function H(t=""){if(!u){var r=d(t+"");return a(r,r),r}var e=s;return e.nodeType!==N?(e.before(e=d()),x(e)):A(e),a(e,e),e}function O(){if(u)return a(s,null),s;var t=document.createDocumentFragment(),r=document.createComment(""),e=d();return t.append(r,e),a(r,e),t}function P(t,r){if(u){var e=_;((e.f&y)===0||e.nodes.end===null)&&(e.nodes.end=s),M();return}t!==null&&t.before(r)}export{P as a,a as b,O as c,F as f,H as t}; diff --git a/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.br b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.br new file mode 100644 index 0000000..28af03b Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.gz b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.gz new file mode 100644 index 0000000..ee63618 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B0IenmM-.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B17metm1.js b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js new file mode 100644 index 0000000..9037ca4 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js @@ -0,0 +1 @@ +import{b as T,T as o,a7 as b,E as h,a8 as p,a9 as A,aa as E,ab as R,ac as g,ad as l}from"./nyjtQ1Ok.js";import{B as v}from"./C3lo34Tx.js";function N(t,c,u=!1){o&&b();var n=new v(t),_=u?h:0;function i(a,r){if(o){const e=p(t);var s;if(e===A?s=0:e===E?s=!1:s=parseInt(e.substring(1)),a!==s){var f=R();g(f),n.anchor=f,l(!1),n.ensure(a,r),l(!0);return}}n.ensure(a,r)}T(()=>{var a=!1;c((r,s=0)=>{a=!0,i(s,r)}),a||i(!1,null)},_)}export{N as i}; diff --git a/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.br b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.br new file mode 100644 index 0000000..89b5fe3 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.gz b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.gz new file mode 100644 index 0000000..37e2885 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B17metm1.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js new file mode 100644 index 0000000..2ed1e8a --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js @@ -0,0 +1 @@ +import{d as c,w as S}from"./DAj0p1rI.js";const H=200;function y(){const{subscribe:t,set:o,update:e}=S({connected:!1,events:[],lastHeartbeat:null,error:null});let n=null,l=null,d=0;function m(i){const u=i||(window.location.port==="5173"?`ws://${window.location.hostname}:3927/ws`:`ws://${window.location.host}/ws`);if((n==null?void 0:n.readyState)!==WebSocket.OPEN)try{n=new WebSocket(u),n.onopen=()=>{d=0,e(a=>({...a,connected:!0,error:null}))},n.onmessage=a=>{try{const s=JSON.parse(a.data);e(b=>{if(s.type==="Heartbeat")return{...b,lastHeartbeat:s};const v=[s,...b.events].slice(0,H);return{...b,events:v}})}catch(s){console.warn("[vestige] Failed to parse WebSocket message:",s)}},n.onclose=()=>{e(a=>({...a,connected:!1})),f(u)},n.onerror=()=>{e(a=>({...a,error:"WebSocket connection failed"}))}}catch(a){e(s=>({...s,error:String(a)}))}}function f(i){l&&clearTimeout(l);const u=Math.min(1e3*2**d,3e4);d++,l=setTimeout(()=>m(i),u)}function p(){l&&clearTimeout(l),n==null||n.close(),n=null,o({connected:!1,events:[],lastHeartbeat:null,error:null})}function w(){e(i=>({...i,events:[]}))}return{subscribe:t,connect:m,disconnect:p,clearEvents:w}}const r=y(),h=c(r,t=>t.connected),k=c(r,t=>t.events);c(r,t=>t.lastHeartbeat);const T=c(r,t=>{var o,e;return((e=(o=t.lastHeartbeat)==null?void 0:o.data)==null?void 0:e.memory_count)??0}),W=c(r,t=>{var o,e;return((e=(o=t.lastHeartbeat)==null?void 0:o.data)==null?void 0:e.avg_retention)??0}),E=c(r,t=>{var o,e;return((e=(o=t.lastHeartbeat)==null?void 0:o.data)==null?void 0:e.suppressed_count)??0});export{W as a,k as e,h as i,T as m,E as s,r as w}; diff --git a/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.br b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.br new file mode 100644 index 0000000..7aea3a9 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.gz b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.gz new file mode 100644 index 0000000..d89b360 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/B6fk3AxI.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.br b/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.br deleted file mode 100644 index 73283e9..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.gz b/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.gz deleted file mode 100644 index d0c256e..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js b/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js new file mode 100644 index 0000000..63d1cde --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js @@ -0,0 +1 @@ +import{T as i,W as d,X as n,Y as v,A as u,Z as h,_ as A,$ as g}from"./nyjtQ1Ok.js";const T=Symbol("is custom element"),l=Symbol("is html"),p=n?"link":"LINK";function S(r){if(i){var s=!1,e=()=>{if(!s){if(s=!0,r.hasAttribute("value")){var a=r.value;t(r,"value",null),r.value=a}if(r.hasAttribute("checked")){var o=r.checked;t(r,"checked",null),r.checked=o}}};r.__on_r=e,u(e),h()}}function t(r,s,e,a){var o=L(r);i&&(o[s]=r.getAttribute(s),s==="src"||s==="srcset"||s==="href"&&r.nodeName===p)||o[s]!==(o[s]=e)&&(s==="loading"&&(r[A]=e),e==null?r.removeAttribute(s):typeof e!="string"&&M(r).includes(s)?r[s]=e:r.setAttribute(s,e))}function L(r){return r.__attributes??(r.__attributes={[T]:r.nodeName.includes("-"),[l]:r.namespaceURI===d})}var c=new Map;function M(r){var s=r.getAttribute("is")||r.nodeName,e=c.get(s);if(e)return e;c.set(s,e=[]);for(var a,o=r,f=Element.prototype;f!==o;){a=g(o);for(var _ in a)a[_].set&&e.push(_);o=v(o)}return e}export{S as r,t as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js.br b/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js.br new file mode 100644 index 0000000..8ab7178 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/BBOOwRwQ.js.br @@ -0,0 +1,3 @@ +@dUտeAz#0N +22cN(eMshXJ{КϹhy +`>5lk-?’`]7|\֖0N ܯΫ٫0ZQij;@elW&k~J'3IZ(:ku쭻AfNjVQ3FeoO!QF0dY+dFbJi7.Uo0RNXq`[TrXZ_t7rDLp>?- Ekx@gv\$PQ`ś(Q.$m9\wŐ ZPi ;$#&NS8i.ܪolE>h!TB{var a=r?e.defaultValue:e.value;if(a=t(e)?o(a):a,u(a),v!==null&&f.add(v),await b(),a!==(a=l())){var n=e.selectionStart,s=e.selectionEnd,d=e.value.length;if(e.value=a??"",s!==null){var c=e.value.length;n===s&&s===d&&c>d?(e.selectionStart=c,e.selectionEnd=c):(e.selectionStart=n,e.selectionEnd=Math.min(s,c))}}}),(y&&e.defaultValue!==e.value||i(l)==null&&e.value)&&(u(t(e)?o(e.value):e.value),v!==null&&f.add(v)),m(()=>{var r=l();if(e===document.activeElement){var a=h??v;if(f.has(a))return}t(e)&&r===o(e.value)||e.type==="date"&&!r&&!e.value||r!==e.value&&(e.value=r??"")})}function t(e){var l=e.type;return l==="number"||l==="range"}function o(e){return e===""?null:+e}export{E as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.br b/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.br new file mode 100644 index 0000000..ec619dd Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.gz b/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.gz new file mode 100644 index 0000000..09d8515 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BOVu8he9.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js new file mode 100644 index 0000000..5dc25d3 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js @@ -0,0 +1 @@ +import{B as m,C as D,P as T,g as P,c as B,h as b,D as M,F as N,G as Y,H as h,n as U,I as w,J as x,K as C,w as G,L as $,M as q,S as z,N as F}from"./nyjtQ1Ok.js";import{c as H}from"./C3ZC25l2.js";function Z(r,a,t,s){var o;var f=!w||(t&x)!==0,v=(t&h)!==0,O=(t&q)!==0,n=s,c=!0,I=()=>(c&&(c=!1,n=O?U(s):s),n),u;if(v){var R=z in r||F in r;u=((o=m(r,a))==null?void 0:o.set)??(R&&a in r?e=>r[a]=e:void 0)}var _,g=!1;v?[_,g]=H(()=>r[a]):_=r[a],_===void 0&&s!==void 0&&(_=I(),u&&(f&&D(),u(_)));var i;if(f?i=()=>{var e=r[a];return e===void 0?I():(c=!0,e)}:i=()=>{var e=r[a];return e!==void 0&&(n=void 0),e===void 0?n:e},f&&(t&T)===0)return i;if(u){var A=r.$$legacy;return(function(e,S){return arguments.length>0?((!f||!S||A||g)&&u(S?i():e),e):i()})}var l=!1,d=((t&C)!==0?G:$)(()=>(l=!1,i()));v&&P(d);var L=N;return(function(e,S){if(arguments.length>0){const E=S?P(d):f&&v?B(e):e;return b(d,E),l=!0,n!==void 0&&(n=E),e}return M&&l||(L.f&Y)!==0?d.v:P(d)})}export{Z as p}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.br b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.br new file mode 100644 index 0000000..ba8788a Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.gz b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.gz new file mode 100644 index 0000000..c088fc6 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BPtVz5jm.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js b/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js deleted file mode 100644 index 1a3227d..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js +++ /dev/null @@ -1 +0,0 @@ -import{J as i,N as d,O as n,Q as v,q as u,R as h,T as g,U as A}from"./BBD-8XME.js";const N=Symbol("is custom element"),T=Symbol("is html"),l=n?"link":"LINK";function S(r){if(i){var s=!1,e=()=>{if(!s){if(s=!0,r.hasAttribute("value")){var a=r.value;t(r,"value",null),r.value=a}if(r.hasAttribute("checked")){var o=r.checked;t(r,"checked",null),r.checked=o}}};r.__on_r=e,u(e),h()}}function t(r,s,e,a){var o=p(r);i&&(o[s]=r.getAttribute(s),s==="src"||s==="srcset"||s==="href"&&r.nodeName===l)||o[s]!==(o[s]=e)&&(s==="loading"&&(r[g]=e),e==null?r.removeAttribute(s):typeof e!="string"&&L(r).includes(s)?r[s]=e:r.setAttribute(s,e))}function p(r){return r.__attributes??(r.__attributes={[N]:r.nodeName.includes("-"),[T]:r.namespaceURI===d})}var c=new Map;function L(r){var s=r.getAttribute("is")||r.nodeName,e=c.get(s);if(e)return e;c.set(s,e=[]);for(var a,o=r,f=Element.prototype;f!==o;){a=A(o);for(var _ in a)a[_].set&&e.push(_);o=v(o)}return e}export{S as r,t as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.br b/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.br deleted file mode 100644 index fa8002a..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.gz b/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.gz deleted file mode 100644 index 83e86b1..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BVZqxpRe.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BcuCGYSa.js.gz b/apps/dashboard/build/_app/immutable/chunks/BcuCGYSa.js.gz index 4a66d09..54fb916 100644 Binary files a/apps/dashboard/build/_app/immutable/chunks/BcuCGYSa.js.gz and b/apps/dashboard/build/_app/immutable/chunks/BcuCGYSa.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js b/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js deleted file mode 100644 index e64b77e..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js +++ /dev/null @@ -1 +0,0 @@ -var x=t=>{throw TypeError(t)};var B=(t,e,n)=>e.has(t)||x("Cannot "+n);var a=(t,e,n)=>(B(t,e,"read from private field"),n?n.call(t):e.get(t)),c=(t,e,n)=>e.has(t)?x("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,n);import{o as I}from"./DUC-ssvh.js";import{s as u,g as f,h as d}from"./BBD-8XME.js";import{w as G}from"./Br8WXJxx.js";new URL("sveltekit-internal://");function ae(t,e){return t==="/"||e==="ignore"?t:e==="never"?t.endsWith("/")?t.slice(0,-1):t:e==="always"&&!t.endsWith("/")?t+"/":t}function oe(t){return t.split("%25").map(decodeURI).join("%25")}function ie(t){for(const e in t)t[e]=decodeURIComponent(t[e]);return t}function le({href:t}){return t.split("#")[0]}function W(...t){let e=5381;for(const n of t)if(typeof n=="string"){let r=n.length;for(;r;)e=e*33^n.charCodeAt(--r)}else if(ArrayBuffer.isView(n)){const r=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let s=r.length;for(;s;)e=e*33^r[--s]}else throw new TypeError("value must be a string or TypedArray");return(e>>>0).toString(36)}new TextEncoder;new TextDecoder;function X(t){const e=atob(t),n=new Uint8Array(e.length);for(let r=0;r((t instanceof Request?t.method:(e==null?void 0:e.method)||"GET")!=="GET"&&b.delete(U(t)),z(t,e));const b=new Map;function ce(t,e){const n=U(t,e),r=document.querySelector(n);if(r!=null&&r.textContent){r.remove();let{body:s,...l}=JSON.parse(r.textContent);const o=r.getAttribute("data-ttl");return o&&b.set(n,{body:s,init:l,ttl:1e3*Number(o)}),r.getAttribute("data-b64")!==null&&(s=X(s)),Promise.resolve(new Response(s,l))}return window.fetch(t,e)}function ue(t,e,n){if(b.size>0){const r=U(t,n),s=b.get(r);if(s){if(performance.now()o)}function s(o){n=!1,e.set(o)}function l(o){let i;return e.subscribe(h=>{(i===void 0||n&&h!==i)&&o(i=h)})}return{notify:r,set:s,subscribe:l}}const D={v:()=>{}};function Re(){const{set:t,subscribe:e}=G(!1);let n;async function r(){clearTimeout(n);try{const s=await fetch(`${M}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!s.ok)return!1;const o=(await s.json()).version!==F;return o&&(t(!0),D.v(),clearTimeout(n)),o}catch{return!1}}return{subscribe:e,check:r}}function Q(t,e,n){return t.origin!==Y||!t.pathname.startsWith(e)?!0:n?t.pathname!==location.pathname:!1}function Se(t){}const H=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...H];const Z=new Set([...H]);[...Z];let E,O,T;const ee=I.toString().includes("$$")||/function \w+\(\) \{\}/.test(I.toString());var _,m,w,p,v,y,A,R,C,S,P,k,V;ee?(E={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL("https://example.com")},O={current:null},T={current:!1}):(E=new(C=class{constructor(){c(this,_,u({}));c(this,m,u(null));c(this,w,u(null));c(this,p,u({}));c(this,v,u({id:null}));c(this,y,u({}));c(this,A,u(-1));c(this,R,u(new URL("https://example.com")))}get data(){return f(a(this,_))}set data(e){d(a(this,_),e)}get form(){return f(a(this,m))}set form(e){d(a(this,m),e)}get error(){return f(a(this,w))}set error(e){d(a(this,w),e)}get params(){return f(a(this,p))}set params(e){d(a(this,p),e)}get route(){return f(a(this,v))}set route(e){d(a(this,v),e)}get state(){return f(a(this,y))}set state(e){d(a(this,y),e)}get status(){return f(a(this,A))}set status(e){d(a(this,A),e)}get url(){return f(a(this,R))}set url(e){d(a(this,R),e)}},_=new WeakMap,m=new WeakMap,w=new WeakMap,p=new WeakMap,v=new WeakMap,y=new WeakMap,A=new WeakMap,R=new WeakMap,C),O=new(P=class{constructor(){c(this,S,u(null))}get current(){return f(a(this,S))}set current(e){d(a(this,S),e)}},S=new WeakMap,P),T=new(V=class{constructor(){c(this,k,u(!1))}get current(){return f(a(this,k))}set current(e){d(a(this,k),e)}},k=new WeakMap,V),D.v=()=>T.current=!0);function Ue(t){Object.assign(E,t)}export{be as H,_e as N,ge as P,he as S,ye as a,J as b,Re as c,le as d,ie as e,pe as f,ve as g,ae as h,Q as i,N as j,oe as k,fe as l,ue as m,O as n,Y as o,E as p,ce as q,me as r,we as s,de as t,Ae as u,Ue as v,Se as w}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.br b/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.br deleted file mode 100644 index 73f5d6f..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.gz b/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.gz deleted file mode 100644 index ad04a55..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BeSd-T80.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js b/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js deleted file mode 100644 index d76449b..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js +++ /dev/null @@ -1 +0,0 @@ -import{s as c,g as l}from"./Br8WXJxx.js";import{V as o,W as a,X as b,g as p,h as d,Y as g}from"./BBD-8XME.js";let s=!1,i=Symbol();function y(e,n,r){const u=r[n]??(r[n]={store:null,source:b(void 0),unsubscribe:a});if(u.store!==e&&!(i in r))if(u.unsubscribe(),u.store=e??null,e==null)u.source.v=void 0,u.unsubscribe=a;else{var t=!0;u.unsubscribe=c(e,f=>{t?u.source.v=f:d(u.source,f)}),t=!1}return e&&i in r?l(e):p(u.source)}function m(){const e={};function n(){o(()=>{for(var r in e)e[r].unsubscribe();g(e,i,{enumerable:!1,value:!0})})}return[e,n]}function N(e){var n=s;try{return s=!1,[e(),s]}finally{s=n}}export{y as a,N as c,m as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.br b/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.br deleted file mode 100644 index 76f5426..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.gz b/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.gz deleted file mode 100644 index a1c063e..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BexJutgU.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js similarity index 76% rename from apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js rename to apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js index 0a9ca52..4ccb0ae 100644 --- a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js +++ b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js @@ -1 +1 @@ -import{t as l}from"./C5a--lgk.js";import{J as e}from"./BBD-8XME.js";function u(s,c,r,f,p,i){var a=s.__className;if(e||a!==r||a===void 0){var t=l(r);(!e||t!==s.getAttribute("class"))&&(t==null?s.removeAttribute("class"):s.className=t),s.__className=r}return i}export{u as s}; +import{t as l}from"./BilMa3tw.js";import{T as e}from"./nyjtQ1Ok.js";function u(s,c,r,f,p,i){var a=s.__className;if(e||a!==r||a===void 0){var t=l(r);(!e||t!==s.getAttribute("class"))&&(t==null?s.removeAttribute("class"):s.className=t),s.__className=r}return i}export{u as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.br b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.br new file mode 100644 index 0000000..f379f02 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.br @@ -0,0 +1 @@ +`Ĭ|brْgJh8ݾւZ(d!>cF5Q=ӌTA/~G&p<*+{Mg9V8=8#~8i3ШVv[`/_] \ No newline at end of file diff --git a/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.gz b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.gz new file mode 100644 index 0000000..12157ac Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BgOFZ9jq.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js new file mode 100644 index 0000000..5a45141 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js @@ -0,0 +1 @@ +import{ah as F,b as fe,an as ae,T as D,ac as L,ao as ie,a7 as le,g as W,a8 as ue,aa as se,ab as Z,ad as q,aj as z,ap as oe,aq as te,ar as $,U as ve,as as T,ai as y,at as de,al as ce,L as pe,a4 as _e,au as V,av as he,aw as ge,a2 as Ee,ax as j,ay as me,ae as ne,ag as re,az as B,A as Te,aA as Ae,aB as Ce,aC as we,af as Se,aD as Ie}from"./nyjtQ1Ok.js";function De(e,n){return n}function Ne(e,n,l){for(var t=[],g=n.length,s,u=n.length,c=0;c{if(s){if(s.pending.delete(E),s.done.add(E),s.pending.size===0){var o=e.outrogroups;U(V(s.done)),o.delete(s),o.size===0&&(e.outrogroups=null)}}else u-=1},!1)}if(u===0){var i=t.length===0&&l!==null;if(i){var v=l,r=v.parentNode;we(r),r.append(v),e.items.clear()}U(n,!i)}else s={pending:new Set(n),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(s)}function U(e,n=!0){for(var l=0;l{var f=l();return _e(f)?f:f==null?[]:V(f)}),o,d=!0;function C(){a.fallback=r,xe(a,o,u,n,t),r!==null&&(o.length===0?(r.f&T)===0?ne(r):(r.f^=T,M(r,null,u)):re(r,()=>{r=null}))}var I=fe(()=>{o=W(E);var f=o.length;let N=!1;if(D){var x=ue(u)===se;x!==(f===0)&&(u=Z(),L(u),q(!1),N=!0)}for(var _=new Set,w=ve,b=ce(),p=0;ps(u)):(r=y(()=>s(ee??(ee=F()))),r.f|=T)),f>_.size&&de(),D&&f>0&&L(Z()),!d)if(b){for(const[k,O]of c)_.has(k)||w.skip_effect(O.e);w.oncommit(C),w.ondiscard(()=>{})}else C();N&&q(!0),W(E)}),a={effect:I,items:c,outrogroups:null,fallback:r};d=!1,D&&(u=z)}function H(e){for(;e!==null&&(e.f&Ae)===0;)e=e.next;return e}function xe(e,n,l,t,g){var h,k,O,Y,X,G,J,K,P;var s=(t&Ce)!==0,u=n.length,c=e.items,i=H(e.effect.first),v,r=null,E,o=[],d=[],C,I,a,f;if(s)for(f=0;f0){var R=(t&ae)!==0&&u===0?l:null;if(s){for(f=0;f{var m,Q;if(E!==void 0)for(a of E)(Q=(m=a.nodes)==null?void 0:m.a)==null||Q.apply()})}function be(e,n,l,t,g,s,u,c){var i=(u&he)!==0?(u&ge)===0?Ee(l,!1,!1):j(l):null,v=(u&me)!==0?j(g):null;return{v:i,i:v,e:y(()=>(s(n,i??l,v??g,c),()=>{e.delete(t)}))}}function M(e,n,l){if(e.nodes)for(var t=e.nodes.start,g=e.nodes.end,s=n&&(n.f&T)===0?n.nodes.start:l;t!==null;){var u=Ie(t);if(s.before(t),t===g)return;t=u}}function A(e,n,l){n===null?e.effect.first=l:n.next=l,l===null?e.effect.last=n:l.prev=n}function Me(e,n,l){var t=e==null?"":""+e;return t===""?null:t}function ke(e,n){return e==null?null:String(e)}export{ke as a,He as e,De as i,Me as t}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.br b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.br new file mode 100644 index 0000000..3c74194 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.gz b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.gz new file mode 100644 index 0000000..f094183 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/BilMa3tw.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.br b/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.br deleted file mode 100644 index 7ef5f6f..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.gz b/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.gz deleted file mode 100644 index d2fcc24..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js b/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js deleted file mode 100644 index e56bc99..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js +++ /dev/null @@ -1 +0,0 @@ -import{H as m,I as _,m as b,l as i,J as y,K as v,M as h}from"./BBD-8XME.js";function E(e,l,u=l){var f=new WeakSet;m(e,"input",async r=>{var a=r?e.defaultValue:e.value;if(a=t(e)?o(a):a,u(a),v!==null&&f.add(v),await _(),a!==(a=l())){var d=e.selectionStart,s=e.selectionEnd,n=e.value.length;if(e.value=a??"",s!==null){var c=e.value.length;d===s&&s===n&&c>n?(e.selectionStart=c,e.selectionEnd=c):(e.selectionStart=d,e.selectionEnd=Math.min(s,c))}}}),(y&&e.defaultValue!==e.value||b(l)==null&&e.value)&&(u(t(e)?o(e.value):e.value),v!==null&&f.add(v)),i(()=>{var r=l();if(e===document.activeElement){var a=h??v;if(f.has(a))return}t(e)&&r===o(e.value)||e.type==="date"&&!r&&!e.value||r!==e.value&&(e.value=r??"")})}function t(e){var l=e.type;return l==="number"||l==="range"}function o(e){return e===""?null:+e}export{E as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.br b/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.br deleted file mode 100644 index dfe66fb..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.gz b/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.gz deleted file mode 100644 index c05afcd..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/BxfT1SOA.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Bzak7iHL.js.gz b/apps/dashboard/build/_app/immutable/chunks/Bzak7iHL.js.gz index df094a8..f429ed1 100644 Binary files a/apps/dashboard/build/_app/immutable/chunks/Bzak7iHL.js.gz and b/apps/dashboard/build/_app/immutable/chunks/Bzak7iHL.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js b/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js deleted file mode 100644 index 6fb580c..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js +++ /dev/null @@ -1 +0,0 @@ -import{H as s,k as o,V as c,Z as b,_ as m,$ as h,K as v,M as y}from"./BBD-8XME.js";function d(e,r,f=!1){if(e.multiple){if(r==null)return;if(!b(r))return m();for(var a of e.options)a.selected=r.includes(i(a));return}for(a of e.options){var t=i(a);if(h(t,r)){a.selected=!0;return}}(!f||r!==void 0)&&(e.selectedIndex=-1)}function q(e){var r=new MutationObserver(()=>{d(e,e.__value)});r.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),c(()=>{r.disconnect()})}function k(e,r,f=r){var a=new WeakSet,t=!0;s(e,"change",u=>{var l=u?"[selected]":":checked",n;if(e.multiple)n=[].map.call(e.querySelectorAll(l),i);else{var _=e.querySelector(l)??e.querySelector("option:not([disabled])");n=_&&i(_)}f(n),v!==null&&a.add(v)}),o(()=>{var u=r();if(e===document.activeElement){var l=y??v;if(a.has(l))return}if(d(e,u,t),t&&u===void 0){var n=e.querySelector(":checked");n!==null&&(u=i(n),f(u))}e.__value=u,t=!1}),q(e)}function i(e){return"__value"in e?e.__value:e.value}export{k as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.br b/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.br deleted file mode 100644 index 17877ab..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.gz b/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.gz deleted file mode 100644 index e8fab48..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/C-QujEl6.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js new file mode 100644 index 0000000..c72a64e --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js @@ -0,0 +1 @@ +import{s as c,g as l}from"./DAj0p1rI.js";import{a0 as o,a1 as f,a2 as b,g as p,h as d,a3 as g}from"./nyjtQ1Ok.js";let s=!1,i=Symbol();function y(e,n,r){const u=r[n]??(r[n]={store:null,source:b(void 0),unsubscribe:f});if(u.store!==e&&!(i in r))if(u.unsubscribe(),u.store=e??null,e==null)u.source.v=void 0,u.unsubscribe=f;else{var t=!0;u.unsubscribe=c(e,a=>{t?u.source.v=a:d(u.source,a)}),t=!1}return e&&i in r?l(e):p(u.source)}function m(){const e={};function n(){o(()=>{for(var r in e)e[r].unsubscribe();g(e,i,{enumerable:!1,value:!0})})}return[e,n]}function N(e){var n=s;try{return s=!1,[e(),s]}finally{s=n}}export{y as a,N as c,m as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.br b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.br new file mode 100644 index 0000000..0bea27f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.gz b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.gz new file mode 100644 index 0000000..894fafe Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C3ZC25l2.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js similarity index 80% rename from apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js rename to apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js index 76395b7..6e34d55 100644 --- a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js +++ b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js @@ -1 +1 @@ -var D=Object.defineProperty;var g=a=>{throw TypeError(a)};var F=(a,e,s)=>e in a?D(a,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[e]=s;var w=(a,e,s)=>F(a,typeof e!="symbol"?e+"":e,s),y=(a,e,s)=>e.has(a)||g("Cannot "+s);var t=(a,e,s)=>(y(a,e,"read from private field"),s?s.call(a):e.get(a)),l=(a,e,s)=>e.has(a)?g("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(a):e.set(a,s),M=(a,e,s,i)=>(y(a,e,"write to private field"),i?i.call(a,s):e.set(a,s),s);import{K as x,a7 as C,a8 as k,a9 as J,aa as A,ab as B,J as K,ac as S,ad as j,ae as q}from"./BBD-8XME.js";var r,n,h,u,p,_,v;class G{constructor(e,s=!0){w(this,"anchor");l(this,r,new Map);l(this,n,new Map);l(this,h,new Map);l(this,u,new Set);l(this,p,!0);l(this,_,()=>{var e=x;if(t(this,r).has(e)){var s=t(this,r).get(e),i=t(this,n).get(s);if(i)C(i),t(this,u).delete(s);else{var c=t(this,h).get(s);c&&(t(this,n).set(s,c.effect),t(this,h).delete(s),c.fragment.lastChild.remove(),this.anchor.before(c.fragment),i=c.effect)}for(const[f,o]of t(this,r)){if(t(this,r).delete(f),f===e)break;const d=t(this,h).get(o);d&&(k(d.effect),t(this,h).delete(o))}for(const[f,o]of t(this,n)){if(f===s||t(this,u).has(f))continue;const d=()=>{if(Array.from(t(this,r).values()).includes(f)){var b=document.createDocumentFragment();j(o,b),b.append(A()),t(this,h).set(f,{effect:o,fragment:b})}else k(o);t(this,u).delete(f),t(this,n).delete(f)};t(this,p)||!i?(t(this,u).add(f),J(o,d,!1)):d()}}});l(this,v,e=>{t(this,r).delete(e);const s=Array.from(t(this,r).values());for(const[i,c]of t(this,h))s.includes(i)||(k(c.effect),t(this,h).delete(i))});this.anchor=e,M(this,p,s)}ensure(e,s){var i=x,c=q();if(s&&!t(this,n).has(e)&&!t(this,h).has(e))if(c){var f=document.createDocumentFragment(),o=A();f.append(o),t(this,h).set(e,{effect:B(()=>s(o)),fragment:f})}else t(this,n).set(e,B(()=>s(this.anchor)));if(t(this,r).set(i,e),c){for(const[d,m]of t(this,n))d===e?i.unskip_effect(m):i.skip_effect(m);for(const[d,m]of t(this,h))d===e?i.unskip_effect(m.effect):i.skip_effect(m.effect);i.oncommit(t(this,_)),i.ondiscard(t(this,v))}else K&&(this.anchor=S),t(this,_).call(this)}}r=new WeakMap,n=new WeakMap,h=new WeakMap,u=new WeakMap,p=new WeakMap,_=new WeakMap,v=new WeakMap;export{G as B}; +var D=Object.defineProperty;var g=a=>{throw TypeError(a)};var F=(a,e,s)=>e in a?D(a,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[e]=s;var w=(a,e,s)=>F(a,typeof e!="symbol"?e+"":e,s),y=(a,e,s)=>e.has(a)||g("Cannot "+s);var t=(a,e,s)=>(y(a,e,"read from private field"),s?s.call(a):e.get(a)),l=(a,e,s)=>e.has(a)?g("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(a):e.set(a,s),M=(a,e,s,i)=>(y(a,e,"write to private field"),i?i.call(a,s):e.set(a,s),s);import{U as x,ae as j,af as k,ag as C,ah as A,ai as B,T as S,aj as T,ak as U,al as q}from"./nyjtQ1Ok.js";var r,n,h,u,p,_,v;class G{constructor(e,s=!0){w(this,"anchor");l(this,r,new Map);l(this,n,new Map);l(this,h,new Map);l(this,u,new Set);l(this,p,!0);l(this,_,()=>{var e=x;if(t(this,r).has(e)){var s=t(this,r).get(e),i=t(this,n).get(s);if(i)j(i),t(this,u).delete(s);else{var c=t(this,h).get(s);c&&(t(this,n).set(s,c.effect),t(this,h).delete(s),c.fragment.lastChild.remove(),this.anchor.before(c.fragment),i=c.effect)}for(const[f,o]of t(this,r)){if(t(this,r).delete(f),f===e)break;const d=t(this,h).get(o);d&&(k(d.effect),t(this,h).delete(o))}for(const[f,o]of t(this,n)){if(f===s||t(this,u).has(f))continue;const d=()=>{if(Array.from(t(this,r).values()).includes(f)){var b=document.createDocumentFragment();U(o,b),b.append(A()),t(this,h).set(f,{effect:o,fragment:b})}else k(o);t(this,u).delete(f),t(this,n).delete(f)};t(this,p)||!i?(t(this,u).add(f),C(o,d,!1)):d()}}});l(this,v,e=>{t(this,r).delete(e);const s=Array.from(t(this,r).values());for(const[i,c]of t(this,h))s.includes(i)||(k(c.effect),t(this,h).delete(i))});this.anchor=e,M(this,p,s)}ensure(e,s){var i=x,c=q();if(s&&!t(this,n).has(e)&&!t(this,h).has(e))if(c){var f=document.createDocumentFragment(),o=A();f.append(o),t(this,h).set(e,{effect:B(()=>s(o)),fragment:f})}else t(this,n).set(e,B(()=>s(this.anchor)));if(t(this,r).set(i,e),c){for(const[d,m]of t(this,n))d===e?i.unskip_effect(m):i.skip_effect(m);for(const[d,m]of t(this,h))d===e?i.unskip_effect(m.effect):i.skip_effect(m.effect);i.oncommit(t(this,_)),i.ondiscard(t(this,v))}else S&&(this.anchor=T),t(this,_).call(this)}}r=new WeakMap,n=new WeakMap,h=new WeakMap,u=new WeakMap,p=new WeakMap,_=new WeakMap,v=new WeakMap;export{G as B}; diff --git a/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.br b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.br new file mode 100644 index 0000000..bc15930 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.gz b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.gz new file mode 100644 index 0000000..ba6408a Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C3lo34Tx.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js new file mode 100644 index 0000000..edb90b7 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js @@ -0,0 +1,2 @@ +var Ye=Object.defineProperty;var ce=t=>{throw TypeError(t)};var Ie=(t,e,r)=>e in t?Ye(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var j=(t,e,r)=>Ie(t,typeof e!="symbol"?e+"":e,r),re=(t,e,r)=>e.has(t)||ce("Cannot "+r);var s=(t,e,r)=>(re(t,e,"read from private field"),r?r.call(t):e.get(t)),d=(t,e,r)=>e.has(t)?ce("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),a=(t,e,r,n)=>(re(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),p=(t,e,r)=>(re(t,e,"access private method"),r);import{aL as Me,g as Te,z as Ce,n as Pe,aM as ue,A as J,ax as Ee,aj as Y,T as I,F as x,aN as _e,b as Ve,a7 as xe,aa as Be,aO as pe,ai as F,ah as we,aP as se,ag as ie,ak as He,aQ as ge,aR as Le,aS as ve,aT as qe,aU as We,aV as Z,aW as G,aX as ye,aY as je,aZ as Re,k as Se,ar as ze,af as ae,ac as K,O as $e,ab as Ue,a_ as z,E as Je,a$ as Qe,b0 as Xe,b1 as Ze,a3 as Ge,b2 as ne,ao as Ke,ap as De,a9 as et,aD as tt,b3 as fe,ad as $,b4 as rt,aC as st,b5 as it,au as at,p as nt,aq as ft,b6 as ht,a as ot}from"./nyjtQ1Ok.js";import{b as dt}from"./B0IenmM-.js";function lt(t){let e=0,r=Ee(0),n;return()=>{Me()&&(Te(r),Ce(()=>(e===0&&(n=Pe(()=>t(()=>ue(r)))),e+=1,()=>{J(()=>{e-=1,e===0&&(n==null||n(),n=void 0,ue(r))})})))}}var ct=Je|Qe;function ut(t,e,r,n){new _t(t,e,r,n)}var m,W,w,C,g,R,T,E,S,P,A,B,H,L,D,ee,h,Ne,Ae,Oe,he,Q,X,oe;class _t{constructor(e,r,n,c){d(this,h);j(this,"parent");j(this,"is_pending",!1);j(this,"transform_error");d(this,m);d(this,W,I?Y:null);d(this,w);d(this,C);d(this,g);d(this,R,null);d(this,T,null);d(this,E,null);d(this,S,null);d(this,P,0);d(this,A,0);d(this,B,!1);d(this,H,new Set);d(this,L,new Set);d(this,D,null);d(this,ee,lt(()=>(a(this,D,Ee(s(this,P))),()=>{a(this,D,null)})));var i;a(this,m,e),a(this,w,r),a(this,C,f=>{var u=x;u.b=this,u.f|=_e,n(f)}),this.parent=x.b,this.transform_error=c??((i=this.parent)==null?void 0:i.transform_error)??(f=>f),a(this,g,Ve(()=>{if(I){const f=s(this,W);xe();const u=f.data===Be;if(f.data.startsWith(pe)){const l=JSON.parse(f.data.slice(pe.length));p(this,h,Ae).call(this,l)}else u?p(this,h,Oe).call(this):p(this,h,Ne).call(this)}else p(this,h,he).call(this)},ct)),I&&a(this,m,Y)}defer_effect(e){We(e,s(this,H),s(this,L))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!s(this,w).pending}update_pending_count(e){p(this,h,oe).call(this,e),a(this,P,s(this,P)+e),!(!s(this,D)||s(this,B))&&(a(this,B,!0),J(()=>{a(this,B,!1),s(this,D)&&ze(s(this,D),s(this,P))}))}get_effect_pending(){return s(this,ee).call(this),Te(s(this,D))}error(e){var r=s(this,w).onerror;let n=s(this,w).failed;if(!r&&!n)throw e;s(this,R)&&(ae(s(this,R)),a(this,R,null)),s(this,T)&&(ae(s(this,T)),a(this,T,null)),s(this,E)&&(ae(s(this,E)),a(this,E,null)),I&&(K(s(this,W)),$e(),K(Ue()));var c=!1,i=!1;const f=()=>{if(c){Ze();return}c=!0,i&&Xe(),s(this,E)!==null&&ie(s(this,E),()=>{a(this,E,null)}),p(this,h,X).call(this,()=>{se.ensure(),p(this,h,he).call(this)})},u=o=>{try{i=!0,r==null||r(o,f),i=!1}catch(l){z(l,s(this,g)&&s(this,g).parent)}n&&a(this,E,p(this,h,X).call(this,()=>{se.ensure();try{return F(()=>{var l=x;l.b=this,l.f|=_e,n(s(this,m),()=>o,()=>f)})}catch(l){return z(l,s(this,g).parent),null}}))};J(()=>{var o;try{o=this.transform_error(e)}catch(l){z(l,s(this,g)&&s(this,g).parent);return}o!==null&&typeof o=="object"&&typeof o.then=="function"?o.then(u,l=>z(l,s(this,g)&&s(this,g).parent)):u(o)})}}m=new WeakMap,W=new WeakMap,w=new WeakMap,C=new WeakMap,g=new WeakMap,R=new WeakMap,T=new WeakMap,E=new WeakMap,S=new WeakMap,P=new WeakMap,A=new WeakMap,B=new WeakMap,H=new WeakMap,L=new WeakMap,D=new WeakMap,ee=new WeakMap,h=new WeakSet,Ne=function(){try{a(this,R,F(()=>s(this,C).call(this,s(this,m))))}catch(e){this.error(e)}},Ae=function(e){const r=s(this,w).failed;r&&a(this,E,F(()=>{r(s(this,m),()=>e,()=>()=>{})}))},Oe=function(){const e=s(this,w).pending;e&&(this.is_pending=!0,a(this,T,F(()=>e(s(this,m)))),J(()=>{var r=a(this,S,document.createDocumentFragment()),n=we();r.append(n),a(this,R,p(this,h,X).call(this,()=>(se.ensure(),F(()=>s(this,C).call(this,n))))),s(this,A)===0&&(s(this,m).before(r),a(this,S,null),ie(s(this,T),()=>{a(this,T,null)}),p(this,h,Q).call(this))}))},he=function(){try{if(this.is_pending=this.has_pending_snippet(),a(this,A,0),a(this,P,0),a(this,R,F(()=>{s(this,C).call(this,s(this,m))})),s(this,A)>0){var e=a(this,S,document.createDocumentFragment());He(s(this,R),e);const r=s(this,w).pending;a(this,T,F(()=>r(s(this,m))))}else p(this,h,Q).call(this)}catch(r){this.error(r)}},Q=function(){this.is_pending=!1;for(const e of s(this,H))ge(e,Le),ve(e);for(const e of s(this,L))ge(e,qe),ve(e);s(this,H).clear(),s(this,L).clear()},X=function(e){var r=x,n=Re,c=Se;Z(s(this,g)),G(s(this,g)),ye(s(this,g).ctx);try{return e()}catch(i){return je(i),null}finally{Z(r),G(n),ye(c)}},oe=function(e){var r;if(!this.has_pending_snippet()){this.parent&&p(r=this.parent,h,oe).call(r,e);return}a(this,A,s(this,A)+e),s(this,A)===0&&(p(this,h,Q).call(this),s(this,T)&&ie(s(this,T),()=>{a(this,T,null)}),s(this,S)&&(s(this,m).before(s(this,S)),a(this,S,null)))};const pt=["touchstart","touchmove"];function gt(t){return pt.includes(t)}const M=Symbol("events"),ke=new Set,de=new Set;function Tt(t,e,r){(e[M]??(e[M]={}))[t]=r}function Et(t){for(var e=0;e{throw k});throw N}}finally{t[M]=e,delete t.currentTarget,G(V),Z(q)}}}function wt(t,e){var r=e==null?"":typeof e=="object"?e+"":e;r!==(t.__t??(t.__t=t.nodeValue))&&(t.__t=r,t.nodeValue=r+"")}function vt(t,e){return Fe(t,e)}function Rt(t,e){ne(),e.intro=e.intro??!1;const r=e.target,n=I,c=Y;try{for(var i=Ke(r);i&&(i.nodeType!==De||i.data!==et);)i=tt(i);if(!i)throw fe;$(!0),K(i);const f=Fe(t,{...e,anchor:i});return $(!1),f}catch(f){if(f instanceof Error&&f.message.split(` +`).some(u=>u.startsWith("https://svelte.dev/e/")))throw f;return f!==fe&&console.warn("Failed to hydrate: ",f),e.recover===!1&&rt(),ne(),st(r),$(!1),vt(t,e)}finally{$(n),K(c)}}const U=new Map;function Fe(t,{target:e,anchor:r,props:n={},events:c,context:i,intro:f=!0,transformError:u}){ne();var o=void 0,l=it(()=>{var V=r??e.appendChild(we());ut(V,{pending:()=>{}},v=>{nt({});var _=Se;if(i&&(_.c=i),c&&(n.$$events=c),I&&dt(v,null),o=t(v,n)||{},I&&(x.nodes.end=Y,Y===null||Y.nodeType!==De||Y.data!==ft))throw ht(),fe;ot()},u);var q=new Set,N=v=>{for(var _=0;_{var O;for(var v of q)for(const b of[e,document]){var _=U.get(b),y=_.get(v);--y==0?(b.removeEventListener(v,me),_.delete(v),_.size===0&&U.delete(b)):_.set(v,y)}de.delete(N),V!==r&&((O=V.parentNode)==null||O.removeChild(V))}});return le.set(o,l),o}let le=new WeakMap;function St(t,e){const r=le.get(t);return r?(le.delete(t),r(e)):Promise.resolve()}export{Tt as a,Et as d,Rt as h,vt as m,wt as s,St as u}; diff --git a/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.br b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.br new file mode 100644 index 0000000..17bcd56 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.gz b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.gz new file mode 100644 index 0000000..55e9633 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/C4L78yoI.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js b/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js deleted file mode 100644 index 512c677..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js +++ /dev/null @@ -1 +0,0 @@ -import{aa as F,b as fe,an as ne,J as D,a5 as q,ao as ie,a0 as le,g as Q,a1 as ue,a3 as se,a4 as W,a6 as L,ac as z,ap as oe,aq as te,ar as $,K as ve,as as C,ab as y,at as de,ae as ce,C as pe,Z as _e,au as X,av as he,aw as ge,X as Ee,ax as j,ay as me,a7 as re,a9 as ae,az as B,q as Ce,aA as Te,aB as Ae,aC as we,a8 as Se,aD as Ie}from"./BBD-8XME.js";function De(e,r){return r}function Ne(e,r,l){for(var t=[],g=r.length,s,u=r.length,c=0;c{if(s){if(s.pending.delete(E),s.done.add(E),s.pending.size===0){var o=e.outrogroups;V(X(s.done)),o.delete(s),o.size===0&&(e.outrogroups=null)}}else u-=1},!1)}if(u===0){var i=t.length===0&&l!==null;if(i){var v=l,a=v.parentNode;we(a),a.append(v),e.items.clear()}V(r,!i)}else s={pending:new Set(r),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(s)}function V(e,r=!0){for(var l=0;l{var f=l();return _e(f)?f:f==null?[]:X(f)}),o,d=!0;function A(){n.fallback=a,xe(n,o,u,r,t),a!==null&&(o.length===0?(a.f&C)===0?re(a):(a.f^=C,M(a,null,u)):ae(a,()=>{a=null}))}var I=fe(()=>{o=Q(E);var f=o.length;let N=!1;if(D){var x=ue(u)===se;x!==(f===0)&&(u=W(),q(u),L(!1),N=!0)}for(var _=new Set,w=ve,b=ce(),p=0;ps(u)):(a=y(()=>s(ee??(ee=F()))),a.f|=C)),f>_.size&&de(),D&&f>0&&q(W()),!d)if(b){for(const[k,O]of c)_.has(k)||w.skip_effect(O.e);w.oncommit(A),w.ondiscard(()=>{})}else A();N&&L(!0),Q(E)}),n={effect:I,items:c,outrogroups:null,fallback:a};d=!1,D&&(u=z)}function H(e){for(;e!==null&&(e.f&Te)===0;)e=e.next;return e}function xe(e,r,l,t,g){var h,k,O,Y,J,K,U,Z,G;var s=(t&Ae)!==0,u=r.length,c=e.items,i=H(e.effect.first),v,a=null,E,o=[],d=[],A,I,n,f;if(s)for(f=0;f0){var R=(t&ne)!==0&&u===0?l:null;if(s){for(f=0;f{var m,P;if(E!==void 0)for(n of E)(P=(m=n.nodes)==null?void 0:m.a)==null||P.apply()})}function be(e,r,l,t,g,s,u,c){var i=(u&he)!==0?(u&ge)===0?Ee(l,!1,!1):j(l):null,v=(u&me)!==0?j(g):null;return{v:i,i:v,e:y(()=>(s(r,i??l,v??g,c),()=>{e.delete(t)}))}}function M(e,r,l){if(e.nodes)for(var t=e.nodes.start,g=e.nodes.end,s=r&&(r.f&C)===0?r.nodes.start:l;t!==null;){var u=Ie(t);if(s.before(t),t===g)return;t=u}}function T(e,r,l){r===null?e.effect.first=l:r.next=l,l===null?e.effect.last=r:l.prev=r}function Me(e,r,l){var t=e==null?"":""+e;return t===""?null:t}function ke(e,r){return e==null?null:String(e)}export{ke as a,He as e,De as i,Me as t}; diff --git a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.br b/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.br deleted file mode 100644 index ee69479..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.gz b/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.gz deleted file mode 100644 index fe9fcb7..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/C5a--lgk.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.br b/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.br deleted file mode 100644 index c2bbca9..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.gz b/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.gz deleted file mode 100644 index a075113..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CBWLjDtu.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js b/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js deleted file mode 100644 index 7d2ed73..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js +++ /dev/null @@ -1 +0,0 @@ -import{aE as h,aa as d,ao as l,aF as p,w as _,aG as E,aH as g,J as u,ac as s,aI as y,a0 as M,aJ as N,a5 as x,aK as A}from"./BBD-8XME.js";var f;const i=((f=globalThis==null?void 0:globalThis.window)==null?void 0:f.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function b(t){return(i==null?void 0:i.createHTML(t))??t}function w(t){var r=h("template");return r.innerHTML=b(t.replaceAll("","")),r.content}function a(t,r){var e=_;e.nodes===null&&(e.nodes={start:t,end:r,a:null,t:null})}function H(t,r){var e=(r&E)!==0,c=(r&g)!==0,n,m=!t.startsWith("");return()=>{if(u)return a(s,null),s;n===void 0&&(n=w(m?t:""+t),e||(n=l(n)));var o=c||p?document.importNode(n,!0):n.cloneNode(!0);if(e){var v=l(o),T=o.lastChild;a(v,T)}else a(o,o);return o}}function O(t=""){if(!u){var r=d(t+"");return a(r,r),r}var e=s;return e.nodeType!==N?(e.before(e=d()),x(e)):A(e),a(e,e),e}function P(){if(u)return a(s,null),s;var t=document.createDocumentFragment(),r=document.createComment(""),e=d();return t.append(r,e),a(r,e),t}function R(t,r){if(u){var e=_;((e.f&y)===0||e.nodes.end===null)&&(e.nodes.end=s),M();return}t!==null&&t.before(r)}export{R as a,a as b,P as c,H as f,O as t}; diff --git a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.br b/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.br deleted file mode 100644 index b6e08e0..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.br +++ /dev/null @@ -1,2 +0,0 @@ -@dS,A\`ԗ)o9ZI9l<¶ -^UIB'1$L/eȘ`W?F .cx X a0Mx;x=4AQ鍳URG c6CJ,ұX,JM1XLtH͂A4c@q*LdOhO(&,iA5Ѓe[Z@D<> ]PѕH d1,gNCP#E!DH^3o0.RVsȒr$.J % )k͘Af )!A7{5T2gWtb'bmBVHpRnsLjMkbqHhj2EIfIz[,,x{T \ No newline at end of file diff --git a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.gz b/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.gz deleted file mode 100644 index 98846df..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CKcqngaU.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js b/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js deleted file mode 100644 index 631fc9b..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js +++ /dev/null @@ -1 +0,0 @@ -const e={fact:"#00A8FF",concept:"#9D00FF",event:"#FFB800",person:"#00FFD1",place:"#00D4FF",note:"#8B95A5",pattern:"#FF3CAC",decision:"#FF4757"},F={MemoryCreated:"#00FFD1",MemoryUpdated:"#00A8FF",MemoryDeleted:"#FF4757",MemoryPromoted:"#00FF88",MemoryDemoted:"#FF6B35",SearchPerformed:"#818CF8",DreamStarted:"#9D00FF",DreamProgress:"#B44AFF",DreamCompleted:"#C084FC",ConsolidationStarted:"#FFB800",ConsolidationCompleted:"#FF9500",RetentionDecayed:"#FF4757",ConnectionDiscovered:"#00D4FF",ActivationSpread:"#14E8C6",ImportanceScored:"#FF3CAC",Heartbeat:"#8B95A5"};export{F as E,e as N}; diff --git a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.br b/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.br deleted file mode 100644 index 1fc079b..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.gz b/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.gz deleted file mode 100644 index 0a36621..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CZ45jJaw.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js new file mode 100644 index 0000000..874e450 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js @@ -0,0 +1 @@ +import{k as d,l as g,m as i,n as m,o as l,q as v,g as p,v as b,w as k}from"./nyjtQ1Ok.js";function x(n=!1){const s=d,e=s.l.u;if(!e)return;let r=()=>b(s.s);if(n){let o=0,t={};const _=k(()=>{let c=!1;const a=s.s;for(const f in a)a[f]!==t[f]&&(t[f]=a[f],c=!0);return c&&o++,o});r=()=>p(_)}e.b.length&&g(()=>{u(s,r),l(e.b)}),i(()=>{const o=m(()=>e.m.map(v));return()=>{for(const t of o)typeof t=="function"&&t()}}),e.a.length&&i(()=>{u(s,r),l(e.a)})}function u(n,s){if(n.l.s)for(const e of n.l.s)p(e);s()}export{x as i}; diff --git a/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.br b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.br new file mode 100644 index 0000000..3260552 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.gz b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.gz new file mode 100644 index 0000000..6ce5f7d Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/Ck7jSX2P.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js new file mode 100644 index 0000000..e2902cf --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js @@ -0,0 +1 @@ +import{b as p,E as t}from"./nyjtQ1Ok.js";import{B as c}from"./C3lo34Tx.js";function E(r,s,...a){var e=new c(r);p(()=>{const n=s()??null;e.ensure(n,n&&(o=>n(o,...a)))},t)}export{E as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.br b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.br new file mode 100644 index 0000000..0d96ec6 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.gz b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.gz new file mode 100644 index 0000000..3ff3a71 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/Ckx7gB9J.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js b/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js deleted file mode 100644 index 6d8a62b..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js +++ /dev/null @@ -1 +0,0 @@ -import{d as l,w as S}from"./Br8WXJxx.js";const y=200;function H(){const{subscribe:n,set:c,update:e}=S({connected:!1,events:[],lastHeartbeat:null,error:null});let t=null,a=null,d=0;function m(r){const u=r||(window.location.port==="5173"?`ws://${window.location.hostname}:3927/ws`:`ws://${window.location.host}/ws`);if((t==null?void 0:t.readyState)!==WebSocket.OPEN)try{t=new WebSocket(u),t.onopen=()=>{d=0,e(o=>({...o,connected:!0,error:null}))},t.onmessage=o=>{try{const s=JSON.parse(o.data);e(b=>{if(s.type==="Heartbeat")return{...b,lastHeartbeat:s};const p=[s,...b.events].slice(0,y);return{...b,events:p}})}catch{}},t.onclose=()=>{e(o=>({...o,connected:!1})),f(u)},t.onerror=()=>{e(o=>({...o,error:"WebSocket connection failed"}))}}catch(o){e(s=>({...s,error:String(o)}))}}function f(r){a&&clearTimeout(a);const u=Math.min(1e3*2**d,3e4);d++,a=setTimeout(()=>m(r),u)}function w(){a&&clearTimeout(a),t==null||t.close(),t=null,c({connected:!1,events:[],lastHeartbeat:null,error:null})}function v(){e(r=>({...r,events:[]}))}return{subscribe:n,connect:m,disconnect:w,clearEvents:v}}const i=H(),k=l(i,n=>n.connected),T=l(i,n=>n.events);l(i,n=>n.lastHeartbeat);const g=l(i,n=>{var c,e;return((e=(c=n.lastHeartbeat)==null?void 0:c.data)==null?void 0:e.memory_count)??0}),E=l(i,n=>{var c,e;return((e=(c=n.lastHeartbeat)==null?void 0:c.data)==null?void 0:e.avg_retention)??0});export{E as a,T as e,k as i,g as m,i as w}; diff --git a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.br b/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.br deleted file mode 100644 index 24c2b14..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.gz b/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.gz deleted file mode 100644 index 41facb8..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CruZBLYW.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js b/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js deleted file mode 100644 index bca8b90..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js +++ /dev/null @@ -1 +0,0 @@ -import{n as L,o as D,P as T,g as P,c as B,h as b,v as Y,w as h,D as x,x as M,m as N,y as U,z as w,A as z,B as C,C as $,F as q,S as y,L as F}from"./BBD-8XME.js";import{c as G}from"./BexJutgU.js";function H(r,a,t,s){var o;var f=!U||(t&w)!==0,v=(t&M)!==0,E=(t&q)!==0,n=s,c=!0,g=()=>(c&&(c=!1,n=E?N(s):s),n),u;if(v){var O=y in r||F in r;u=((o=L(r,a))==null?void 0:o.set)??(O&&a in r?e=>r[a]=e:void 0)}var _,I=!1;v?[_,I]=G(()=>r[a]):_=r[a],_===void 0&&s!==void 0&&(_=g(),u&&(f&&D(),u(_)));var i;if(f?i=()=>{var e=r[a];return e===void 0?g():(c=!0,e)}:i=()=>{var e=r[a];return e!==void 0&&(n=void 0),e===void 0?n:e},f&&(t&T)===0)return i;if(u){var R=r.$$legacy;return(function(e,S){return arguments.length>0?((!f||!S||R||I)&&u(S?i():e),e):i()})}var l=!1,d=((t&z)!==0?C:$)(()=>(l=!1,i()));v&&P(d);var m=h;return(function(e,S){if(arguments.length>0){const A=S?P(d):f&&v?B(e):e;return b(d,A),l=!0,n!==void 0&&(n=A),e}return Y&&l||(m.f&x)!==0?d.v:P(d)})}export{H as p}; diff --git a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.br b/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.br deleted file mode 100644 index 712779c..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.gz b/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.gz deleted file mode 100644 index 1b84b06..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/CzkEqL6J.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js b/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js deleted file mode 100644 index 5cd86b3..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js +++ /dev/null @@ -1 +0,0 @@ -import{af as g,ag as d,ah as c,m,ai as i,aj as b,g as p,ak as h,B as k,al as v}from"./BBD-8XME.js";function x(t=!1){const a=g,e=a.l.u;if(!e)return;let o=()=>h(a.s);if(t){let n=0,s={};const _=k(()=>{let l=!1;const r=a.s;for(const f in r)r[f]!==s[f]&&(s[f]=r[f],l=!0);return l&&n++,n});o=()=>p(_)}e.b.length&&d(()=>{u(a,o),i(e.b)}),c(()=>{const n=m(()=>e.m.map(b));return()=>{for(const s of n)typeof s=="function"&&s()}}),e.a.length&&c(()=>{u(a,o),i(e.a)})}function u(t,a){if(t.l.s)for(const e of t.l.s)p(e);a()}v();export{x as i}; diff --git a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.br b/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.br deleted file mode 100644 index f2a4f7b..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.gz b/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.gz deleted file mode 100644 index 4735b18..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/D1BK9eoQ.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js similarity index 74% rename from apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js rename to apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js index 0260b51..a9eaa89 100644 --- a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js +++ b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js @@ -1 +1 @@ -import{a as y}from"./C5a--lgk.js";import{J as r}from"./BBD-8XME.js";function a(t,e,f,i){var l=t.__style;if(r||l!==e){var s=y(e);(!r||s!==t.getAttribute("style"))&&(s==null?t.removeAttribute("style"):t.style.cssText=s),t.__style=e}return i}export{a as s}; +import{a as y}from"./BilMa3tw.js";import{T as r}from"./nyjtQ1Ok.js";function a(t,e,f,i){var l=t.__style;if(r||l!==e){var s=y(e);(!r||s!==t.getAttribute("style"))&&(s==null?t.removeAttribute("style"):t.style.cssText=s),t.__style=e}return i}export{a as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.br b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.br new file mode 100644 index 0000000..905824e Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.gz b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.gz new file mode 100644 index 0000000..356ab5c Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/D2QmVWrb.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js new file mode 100644 index 0000000..91c75c2 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js @@ -0,0 +1 @@ +import{y as S,z as h,n as k,A,S as T}from"./nyjtQ1Ok.js";function t(r,i){return r===i||(r==null?void 0:r[T])===i}function x(r={},i,a,c){return S(()=>{var f,s;return h(()=>{f=s,s=[],k(()=>{r!==a(...s)&&(i(r,...s),f&&t(a(...f),r)&&i(null,...f))})}),()=>{A(()=>{s&&t(a(...s),r)&&i(null,...s)})}}),r}export{x as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.br b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.br new file mode 100644 index 0000000..73181a6 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.gz b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.gz new file mode 100644 index 0000000..412d4a1 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DAhpUNCK.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js similarity index 94% rename from apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js rename to apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js index f5097b8..2aa02ba 100644 --- a/apps/dashboard/build/_app/immutable/chunks/Br8WXJxx.js +++ b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js @@ -1 +1 @@ -import{W as a,m as w,am as q,ai as x}from"./BBD-8XME.js";function _(e,t,n){if(e==null)return t(void 0),n&&n(void 0),a;const r=w(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}const f=[];function z(e,t){return{subscribe:A(e,t).subscribe}}function A(e,t=a){let n=null;const r=new Set;function i(u){if(q(e,u)&&(e=u,n)){const o=!f.length;for(const s of r)s[1](),f.push(s,e);if(o){for(let s=0;s{r.delete(s),r.size===0&&n&&(n(),n=null)}}return{set:i,update:b,subscribe:l}}function B(e,t,n){const r=!Array.isArray(e),i=r?[e]:e;if(!i.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const b=t.length<2;return z(n,(l,u)=>{let o=!1;const s=[];let d=0,p=a;const y=()=>{if(d)return;p();const c=t(r?s[0]:s,l,u);b?l(c):p=typeof c=="function"?c:a},h=i.map((c,g)=>_(c,m=>{s[g]=m,d&=~(1<{d|=1<t=n)(),t}export{B as d,E as g,_ as s,A as w}; +import{a1 as a,n as w,am as q,o as x}from"./nyjtQ1Ok.js";function _(e,t,n){if(e==null)return t(void 0),n&&n(void 0),a;const r=w(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}const f=[];function z(e,t){return{subscribe:A(e,t).subscribe}}function A(e,t=a){let n=null;const r=new Set;function i(u){if(q(e,u)&&(e=u,n)){const o=!f.length;for(const s of r)s[1](),f.push(s,e);if(o){for(let s=0;s{r.delete(s),r.size===0&&n&&(n(),n=null)}}return{set:i,update:b,subscribe:l}}function B(e,t,n){const r=!Array.isArray(e),i=r?[e]:e;if(!i.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const b=t.length<2;return z(n,(l,u)=>{let o=!1;const s=[];let d=0,p=a;const y=()=>{if(d)return;p();const c=t(r?s[0]:s,l,u);b?l(c):p=typeof c=="function"?c:a},h=i.map((c,g)=>_(c,m=>{s[g]=m,d&=~(1<{d|=1<t=n)(),t}export{B as d,E as g,_ as s,A as w}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.br b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.br new file mode 100644 index 0000000..5c5ab52 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.gz b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.gz new file mode 100644 index 0000000..035f57e Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DAj0p1rI.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.br b/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.br deleted file mode 100644 index 8351992..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.gz b/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.gz deleted file mode 100644 index d531b34..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DBfx-YTU.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js b/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js deleted file mode 100644 index 7158e59..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js +++ /dev/null @@ -1,2 +0,0 @@ -var ke=Object.defineProperty;var ce=t=>{throw TypeError(t)};var Ie=(t,e,r)=>e in t?ke(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var $=(t,e,r)=>Ie(t,typeof e!="symbol"?e+"":e,r),re=(t,e,r)=>e.has(t)||ce("Cannot "+r);var s=(t,e,r)=>(re(t,e,"read from private field"),r?r.call(t):e.get(t)),l=(t,e,r)=>e.has(t)?ce("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),a=(t,e,r,n)=>(re(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),p=(t,e,r)=>(re(t,e,"access private method"),r);import{aL as Me,g as Ee,l as Ce,m as Pe,aM as ue,q as U,ax as Te,ac as k,J as I,w as q,aN as _e,b as Ve,a0 as qe,a3 as xe,aO as pe,ab as F,aa as we,aP as se,a9 as ie,ad as Be,aQ as ge,aR as He,aS as ve,aT as Le,aU as We,aV as X,aW as Z,aX as ye,aY as $e,aZ as Re,af as Se,ar as je,a8 as ae,a5 as K,G as ze,a4 as Je,a_ as j,E as Ue,a$ as Ge,b0 as Qe,b1 as Xe,Y as Ze,b2 as ne,ao as Ke,ap as De,a2 as et,aD as tt,b3 as fe,a6 as z,b4 as rt,aC as st,b5 as it,au as at,p as nt,aq as ft,b6 as ht,a as ot}from"./BBD-8XME.js";import{b as lt}from"./CKcqngaU.js";function dt(t){let e=0,r=Te(0),n;return()=>{Me()&&(Ee(r),Ce(()=>(e===0&&(n=Pe(()=>t(()=>ue(r)))),e+=1,()=>{U(()=>{e-=1,e===0&&(n==null||n(),n=void 0,ue(r))})})))}}var ct=Ue|Ge;function ut(t,e,r,n){new _t(t,e,r,n)}var m,W,w,C,g,R,E,T,S,P,A,x,B,H,D,ee,h,Ne,Ae,Oe,he,G,Q,oe;class _t{constructor(e,r,n,c){l(this,h);$(this,"parent");$(this,"is_pending",!1);$(this,"transform_error");l(this,m);l(this,W,I?k:null);l(this,w);l(this,C);l(this,g);l(this,R,null);l(this,E,null);l(this,T,null);l(this,S,null);l(this,P,0);l(this,A,0);l(this,x,!1);l(this,B,new Set);l(this,H,new Set);l(this,D,null);l(this,ee,dt(()=>(a(this,D,Te(s(this,P))),()=>{a(this,D,null)})));var i;a(this,m,e),a(this,w,r),a(this,C,f=>{var u=q;u.b=this,u.f|=_e,n(f)}),this.parent=q.b,this.transform_error=c??((i=this.parent)==null?void 0:i.transform_error)??(f=>f),a(this,g,Ve(()=>{if(I){const f=s(this,W);qe();const u=f.data===xe;if(f.data.startsWith(pe)){const d=JSON.parse(f.data.slice(pe.length));p(this,h,Ae).call(this,d)}else u?p(this,h,Oe).call(this):p(this,h,Ne).call(this)}else p(this,h,he).call(this)},ct)),I&&a(this,m,k)}defer_effect(e){We(e,s(this,B),s(this,H))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!s(this,w).pending}update_pending_count(e){p(this,h,oe).call(this,e),a(this,P,s(this,P)+e),!(!s(this,D)||s(this,x))&&(a(this,x,!0),U(()=>{a(this,x,!1),s(this,D)&&je(s(this,D),s(this,P))}))}get_effect_pending(){return s(this,ee).call(this),Ee(s(this,D))}error(e){var r=s(this,w).onerror;let n=s(this,w).failed;if(!r&&!n)throw e;s(this,R)&&(ae(s(this,R)),a(this,R,null)),s(this,E)&&(ae(s(this,E)),a(this,E,null)),s(this,T)&&(ae(s(this,T)),a(this,T,null)),I&&(K(s(this,W)),ze(),K(Je()));var c=!1,i=!1;const f=()=>{if(c){Xe();return}c=!0,i&&Qe(),s(this,T)!==null&&ie(s(this,T),()=>{a(this,T,null)}),p(this,h,Q).call(this,()=>{se.ensure(),p(this,h,he).call(this)})},u=o=>{try{i=!0,r==null||r(o,f),i=!1}catch(d){j(d,s(this,g)&&s(this,g).parent)}n&&a(this,T,p(this,h,Q).call(this,()=>{se.ensure();try{return F(()=>{var d=q;d.b=this,d.f|=_e,n(s(this,m),()=>o,()=>f)})}catch(d){return j(d,s(this,g).parent),null}}))};U(()=>{var o;try{o=this.transform_error(e)}catch(d){j(d,s(this,g)&&s(this,g).parent);return}o!==null&&typeof o=="object"&&typeof o.then=="function"?o.then(u,d=>j(d,s(this,g)&&s(this,g).parent)):u(o)})}}m=new WeakMap,W=new WeakMap,w=new WeakMap,C=new WeakMap,g=new WeakMap,R=new WeakMap,E=new WeakMap,T=new WeakMap,S=new WeakMap,P=new WeakMap,A=new WeakMap,x=new WeakMap,B=new WeakMap,H=new WeakMap,D=new WeakMap,ee=new WeakMap,h=new WeakSet,Ne=function(){try{a(this,R,F(()=>s(this,C).call(this,s(this,m))))}catch(e){this.error(e)}},Ae=function(e){const r=s(this,w).failed;r&&a(this,T,F(()=>{r(s(this,m),()=>e,()=>()=>{})}))},Oe=function(){const e=s(this,w).pending;e&&(this.is_pending=!0,a(this,E,F(()=>e(s(this,m)))),U(()=>{var r=a(this,S,document.createDocumentFragment()),n=we();r.append(n),a(this,R,p(this,h,Q).call(this,()=>(se.ensure(),F(()=>s(this,C).call(this,n))))),s(this,A)===0&&(s(this,m).before(r),a(this,S,null),ie(s(this,E),()=>{a(this,E,null)}),p(this,h,G).call(this))}))},he=function(){try{if(this.is_pending=this.has_pending_snippet(),a(this,A,0),a(this,P,0),a(this,R,F(()=>{s(this,C).call(this,s(this,m))})),s(this,A)>0){var e=a(this,S,document.createDocumentFragment());Be(s(this,R),e);const r=s(this,w).pending;a(this,E,F(()=>r(s(this,m))))}else p(this,h,G).call(this)}catch(r){this.error(r)}},G=function(){this.is_pending=!1;for(const e of s(this,B))ge(e,He),ve(e);for(const e of s(this,H))ge(e,Le),ve(e);s(this,B).clear(),s(this,H).clear()},Q=function(e){var r=q,n=Re,c=Se;X(s(this,g)),Z(s(this,g)),ye(s(this,g).ctx);try{return e()}catch(i){return $e(i),null}finally{X(r),Z(n),ye(c)}},oe=function(e){var r;if(!this.has_pending_snippet()){this.parent&&p(r=this.parent,h,oe).call(r,e);return}a(this,A,s(this,A)+e),s(this,A)===0&&(p(this,h,G).call(this),s(this,E)&&ie(s(this,E),()=>{a(this,E,null)}),s(this,S)&&(s(this,m).before(s(this,S)),a(this,S,null)))};const pt=["touchstart","touchmove"];function gt(t){return pt.includes(t)}const M=Symbol("events"),Ye=new Set,le=new Set;function Et(t,e,r){(e[M]??(e[M]={}))[t]=r}function Tt(t){for(var e=0;e{throw Y});throw N}}finally{t[M]=e,delete t.currentTarget,Z(V),X(L)}}}function wt(t,e){var r=e==null?"":typeof e=="object"?e+"":e;r!==(t.__t??(t.__t=t.nodeValue))&&(t.__t=r,t.nodeValue=r+"")}function vt(t,e){return Fe(t,e)}function Rt(t,e){ne(),e.intro=e.intro??!1;const r=e.target,n=I,c=k;try{for(var i=Ke(r);i&&(i.nodeType!==De||i.data!==et);)i=tt(i);if(!i)throw fe;z(!0),K(i);const f=Fe(t,{...e,anchor:i});return z(!1),f}catch(f){if(f instanceof Error&&f.message.split(` -`).some(u=>u.startsWith("https://svelte.dev/e/")))throw f;return f!==fe&&console.warn("Failed to hydrate: ",f),e.recover===!1&&rt(),ne(),st(r),z(!1),vt(t,e)}finally{z(n),K(c)}}const J=new Map;function Fe(t,{target:e,anchor:r,props:n={},events:c,context:i,intro:f=!0,transformError:u}){ne();var o=void 0,d=it(()=>{var V=r??e.appendChild(we());ut(V,{pending:()=>{}},v=>{nt({});var _=Se;if(i&&(_.c=i),c&&(n.$$events=c),I&<(v,null),o=t(v,n)||{},I&&(q.nodes.end=k,k===null||k.nodeType!==De||k.data!==ft))throw ht(),fe;ot()},u);var L=new Set,N=v=>{for(var _=0;_{var O;for(var v of L)for(const b of[e,document]){var _=J.get(b),y=_.get(v);--y==0?(b.removeEventListener(v,me),_.delete(v),_.size===0&&J.delete(b)):_.set(v,y)}le.delete(N),V!==r&&((O=V.parentNode)==null||O.removeChild(V))}});return de.set(o,d),o}let de=new WeakMap;function St(t,e){const r=de.get(t);return r?(de.delete(t),r(e)):Promise.resolve()}export{Et as a,Tt as d,Rt as h,vt as m,wt as s,St as u}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.br b/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.br deleted file mode 100644 index 6a034f7..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.gz b/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.gz deleted file mode 100644 index b58a5b1..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DNn3Nckx.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js b/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js deleted file mode 100644 index ae0844d..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js +++ /dev/null @@ -1 +0,0 @@ -import{ah as a,af as t,y as u,m as o}from"./BBD-8XME.js";function c(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function l(e){t===null&&c(),u&&t.l!==null?f(t).m.push(e):a(()=>{const n=o(e);if(typeof n=="function")return n})}function s(e){t===null&&c(),l(()=>()=>o(e))}function f(e){var n=e.l;return n.u??(n.u={a:[],b:[],m:[]})}export{s as a,l as o}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.br b/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.br deleted file mode 100644 index 9e56a49..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.gz b/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.gz deleted file mode 100644 index f18a8d7..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DUC-ssvh.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js b/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js deleted file mode 100644 index 9024538..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js +++ /dev/null @@ -1 +0,0 @@ -import{b as p,E as t}from"./BBD-8XME.js";import{B as c}from"./gqVpgJ8U.js";function E(r,s,...a){var e=new c(r);p(()=>{const n=s()??null;e.ensure(n,n&&(o=>n(o,...a)))},t)}export{E as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.br b/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.br deleted file mode 100644 index f7a2906..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.gz b/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.gz deleted file mode 100644 index 741bb0f..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DZuEJlJ5.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js new file mode 100644 index 0000000..5dc253c --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js @@ -0,0 +1 @@ +import{x as a}from"./nyjtQ1Ok.js";a(); diff --git a/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.br b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.br new file mode 100644 index 0000000..c8a4fda --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.br @@ -0,0 +1,2 @@ + import{x as a}from"./nyjtQ1Ok.js";a(); + \ No newline at end of file diff --git a/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.gz b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.gz new file mode 100644 index 0000000..2dca750 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/D_N1HvA5.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js new file mode 100644 index 0000000..4962a25 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js @@ -0,0 +1 @@ +import{m as u,k as t,I as l,n as o}from"./nyjtQ1Ok.js";function c(n){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function a(n){t===null&&c(),l&&t.l!==null?i(t).m.push(n):u(()=>{const e=o(n);if(typeof e=="function")return e})}function f(n){t===null&&c(),a(()=>()=>o(n))}function i(n){var e=n.l;return e.u??(e.u={a:[],b:[],m:[]})}export{f as a,a as o}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.br b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.br new file mode 100644 index 0000000..41a14c4 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.gz b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.gz new file mode 100644 index 0000000..18730fe Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DeTA_5mp.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js b/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js deleted file mode 100644 index 5063e44..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js +++ /dev/null @@ -1 +0,0 @@ -import{k as t,l as S,m as h,q,S as T}from"./BBD-8XME.js";function k(r,i){return r===i||(r==null?void 0:r[T])===i}function A(r={},i,a,c){return t(()=>{var f,s;return S(()=>{f=s,s=[],h(()=>{r!==a(...s)&&(i(r,...s),f&&k(a(...f),r)&&i(null,...f))})}),()=>{q(()=>{s&&k(a(...s),r)&&i(null,...s)})}}),r}export{A as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.br b/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.br deleted file mode 100644 index 6dbfbe3..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.br +++ /dev/null @@ -1,2 +0,0 @@ -7 ,o*̾XK*QIk8*oc}CK!4 -nhشۈU7խ׼F@ 3r6JAF͑Q-3,vaA߉ PYkV(Fئ~HyFI$hGD@Z6Hv4<FrZATN-z -: \ No newline at end of file diff --git a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.gz b/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.gz deleted file mode 100644 index bc7dfd2..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/DtXypsxD.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js new file mode 100644 index 0000000..f470a9d --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js @@ -0,0 +1 @@ +import{R as J,b8 as ee}from"./nyjtQ1Ok.js";import{w as ae}from"./DAj0p1rI.js";import{c as ne,H as N,N as B,r as mt,i as _t,b as L,s as C,p as x,n as ft,f as $t,g as ut,a as X,d as it,S as Nt,P as re,e as oe,h as se,o as Dt,j as q,k as ie,l as qt,m as ce,q as le,t as Kt,u as Pt,v as fe}from"./urMNLRPv.js";class wt{constructor(a,e){this.status=a,typeof e=="string"?this.body={message:e}:e?this.body=e:this.body={message:`Error: ${a}`}}toString(){return JSON.stringify(this.body)}}class vt{constructor(a,e){this.status=a,this.location=e}}class yt extends Error{constructor(a,e,r){super(r),this.status=a,this.text=e}}const ue=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function he(t){const a=[];return{pattern:t==="/"?/^\/$/:new RegExp(`^${pe(t).map(r=>{const n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(r);if(n)return a.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const o=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(r);if(o)return a.push({name:o[1],matcher:o[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!r)return;const s=r.split(/\[(.+?)\](?!\])/);return"/"+s.map((c,l)=>{if(l%2){if(c.startsWith("x+"))return ct(String.fromCharCode(parseInt(c.slice(2),16)));if(c.startsWith("u+"))return ct(String.fromCharCode(...c.slice(2).split("-").map(_=>parseInt(_,16))));const h=ue.exec(c),[,u,w,f,d]=h;return a.push({name:f,matcher:d,optional:!!u,rest:!!w,chained:w?l===1&&s[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return ct(c)}).join("")}).join("")}/?$`),params:a}}function de(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function pe(t){return t.slice(1).split("/").filter(de)}function ge(t,a,e){const r={},n=t.slice(1),o=n.filter(i=>i!==void 0);let s=0;for(let i=0;ih).join("/"),s=0),l===void 0)if(c.rest)l="";else continue;if(!c.matcher||e[c.matcher](l)){r[c.name]=l;const h=a[i+1],u=n[i+1];h&&!h.rest&&h.optional&&u&&c.chained&&(s=0),!h&&!u&&Object.keys(r).length===o.length&&(s=0);continue}if(c.optional&&c.chained){s++;continue}return}if(!s)return r}function ct(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function me({nodes:t,server_loads:a,dictionary:e,matchers:r}){const n=new Set(a);return Object.entries(e).map(([i,[c,l,h]])=>{const{pattern:u,params:w}=he(i),f={id:i,exec:d=>{const _=u.exec(d);if(_)return ge(_,w,r)},errors:[1,...h||[]].map(d=>t[d]),layouts:[0,...l||[]].map(s),leaf:o(c)};return f.errors.length=f.layouts.length=Math.max(f.errors.length,f.layouts.length),f});function o(i){const c=i<0;return c&&(i=~i),[c,t[i]]}function s(i){return i===void 0?i:[n.has(i),t[i]]}}function Ft(t,a=JSON.parse){try{return a(sessionStorage[t])}catch{}}function It(t,a,e=JSON.stringify){const r=e(a);try{sessionStorage[t]=r}catch{}}function _e(t){return t.filter(a=>a!=null)}function Et(t){return t instanceof wt||t instanceof yt?t.status:500}function we(t){return t instanceof yt?t.text:"Internal Error"}const ve=new Set(["icon","shortcut icon","apple-touch-icon"]),I=Ft(Kt)??{},M=Ft(qt)??{},P={url:Pt({}),page:Pt({}),navigating:ae(null),updated:ne()};function bt(t){I[t]=C()}function ye(t,a){let e=t+1;for(;I[e];)delete I[e],e+=1;for(e=a+1;M[e];)delete M[e],e+=1}function V(t,a=!1){return a?location.replace(t.href):location.href=t.href,new Promise(()=>{})}async function Bt(){if("serviceWorker"in navigator){const t=await navigator.serviceWorker.getRegistration(L||"/");t&&await t.update()}}function Tt(){}let kt,ht,Q,U,dt,b;const Z=[],tt=[];let v=null;function pt(){var t;(t=v==null?void 0:v.fork)==null||t.then(a=>a==null?void 0:a.discard()),v=null}const G=new Map,Mt=new Set,Ee=new Set,F=new Set;let m={branch:[],error:null,url:null},Vt=!1,et=!1,Ot=!0,H=!1,K=!1,Ht=!1,St=!1,Yt,E,R,O;const at=new Set,Ct=new Map;async function Fe(t,a,e){var o,s,i,c,l;(o=globalThis.__sveltekit_1ysfr3o)!=null&&o.data&&globalThis.__sveltekit_1ysfr3o.data,document.URL!==location.href&&(location.href=location.href),b=t,await((i=(s=t.hooks).init)==null?void 0:i.call(s)),kt=me(t),U=document.documentElement,dt=a,ht=t.nodes[0],Q=t.nodes[1],ht(),Q(),E=(c=history.state)==null?void 0:c[N],R=(l=history.state)==null?void 0:l[B],E||(E=R=Date.now(),history.replaceState({...history.state,[N]:E,[B]:R},""));const r=I[E];function n(){r&&(history.scrollRestoration="manual",scrollTo(r.x,r.y))}e?(n(),await Ce(dt,e)):(await D({type:"enter",url:mt(b.hash?Ne(new URL(location.href)):location.href),replace_state:!0}),n()),Oe()}function be(){Z.length=0,St=!1}function zt(t){tt.some(a=>a==null?void 0:a.snapshot)&&(M[t]=tt.map(a=>{var e;return(e=a==null?void 0:a.snapshot)==null?void 0:e.capture()}))}function Wt(t){var a;(a=M[t])==null||a.forEach((e,r)=>{var n,o;(o=(n=tt[r])==null?void 0:n.snapshot)==null||o.restore(e)})}function jt(){bt(E),It(Kt,I),zt(R),It(qt,M)}async function Gt(t,a,e,r){let n;a.invalidateAll&&pt(),await D({type:"goto",url:mt(t),keepfocus:a.keepFocus,noscroll:a.noScroll,replace_state:a.replaceState,state:a.state,redirect_count:e,nav_token:r,accept:()=>{a.invalidateAll&&(St=!0,n=[...Ct.keys()]),a.invalidate&&a.invalidate.forEach(Te)}}),a.invalidateAll&&J().then(J).then(()=>{Ct.forEach(({resource:o},s)=>{var i;n!=null&&n.includes(s)&&((i=o.refresh)==null||i.call(o))})})}async function ke(t){if(t.id!==(v==null?void 0:v.id)){pt();const a={};at.add(a),v={id:t.id,token:a,promise:Xt({...t,preload:a}).then(e=>(at.delete(a),e.type==="loaded"&&e.state.error&&pt(),e)),fork:null}}return v.promise}async function lt(t){var e;const a=(e=await ot(t,!1))==null?void 0:e.route;a&&await Promise.all([...a.layouts,a.leaf].filter(Boolean).map(r=>r[1]()))}async function Jt(t,a,e){var n;m=t.state;const r=document.querySelector("style[data-sveltekit]");if(r&&r.remove(),Object.assign(x,t.props.page),Yt=new b.root({target:a,props:{...t.props,stores:P,components:tt},hydrate:e,sync:!1}),await Promise.resolve(),Wt(R),e){const o={from:null,to:{params:m.params,route:{id:((n=m.route)==null?void 0:n.id)??null},url:new URL(location.href),scroll:I[E]??C()},willUnload:!1,type:"enter",complete:Promise.resolve()};F.forEach(s=>s(o))}et=!0}function nt({url:t,params:a,branch:e,status:r,error:n,route:o,form:s}){let i="never";if(L&&(t.pathname===L||t.pathname===L+"/"))i="always";else for(const f of e)(f==null?void 0:f.slash)!==void 0&&(i=f.slash);t.pathname=se(t.pathname,i),t.search=t.search;const c={type:"loaded",state:{url:t,params:a,branch:e,error:n,route:o},props:{constructors:_e(e).map(f=>f.node.component),page:At(x)}};s!==void 0&&(c.props.form=s);let l={},h=!x,u=0;for(let f=0;fi(new URL(s))))return!0;return!1}function xt(t,a){return(t==null?void 0:t.type)==="data"?t:(t==null?void 0:t.type)==="skip"?a??null:null}function xe(t,a){if(!t)return new Set(a.searchParams.keys());const e=new Set([...t.searchParams.keys(),...a.searchParams.keys()]);for(const r of e){const n=t.searchParams.getAll(r),o=a.searchParams.getAll(r);n.every(s=>o.includes(s))&&o.every(s=>n.includes(s))&&e.delete(r)}return e}function Le({error:t,url:a,route:e,params:r}){return{type:"loaded",state:{error:t,url:a,route:e,params:r,branch:[]},props:{page:At(x),constructors:[]}}}async function Xt({id:t,invalidating:a,url:e,params:r,route:n,preload:o}){if((v==null?void 0:v.id)===t)return at.delete(v.token),v.promise;const{errors:s,layouts:i,leaf:c}=n,l=[...i,c];s.forEach(g=>g==null?void 0:g().catch(()=>{})),l.forEach(g=>g==null?void 0:g[1]().catch(()=>{}));const h=m.url?t!==rt(m.url):!1,u=m.route?n.id!==m.route.id:!1,w=xe(m.url,e);let f=!1;const d=l.map(async(g,p)=>{var A;if(!g)return;const y=m.branch[p];return g[1]===(y==null?void 0:y.loader)&&!Re(f,u,h,w,(A=y.universal)==null?void 0:A.uses,r)?y:(f=!0,Rt({loader:g[1],url:e,params:r,route:n,parent:async()=>{var z;const T={};for(let j=0;j{});const _=[];for(let g=0;gPromise.resolve({}),server_data_node:xt(o)}),i={node:await Q(),loader:Q,universal:null,server:null,data:null};return nt({url:e,params:n,branch:[s,i],status:t,error:a,route:null})}catch(s){if(s instanceof vt)return Gt(new URL(s.location,location.href),{},0);throw s}}async function Ae(t){const a=t.href;if(G.has(a))return G.get(a);let e;try{const r=(async()=>{let n=await b.hooks.reroute({url:new URL(t),fetch:async(o,s)=>Se(o,s,t).promise})??t;if(typeof n=="string"){const o=new URL(t);b.hash?o.hash=n:o.pathname=n,n=o}return n})();G.set(a,r),e=await r}catch{G.delete(a);return}return e}async function ot(t,a){if(t&&!_t(t,L,b.hash)){const e=await Ae(t);if(!e)return;const r=Pe(e);for(const n of kt){const o=n.exec(r);if(o)return{id:rt(t),invalidating:a,route:n,params:oe(o),url:t}}}}function Pe(t){return ie(b.hash?t.hash.replace(/^#/,"").replace(/[?#].+/,""):t.pathname.slice(L.length))||"/"}function rt(t){return(b.hash?t.hash.replace(/^#/,""):t.pathname)+t.search}function Qt({url:t,type:a,intent:e,delta:r,event:n,scroll:o}){let s=!1;const i=Ut(m,e,t,a,o??null);r!==void 0&&(i.navigation.delta=r),n!==void 0&&(i.navigation.event=n);const c={...i.navigation,cancel:()=>{s=!0,i.reject(new Error("navigation cancelled"))}};return H||Mt.forEach(l=>l(c)),s?null:i}async function D({type:t,url:a,popped:e,keepfocus:r,noscroll:n,replace_state:o,state:s={},redirect_count:i=0,nav_token:c={},accept:l=Tt,block:h=Tt,event:u}){var j;const w=O;O=c;const f=await ot(a,!1),d=t==="enter"?Ut(m,f,a,t):Qt({url:a,type:t,delta:e==null?void 0:e.delta,intent:f,scroll:e==null?void 0:e.scroll,event:u});if(!d){h(),O===c&&(O=w);return}const _=E,g=R;l(),H=!0,et&&d.navigation.type!=="enter"&&P.navigating.set(ft.current=d.navigation);let p=f&&await Xt(f);if(!p){if(_t(a,L,b.hash))return await V(a,o);p=await Zt(a,{id:null},await Y(new yt(404,"Not Found",`Not found: ${a.pathname}`),{url:a,params:{},route:{id:null}}),404,o)}if(a=(f==null?void 0:f.url)||a,O!==c)return d.reject(new Error("navigation aborted")),!1;if(p.type==="redirect"){if(i<20){await D({type:t,url:new URL(p.location,a),popped:e,keepfocus:r,noscroll:n,replace_state:o,state:s,redirect_count:i+1,nav_token:c}),d.fulfil(void 0);return}p=await Lt({status:500,error:await Y(new Error("Redirect loop"),{url:a,params:{},route:{id:null}}),url:a,route:{id:null}})}else p.props.page.status>=400&&await P.updated.check()&&(await Bt(),await V(a,o));if(be(),bt(_),zt(g),p.props.page.url.pathname!==a.pathname&&(a.pathname=p.props.page.url.pathname),s=e?e.state:s,!e){const k=o?0:1,W={[N]:E+=k,[B]:R+=k,[Nt]:s};(o?history.replaceState:history.pushState).call(history,W,"",a),o||ye(E,R)}const y=f&&(v==null?void 0:v.id)===f.id?v.fork:null;v=null,p.props.page.state=s;let S;if(et){const k=(await Promise.all(Array.from(Ee,$=>$(d.navigation)))).filter($=>typeof $=="function");if(k.length>0){let $=function(){k.forEach(st=>{F.delete(st)})};k.push($),k.forEach(st=>{F.add(st)})}m=p.state,p.props.page&&(p.props.page.url=a);const W=y&&await y;W?S=W.commit():(Yt.$set(p.props),fe(p.props.page),S=(j=ee)==null?void 0:j()),Ht=!0}else await Jt(p,dt,!1);const{activeElement:A}=document;await S,await J(),await J();let T=null;if(Ot){const k=e?e.scroll:n?C():null;k?scrollTo(k.x,k.y):(T=a.hash&&document.getElementById(te(a)))?T.scrollIntoView():scrollTo(0,0)}const z=document.activeElement!==A&&document.activeElement!==document.body;!r&&!z&&$e(a,!T),Ot=!0,p.props.page&&Object.assign(x,p.props.page),H=!1,t==="popstate"&&Wt(R),d.fulfil(void 0),d.navigation.to&&(d.navigation.to.scroll=C()),F.forEach(k=>k(d.navigation)),P.navigating.set(ft.current=null)}async function Zt(t,a,e,r,n){return t.origin===Dt&&t.pathname===location.pathname&&!Vt?await Lt({status:r,error:e,url:t,route:a}):await V(t,n)}function Ie(){let t,a={element:void 0,href:void 0},e;U.addEventListener("mousemove",i=>{const c=i.target;clearTimeout(t),t=setTimeout(()=>{o(c,q.hover)},20)});function r(i){i.defaultPrevented||o(i.composedPath()[0],q.tap)}U.addEventListener("mousedown",r),U.addEventListener("touchstart",r,{passive:!0});const n=new IntersectionObserver(i=>{for(const c of i)c.isIntersecting&&(lt(new URL(c.target.href)),n.unobserve(c.target))},{threshold:0});async function o(i,c){const l=$t(i,U),h=l===a.element&&(l==null?void 0:l.href)===a.href&&c>=e;if(!l||h)return;const{url:u,external:w,download:f}=ut(l,L,b.hash);if(w||f)return;const d=X(l),_=u&&rt(m.url)===rt(u);if(!(d.reload||_))if(c<=d.preload_data){a={element:l,href:l.href},e=q.tap;const g=await ot(u,!1);if(!g)return;ke(g)}else c<=d.preload_code&&(a={element:l,href:l.href},e=c,lt(u))}function s(){n.disconnect();for(const i of U.querySelectorAll("a")){const{url:c,external:l,download:h}=ut(i,L,b.hash);if(l||h)continue;const u=X(i);u.reload||(u.preload_code===q.viewport&&n.observe(i),u.preload_code===q.eager&<(c))}}F.add(s),s()}function Y(t,a){if(t instanceof wt)return t.body;const e=Et(t),r=we(t);return b.hooks.handleError({error:t,event:a,status:e,message:r})??{message:r}}function Be(t,a={}){return t=new URL(mt(t)),t.origin!==Dt?Promise.reject(new Error("goto: invalid URL")):Gt(t,a,0)}function Te(t){if(typeof t=="function")Z.push(t);else{const{href:a}=new URL(t,location.href);Z.push(e=>e.href===a)}}function Oe(){var a;history.scrollRestoration="manual",addEventListener("beforeunload",e=>{let r=!1;if(jt(),!H){const n=Ut(m,void 0,null,"leave"),o={...n.navigation,cancel:()=>{r=!0,n.reject(new Error("navigation cancelled"))}};Mt.forEach(s=>s(o))}r?(e.preventDefault(),e.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&jt()}),(a=navigator.connection)!=null&&a.saveData||Ie(),U.addEventListener("click",async e=>{if(e.button||e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.defaultPrevented)return;const r=$t(e.composedPath()[0],U);if(!r)return;const{url:n,external:o,target:s,download:i}=ut(r,L,b.hash);if(!n)return;if(s==="_parent"||s==="_top"){if(window.parent!==window)return}else if(s&&s!=="_self")return;const c=X(r);if(!(r instanceof SVGAElement)&&n.protocol!==location.protocol&&!(n.protocol==="https:"||n.protocol==="http:")||i)return;const[h,u]=(b.hash?n.hash.replace(/^#/,""):n.href).split("#"),w=h===it(location);if(o||c.reload&&(!w||!u)){Qt({url:n,type:"link",event:e})?H=!0:e.preventDefault();return}if(u!==void 0&&w){const[,f]=m.url.href.split("#");if(f===u){if(e.preventDefault(),u===""||u==="top"&&r.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const d=r.ownerDocument.getElementById(decodeURIComponent(u));d&&(d.scrollIntoView(),d.focus())}return}if(K=!0,bt(E),t(n),!c.replace_state)return;K=!1}e.preventDefault(),await new Promise(f=>{requestAnimationFrame(()=>{setTimeout(f,0)}),setTimeout(f,100)}),await D({type:"link",url:n,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??n.href===location.href,event:e})}),U.addEventListener("submit",e=>{if(e.defaultPrevented)return;const r=HTMLFormElement.prototype.cloneNode.call(e.target),n=e.submitter;if(((n==null?void 0:n.formTarget)||r.target)==="_blank"||((n==null?void 0:n.formMethod)||r.method)!=="get")return;const i=new URL((n==null?void 0:n.hasAttribute("formaction"))&&(n==null?void 0:n.formAction)||r.action);if(_t(i,L,!1))return;const c=e.target,l=X(c);if(l.reload)return;e.preventDefault(),e.stopPropagation();const h=new FormData(c,n);i.search=new URLSearchParams(h).toString(),D({type:"form",url:i,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??i.href===location.href,event:e})}),addEventListener("popstate",async e=>{var r;if(!gt){if((r=e.state)!=null&&r[N]){const n=e.state[N];if(O={},n===E)return;const o=I[n],s=e.state[Nt]??{},i=new URL(e.state[re]??location.href),c=e.state[B],l=m.url?it(location)===it(m.url):!1;if(c===R&&(Ht||l)){s!==x.state&&(x.state=s),t(i),I[E]=C(),o&&scrollTo(o.x,o.y),E=n;return}const u=n-E;await D({type:"popstate",url:i,popped:{state:s,scroll:o,delta:u},accept:()=>{E=n,R=c},block:()=>{history.go(-u)},nav_token:O,event:e})}else if(!K){const n=new URL(location.href);t(n),b.hash&&location.reload()}}}),addEventListener("hashchange",()=>{K&&(K=!1,history.replaceState({...history.state,[N]:++E,[B]:R},"",location.href))});for(const e of document.querySelectorAll("link"))ve.has(e.rel)&&(e.href=e.href);addEventListener("pageshow",e=>{e.persisted&&P.navigating.set(ft.current=null)});function t(e){m.url=x.url=e,P.page.set(At(x)),P.page.notify()}}async function Ce(t,{status:a=200,error:e,node_ids:r,params:n,route:o,server_route:s,data:i,form:c}){Vt=!0;const l=new URL(location.href);let h;({params:n={},route:o={id:null}}=await ot(l,!1)||{}),h=kt.find(({id:f})=>f===o.id);let u,w=!0;try{const f=r.map(async(_,g)=>{const p=i[g];return p!=null&&p.uses&&(p.uses=je(p.uses)),Rt({loader:b.nodes[_],url:l,params:n,route:o,parent:async()=>{const y={};for(let S=0;S{const i=history.state;gt=!0,location.replace(new URL(`#${r}`,location.href)),history.replaceState(i,"",t),a&&scrollTo(o,s),gt=!1})}else{const o=document.body,s=o.getAttribute("tabindex");o.tabIndex=-1,o.focus({preventScroll:!0,focusVisible:!1}),s!==null?o.setAttribute("tabindex",s):o.removeAttribute("tabindex")}const n=getSelection();if(n&&n.type!=="None"){const o=[];for(let s=0;s{if(n.rangeCount===o.length){for(let s=0;s{o=u,s=w});return i.catch(()=>{}),{navigation:{from:{params:t.params,route:{id:((l=t.route)==null?void 0:l.id)??null},url:t.url,scroll:C()},to:e&&{params:(a==null?void 0:a.params)??null,route:{id:((h=a==null?void 0:a.route)==null?void 0:h.id)??null},url:e,scroll:n},willUnload:!a,type:r,complete:i},fulfil:o,reject:s}}function At(t){return{data:t.data,error:t.error,form:t.form,params:t.params,route:t.route,state:t.state,status:t.status,url:t.url}}function Ne(t){const a=new URL(t);return a.hash=decodeURIComponent(t.hash),a}function te(t){let a;if(b.hash){const[,,e]=t.hash.split("#",3);a=e??""}else a=t.hash.slice(1);return decodeURIComponent(a)}export{Fe as a,Be as g,P as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.br b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.br new file mode 100644 index 0000000..a1159bf Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.gz b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.gz new file mode 100644 index 0000000..d290fcc Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/DwA4GIGc.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js new file mode 100644 index 0000000..757785f --- /dev/null +++ b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js @@ -0,0 +1 @@ +import{Q as s,y as o,a0 as c,a4 as b,a5 as m,a6 as h,U as v,V as y}from"./nyjtQ1Ok.js";function _(e,r,f=!1){if(e.multiple){if(r==null)return;if(!b(r))return m();for(var a of e.options)a.selected=r.includes(i(a));return}for(a of e.options){var t=i(a);if(h(t,r)){a.selected=!0;return}}(!f||r!==void 0)&&(e.selectedIndex=-1)}function q(e){var r=new MutationObserver(()=>{_(e,e.__value)});r.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),c(()=>{r.disconnect()})}function p(e,r,f=r){var a=new WeakSet,t=!0;s(e,"change",u=>{var l=u?"[selected]":":checked",n;if(e.multiple)n=[].map.call(e.querySelectorAll(l),i);else{var d=e.querySelector(l)??e.querySelector("option:not([disabled])");n=d&&i(d)}f(n),v!==null&&a.add(v)}),o(()=>{var u=r();if(e===document.activeElement){var l=y??v;if(a.has(l))return}if(_(e,u,t),t&&u===void 0){var n=e.querySelector(":checked");n!==null&&(u=i(n),f(u))}e.__value=u,t=!1}),q(e)}function i(e){return"__value"in e?e.__value:e.value}export{p as b}; diff --git a/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.br b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.br new file mode 100644 index 0000000..5713609 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.gz b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.gz new file mode 100644 index 0000000..11aba1f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/J2LZW-kP.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js b/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js deleted file mode 100644 index 7cac585..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js +++ /dev/null @@ -1 +0,0 @@ -import{b as T,J as o,a0 as b,E as h,a1 as p,a2 as A,a3 as E,a4 as R,a5 as g,a6 as l}from"./BBD-8XME.js";import{B as v}from"./gqVpgJ8U.js";function S(t,u,_=!1){o&&b();var n=new v(t),c=_?h:0;function i(a,r){if(o){const e=p(t);var s;if(e===A?s=0:e===E?s=!1:s=parseInt(e.substring(1)),a!==s){var f=R();g(f),n.anchor=f,l(!1),n.ensure(a,r),l(!0);return}}n.ensure(a,r)}T(()=>{var a=!1;u((r,s=0)=>{a=!0,i(s,r)}),a||i(!1,null)},c)}export{S as i}; diff --git a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.br b/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.br deleted file mode 100644 index 3beee39..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.gz b/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.gz deleted file mode 100644 index 51ba4d8..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/RaRNNC-y.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js b/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js deleted file mode 100644 index cbeecd4..0000000 --- a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js +++ /dev/null @@ -1 +0,0 @@ -import{I as J,b8 as ee}from"./BBD-8XME.js";import{w as ae}from"./Br8WXJxx.js";import{c as ne,H as N,N as B,r as gt,i as _t,b as L,s as j,p as x,n as ft,f as $t,g as ut,a as X,d as it,S as Nt,P as re,e as oe,h as se,o as Dt,j as q,k as ie,l as qt,m as ce,q as le,t as Kt,u as Pt,v as fe}from"./BeSd-T80.js";class wt{constructor(a,e){this.status=a,typeof e=="string"?this.body={message:e}:e?this.body=e:this.body={message:`Error: ${a}`}}toString(){return JSON.stringify(this.body)}}class vt{constructor(a,e){this.status=a,this.location=e}}class yt extends Error{constructor(a,e,r){super(r),this.status=a,this.text=e}}const ue=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function he(t){const a=[];return{pattern:t==="/"?/^\/$/:new RegExp(`^${pe(t).map(r=>{const n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(r);if(n)return a.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const o=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(r);if(o)return a.push({name:o[1],matcher:o[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!r)return;const s=r.split(/\[(.+?)\](?!\])/);return"/"+s.map((c,l)=>{if(l%2){if(c.startsWith("x+"))return ct(String.fromCharCode(parseInt(c.slice(2),16)));if(c.startsWith("u+"))return ct(String.fromCharCode(...c.slice(2).split("-").map(_=>parseInt(_,16))));const h=ue.exec(c),[,u,w,f,d]=h;return a.push({name:f,matcher:d,optional:!!u,rest:!!w,chained:w?l===1&&s[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return ct(c)}).join("")}).join("")}/?$`),params:a}}function de(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function pe(t){return t.slice(1).split("/").filter(de)}function me(t,a,e){const r={},n=t.slice(1),o=n.filter(i=>i!==void 0);let s=0;for(let i=0;ih).join("/"),s=0),l===void 0)if(c.rest)l="";else continue;if(!c.matcher||e[c.matcher](l)){r[c.name]=l;const h=a[i+1],u=n[i+1];h&&!h.rest&&h.optional&&u&&c.chained&&(s=0),!h&&!u&&Object.keys(r).length===o.length&&(s=0);continue}if(c.optional&&c.chained){s++;continue}return}if(!s)return r}function ct(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function ge({nodes:t,server_loads:a,dictionary:e,matchers:r}){const n=new Set(a);return Object.entries(e).map(([i,[c,l,h]])=>{const{pattern:u,params:w}=he(i),f={id:i,exec:d=>{const _=u.exec(d);if(_)return me(_,w,r)},errors:[1,...h||[]].map(d=>t[d]),layouts:[0,...l||[]].map(s),leaf:o(c)};return f.errors.length=f.layouts.length=Math.max(f.errors.length,f.layouts.length),f});function o(i){const c=i<0;return c&&(i=~i),[c,t[i]]}function s(i){return i===void 0?i:[n.has(i),t[i]]}}function Ft(t,a=JSON.parse){try{return a(sessionStorage[t])}catch{}}function It(t,a,e=JSON.stringify){const r=e(a);try{sessionStorage[t]=r}catch{}}function _e(t){return t.filter(a=>a!=null)}function Et(t){return t instanceof wt||t instanceof yt?t.status:500}function we(t){return t instanceof yt?t.text:"Internal Error"}const ve=new Set(["icon","shortcut icon","apple-touch-icon"]),I=Ft(Kt)??{},M=Ft(qt)??{},P={url:Pt({}),page:Pt({}),navigating:ae(null),updated:ne()};function bt(t){I[t]=j()}function ye(t,a){let e=t+1;for(;I[e];)delete I[e],e+=1;for(e=a+1;M[e];)delete M[e],e+=1}function V(t,a=!1){return a?location.replace(t.href):location.href=t.href,new Promise(()=>{})}async function Bt(){if("serviceWorker"in navigator){const t=await navigator.serviceWorker.getRegistration(L||"/");t&&await t.update()}}function Tt(){}let kt,ht,Q,U,dt,b;const Z=[],tt=[];let v=null;function pt(){var t;(t=v==null?void 0:v.fork)==null||t.then(a=>a==null?void 0:a.discard()),v=null}const G=new Map,Mt=new Set,Ee=new Set,F=new Set;let g={branch:[],error:null,url:null},Vt=!1,et=!1,Ot=!0,H=!1,K=!1,Ht=!1,St=!1,Yt,E,R,O;const at=new Set,jt=new Map;async function Fe(t,a,e){var o,s,i,c,l;(o=globalThis.__sveltekit_6jo0pm)!=null&&o.data&&globalThis.__sveltekit_6jo0pm.data,document.URL!==location.href&&(location.href=location.href),b=t,await((i=(s=t.hooks).init)==null?void 0:i.call(s)),kt=ge(t),U=document.documentElement,dt=a,ht=t.nodes[0],Q=t.nodes[1],ht(),Q(),E=(c=history.state)==null?void 0:c[N],R=(l=history.state)==null?void 0:l[B],E||(E=R=Date.now(),history.replaceState({...history.state,[N]:E,[B]:R},""));const r=I[E];function n(){r&&(history.scrollRestoration="manual",scrollTo(r.x,r.y))}e?(n(),await je(dt,e)):(await D({type:"enter",url:gt(b.hash?Ne(new URL(location.href)):location.href),replace_state:!0}),n()),Oe()}function be(){Z.length=0,St=!1}function zt(t){tt.some(a=>a==null?void 0:a.snapshot)&&(M[t]=tt.map(a=>{var e;return(e=a==null?void 0:a.snapshot)==null?void 0:e.capture()}))}function Wt(t){var a;(a=M[t])==null||a.forEach((e,r)=>{var n,o;(o=(n=tt[r])==null?void 0:n.snapshot)==null||o.restore(e)})}function Ct(){bt(E),It(Kt,I),zt(R),It(qt,M)}async function Gt(t,a,e,r){let n;a.invalidateAll&&pt(),await D({type:"goto",url:gt(t),keepfocus:a.keepFocus,noscroll:a.noScroll,replace_state:a.replaceState,state:a.state,redirect_count:e,nav_token:r,accept:()=>{a.invalidateAll&&(St=!0,n=[...jt.keys()]),a.invalidate&&a.invalidate.forEach(Te)}}),a.invalidateAll&&J().then(J).then(()=>{jt.forEach(({resource:o},s)=>{var i;n!=null&&n.includes(s)&&((i=o.refresh)==null||i.call(o))})})}async function ke(t){if(t.id!==(v==null?void 0:v.id)){pt();const a={};at.add(a),v={id:t.id,token:a,promise:Xt({...t,preload:a}).then(e=>(at.delete(a),e.type==="loaded"&&e.state.error&&pt(),e)),fork:null}}return v.promise}async function lt(t){var e;const a=(e=await ot(t,!1))==null?void 0:e.route;a&&await Promise.all([...a.layouts,a.leaf].filter(Boolean).map(r=>r[1]()))}async function Jt(t,a,e){var n;g=t.state;const r=document.querySelector("style[data-sveltekit]");if(r&&r.remove(),Object.assign(x,t.props.page),Yt=new b.root({target:a,props:{...t.props,stores:P,components:tt},hydrate:e,sync:!1}),await Promise.resolve(),Wt(R),e){const o={from:null,to:{params:g.params,route:{id:((n=g.route)==null?void 0:n.id)??null},url:new URL(location.href),scroll:I[E]??j()},willUnload:!1,type:"enter",complete:Promise.resolve()};F.forEach(s=>s(o))}et=!0}function nt({url:t,params:a,branch:e,status:r,error:n,route:o,form:s}){let i="never";if(L&&(t.pathname===L||t.pathname===L+"/"))i="always";else for(const f of e)(f==null?void 0:f.slash)!==void 0&&(i=f.slash);t.pathname=se(t.pathname,i),t.search=t.search;const c={type:"loaded",state:{url:t,params:a,branch:e,error:n,route:o},props:{constructors:_e(e).map(f=>f.node.component),page:At(x)}};s!==void 0&&(c.props.form=s);let l={},h=!x,u=0;for(let f=0;fi(new URL(s))))return!0;return!1}function xt(t,a){return(t==null?void 0:t.type)==="data"?t:(t==null?void 0:t.type)==="skip"?a??null:null}function xe(t,a){if(!t)return new Set(a.searchParams.keys());const e=new Set([...t.searchParams.keys(),...a.searchParams.keys()]);for(const r of e){const n=t.searchParams.getAll(r),o=a.searchParams.getAll(r);n.every(s=>o.includes(s))&&o.every(s=>n.includes(s))&&e.delete(r)}return e}function Le({error:t,url:a,route:e,params:r}){return{type:"loaded",state:{error:t,url:a,route:e,params:r,branch:[]},props:{page:At(x),constructors:[]}}}async function Xt({id:t,invalidating:a,url:e,params:r,route:n,preload:o}){if((v==null?void 0:v.id)===t)return at.delete(v.token),v.promise;const{errors:s,layouts:i,leaf:c}=n,l=[...i,c];s.forEach(m=>m==null?void 0:m().catch(()=>{})),l.forEach(m=>m==null?void 0:m[1]().catch(()=>{}));const h=g.url?t!==rt(g.url):!1,u=g.route?n.id!==g.route.id:!1,w=xe(g.url,e);let f=!1;const d=l.map(async(m,p)=>{var A;if(!m)return;const y=g.branch[p];return m[1]===(y==null?void 0:y.loader)&&!Re(f,u,h,w,(A=y.universal)==null?void 0:A.uses,r)?y:(f=!0,Rt({loader:m[1],url:e,params:r,route:n,parent:async()=>{var z;const T={};for(let C=0;C{});const _=[];for(let m=0;mPromise.resolve({}),server_data_node:xt(o)}),i={node:await Q(),loader:Q,universal:null,server:null,data:null};return nt({url:e,params:n,branch:[s,i],status:t,error:a,route:null})}catch(s){if(s instanceof vt)return Gt(new URL(s.location,location.href),{},0);throw s}}async function Ae(t){const a=t.href;if(G.has(a))return G.get(a);let e;try{const r=(async()=>{let n=await b.hooks.reroute({url:new URL(t),fetch:async(o,s)=>Se(o,s,t).promise})??t;if(typeof n=="string"){const o=new URL(t);b.hash?o.hash=n:o.pathname=n,n=o}return n})();G.set(a,r),e=await r}catch{G.delete(a);return}return e}async function ot(t,a){if(t&&!_t(t,L,b.hash)){const e=await Ae(t);if(!e)return;const r=Pe(e);for(const n of kt){const o=n.exec(r);if(o)return{id:rt(t),invalidating:a,route:n,params:oe(o),url:t}}}}function Pe(t){return ie(b.hash?t.hash.replace(/^#/,"").replace(/[?#].+/,""):t.pathname.slice(L.length))||"/"}function rt(t){return(b.hash?t.hash.replace(/^#/,""):t.pathname)+t.search}function Qt({url:t,type:a,intent:e,delta:r,event:n,scroll:o}){let s=!1;const i=Ut(g,e,t,a,o??null);r!==void 0&&(i.navigation.delta=r),n!==void 0&&(i.navigation.event=n);const c={...i.navigation,cancel:()=>{s=!0,i.reject(new Error("navigation cancelled"))}};return H||Mt.forEach(l=>l(c)),s?null:i}async function D({type:t,url:a,popped:e,keepfocus:r,noscroll:n,replace_state:o,state:s={},redirect_count:i=0,nav_token:c={},accept:l=Tt,block:h=Tt,event:u}){var C;const w=O;O=c;const f=await ot(a,!1),d=t==="enter"?Ut(g,f,a,t):Qt({url:a,type:t,delta:e==null?void 0:e.delta,intent:f,scroll:e==null?void 0:e.scroll,event:u});if(!d){h(),O===c&&(O=w);return}const _=E,m=R;l(),H=!0,et&&d.navigation.type!=="enter"&&P.navigating.set(ft.current=d.navigation);let p=f&&await Xt(f);if(!p){if(_t(a,L,b.hash))return await V(a,o);p=await Zt(a,{id:null},await Y(new yt(404,"Not Found",`Not found: ${a.pathname}`),{url:a,params:{},route:{id:null}}),404,o)}if(a=(f==null?void 0:f.url)||a,O!==c)return d.reject(new Error("navigation aborted")),!1;if(p.type==="redirect"){if(i<20){await D({type:t,url:new URL(p.location,a),popped:e,keepfocus:r,noscroll:n,replace_state:o,state:s,redirect_count:i+1,nav_token:c}),d.fulfil(void 0);return}p=await Lt({status:500,error:await Y(new Error("Redirect loop"),{url:a,params:{},route:{id:null}}),url:a,route:{id:null}})}else p.props.page.status>=400&&await P.updated.check()&&(await Bt(),await V(a,o));if(be(),bt(_),zt(m),p.props.page.url.pathname!==a.pathname&&(a.pathname=p.props.page.url.pathname),s=e?e.state:s,!e){const k=o?0:1,W={[N]:E+=k,[B]:R+=k,[Nt]:s};(o?history.replaceState:history.pushState).call(history,W,"",a),o||ye(E,R)}const y=f&&(v==null?void 0:v.id)===f.id?v.fork:null;v=null,p.props.page.state=s;let S;if(et){const k=(await Promise.all(Array.from(Ee,$=>$(d.navigation)))).filter($=>typeof $=="function");if(k.length>0){let $=function(){k.forEach(st=>{F.delete(st)})};k.push($),k.forEach(st=>{F.add(st)})}g=p.state,p.props.page&&(p.props.page.url=a);const W=y&&await y;W?S=W.commit():(Yt.$set(p.props),fe(p.props.page),S=(C=ee)==null?void 0:C()),Ht=!0}else await Jt(p,dt,!1);const{activeElement:A}=document;await S,await J(),await J();let T=null;if(Ot){const k=e?e.scroll:n?j():null;k?scrollTo(k.x,k.y):(T=a.hash&&document.getElementById(te(a)))?T.scrollIntoView():scrollTo(0,0)}const z=document.activeElement!==A&&document.activeElement!==document.body;!r&&!z&&$e(a,!T),Ot=!0,p.props.page&&Object.assign(x,p.props.page),H=!1,t==="popstate"&&Wt(R),d.fulfil(void 0),d.navigation.to&&(d.navigation.to.scroll=j()),F.forEach(k=>k(d.navigation)),P.navigating.set(ft.current=null)}async function Zt(t,a,e,r,n){return t.origin===Dt&&t.pathname===location.pathname&&!Vt?await Lt({status:r,error:e,url:t,route:a}):await V(t,n)}function Ie(){let t,a={element:void 0,href:void 0},e;U.addEventListener("mousemove",i=>{const c=i.target;clearTimeout(t),t=setTimeout(()=>{o(c,q.hover)},20)});function r(i){i.defaultPrevented||o(i.composedPath()[0],q.tap)}U.addEventListener("mousedown",r),U.addEventListener("touchstart",r,{passive:!0});const n=new IntersectionObserver(i=>{for(const c of i)c.isIntersecting&&(lt(new URL(c.target.href)),n.unobserve(c.target))},{threshold:0});async function o(i,c){const l=$t(i,U),h=l===a.element&&(l==null?void 0:l.href)===a.href&&c>=e;if(!l||h)return;const{url:u,external:w,download:f}=ut(l,L,b.hash);if(w||f)return;const d=X(l),_=u&&rt(g.url)===rt(u);if(!(d.reload||_))if(c<=d.preload_data){a={element:l,href:l.href},e=q.tap;const m=await ot(u,!1);if(!m)return;ke(m)}else c<=d.preload_code&&(a={element:l,href:l.href},e=c,lt(u))}function s(){n.disconnect();for(const i of U.querySelectorAll("a")){const{url:c,external:l,download:h}=ut(i,L,b.hash);if(l||h)continue;const u=X(i);u.reload||(u.preload_code===q.viewport&&n.observe(i),u.preload_code===q.eager&<(c))}}F.add(s),s()}function Y(t,a){if(t instanceof wt)return t.body;const e=Et(t),r=we(t);return b.hooks.handleError({error:t,event:a,status:e,message:r})??{message:r}}function Be(t,a={}){return t=new URL(gt(t)),t.origin!==Dt?Promise.reject(new Error("goto: invalid URL")):Gt(t,a,0)}function Te(t){if(typeof t=="function")Z.push(t);else{const{href:a}=new URL(t,location.href);Z.push(e=>e.href===a)}}function Oe(){var a;history.scrollRestoration="manual",addEventListener("beforeunload",e=>{let r=!1;if(Ct(),!H){const n=Ut(g,void 0,null,"leave"),o={...n.navigation,cancel:()=>{r=!0,n.reject(new Error("navigation cancelled"))}};Mt.forEach(s=>s(o))}r?(e.preventDefault(),e.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&Ct()}),(a=navigator.connection)!=null&&a.saveData||Ie(),U.addEventListener("click",async e=>{if(e.button||e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.defaultPrevented)return;const r=$t(e.composedPath()[0],U);if(!r)return;const{url:n,external:o,target:s,download:i}=ut(r,L,b.hash);if(!n)return;if(s==="_parent"||s==="_top"){if(window.parent!==window)return}else if(s&&s!=="_self")return;const c=X(r);if(!(r instanceof SVGAElement)&&n.protocol!==location.protocol&&!(n.protocol==="https:"||n.protocol==="http:")||i)return;const[h,u]=(b.hash?n.hash.replace(/^#/,""):n.href).split("#"),w=h===it(location);if(o||c.reload&&(!w||!u)){Qt({url:n,type:"link",event:e})?H=!0:e.preventDefault();return}if(u!==void 0&&w){const[,f]=g.url.href.split("#");if(f===u){if(e.preventDefault(),u===""||u==="top"&&r.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const d=r.ownerDocument.getElementById(decodeURIComponent(u));d&&(d.scrollIntoView(),d.focus())}return}if(K=!0,bt(E),t(n),!c.replace_state)return;K=!1}e.preventDefault(),await new Promise(f=>{requestAnimationFrame(()=>{setTimeout(f,0)}),setTimeout(f,100)}),await D({type:"link",url:n,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??n.href===location.href,event:e})}),U.addEventListener("submit",e=>{if(e.defaultPrevented)return;const r=HTMLFormElement.prototype.cloneNode.call(e.target),n=e.submitter;if(((n==null?void 0:n.formTarget)||r.target)==="_blank"||((n==null?void 0:n.formMethod)||r.method)!=="get")return;const i=new URL((n==null?void 0:n.hasAttribute("formaction"))&&(n==null?void 0:n.formAction)||r.action);if(_t(i,L,!1))return;const c=e.target,l=X(c);if(l.reload)return;e.preventDefault(),e.stopPropagation();const h=new FormData(c,n);i.search=new URLSearchParams(h).toString(),D({type:"form",url:i,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??i.href===location.href,event:e})}),addEventListener("popstate",async e=>{var r;if(!mt){if((r=e.state)!=null&&r[N]){const n=e.state[N];if(O={},n===E)return;const o=I[n],s=e.state[Nt]??{},i=new URL(e.state[re]??location.href),c=e.state[B],l=g.url?it(location)===it(g.url):!1;if(c===R&&(Ht||l)){s!==x.state&&(x.state=s),t(i),I[E]=j(),o&&scrollTo(o.x,o.y),E=n;return}const u=n-E;await D({type:"popstate",url:i,popped:{state:s,scroll:o,delta:u},accept:()=>{E=n,R=c},block:()=>{history.go(-u)},nav_token:O,event:e})}else if(!K){const n=new URL(location.href);t(n),b.hash&&location.reload()}}}),addEventListener("hashchange",()=>{K&&(K=!1,history.replaceState({...history.state,[N]:++E,[B]:R},"",location.href))});for(const e of document.querySelectorAll("link"))ve.has(e.rel)&&(e.href=e.href);addEventListener("pageshow",e=>{e.persisted&&P.navigating.set(ft.current=null)});function t(e){g.url=x.url=e,P.page.set(At(x)),P.page.notify()}}async function je(t,{status:a=200,error:e,node_ids:r,params:n,route:o,server_route:s,data:i,form:c}){Vt=!0;const l=new URL(location.href);let h;({params:n={},route:o={id:null}}=await ot(l,!1)||{}),h=kt.find(({id:f})=>f===o.id);let u,w=!0;try{const f=r.map(async(_,m)=>{const p=i[m];return p!=null&&p.uses&&(p.uses=Ce(p.uses)),Rt({loader:b.nodes[_],url:l,params:n,route:o,parent:async()=>{const y={};for(let S=0;S{const i=history.state;mt=!0,location.replace(new URL(`#${r}`,location.href)),history.replaceState(i,"",t),a&&scrollTo(o,s),mt=!1})}else{const o=document.body,s=o.getAttribute("tabindex");o.tabIndex=-1,o.focus({preventScroll:!0,focusVisible:!1}),s!==null?o.setAttribute("tabindex",s):o.removeAttribute("tabindex")}const n=getSelection();if(n&&n.type!=="None"){const o=[];for(let s=0;s{if(n.rangeCount===o.length){for(let s=0;s{o=u,s=w});return i.catch(()=>{}),{navigation:{from:{params:t.params,route:{id:((l=t.route)==null?void 0:l.id)??null},url:t.url,scroll:j()},to:e&&{params:(a==null?void 0:a.params)??null,route:{id:((h=a==null?void 0:a.route)==null?void 0:h.id)??null},url:e,scroll:n},willUnload:!a,type:r,complete:i},fulfil:o,reject:s}}function At(t){return{data:t.data,error:t.error,form:t.form,params:t.params,route:t.route,state:t.state,status:t.status,url:t.url}}function Ne(t){const a=new URL(t);return a.hash=decodeURIComponent(t.hash),a}function te(t){let a;if(b.hash){const[,,e]=t.hash.split("#",3);a=e??""}else a=t.hash.slice(1);return decodeURIComponent(a)}export{Fe as a,Be as g,P as s}; diff --git a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.br b/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.br deleted file mode 100644 index a4b3fb9..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.gz b/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.gz deleted file mode 100644 index d5427a2..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/cIQD_rb4.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.br b/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.br deleted file mode 100644 index 33b0414..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.gz b/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.gz deleted file mode 100644 index d30defe..0000000 Binary files a/apps/dashboard/build/_app/immutable/chunks/gqVpgJ8U.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js b/apps/dashboard/build/_app/immutable/chunks/nyjtQ1Ok.js similarity index 95% rename from apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js rename to apps/dashboard/build/_app/immutable/chunks/nyjtQ1Ok.js index e2808a5..92e85dc 100644 --- a/apps/dashboard/build/_app/immutable/chunks/BBD-8XME.js +++ b/apps/dashboard/build/_app/immutable/chunks/nyjtQ1Ok.js @@ -1 +1 @@ -var cn=Object.defineProperty;var wt=e=>{throw TypeError(e)};var _n=(e,t,n)=>t in e?cn(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var de=(e,t,n)=>_n(e,typeof t!="symbol"?t+"":t,n),Ke=(e,t,n)=>t.has(e)||wt("Cannot "+n);var p=(e,t,n)=>(Ke(e,t,"read from private field"),n?n.call(e):t.get(e)),F=(e,t,n)=>t.has(e)?wt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),z=(e,t,n,r)=>(Ke(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n),K=(e,t,n)=>(Ke(e,t,"access private method"),n);var vn=Array.isArray,dn=Array.prototype.indexOf,Ee=Array.prototype.includes,ar=Array.from,lr=Object.defineProperty,Re=Object.getOwnPropertyDescriptor,pn=Object.getOwnPropertyDescriptors,hn=Object.prototype,wn=Array.prototype,kt=Object.getPrototypeOf,yt=Object.isExtensible;const yn=()=>{};function or(e){return e()}function En(e){for(var t=0;t{e=r,t=s});return{promise:n,resolve:e,reject:t}}function ur(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);const n=[];for(const r of e)if(n.push(r),n.length===t)break;return n}const A=2,De=4,Ie=8,Dt=1<<24,G=16,H=32,ve=64,mn=128,P=512,g=1024,R=2048,Y=4096,j=8192,$=16384,oe=32768,je=65536,Et=1<<17,It=1<<18,Pe=1<<19,Pt=1<<20,cr=1<<25,ue=65536,$e=1<<21,st=1<<22,Z=1<<23,ae=Symbol("$state"),_r=Symbol("legacy props"),vr=Symbol(""),ne=new class extends Error{constructor(){super(...arguments);de(this,"name","StaleReactionError");de(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var Nt;const pr=!!((Nt=globalThis.document)!=null&&Nt.contentType)&&globalThis.document.contentType.includes("xml"),Ue=3,Ct=8;function gn(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function hr(e,t,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Tn(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function bn(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function An(e){throw new Error("https://svelte.dev/e/effect_orphan")}function Sn(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function wr(){throw new Error("https://svelte.dev/e/hydration_failed")}function yr(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function Rn(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function On(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Nn(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Er(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const mr=1,gr=2,Tr=4,br=8,Ar=16,Sr=1,Rr=2,Or=4,Nr=8,kr=16,xr=1,Dr=2,kn="[",xn="[!",Ir="[?",Dn="]",ft={},T=Symbol(),In="http://www.w3.org/1999/xhtml";function it(e){console.warn("https://svelte.dev/e/hydration_mismatch")}function Pr(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Cr(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}let J=!1;function Fr(e){J=e}let m;function me(e){if(e===null)throw it(),ft;return m=e}function Mr(){return me(ee(m))}function Lr(e){if(J){if(ee(m)!==null)throw it(),ft;m=e}}function jr(e=1){if(J){for(var t=e,n=m;t--;)n=ee(n);m=n}}function Yr(e=!0){for(var t=0,n=m;;){if(n.nodeType===Ct){var r=n.data;if(r===Dn){if(t===0)return n;t-=1}else(r===kn||r===xn||r[0]==="["&&!isNaN(Number(r.slice(1))))&&(t+=1)}var s=ee(n);e&&n.remove(),n=s}}function Hr(e){if(!e||e.nodeType!==Ct)throw it(),ft;return e.data}function Ft(e){return e===this.v}function Pn(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function Mt(e){return!Pn(e,this.v)}let Be=!1;function qr(){Be=!0}let S=null;function Ye(e){S=e}function Vr(e,t=!1,n){S={p:S,i:!1,c:null,e:null,s:e,x:null,l:Be&&!t?{s:null,u:null,$:[]}:null}}function Ur(e){var t=S,n=t.e;if(n!==null){t.e=null;for(var r of n)Jt(r)}return t.i=!0,S=t.p,{}}function Ce(){return!Be||S!==null&&S.l===null}let re=[];function Lt(){var e=re;re=[],En(e)}function mt(e){if(re.length===0&&!Oe){var t=re;queueMicrotask(()=>{t===re&&Lt()})}re.push(e)}function Cn(){for(;re.length>0;)Lt()}function Fn(e){var t=w;if(t===null)return _.f|=Z,e;if((t.f&oe)===0&&(t.f&De)===0)throw e;He(e,t)}function He(e,t){for(;t!==null;){if((t.f&mn)!==0){if((t.f&oe)===0)throw e;try{t.b.error(e);return}catch(n){e=n}}t=t.parent}throw e}const Mn=-7169;function E(e,t){e.f=e.f&Mn|t}function at(e){(e.f&P)!==0||e.deps===null?E(e,g):E(e,Y)}function jt(e){if(e!==null)for(const t of e)(t.f&A)===0||(t.f&ue)===0||(t.f^=ue,jt(t.deps))}function Ln(e,t,n){(e.f&R)!==0?t.add(e):(e.f&Y)!==0&&n.add(e),jt(e.deps),E(e,g)}const Me=new Set;let d=null,gt=null,b=null,N=[],Ge=null,Ze=!1,Oe=!1;var pe,he,fe,we,ke,xe,ie,U,ye,D,We,Je,Qe,Yt;const dt=class dt{constructor(){F(this,D);de(this,"current",new Map);de(this,"previous",new Map);F(this,pe,new Set);F(this,he,new Set);F(this,fe,0);F(this,we,0);F(this,ke,null);F(this,xe,new Set);F(this,ie,new Set);F(this,U,new Map);de(this,"is_fork",!1);F(this,ye,!1)}skip_effect(t){p(this,U).has(t)||p(this,U).set(t,{d:[],m:[]})}unskip_effect(t){var n=p(this,U).get(t);if(n){p(this,U).delete(t);for(var r of n.d)E(r,R),B(r);for(r of n.m)E(r,Y),B(r)}}process(t){var s;N=[],this.apply();var n=[],r=[];for(const f of t)K(this,D,Je).call(this,f,n,r);if(K(this,D,We).call(this)){K(this,D,Qe).call(this,r),K(this,D,Qe).call(this,n);for(const[f,a]of p(this,U))Ut(f,a)}else{for(const f of p(this,pe))f();p(this,pe).clear(),p(this,fe)===0&&K(this,D,Yt).call(this),gt=this,d=null,Tt(r),Tt(n),gt=null,(s=p(this,ke))==null||s.resolve()}b=null}capture(t,n){n!==T&&!this.previous.has(t)&&this.previous.set(t,n),(t.f&Z)===0&&(this.current.set(t,t.v),b==null||b.set(t,t.v))}activate(){d=this,this.apply()}deactivate(){d===this&&(d=null,b=null)}flush(){if(this.activate(),N.length>0){if(Ht(),d!==null&&d!==this)return}else p(this,fe)===0&&this.process([]);this.deactivate()}discard(){for(const t of p(this,he))t(this);p(this,he).clear()}increment(t){z(this,fe,p(this,fe)+1),t&&z(this,we,p(this,we)+1)}decrement(t){z(this,fe,p(this,fe)-1),t&&z(this,we,p(this,we)-1),!p(this,ye)&&(z(this,ye,!0),mt(()=>{z(this,ye,!1),K(this,D,We).call(this)?N.length>0&&this.flush():this.revive()}))}revive(){for(const t of p(this,xe))p(this,ie).delete(t),E(t,R),B(t);for(const t of p(this,ie))E(t,Y),B(t);this.flush()}oncommit(t){p(this,pe).add(t)}ondiscard(t){p(this,he).add(t)}settled(){return(p(this,ke)??z(this,ke,xt())).promise}static ensure(){if(d===null){const t=d=new dt;Me.add(d),Oe||mt(()=>{d===t&&t.flush()})}return d}apply(){}};pe=new WeakMap,he=new WeakMap,fe=new WeakMap,we=new WeakMap,ke=new WeakMap,xe=new WeakMap,ie=new WeakMap,U=new WeakMap,ye=new WeakMap,D=new WeakSet,We=function(){return this.is_fork||p(this,we)>0},Je=function(t,n,r){t.f^=g;for(var s=t.first;s!==null;){var f=s.f,a=(f&(H|ve))!==0,l=a&&(f&g)!==0,i=l||(f&j)!==0||p(this,U).has(s);if(!i&&s.fn!==null){a?s.f^=g:(f&De)!==0?n.push(s):Fe(s)&&((f&G)!==0&&p(this,ie).add(s),be(s));var o=s.first;if(o!==null){s=o;continue}}for(;s!==null;){var c=s.next;if(c!==null){s=c;break}s=s.parent}}},Qe=function(t){for(var n=0;n1){this.previous.clear();var t=b,n=!0;for(const f of Me){if(f===this){n=!1;continue}const a=[];for(const[i,o]of this.current){if(f.current.has(i))if(n&&o!==f.current.get(i))f.current.set(i,o);else continue;a.push(i)}if(a.length===0)continue;const l=[...f.current.keys()].filter(i=>!this.current.has(i));if(l.length>0){var r=N;N=[];const i=new Set,o=new Map;for(const c of a)qt(c,l,i,o);if(N.length>0){d=f,f.apply();for(const c of N)K(s=f,D,Je).call(s,c,[],[]);f.deactivate()}N=r}}d=null,b=t}Me.delete(this)};let ge=dt;function jn(e){var t=Oe;Oe=!0;try{for(var n;;){if(Cn(),N.length===0&&(d==null||d.flush(),N.length===0))return Ge=null,n;Ht()}}finally{Oe=t}}function Ht(){Ze=!0;var e=null;try{for(var t=0;N.length>0;){var n=ge.ensure();if(t++>1e3){var r,s;Yn()}n.process(N),W.clear()}}finally{N=[],Ze=!1,Ge=null}}function Yn(){try{Sn()}catch(e){He(e,Ge)}}let M=null;function Tt(e){var t=e.length;if(t!==0){for(var n=0;n0)){W.clear();for(const s of M){if((s.f&($|j))!==0)continue;const f=[s];let a=s.parent;for(;a!==null;)M.has(a)&&(M.delete(a),f.push(a)),a=a.parent;for(let l=f.length-1;l>=0;l--){const i=f[l];(i.f&($|j))===0&&be(i)}}M.clear()}}M=null}}function qt(e,t,n,r){if(!n.has(e)&&(n.add(e),e.reactions!==null))for(const s of e.reactions){const f=s.f;(f&A)!==0?qt(s,t,n,r):(f&(st|G))!==0&&(f&R)===0&&Vt(s,t,r)&&(E(s,R),B(s))}}function Vt(e,t,n){const r=n.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const s of e.deps){if(Ee.call(t,s))return!0;if((s.f&A)!==0&&Vt(s,t,n))return n.set(s,!0),!0}return n.set(e,!1),!1}function B(e){var t=Ge=e,n=t.b;if(n!=null&&n.is_pending&&(e.f&(De|Ie|Dt))!==0&&(e.f&oe)===0){n.defer_effect(e);return}for(;t.parent!==null;){t=t.parent;var r=t.f;if(Ze&&t===w&&(r&G)!==0&&(r&It)===0&&(r&oe)!==0)return;if((r&(ve|H))!==0){if((r&g)===0)return;t.f^=g}}N.push(t)}function Ut(e,t){if(!((e.f&H)!==0&&(e.f&g)!==0)){(e.f&R)!==0?t.d.push(e):(e.f&Y)!==0&&t.m.push(e),E(e,g);for(var n=e.first;n!==null;)Ut(n,t),n=n.next}}function Hn(e,t,n,r){const s=Ce()?lt:Bn;var f=e.filter(u=>!u.settled);if(n.length===0&&f.length===0){r(t.map(s));return}var a=w,l=qn(),i=f.length===1?f[0].promise:f.length>1?Promise.all(f.map(u=>u.promise)):null;function o(u){l();try{r(u)}catch(v){(a.f&$)===0&&He(v,a)}et()}if(n.length===0){i.then(()=>o(t.map(s)));return}function c(){l(),Promise.all(n.map(u=>Un(u))).then(u=>o([...t.map(s),...u])).catch(u=>He(u,a))}i?i.then(c):c()}function qn(){var e=w,t=_,n=S,r=d;return function(f=!0){Te(e),Q(t),Ye(n),f&&(r==null||r.activate())}}function et(e=!0){Te(null),Q(null),Ye(null),e&&(d==null||d.deactivate())}function Vn(){var e=w.b,t=d,n=e.is_rendered();return e.update_pending_count(1),t.increment(n),()=>{e.update_pending_count(-1),t.decrement(n)}}function lt(e){var t=A|R,n=_!==null&&(_.f&A)!==0?_:null;return w!==null&&(w.f|=Pe),{ctx:S,deps:null,effects:null,equals:Ft,f:t,fn:e,reactions:null,rv:0,v:T,wv:0,parent:n??w,ac:null}}function Un(e,t,n){w===null&&gn();var s=void 0,f=ut(T),a=!_,l=new Map;return er(()=>{var v;var i=xt();s=i.promise;try{Promise.resolve(e()).then(i.resolve,i.reject).finally(et)}catch(y){i.reject(y),et()}var o=d;if(a){var c=Vn();(v=l.get(o))==null||v.reject(ne),l.delete(o),l.set(o,i)}const u=(y,h=void 0)=>{if(o.activate(),h)h!==ne&&(f.f|=Z,nt(f,h));else{(f.f&Z)!==0&&(f.f^=Z),nt(f,y);for(const[V,O]of l){if(l.delete(V),V===o)break;O.reject(ne)}}c&&c()};i.promise.then(u,y=>u(null,y||"unknown"))}),Qn(()=>{for(const i of l.values())i.reject(ne)}),new Promise(i=>{function o(c){function u(){c===s?i(f):o(s)}c.then(u,u)}o(s)})}function Br(e){const t=lt(e);return rn(t),t}function Bn(e){const t=lt(e);return t.equals=Mt,t}function Gn(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n0&&!zt&&Xn()}return t}function Xn(){zt=!1;for(const e of tt)(e.f&g)!==0&&E(e,Y),Fe(e)&&be(e);tt.clear()}function Xe(e){te(e,e.v+1)}function Kt(e,t){var n=e.reactions;if(n!==null)for(var r=Ce(),s=n.length,f=0;f{if(le===f)return l();var i=_,o=le;Q(null),Ot(f);var c=l();return Q(i),Ot(o),c};return r&&n.set("length",X(e.length)),new Proxy(e,{defineProperty(l,i,o){(!("value"in o)||o.configurable===!1||o.enumerable===!1||o.writable===!1)&&Rn();var c=n.get(i);return c===void 0?a(()=>{var u=X(o.value);return n.set(i,u),u}):te(c,o.value,!0),!0},deleteProperty(l,i){var o=n.get(i);if(o===void 0){if(i in l){const c=a(()=>X(T));n.set(i,c),Xe(s)}}else te(o,T),Xe(s);return!0},get(l,i,o){var y;if(i===ae)return e;var c=n.get(i),u=i in l;if(c===void 0&&(!u||(y=Re(l,i))!=null&&y.writable)&&(c=a(()=>{var h=Ae(u?l[i]:T),V=X(h);return V}),n.set(i,c)),c!==void 0){var v=Se(c);return v===T?void 0:v}return Reflect.get(l,i,o)},getOwnPropertyDescriptor(l,i){var o=Reflect.getOwnPropertyDescriptor(l,i);if(o&&"value"in o){var c=n.get(i);c&&(o.value=Se(c))}else if(o===void 0){var u=n.get(i),v=u==null?void 0:u.v;if(u!==void 0&&v!==T)return{enumerable:!0,configurable:!0,value:v,writable:!0}}return o},has(l,i){var v;if(i===ae)return!0;var o=n.get(i),c=o!==void 0&&o.v!==T||Reflect.has(l,i);if(o!==void 0||w!==null&&(!c||(v=Re(l,i))!=null&&v.writable)){o===void 0&&(o=a(()=>{var y=c?Ae(l[i]):T,h=X(y);return h}),n.set(i,o));var u=Se(o);if(u===T)return!1}return c},set(l,i,o,c){var ht;var u=n.get(i),v=i in l;if(r&&i==="length")for(var y=o;yX(T)),n.set(y+"",h))}if(u===void 0)(!v||(ht=Re(l,i))!=null&&ht.writable)&&(u=a(()=>X(void 0)),te(u,Ae(o)),n.set(i,u));else{v=u.v!==T;var V=a(()=>Ae(o));te(u,V)}var O=Reflect.getOwnPropertyDescriptor(l,i);if(O!=null&&O.set&&O.set.call(c,o),!v){if(r&&typeof i=="string"){var pt=n.get("length"),ze=Number(i);Number.isInteger(ze)&&ze>=pt.v&&te(pt,ze+1)}Xe(s)}return!0},ownKeys(l){Se(s);var i=Reflect.ownKeys(l).filter(u=>{var v=n.get(u);return v===void 0||v.v!==T});for(var[o,c]of n)c.v!==T&&!(o in l)&&i.push(o);return i},setPrototypeOf(){On()}})}function bt(e){try{if(e!==null&&typeof e=="object"&&ae in e)return e[ae]}catch{}return e}function zr(e,t){return Object.is(bt(e),bt(t))}var At,$n,Xt,$t;function Kr(){if(At===void 0){At=window,$n=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;Xt=Re(t,"firstChild").get,$t=Re(t,"nextSibling").get,yt(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),yt(n)&&(n.__t=void 0)}}function qe(e=""){return document.createTextNode(e)}function Ve(e){return Xt.call(e)}function ee(e){return $t.call(e)}function Xr(e,t){if(!J)return Ve(e);var n=Ve(m);if(n===null)n=m.appendChild(qe());else if(t&&n.nodeType!==Ue){var r=qe();return n==null||n.before(r),me(r),r}return t&&ct(n),me(n),n}function $r(e,t=!1){if(!J){var n=Ve(e);return n instanceof Comment&&n.data===""?ee(n):n}if(t){if((m==null?void 0:m.nodeType)!==Ue){var r=qe();return m==null||m.before(r),me(r),r}ct(m)}return m}function Zr(e,t=1,n=!1){let r=J?m:e;for(var s;t--;)s=r,r=ee(r);if(!J)return r;if(n){if((r==null?void 0:r.nodeType)!==Ue){var f=qe();return r===null?s==null||s.after(f):r.before(f),me(f),f}ct(r)}return me(r),r}function Zn(e){e.textContent=""}function Wr(){return!1}function Jr(e,t,n){return document.createElementNS(In,e,void 0)}function ct(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===Ue;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function Qr(e){J&&Ve(e)!==null&&Zn(e)}let St=!1;function Wn(){St||(St=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var t;if(!e.defaultPrevented)for(const n of e.target.elements)(t=n.__on_r)==null||t.call(n)})},{capture:!0}))}function _t(e){var t=_,n=w;Q(null),Te(null);try{return e()}finally{Q(t),Te(n)}}function es(e,t,n,r=n){e.addEventListener(t,()=>_t(n));const s=e.__on_r;s?e.__on_r=()=>{s(),r(!0)}:e.__on_r=()=>r(!0),Wn()}function Zt(e){w===null&&(_===null&&An(),bn()),_e&&Tn()}function Jn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function q(e,t,n){var r=w;r!==null&&(r.f&j)!==0&&(e|=j);var s={ctx:S,deps:null,nodes:null,f:e|R|P,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};if(n)try{be(s)}catch(l){throw ce(s),l}else t!==null&&B(s);var f=s;if(n&&f.deps===null&&f.teardown===null&&f.nodes===null&&f.first===f.last&&(f.f&Pe)===0&&(f=f.first,(e&G)!==0&&(e&je)!==0&&f!==null&&(f.f|=je)),f!==null&&(f.parent=r,r!==null&&Jn(f,r),_!==null&&(_.f&A)!==0&&(e&ve)===0)){var a=_;(a.effects??(a.effects=[])).push(f)}return s}function Wt(){return _!==null&&!L}function Qn(e){const t=q(Ie,null,!1);return E(t,g),t.teardown=e,t}function ts(e){Zt();var t=w.f,n=!_&&(t&H)!==0&&(t&oe)===0;if(n){var r=S;(r.e??(r.e=[])).push(e)}else return Jt(e)}function Jt(e){return q(De|Pt,e,!1)}function ns(e){return Zt(),q(Ie|Pt,e,!0)}function rs(e){ge.ensure();const t=q(ve|Pe,e,!0);return(n={})=>new Promise(r=>{n.outro?rr(t,()=>{ce(t),r(void 0)}):(ce(t),r(void 0))})}function ss(e){return q(De,e,!1)}function er(e){return q(st|Pe,e,!0)}function fs(e,t=0){return q(Ie|t,e,!0)}function is(e,t=[],n=[],r=[]){Hn(r,t,n,s=>{q(Ie,()=>e(...s.map(Se)),!0)})}function as(e,t=0){var n=q(G|t,e,!0);return n}function ls(e){return q(H|Pe,e,!0)}function Qt(e){var t=e.teardown;if(t!==null){const n=_e,r=_;Rt(!0),Q(null);try{t.call(null)}finally{Rt(n),Q(r)}}}function vt(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){const s=n.ac;s!==null&&_t(()=>{s.abort(ne)});var r=n.next;(n.f&ve)!==0?n.parent=null:ce(n,t),n=r}}function tr(e){for(var t=e.first;t!==null;){var n=t.next;(t.f&H)===0&&ce(t),t=n}}function ce(e,t=!0){var n=!1;(t||(e.f&It)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(nr(e.nodes.start,e.nodes.end),n=!0),vt(e,t&&!n),Ne(e,0),E(e,$);var r=e.nodes&&e.nodes.t;if(r!==null)for(const f of r)f.stop();Qt(e);var s=e.parent;s!==null&&s.first!==null&&en(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function nr(e,t){for(;e!==null;){var n=e===t?null:ee(e);e.remove(),e=n}}function en(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function rr(e,t,n=!0){var r=[];tn(e,r,!0);var s=()=>{n&&ce(e),t&&t()},f=r.length;if(f>0){var a=()=>--f||s();for(var l of r)l.out(a)}else s()}function tn(e,t,n){if((e.f&j)===0){e.f^=j;var r=e.nodes&&e.nodes.t;if(r!==null)for(const l of r)(l.is_global||n)&&t.push(l);for(var s=e.first;s!==null;){var f=s.next,a=(s.f&je)!==0||(s.f&H)!==0&&(e.f&G)!==0;tn(s,t,a?n:!1),s=f}}}function os(e){nn(e,!0)}function nn(e,t){if((e.f&j)!==0){e.f^=j,(e.f&g)===0&&(E(e,R),B(e));for(var n=e.first;n!==null;){var r=n.next,s=(n.f&je)!==0||(n.f&H)!==0;nn(n,s?t:!1),n=r}var f=e.nodes&&e.nodes.t;if(f!==null)for(const a of f)(a.is_global||t)&&a.in()}}function us(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var s=n===r?null:ee(n);t.append(n),n=s}}let Le=!1,_e=!1;function Rt(e){_e=e}let _=null,L=!1;function Q(e){_=e}let w=null;function Te(e){w=e}let C=null;function rn(e){_!==null&&(C===null?C=[e]:C.push(e))}let k=null,x=0,I=null;function sr(e){I=e}let sn=1,se=0,le=se;function Ot(e){le=e}function fn(){return++sn}function Fe(e){var t=e.f;if((t&R)!==0)return!0;if(t&A&&(e.f&=~ue),(t&Y)!==0){for(var n=e.deps,r=n.length,s=0;se.wv)return!0}(t&P)!==0&&b===null&&E(e,g)}return!1}function an(e,t,n=!0){var r=e.reactions;if(r!==null&&!(C!==null&&Ee.call(C,e)))for(var s=0;s{e.ac.abort(ne)}),e.ac=null);try{e.f|=$e;var c=e.fn,u=c();e.f|=oe;var v=e.deps,y=d==null?void 0:d.is_fork;if(k!==null){var h;if(y||Ne(e,x),v!==null&&x>0)for(v.length=x+k.length,h=0;h{throw TypeError(e)};var _n=(e,t,n)=>t in e?cn(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var de=(e,t,n)=>_n(e,typeof t!="symbol"?t+"":t,n),Ke=(e,t,n)=>t.has(e)||wt("Cannot "+n);var p=(e,t,n)=>(Ke(e,t,"read from private field"),n?n.call(e):t.get(e)),F=(e,t,n)=>t.has(e)?wt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),z=(e,t,n,r)=>(Ke(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n),K=(e,t,n)=>(Ke(e,t,"access private method"),n);var vn=Array.isArray,dn=Array.prototype.indexOf,Ee=Array.prototype.includes,ar=Array.from,lr=Object.defineProperty,Re=Object.getOwnPropertyDescriptor,pn=Object.getOwnPropertyDescriptors,hn=Object.prototype,wn=Array.prototype,kt=Object.getPrototypeOf,yt=Object.isExtensible;const yn=()=>{};function or(e){return e()}function En(e){for(var t=0;t{e=r,t=s});return{promise:n,resolve:e,reject:t}}function ur(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);const n=[];for(const r of e)if(n.push(r),n.length===t)break;return n}const A=2,De=4,Ie=8,Dt=1<<24,G=16,H=32,ve=64,mn=128,P=512,g=1024,R=2048,Y=4096,j=8192,$=16384,oe=32768,je=65536,Et=1<<17,It=1<<18,Pe=1<<19,Pt=1<<20,cr=1<<25,ue=65536,$e=1<<21,st=1<<22,Z=1<<23,ae=Symbol("$state"),_r=Symbol("legacy props"),vr=Symbol(""),ne=new class extends Error{constructor(){super(...arguments);de(this,"name","StaleReactionError");de(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var Nt;const pr=!!((Nt=globalThis.document)!=null&&Nt.contentType)&&globalThis.document.contentType.includes("xml"),Ue=3,Ct=8;function gn(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function hr(e,t,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Tn(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function bn(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function An(e){throw new Error("https://svelte.dev/e/effect_orphan")}function Sn(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function wr(){throw new Error("https://svelte.dev/e/hydration_failed")}function yr(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function Rn(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function On(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Nn(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Er(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const mr=1,gr=2,Tr=4,br=8,Ar=16,Sr=1,Rr=2,Or=4,Nr=8,kr=16,xr=1,Dr=2,kn="[",xn="[!",Ir="[?",Dn="]",ft={},T=Symbol(),In="http://www.w3.org/1999/xhtml";function it(e){console.warn("https://svelte.dev/e/hydration_mismatch")}function Pr(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Cr(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}let J=!1;function Fr(e){J=e}let m;function me(e){if(e===null)throw it(),ft;return m=e}function Mr(){return me(ee(m))}function Lr(e){if(J){if(ee(m)!==null)throw it(),ft;m=e}}function jr(e=1){if(J){for(var t=e,n=m;t--;)n=ee(n);m=n}}function Yr(e=!0){for(var t=0,n=m;;){if(n.nodeType===Ct){var r=n.data;if(r===Dn){if(t===0)return n;t-=1}else(r===kn||r===xn||r[0]==="["&&!isNaN(Number(r.slice(1))))&&(t+=1)}var s=ee(n);e&&n.remove(),n=s}}function Hr(e){if(!e||e.nodeType!==Ct)throw it(),ft;return e.data}function Ft(e){return e===this.v}function Pn(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function Mt(e){return!Pn(e,this.v)}let Be=!1;function qr(){Be=!0}let S=null;function Ye(e){S=e}function Vr(e,t=!1,n){S={p:S,i:!1,c:null,e:null,s:e,x:null,l:Be&&!t?{s:null,u:null,$:[]}:null}}function Ur(e){var t=S,n=t.e;if(n!==null){t.e=null;for(var r of n)Jt(r)}return t.i=!0,S=t.p,{}}function Ce(){return!Be||S!==null&&S.l===null}let re=[];function Lt(){var e=re;re=[],En(e)}function mt(e){if(re.length===0&&!Oe){var t=re;queueMicrotask(()=>{t===re&&Lt()})}re.push(e)}function Cn(){for(;re.length>0;)Lt()}function Fn(e){var t=w;if(t===null)return _.f|=Z,e;if((t.f&oe)===0&&(t.f&De)===0)throw e;He(e,t)}function He(e,t){for(;t!==null;){if((t.f&mn)!==0){if((t.f&oe)===0)throw e;try{t.b.error(e);return}catch(n){e=n}}t=t.parent}throw e}const Mn=-7169;function E(e,t){e.f=e.f&Mn|t}function at(e){(e.f&P)!==0||e.deps===null?E(e,g):E(e,Y)}function jt(e){if(e!==null)for(const t of e)(t.f&A)===0||(t.f&ue)===0||(t.f^=ue,jt(t.deps))}function Ln(e,t,n){(e.f&R)!==0?t.add(e):(e.f&Y)!==0&&n.add(e),jt(e.deps),E(e,g)}const Me=new Set;let d=null,gt=null,b=null,N=[],Ge=null,Ze=!1,Oe=!1;var pe,he,fe,we,ke,xe,ie,U,ye,D,We,Je,Qe,Yt;const dt=class dt{constructor(){F(this,D);de(this,"current",new Map);de(this,"previous",new Map);F(this,pe,new Set);F(this,he,new Set);F(this,fe,0);F(this,we,0);F(this,ke,null);F(this,xe,new Set);F(this,ie,new Set);F(this,U,new Map);de(this,"is_fork",!1);F(this,ye,!1)}skip_effect(t){p(this,U).has(t)||p(this,U).set(t,{d:[],m:[]})}unskip_effect(t){var n=p(this,U).get(t);if(n){p(this,U).delete(t);for(var r of n.d)E(r,R),B(r);for(r of n.m)E(r,Y),B(r)}}process(t){var s;N=[],this.apply();var n=[],r=[];for(const f of t)K(this,D,Je).call(this,f,n,r);if(K(this,D,We).call(this)){K(this,D,Qe).call(this,r),K(this,D,Qe).call(this,n);for(const[f,a]of p(this,U))Ut(f,a)}else{for(const f of p(this,pe))f();p(this,pe).clear(),p(this,fe)===0&&K(this,D,Yt).call(this),gt=this,d=null,Tt(r),Tt(n),gt=null,(s=p(this,ke))==null||s.resolve()}b=null}capture(t,n){n!==T&&!this.previous.has(t)&&this.previous.set(t,n),(t.f&Z)===0&&(this.current.set(t,t.v),b==null||b.set(t,t.v))}activate(){d=this,this.apply()}deactivate(){d===this&&(d=null,b=null)}flush(){if(this.activate(),N.length>0){if(Ht(),d!==null&&d!==this)return}else p(this,fe)===0&&this.process([]);this.deactivate()}discard(){for(const t of p(this,he))t(this);p(this,he).clear()}increment(t){z(this,fe,p(this,fe)+1),t&&z(this,we,p(this,we)+1)}decrement(t){z(this,fe,p(this,fe)-1),t&&z(this,we,p(this,we)-1),!p(this,ye)&&(z(this,ye,!0),mt(()=>{z(this,ye,!1),K(this,D,We).call(this)?N.length>0&&this.flush():this.revive()}))}revive(){for(const t of p(this,xe))p(this,ie).delete(t),E(t,R),B(t);for(const t of p(this,ie))E(t,Y),B(t);this.flush()}oncommit(t){p(this,pe).add(t)}ondiscard(t){p(this,he).add(t)}settled(){return(p(this,ke)??z(this,ke,xt())).promise}static ensure(){if(d===null){const t=d=new dt;Me.add(d),Oe||mt(()=>{d===t&&t.flush()})}return d}apply(){}};pe=new WeakMap,he=new WeakMap,fe=new WeakMap,we=new WeakMap,ke=new WeakMap,xe=new WeakMap,ie=new WeakMap,U=new WeakMap,ye=new WeakMap,D=new WeakSet,We=function(){return this.is_fork||p(this,we)>0},Je=function(t,n,r){t.f^=g;for(var s=t.first;s!==null;){var f=s.f,a=(f&(H|ve))!==0,l=a&&(f&g)!==0,i=l||(f&j)!==0||p(this,U).has(s);if(!i&&s.fn!==null){a?s.f^=g:(f&De)!==0?n.push(s):Fe(s)&&((f&G)!==0&&p(this,ie).add(s),be(s));var o=s.first;if(o!==null){s=o;continue}}for(;s!==null;){var c=s.next;if(c!==null){s=c;break}s=s.parent}}},Qe=function(t){for(var n=0;n1){this.previous.clear();var t=b,n=!0;for(const f of Me){if(f===this){n=!1;continue}const a=[];for(const[i,o]of this.current){if(f.current.has(i))if(n&&o!==f.current.get(i))f.current.set(i,o);else continue;a.push(i)}if(a.length===0)continue;const l=[...f.current.keys()].filter(i=>!this.current.has(i));if(l.length>0){var r=N;N=[];const i=new Set,o=new Map;for(const c of a)qt(c,l,i,o);if(N.length>0){d=f,f.apply();for(const c of N)K(s=f,D,Je).call(s,c,[],[]);f.deactivate()}N=r}}d=null,b=t}Me.delete(this)};let ge=dt;function jn(e){var t=Oe;Oe=!0;try{for(var n;;){if(Cn(),N.length===0&&(d==null||d.flush(),N.length===0))return Ge=null,n;Ht()}}finally{Oe=t}}function Ht(){Ze=!0;var e=null;try{for(var t=0;N.length>0;){var n=ge.ensure();if(t++>1e3){var r,s;Yn()}n.process(N),W.clear()}}finally{N=[],Ze=!1,Ge=null}}function Yn(){try{Sn()}catch(e){He(e,Ge)}}let M=null;function Tt(e){var t=e.length;if(t!==0){for(var n=0;n0)){W.clear();for(const s of M){if((s.f&($|j))!==0)continue;const f=[s];let a=s.parent;for(;a!==null;)M.has(a)&&(M.delete(a),f.push(a)),a=a.parent;for(let l=f.length-1;l>=0;l--){const i=f[l];(i.f&($|j))===0&&be(i)}}M.clear()}}M=null}}function qt(e,t,n,r){if(!n.has(e)&&(n.add(e),e.reactions!==null))for(const s of e.reactions){const f=s.f;(f&A)!==0?qt(s,t,n,r):(f&(st|G))!==0&&(f&R)===0&&Vt(s,t,r)&&(E(s,R),B(s))}}function Vt(e,t,n){const r=n.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const s of e.deps){if(Ee.call(t,s))return!0;if((s.f&A)!==0&&Vt(s,t,n))return n.set(s,!0),!0}return n.set(e,!1),!1}function B(e){var t=Ge=e,n=t.b;if(n!=null&&n.is_pending&&(e.f&(De|Ie|Dt))!==0&&(e.f&oe)===0){n.defer_effect(e);return}for(;t.parent!==null;){t=t.parent;var r=t.f;if(Ze&&t===w&&(r&G)!==0&&(r&It)===0&&(r&oe)!==0)return;if((r&(ve|H))!==0){if((r&g)===0)return;t.f^=g}}N.push(t)}function Ut(e,t){if(!((e.f&H)!==0&&(e.f&g)!==0)){(e.f&R)!==0?t.d.push(e):(e.f&Y)!==0&&t.m.push(e),E(e,g);for(var n=e.first;n!==null;)Ut(n,t),n=n.next}}function Hn(e,t,n,r){const s=Ce()?lt:Bn;var f=e.filter(u=>!u.settled);if(n.length===0&&f.length===0){r(t.map(s));return}var a=w,l=qn(),i=f.length===1?f[0].promise:f.length>1?Promise.all(f.map(u=>u.promise)):null;function o(u){l();try{r(u)}catch(v){(a.f&$)===0&&He(v,a)}et()}if(n.length===0){i.then(()=>o(t.map(s)));return}function c(){l(),Promise.all(n.map(u=>Un(u))).then(u=>o([...t.map(s),...u])).catch(u=>He(u,a))}i?i.then(c):c()}function qn(){var e=w,t=_,n=S,r=d;return function(f=!0){Te(e),Q(t),Ye(n),f&&(r==null||r.activate())}}function et(e=!0){Te(null),Q(null),Ye(null),e&&(d==null||d.deactivate())}function Vn(){var e=w.b,t=d,n=e.is_rendered();return e.update_pending_count(1),t.increment(n),()=>{e.update_pending_count(-1),t.decrement(n)}}function lt(e){var t=A|R,n=_!==null&&(_.f&A)!==0?_:null;return w!==null&&(w.f|=Pe),{ctx:S,deps:null,effects:null,equals:Ft,f:t,fn:e,reactions:null,rv:0,v:T,wv:0,parent:n??w,ac:null}}function Un(e,t,n){w===null&&gn();var s=void 0,f=ut(T),a=!_,l=new Map;return er(()=>{var v;var i=xt();s=i.promise;try{Promise.resolve(e()).then(i.resolve,i.reject).finally(et)}catch(y){i.reject(y),et()}var o=d;if(a){var c=Vn();(v=l.get(o))==null||v.reject(ne),l.delete(o),l.set(o,i)}const u=(y,h=void 0)=>{if(o.activate(),h)h!==ne&&(f.f|=Z,nt(f,h));else{(f.f&Z)!==0&&(f.f^=Z),nt(f,y);for(const[V,O]of l){if(l.delete(V),V===o)break;O.reject(ne)}}c&&c()};i.promise.then(u,y=>u(null,y||"unknown"))}),Qn(()=>{for(const i of l.values())i.reject(ne)}),new Promise(i=>{function o(c){function u(){c===s?i(f):o(s)}c.then(u,u)}o(s)})}function Br(e){const t=lt(e);return rn(t),t}function Bn(e){const t=lt(e);return t.equals=Mt,t}function Gn(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n0&&!zt&&Xn()}return t}function Xn(){zt=!1;for(const e of tt)(e.f&g)!==0&&E(e,Y),Fe(e)&&be(e);tt.clear()}function Xe(e){te(e,e.v+1)}function Kt(e,t){var n=e.reactions;if(n!==null)for(var r=Ce(),s=n.length,f=0;f{if(le===f)return l();var i=_,o=le;Q(null),Ot(f);var c=l();return Q(i),Ot(o),c};return r&&n.set("length",X(e.length)),new Proxy(e,{defineProperty(l,i,o){(!("value"in o)||o.configurable===!1||o.enumerable===!1||o.writable===!1)&&Rn();var c=n.get(i);return c===void 0?a(()=>{var u=X(o.value);return n.set(i,u),u}):te(c,o.value,!0),!0},deleteProperty(l,i){var o=n.get(i);if(o===void 0){if(i in l){const c=a(()=>X(T));n.set(i,c),Xe(s)}}else te(o,T),Xe(s);return!0},get(l,i,o){var y;if(i===ae)return e;var c=n.get(i),u=i in l;if(c===void 0&&(!u||(y=Re(l,i))!=null&&y.writable)&&(c=a(()=>{var h=Ae(u?l[i]:T),V=X(h);return V}),n.set(i,c)),c!==void 0){var v=Se(c);return v===T?void 0:v}return Reflect.get(l,i,o)},getOwnPropertyDescriptor(l,i){var o=Reflect.getOwnPropertyDescriptor(l,i);if(o&&"value"in o){var c=n.get(i);c&&(o.value=Se(c))}else if(o===void 0){var u=n.get(i),v=u==null?void 0:u.v;if(u!==void 0&&v!==T)return{enumerable:!0,configurable:!0,value:v,writable:!0}}return o},has(l,i){var v;if(i===ae)return!0;var o=n.get(i),c=o!==void 0&&o.v!==T||Reflect.has(l,i);if(o!==void 0||w!==null&&(!c||(v=Re(l,i))!=null&&v.writable)){o===void 0&&(o=a(()=>{var y=c?Ae(l[i]):T,h=X(y);return h}),n.set(i,o));var u=Se(o);if(u===T)return!1}return c},set(l,i,o,c){var ht;var u=n.get(i),v=i in l;if(r&&i==="length")for(var y=o;yX(T)),n.set(y+"",h))}if(u===void 0)(!v||(ht=Re(l,i))!=null&&ht.writable)&&(u=a(()=>X(void 0)),te(u,Ae(o)),n.set(i,u));else{v=u.v!==T;var V=a(()=>Ae(o));te(u,V)}var O=Reflect.getOwnPropertyDescriptor(l,i);if(O!=null&&O.set&&O.set.call(c,o),!v){if(r&&typeof i=="string"){var pt=n.get("length"),ze=Number(i);Number.isInteger(ze)&&ze>=pt.v&&te(pt,ze+1)}Xe(s)}return!0},ownKeys(l){Se(s);var i=Reflect.ownKeys(l).filter(u=>{var v=n.get(u);return v===void 0||v.v!==T});for(var[o,c]of n)c.v!==T&&!(o in l)&&i.push(o);return i},setPrototypeOf(){On()}})}function bt(e){try{if(e!==null&&typeof e=="object"&&ae in e)return e[ae]}catch{}return e}function zr(e,t){return Object.is(bt(e),bt(t))}var At,$n,Xt,$t;function Kr(){if(At===void 0){At=window,$n=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;Xt=Re(t,"firstChild").get,$t=Re(t,"nextSibling").get,yt(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),yt(n)&&(n.__t=void 0)}}function qe(e=""){return document.createTextNode(e)}function Ve(e){return Xt.call(e)}function ee(e){return $t.call(e)}function Xr(e,t){if(!J)return Ve(e);var n=Ve(m);if(n===null)n=m.appendChild(qe());else if(t&&n.nodeType!==Ue){var r=qe();return n==null||n.before(r),me(r),r}return t&&ct(n),me(n),n}function $r(e,t=!1){if(!J){var n=Ve(e);return n instanceof Comment&&n.data===""?ee(n):n}if(t){if((m==null?void 0:m.nodeType)!==Ue){var r=qe();return m==null||m.before(r),me(r),r}ct(m)}return m}function Zr(e,t=1,n=!1){let r=J?m:e;for(var s;t--;)s=r,r=ee(r);if(!J)return r;if(n){if((r==null?void 0:r.nodeType)!==Ue){var f=qe();return r===null?s==null||s.after(f):r.before(f),me(f),f}ct(r)}return me(r),r}function Zn(e){e.textContent=""}function Wr(){return!1}function Jr(e,t,n){return document.createElementNS(In,e,void 0)}function ct(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===Ue;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function Qr(e){J&&Ve(e)!==null&&Zn(e)}let St=!1;function Wn(){St||(St=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var t;if(!e.defaultPrevented)for(const n of e.target.elements)(t=n.__on_r)==null||t.call(n)})},{capture:!0}))}function _t(e){var t=_,n=w;Q(null),Te(null);try{return e()}finally{Q(t),Te(n)}}function es(e,t,n,r=n){e.addEventListener(t,()=>_t(n));const s=e.__on_r;s?e.__on_r=()=>{s(),r(!0)}:e.__on_r=()=>r(!0),Wn()}function Zt(e){w===null&&(_===null&&An(),bn()),_e&&Tn()}function Jn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function q(e,t,n){var r=w;r!==null&&(r.f&j)!==0&&(e|=j);var s={ctx:S,deps:null,nodes:null,f:e|R|P,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};if(n)try{be(s)}catch(l){throw ce(s),l}else t!==null&&B(s);var f=s;if(n&&f.deps===null&&f.teardown===null&&f.nodes===null&&f.first===f.last&&(f.f&Pe)===0&&(f=f.first,(e&G)!==0&&(e&je)!==0&&f!==null&&(f.f|=je)),f!==null&&(f.parent=r,r!==null&&Jn(f,r),_!==null&&(_.f&A)!==0&&(e&ve)===0)){var a=_;(a.effects??(a.effects=[])).push(f)}return s}function Wt(){return _!==null&&!L}function Qn(e){const t=q(Ie,null,!1);return E(t,g),t.teardown=e,t}function ts(e){Zt();var t=w.f,n=!_&&(t&H)!==0&&(t&oe)===0;if(n){var r=S;(r.e??(r.e=[])).push(e)}else return Jt(e)}function Jt(e){return q(De|Pt,e,!1)}function ns(e){return Zt(),q(Ie|Pt,e,!0)}function rs(e){ge.ensure();const t=q(ve|Pe,e,!0);return(n={})=>new Promise(r=>{n.outro?rr(t,()=>{ce(t),r(void 0)}):(ce(t),r(void 0))})}function ss(e){return q(De,e,!1)}function er(e){return q(st|Pe,e,!0)}function fs(e,t=0){return q(Ie|t,e,!0)}function is(e,t=[],n=[],r=[]){Hn(r,t,n,s=>{q(Ie,()=>e(...s.map(Se)),!0)})}function as(e,t=0){var n=q(G|t,e,!0);return n}function ls(e){return q(H|Pe,e,!0)}function Qt(e){var t=e.teardown;if(t!==null){const n=_e,r=_;Rt(!0),Q(null);try{t.call(null)}finally{Rt(n),Q(r)}}}function vt(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){const s=n.ac;s!==null&&_t(()=>{s.abort(ne)});var r=n.next;(n.f&ve)!==0?n.parent=null:ce(n,t),n=r}}function tr(e){for(var t=e.first;t!==null;){var n=t.next;(t.f&H)===0&&ce(t),t=n}}function ce(e,t=!0){var n=!1;(t||(e.f&It)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(nr(e.nodes.start,e.nodes.end),n=!0),vt(e,t&&!n),Ne(e,0),E(e,$);var r=e.nodes&&e.nodes.t;if(r!==null)for(const f of r)f.stop();Qt(e);var s=e.parent;s!==null&&s.first!==null&&en(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function nr(e,t){for(;e!==null;){var n=e===t?null:ee(e);e.remove(),e=n}}function en(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function rr(e,t,n=!0){var r=[];tn(e,r,!0);var s=()=>{n&&ce(e),t&&t()},f=r.length;if(f>0){var a=()=>--f||s();for(var l of r)l.out(a)}else s()}function tn(e,t,n){if((e.f&j)===0){e.f^=j;var r=e.nodes&&e.nodes.t;if(r!==null)for(const l of r)(l.is_global||n)&&t.push(l);for(var s=e.first;s!==null;){var f=s.next,a=(s.f&je)!==0||(s.f&H)!==0&&(e.f&G)!==0;tn(s,t,a?n:!1),s=f}}}function os(e){nn(e,!0)}function nn(e,t){if((e.f&j)!==0){e.f^=j,(e.f&g)===0&&(E(e,R),B(e));for(var n=e.first;n!==null;){var r=n.next,s=(n.f&je)!==0||(n.f&H)!==0;nn(n,s?t:!1),n=r}var f=e.nodes&&e.nodes.t;if(f!==null)for(const a of f)(a.is_global||t)&&a.in()}}function us(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var s=n===r?null:ee(n);t.append(n),n=s}}let Le=!1,_e=!1;function Rt(e){_e=e}let _=null,L=!1;function Q(e){_=e}let w=null;function Te(e){w=e}let C=null;function rn(e){_!==null&&(C===null?C=[e]:C.push(e))}let k=null,x=0,I=null;function sr(e){I=e}let sn=1,se=0,le=se;function Ot(e){le=e}function fn(){return++sn}function Fe(e){var t=e.f;if((t&R)!==0)return!0;if(t&A&&(e.f&=~ue),(t&Y)!==0){for(var n=e.deps,r=n.length,s=0;se.wv)return!0}(t&P)!==0&&b===null&&E(e,g)}return!1}function an(e,t,n=!0){var r=e.reactions;if(r!==null&&!(C!==null&&Ee.call(C,e)))for(var s=0;s{e.ac.abort(ne)}),e.ac=null);try{e.f|=$e;var c=e.fn,u=c();e.f|=oe;var v=e.deps,y=d==null?void 0:d.is_fork;if(k!==null){var h;if(y||Ne(e,x),v!==null&&x>0)for(v.length=x+k.length,h=0;h{throw TypeError(t)};var B=(t,e,n)=>e.has(t)||x("Cannot "+n);var a=(t,e,n)=>(B(t,e,"read from private field"),n?n.call(t):e.get(t)),c=(t,e,n)=>e.has(t)?x("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,n);import{o as I}from"./DeTA_5mp.js";import{s as u,g as f,h as d}from"./nyjtQ1Ok.js";import{w as G}from"./DAj0p1rI.js";new URL("sveltekit-internal://");function ae(t,e){return t==="/"||e==="ignore"?t:e==="never"?t.endsWith("/")?t.slice(0,-1):t:e==="always"&&!t.endsWith("/")?t+"/":t}function oe(t){return t.split("%25").map(decodeURI).join("%25")}function ie(t){for(const e in t)t[e]=decodeURIComponent(t[e]);return t}function le({href:t}){return t.split("#")[0]}function W(...t){let e=5381;for(const n of t)if(typeof n=="string"){let r=n.length;for(;r;)e=e*33^n.charCodeAt(--r)}else if(ArrayBuffer.isView(n)){const r=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let s=r.length;for(;s;)e=e*33^r[--s]}else throw new TypeError("value must be a string or TypedArray");return(e>>>0).toString(36)}new TextEncoder;new TextDecoder;function X(t){const e=atob(t),n=new Uint8Array(e.length);for(let r=0;r((t instanceof Request?t.method:(e==null?void 0:e.method)||"GET")!=="GET"&&b.delete(U(t)),z(t,e));const b=new Map;function ce(t,e){const n=U(t,e),r=document.querySelector(n);if(r!=null&&r.textContent){r.remove();let{body:s,...l}=JSON.parse(r.textContent);const o=r.getAttribute("data-ttl");return o&&b.set(n,{body:s,init:l,ttl:1e3*Number(o)}),r.getAttribute("data-b64")!==null&&(s=X(s)),Promise.resolve(new Response(s,l))}return window.fetch(t,e)}function ue(t,e,n){if(b.size>0){const r=U(t,n),s=b.get(r);if(s){if(performance.now()o)}function s(o){n=!1,e.set(o)}function l(o){let i;return e.subscribe(h=>{(i===void 0||n&&h!==i)&&o(i=h)})}return{notify:r,set:s,subscribe:l}}const D={v:()=>{}};function Re(){const{set:t,subscribe:e}=G(!1);let n;async function r(){clearTimeout(n);try{const s=await fetch(`${M}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!s.ok)return!1;const o=(await s.json()).version!==F;return o&&(t(!0),D.v(),clearTimeout(n)),o}catch{return!1}}return{subscribe:e,check:r}}function Q(t,e,n){return t.origin!==Y||!t.pathname.startsWith(e)?!0:n?t.pathname!==location.pathname:!1}function Se(t){}const H=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...H];const Z=new Set([...H]);[...Z];let E,O,T;const ee=I.toString().includes("$$")||/function \w+\(\) \{\}/.test(I.toString());var _,w,m,p,v,y,A,R,P,S,V,k,j;ee?(E={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL("https://example.com")},O={current:null},T={current:!1}):(E=new(P=class{constructor(){c(this,_,u({}));c(this,w,u(null));c(this,m,u(null));c(this,p,u({}));c(this,v,u({id:null}));c(this,y,u({}));c(this,A,u(-1));c(this,R,u(new URL("https://example.com")))}get data(){return f(a(this,_))}set data(e){d(a(this,_),e)}get form(){return f(a(this,w))}set form(e){d(a(this,w),e)}get error(){return f(a(this,m))}set error(e){d(a(this,m),e)}get params(){return f(a(this,p))}set params(e){d(a(this,p),e)}get route(){return f(a(this,v))}set route(e){d(a(this,v),e)}get state(){return f(a(this,y))}set state(e){d(a(this,y),e)}get status(){return f(a(this,A))}set status(e){d(a(this,A),e)}get url(){return f(a(this,R))}set url(e){d(a(this,R),e)}},_=new WeakMap,w=new WeakMap,m=new WeakMap,p=new WeakMap,v=new WeakMap,y=new WeakMap,A=new WeakMap,R=new WeakMap,P),O=new(V=class{constructor(){c(this,S,u(null))}get current(){return f(a(this,S))}set current(e){d(a(this,S),e)}},S=new WeakMap,V),T=new(j=class{constructor(){c(this,k,u(!1))}get current(){return f(a(this,k))}set current(e){d(a(this,k),e)}},k=new WeakMap,j),D.v=()=>T.current=!0);function Ue(t){Object.assign(E,t)}export{be as H,_e as N,ge as P,he as S,ye as a,J as b,Re as c,le as d,ie as e,pe as f,ve as g,ae as h,Q as i,N as j,oe as k,fe as l,ue as m,O as n,Y as o,E as p,ce as q,we as r,me as s,de as t,Ae as u,Ue as v,Se as w}; diff --git a/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.br b/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.br new file mode 100644 index 0000000..783809f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.br differ diff --git a/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.gz b/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.gz new file mode 100644 index 0000000..c12a01a Binary files /dev/null and b/apps/dashboard/build/_app/immutable/chunks/urMNLRPv.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js b/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js deleted file mode 100644 index d5aa667..0000000 --- a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js +++ /dev/null @@ -1,2 +0,0 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.tUYz2cuZ.js","../chunks/Bzak7iHL.js","../chunks/DUC-ssvh.js","../chunks/BBD-8XME.js","../chunks/DNn3Nckx.js","../chunks/CKcqngaU.js","../chunks/RaRNNC-y.js","../chunks/gqVpgJ8U.js","../chunks/C5a--lgk.js","../chunks/DZuEJlJ5.js","../chunks/BVZqxpRe.js","../chunks/CBWLjDtu.js","../chunks/BxfT1SOA.js","../chunks/DtXypsxD.js","../chunks/BexJutgU.js","../chunks/Br8WXJxx.js","../chunks/cIQD_rb4.js","../chunks/BeSd-T80.js","../chunks/CruZBLYW.js","../assets/0.BChctYiF.css","../nodes/1.CssKLfNx.js","../chunks/D1BK9eoQ.js","../nodes/2.1GJQ3fqu.js","../nodes/3.qBGkDYYb.js","../nodes/4.BYgf5djd.js","../chunks/DBfx-YTU.js","../chunks/BcuCGYSa.js","../nodes/5.DVWNDcwc.js","../chunks/CZ45jJaw.js","../chunks/CzkEqL6J.js","../assets/5.BBx09UGv.css","../nodes/6.CBsTT29y.js","../chunks/C-QujEl6.js","../nodes/7.UPq6Ja2I.js","../nodes/8.B2QXJFjO.js","../nodes/9.B4Pp7ME7.js","../nodes/10.evd80og6.js","../nodes/11.gY7s4Ta3.js"])))=>i.map(i=>d[i]); -var M=r=>{throw TypeError(r)};var Q=(r,t,e)=>t.has(r)||M("Cannot "+e);var m=(r,t,e)=>(Q(r,t,"read from private field"),e?e.call(r):t.get(r)),H=(r,t,e)=>t.has(r)?M("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(r):t.set(r,e),J=(r,t,e,n)=>(Q(r,t,"write to private field"),n?n.call(r,e):t.set(r,e),e);import{J as Z,a0 as ut,b as lt,E as mt,a1 as _t,a4 as dt,a5 as ft,a6 as $,a2 as ht,ac as vt,h as q,L as gt,g as v,b7 as Et,Y as yt,X as pt,p as Pt,ag as Rt,ah as bt,I as Ot,f as L,d as At,a as Tt,s as W,e as Lt,r as wt,t as It,u as V}from"../chunks/BBD-8XME.js";import{h as kt,m as Dt,u as xt,s as Vt}from"../chunks/DNn3Nckx.js";import"../chunks/Bzak7iHL.js";import{o as St}from"../chunks/DUC-ssvh.js";import{i as B}from"../chunks/RaRNNC-y.js";import{a as y,c as k,f as et,t as jt}from"../chunks/CKcqngaU.js";import{B as Ct}from"../chunks/gqVpgJ8U.js";import{b as S}from"../chunks/DtXypsxD.js";import{p as Y}from"../chunks/CzkEqL6J.js";function j(r,t,e){var n;Z&&(n=vt,ut());var o=new Ct(r);lt(()=>{var l=t()??null;if(Z){var s=_t(n),a=s===ht,i=l!==null;if(a!==i){var P=dt();ft(P),o.anchor=P,$(!1),o.ensure(l,l&&(c=>e(c,l))),$(!0);return}}o.ensure(l,l&&(c=>e(c,l)))},mt)}function Bt(r){return class extends Yt{constructor(t){super({component:r,...t})}}}var p,d;class Yt{constructor(t){H(this,p);H(this,d);var l;var e=new Map,n=(s,a)=>{var i=pt(a,!1,!1);return e.set(s,i),i};const o=new Proxy({...t.props||{},$$events:{}},{get(s,a){return v(e.get(a)??n(a,Reflect.get(s,a)))},has(s,a){return a===gt?!0:(v(e.get(a)??n(a,Reflect.get(s,a))),Reflect.has(s,a))},set(s,a,i){return q(e.get(a)??n(a,i),i),Reflect.set(s,a,i)}});J(this,d,(t.hydrate?kt:Dt)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),(!((l=t==null?void 0:t.props)!=null&&l.$$host)||t.sync===!1)&&Et(),J(this,p,o.$$events);for(const s of Object.keys(m(this,d)))s==="$set"||s==="$destroy"||s==="$on"||yt(this,s,{get(){return m(this,d)[s]},set(a){m(this,d)[s]=a},enumerable:!0});m(this,d).$set=s=>{Object.assign(o,s)},m(this,d).$destroy=()=>{xt(m(this,d))}}$set(t){m(this,d).$set(t)}$on(t,e){m(this,p)[t]=m(this,p)[t]||[];const n=(...o)=>e.call(this,...o);return m(this,p)[t].push(n),()=>{m(this,p)[t]=m(this,p)[t].filter(o=>o!==n)}}$destroy(){m(this,d).$destroy()}}p=new WeakMap,d=new WeakMap;const qt="modulepreload",Ft=function(r,t){return new URL(r,t).href},tt={},_=function(t,e,n){let o=Promise.resolve();if(e&&e.length>0){let s=function(c){return Promise.all(c.map(g=>Promise.resolve(g).then(R=>({status:"fulfilled",value:R}),R=>({status:"rejected",reason:R}))))};const a=document.getElementsByTagName("link"),i=document.querySelector("meta[property=csp-nonce]"),P=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));o=s(e.map(c=>{if(c=Ft(c,n),c in tt)return;tt[c]=!0;const g=c.endsWith(".css"),R=g?'[rel="stylesheet"]':"";if(!!n)for(let b=a.length-1;b>=0;b--){const u=a[b];if(u.href===c&&(!g||u.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${R}`))return;const E=document.createElement("link");if(E.rel=g?"stylesheet":qt,g||(E.as="script"),E.crossOrigin="",E.href=c,P&&E.setAttribute("nonce",P),document.head.appendChild(E),g)return new Promise((b,u)=>{E.addEventListener("load",b),E.addEventListener("error",()=>u(new Error(`Unable to preload CSS for ${c}`)))})}))}function l(s){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=s,window.dispatchEvent(a),!a.defaultPrevented)throw s}return o.then(s=>{for(const a of s||[])a.status==="rejected"&&l(a.reason);return t().catch(l)})},ae={};var Nt=et('
'),Ut=et(" ",1);function Gt(r,t){Pt(t,!0);let e=Y(t,"components",23,()=>[]),n=Y(t,"data_0",3,null),o=Y(t,"data_1",3,null),l=Y(t,"data_2",3,null);Rt(()=>t.stores.page.set(t.page)),bt(()=>{t.stores,t.page,t.constructors,e(),t.form,n(),o(),l(),t.stores.page.notify()});let s=W(!1),a=W(!1),i=W(null);St(()=>{const u=t.stores.page.subscribe(()=>{v(s)&&(q(a,!0),Ot().then(()=>{q(i,document.title||"untitled page",!0)}))});return q(s,!0),u});const P=V(()=>t.constructors[2]);var c=Ut(),g=L(c);{var R=u=>{const O=V(()=>t.constructors[0]);var A=k(),D=L(A);j(D,()=>v(O),(T,w)=>{S(w(T,{get data(){return n()},get form(){return t.form},get params(){return t.page.params},children:(f,Jt)=>{var z=k(),at=L(z);{var st=I=>{const F=V(()=>t.constructors[1]);var x=k(),N=L(x);j(N,()=>v(F),(U,G)=>{S(G(U,{get data(){return o()},get form(){return t.form},get params(){return t.page.params},children:(h,Wt)=>{var K=k(),ot=L(K);j(ot,()=>v(P),(it,ct)=>{S(ct(it,{get data(){return l()},get form(){return t.form},get params(){return t.page.params}}),C=>e()[2]=C,()=>{var C;return(C=e())==null?void 0:C[2]})}),y(h,K)},$$slots:{default:!0}}),h=>e()[1]=h,()=>{var h;return(h=e())==null?void 0:h[1]})}),y(I,x)},nt=I=>{const F=V(()=>t.constructors[1]);var x=k(),N=L(x);j(N,()=>v(F),(U,G)=>{S(G(U,{get data(){return o()},get form(){return t.form},get params(){return t.page.params}}),h=>e()[1]=h,()=>{var h;return(h=e())==null?void 0:h[1]})}),y(I,x)};B(at,I=>{t.constructors[2]?I(st):I(nt,!1)})}y(f,z)},$$slots:{default:!0}}),f=>e()[0]=f,()=>{var f;return(f=e())==null?void 0:f[0]})}),y(u,A)},X=u=>{const O=V(()=>t.constructors[0]);var A=k(),D=L(A);j(D,()=>v(O),(T,w)=>{S(w(T,{get data(){return n()},get form(){return t.form},get params(){return t.page.params}}),f=>e()[0]=f,()=>{var f;return(f=e())==null?void 0:f[0]})}),y(u,A)};B(g,u=>{t.constructors[1]?u(R):u(X,!1)})}var E=At(g,2);{var b=u=>{var O=Nt(),A=Lt(O);{var D=T=>{var w=jt();It(()=>Vt(w,v(i))),y(T,w)};B(A,T=>{v(a)&&T(D)})}wt(O),y(u,O)};B(E,u=>{v(s)&&u(b)})}y(r,c),Tt()}const se=Bt(Gt),ne=[()=>_(()=>import("../nodes/0.tUYz2cuZ.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),import.meta.url),()=>_(()=>import("../nodes/1.CssKLfNx.js"),__vite__mapDeps([20,1,21,3,4,5,17,2,15,16]),import.meta.url),()=>_(()=>import("../nodes/2.1GJQ3fqu.js"),__vite__mapDeps([22,1,3,5,9,7]),import.meta.url),()=>_(()=>import("../nodes/3.qBGkDYYb.js"),__vite__mapDeps([23,1,21,3,2,16,15,17]),import.meta.url),()=>_(()=>import("../nodes/4.BYgf5djd.js"),__vite__mapDeps([24,1,3,4,5,6,7,8,10,11,25,12,26]),import.meta.url),()=>_(()=>import("../nodes/5.DVWNDcwc.js"),__vite__mapDeps([27,1,21,3,4,5,6,7,8,25,14,15,18,28,10,11,29,30]),import.meta.url),()=>_(()=>import("../nodes/6.CBsTT29y.js"),__vite__mapDeps([31,1,2,3,4,5,6,7,8,10,11,25,12,32,14,15,17,13,29,28,26,18]),import.meta.url),()=>_(()=>import("../nodes/7.UPq6Ja2I.js"),__vite__mapDeps([33,1,2,3,4,5,6,7,8,11,26]),import.meta.url),()=>_(()=>import("../nodes/8.B2QXJFjO.js"),__vite__mapDeps([34,1,2,3,4,5,6,7,8,10,11,25,12,32,26,28]),import.meta.url),()=>_(()=>import("../nodes/9.B4Pp7ME7.js"),__vite__mapDeps([35,1,2,3,4,5,6,7,8,11,25,14,15,26,18]),import.meta.url),()=>_(()=>import("../nodes/10.evd80og6.js"),__vite__mapDeps([36,1,2,3,4,5,6,7,8,25,26]),import.meta.url),()=>_(()=>import("../nodes/11.gY7s4Ta3.js"),__vite__mapDeps([37,1,2,3,4,5,6,7,8,25,32,26,28]),import.meta.url)],oe=[],ie={"/":[3],"/(app)/explore":[4,[2]],"/(app)/feed":[5,[2]],"/(app)/graph":[6,[2]],"/(app)/intentions":[7,[2]],"/(app)/memories":[8,[2]],"/(app)/settings":[9,[2]],"/(app)/stats":[10,[2]],"/(app)/timeline":[11,[2]]},rt={handleError:(({error:r})=>{console.error(r)}),reroute:(()=>{}),transport:{}},Ht=Object.fromEntries(Object.entries(rt.transport).map(([r,t])=>[r,t.decode])),ce=Object.fromEntries(Object.entries(rt.transport).map(([r,t])=>[r,t.encode])),ue=!1,le=(r,t)=>Ht[r](t);export{le as decode,Ht as decoders,ie as dictionary,ce as encoders,ue as hash,rt as hooks,ae as matchers,ne as nodes,se as root,oe as server_loads}; diff --git a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.br b/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.br deleted file mode 100644 index 441bb9a..0000000 Binary files a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.gz b/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.gz deleted file mode 100644 index 48cb52d..0000000 Binary files a/apps/dashboard/build/_app/immutable/entry/app.C8-C7f17.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js new file mode 100644 index 0000000..728e513 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.CrGZHYMq.js","../chunks/Bzak7iHL.js","../chunks/DeTA_5mp.js","../chunks/nyjtQ1Ok.js","../chunks/C4L78yoI.js","../chunks/B0IenmM-.js","../chunks/B17metm1.js","../chunks/C3lo34Tx.js","../chunks/BilMa3tw.js","../chunks/Ckx7gB9J.js","../chunks/BBOOwRwQ.js","../chunks/BgOFZ9jq.js","../chunks/BOVu8he9.js","../chunks/DAhpUNCK.js","../chunks/C3ZC25l2.js","../chunks/DAj0p1rI.js","../chunks/DwA4GIGc.js","../chunks/urMNLRPv.js","../chunks/B6fk3AxI.js","../chunks/D_N1HvA5.js","../assets/0.D08DCOSm.css","../nodes/1.DUm1yZ6r.js","../chunks/Ck7jSX2P.js","../nodes/2.CGw3wCmL.js","../nodes/3.lMYbfdAF.js","../nodes/4.D5K4f9dC.js","../chunks/D2QmVWrb.js","../chunks/BcuCGYSa.js","../nodes/5.DxlkmHN2.js","../chunks/BNytumrp.js","../chunks/BPtVz5jm.js","../assets/5.BBx09UGv.css","../nodes/6.BEn_WCBk.js","../chunks/J2LZW-kP.js","../nodes/7.404BTmXF.js","../nodes/8.CJVG2CGC.js","../nodes/9.BHweFYNs.js","../nodes/10.CuqTW1-V.js","../nodes/11.C9Q0t9wJ.js"])))=>i.map(i=>d[i]); +var Q=r=>{throw TypeError(r)};var X=(r,t,e)=>t.has(r)||Q("Cannot "+e);var m=(r,t,e)=>(X(r,t,"read from private field"),e?e.call(r):t.get(r)),H=(r,t,e)=>t.has(r)?Q("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(r):t.set(r,e),W=(r,t,e,n)=>(X(r,t,"write to private field"),n?n.call(r,e):t.set(r,e),e);import{T as Z,a7 as ut,b as lt,E as mt,a8 as _t,ab as dt,ac as ft,ad as $,a9 as ht,aj as vt,h as q,N as gt,g as v,b7 as Et,a3 as yt,a2 as pt,p as Pt,l as Rt,m as bt,R as Ot,f as L,d as Tt,a as At,s as z,e as Lt,r as wt,t as kt,u as V}from"../chunks/nyjtQ1Ok.js";import{h as Dt,m as It,u as xt,s as Vt}from"../chunks/C4L78yoI.js";import"../chunks/Bzak7iHL.js";import{o as St}from"../chunks/DeTA_5mp.js";import{i as B}from"../chunks/B17metm1.js";import{a as y,c as D,f as et,t as jt}from"../chunks/B0IenmM-.js";import{B as Ct}from"../chunks/C3lo34Tx.js";import{b as S}from"../chunks/DAhpUNCK.js";import{p as N}from"../chunks/BPtVz5jm.js";function j(r,t,e){var n;Z&&(n=vt,ut());var o=new Ct(r);lt(()=>{var l=t()??null;if(Z){var s=_t(n),a=s===ht,i=l!==null;if(a!==i){var P=dt();ft(P),o.anchor=P,$(!1),o.ensure(l,l&&(c=>e(c,l))),$(!0);return}}o.ensure(l,l&&(c=>e(c,l)))},mt)}function Bt(r){return class extends Nt{constructor(t){super({component:r,...t})}}}var p,d;class Nt{constructor(t){H(this,p);H(this,d);var l;var e=new Map,n=(s,a)=>{var i=pt(a,!1,!1);return e.set(s,i),i};const o=new Proxy({...t.props||{},$$events:{}},{get(s,a){return v(e.get(a)??n(a,Reflect.get(s,a)))},has(s,a){return a===gt?!0:(v(e.get(a)??n(a,Reflect.get(s,a))),Reflect.has(s,a))},set(s,a,i){return q(e.get(a)??n(a,i),i),Reflect.set(s,a,i)}});W(this,d,(t.hydrate?Dt:It)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),(!((l=t==null?void 0:t.props)!=null&&l.$$host)||t.sync===!1)&&Et(),W(this,p,o.$$events);for(const s of Object.keys(m(this,d)))s==="$set"||s==="$destroy"||s==="$on"||yt(this,s,{get(){return m(this,d)[s]},set(a){m(this,d)[s]=a},enumerable:!0});m(this,d).$set=s=>{Object.assign(o,s)},m(this,d).$destroy=()=>{xt(m(this,d))}}$set(t){m(this,d).$set(t)}$on(t,e){m(this,p)[t]=m(this,p)[t]||[];const n=(...o)=>e.call(this,...o);return m(this,p)[t].push(n),()=>{m(this,p)[t]=m(this,p)[t].filter(o=>o!==n)}}$destroy(){m(this,d).$destroy()}}p=new WeakMap,d=new WeakMap;const qt="modulepreload",Ft=function(r,t){return new URL(r,t).href},tt={},_=function(t,e,n){let o=Promise.resolve();if(e&&e.length>0){let s=function(c){return Promise.all(c.map(g=>Promise.resolve(g).then(R=>({status:"fulfilled",value:R}),R=>({status:"rejected",reason:R}))))};const a=document.getElementsByTagName("link"),i=document.querySelector("meta[property=csp-nonce]"),P=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));o=s(e.map(c=>{if(c=Ft(c,n),c in tt)return;tt[c]=!0;const g=c.endsWith(".css"),R=g?'[rel="stylesheet"]':"";if(!!n)for(let b=a.length-1;b>=0;b--){const u=a[b];if(u.href===c&&(!g||u.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${R}`))return;const E=document.createElement("link");if(E.rel=g?"stylesheet":qt,g||(E.as="script"),E.crossOrigin="",E.href=c,P&&E.setAttribute("nonce",P),document.head.appendChild(E),g)return new Promise((b,u)=>{E.addEventListener("load",b),E.addEventListener("error",()=>u(new Error(`Unable to preload CSS for ${c}`)))})}))}function l(s){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=s,window.dispatchEvent(a),!a.defaultPrevented)throw s}return o.then(s=>{for(const a of s||[])a.status==="rejected"&&l(a.reason);return t().catch(l)})},ae={};var Ut=et('
'),Yt=et(" ",1);function Gt(r,t){Pt(t,!0);let e=N(t,"components",23,()=>[]),n=N(t,"data_0",3,null),o=N(t,"data_1",3,null),l=N(t,"data_2",3,null);Rt(()=>t.stores.page.set(t.page)),bt(()=>{t.stores,t.page,t.constructors,e(),t.form,n(),o(),l(),t.stores.page.notify()});let s=z(!1),a=z(!1),i=z(null);St(()=>{const u=t.stores.page.subscribe(()=>{v(s)&&(q(a,!0),Ot().then(()=>{q(i,document.title||"untitled page",!0)}))});return q(s,!0),u});const P=V(()=>t.constructors[2]);var c=Yt(),g=L(c);{var R=u=>{const O=V(()=>t.constructors[0]);var T=D(),I=L(T);j(I,()=>v(O),(A,w)=>{S(w(A,{get data(){return n()},get form(){return t.form},get params(){return t.page.params},children:(f,Wt)=>{var K=D(),at=L(K);{var st=k=>{const F=V(()=>t.constructors[1]);var x=D(),U=L(x);j(U,()=>v(F),(Y,G)=>{S(G(Y,{get data(){return o()},get form(){return t.form},get params(){return t.page.params},children:(h,zt)=>{var M=D(),ot=L(M);j(ot,()=>v(P),(it,ct)=>{S(ct(it,{get data(){return l()},get form(){return t.form},get params(){return t.page.params}}),C=>e()[2]=C,()=>{var C;return(C=e())==null?void 0:C[2]})}),y(h,M)},$$slots:{default:!0}}),h=>e()[1]=h,()=>{var h;return(h=e())==null?void 0:h[1]})}),y(k,x)},nt=k=>{const F=V(()=>t.constructors[1]);var x=D(),U=L(x);j(U,()=>v(F),(Y,G)=>{S(G(Y,{get data(){return o()},get form(){return t.form},get params(){return t.page.params}}),h=>e()[1]=h,()=>{var h;return(h=e())==null?void 0:h[1]})}),y(k,x)};B(at,k=>{t.constructors[2]?k(st):k(nt,!1)})}y(f,K)},$$slots:{default:!0}}),f=>e()[0]=f,()=>{var f;return(f=e())==null?void 0:f[0]})}),y(u,T)},J=u=>{const O=V(()=>t.constructors[0]);var T=D(),I=L(T);j(I,()=>v(O),(A,w)=>{S(w(A,{get data(){return n()},get form(){return t.form},get params(){return t.page.params}}),f=>e()[0]=f,()=>{var f;return(f=e())==null?void 0:f[0]})}),y(u,T)};B(g,u=>{t.constructors[1]?u(R):u(J,!1)})}var E=Tt(g,2);{var b=u=>{var O=Ut(),T=Lt(O);{var I=A=>{var w=jt();kt(()=>Vt(w,v(i))),y(A,w)};B(T,A=>{v(a)&&A(I)})}wt(O),y(u,O)};B(E,u=>{v(s)&&u(b)})}y(r,c),At()}const se=Bt(Gt),ne=[()=>_(()=>import("../nodes/0.CrGZHYMq.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]),import.meta.url),()=>_(()=>import("../nodes/1.DUm1yZ6r.js"),__vite__mapDeps([21,1,19,3,4,5,22,17,2,15,16]),import.meta.url),()=>_(()=>import("../nodes/2.CGw3wCmL.js"),__vite__mapDeps([23,1,3,5,9,7]),import.meta.url),()=>_(()=>import("../nodes/3.lMYbfdAF.js"),__vite__mapDeps([24,1,19,3,2,22,16,15,17]),import.meta.url),()=>_(()=>import("../nodes/4.D5K4f9dC.js"),__vite__mapDeps([25,1,3,4,5,6,7,8,10,11,26,12,27]),import.meta.url),()=>_(()=>import("../nodes/5.DxlkmHN2.js"),__vite__mapDeps([28,1,19,3,4,5,6,7,8,26,22,14,15,18,29,10,11,30,31]),import.meta.url),()=>_(()=>import("../nodes/6.BEn_WCBk.js"),__vite__mapDeps([32,1,2,3,4,5,6,7,8,10,11,26,12,33,14,15,17,13,30,29,27,18]),import.meta.url),()=>_(()=>import("../nodes/7.404BTmXF.js"),__vite__mapDeps([34,1,2,3,4,5,6,7,8,11,27]),import.meta.url),()=>_(()=>import("../nodes/8.CJVG2CGC.js"),__vite__mapDeps([35,1,2,3,4,5,6,7,8,10,11,26,12,33,27,29]),import.meta.url),()=>_(()=>import("../nodes/9.BHweFYNs.js"),__vite__mapDeps([36,1,2,3,4,5,6,7,8,11,26,14,15,27,18]),import.meta.url),()=>_(()=>import("../nodes/10.CuqTW1-V.js"),__vite__mapDeps([37,1,2,3,4,5,6,7,8,26,27]),import.meta.url),()=>_(()=>import("../nodes/11.C9Q0t9wJ.js"),__vite__mapDeps([38,1,2,3,4,5,6,7,8,26,33,27,29]),import.meta.url)],oe=[],ie={"/":[3],"/(app)/explore":[4,[2]],"/(app)/feed":[5,[2]],"/(app)/graph":[6,[2]],"/(app)/intentions":[7,[2]],"/(app)/memories":[8,[2]],"/(app)/settings":[9,[2]],"/(app)/stats":[10,[2]],"/(app)/timeline":[11,[2]]},rt={handleError:(({error:r})=>{console.error(r)}),reroute:(()=>{}),transport:{}},Ht=Object.fromEntries(Object.entries(rt.transport).map(([r,t])=>[r,t.decode])),ce=Object.fromEntries(Object.entries(rt.transport).map(([r,t])=>[r,t.encode])),ue=!1,le=(r,t)=>Ht[r](t);export{le as decode,Ht as decoders,ie as dictionary,ce as encoders,ue as hash,rt as hooks,ae as matchers,ne as nodes,se as root,oe as server_loads}; diff --git a/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.br b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.br new file mode 100644 index 0000000..8a0d14f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.br differ diff --git a/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.gz b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.gz new file mode 100644 index 0000000..b87fcba Binary files /dev/null and b/apps/dashboard/build/_app/immutable/entry/app.DzQ7RYYG.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js new file mode 100644 index 0000000..8fe18fd --- /dev/null +++ b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js @@ -0,0 +1 @@ +import{a as r}from"../chunks/DwA4GIGc.js";import{w as t}from"../chunks/urMNLRPv.js";export{t as load_css,r as start}; diff --git a/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.br b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.br new file mode 100644 index 0000000..01fa819 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.br differ diff --git a/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.gz b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.gz new file mode 100644 index 0000000..a1bc86f Binary files /dev/null and b/apps/dashboard/build/_app/immutable/entry/start.CM2cmm4m.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js b/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js deleted file mode 100644 index aa1cf87..0000000 --- a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js +++ /dev/null @@ -1 +0,0 @@ -import{a as r}from"../chunks/cIQD_rb4.js";import{w as t}from"../chunks/BeSd-T80.js";export{t as load_css,r as start}; diff --git a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.br b/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.br deleted file mode 100644 index a38b9d4..0000000 Binary files a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.gz b/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.gz deleted file mode 100644 index 44f8437..0000000 Binary files a/apps/dashboard/build/_app/immutable/entry/start.DA6kJu-O.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js new file mode 100644 index 0000000..def5885 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js @@ -0,0 +1,3 @@ +import"../chunks/Bzak7iHL.js";import{o as Te}from"../chunks/DeTA_5mp.js";import{f as xe,d as n,e as a,r as t,t as A,p as qe,a as Ie,h as c,g as s,s as U,u as X,O as Ne}from"../chunks/nyjtQ1Ok.js";import{s as v,d as je,a as $}from"../chunks/C4L78yoI.js";import{i as N}from"../chunks/B17metm1.js";import{e as Y,i as Z}from"../chunks/BilMa3tw.js";import{c as De,a as b,f as g}from"../chunks/B0IenmM-.js";import{s as ze}from"../chunks/Ckx7gB9J.js";import{s as P,r as Ge}from"../chunks/BBOOwRwQ.js";import{s as ee}from"../chunks/BgOFZ9jq.js";import{b as Re}from"../chunks/BOVu8he9.js";import{b as He}from"../chunks/DAhpUNCK.js";import{a as k,s as be}from"../chunks/C3ZC25l2.js";import{s as Oe,g as me}from"../chunks/DwA4GIGc.js";import{b as _}from"../chunks/urMNLRPv.js";import{s as ge,w as fe,a as Ve,i as We,m as Qe}from"../chunks/B6fk3AxI.js";import"../chunks/D_N1HvA5.js";const Be=()=>{const m=Oe;return{page:{subscribe:m.page.subscribe},navigating:{subscribe:m.navigating.subscribe},updated:m.updated}},Je={subscribe(m){return Be().page.subscribe(m)}};var Ue=g('
');function Xe(m){const h=()=>k(ge,"$suppressedCount",M),[M,K]=be();var L=De(),j=xe(L);{var D=f=>{var F=Ue(),d=n(a(F),2),u=a(d);t(d),t(F),A(()=>v(u,`Actively forgetting ${h()??""} ${h()===1?"memory":"memories"}`)),b(f,F)};N(j,f=>{h()>0&&f(D)})}b(m,L),K()}var Ye=g(' '),Ze=g(''),Pe=g(' '),et=g(''),tt=g('
No matches
'),at=g('
esc
'),st=g('
',1);function yt(m,h){qe(h,!0);const M=()=>k(Je,"$page",f),K=()=>k(We,"$isConnected",f),L=()=>k(Qe,"$memoryCount",f),j=()=>k(Ve,"$avgRetention",f),D=()=>k(ge,"$suppressedCount",f),[f,F]=be();let d=U(!1),u=U(""),C=U(void 0);Te(()=>{fe.connect();function r(e){if((e.metaKey||e.ctrlKey)&&e.key==="k"){e.preventDefault(),c(d,!s(d)),c(u,""),s(d)&&requestAnimationFrame(()=>{var o;return(o=s(C))==null?void 0:o.focus()});return}if(e.key==="Escape"&&s(d)){c(d,!1);return}if(e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement)return;if(e.key==="/"){e.preventDefault();const o=document.querySelector('input[type="text"]');o==null||o.focus();return}const i={g:"/graph",m:"/memories",t:"/timeline",f:"/feed",e:"/explore",i:"/intentions",s:"/stats"}[e.key.toLowerCase()];i&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&(e.preventDefault(),me(`${_}${i}`))}return window.addEventListener("keydown",r),()=>{fe.disconnect(),window.removeEventListener("keydown",r)}});const S=[{href:"/graph",label:"Graph",icon:"◎",shortcut:"G"},{href:"/memories",label:"Memories",icon:"◈",shortcut:"M"},{href:"/timeline",label:"Timeline",icon:"◷",shortcut:"T"},{href:"/feed",label:"Feed",icon:"◉",shortcut:"F"},{href:"/explore",label:"Explore",icon:"◬",shortcut:"E"},{href:"/intentions",label:"Intentions",icon:"◇",shortcut:"I"},{href:"/stats",label:"Stats",icon:"◫",shortcut:"S"},{href:"/settings",label:"Settings",icon:"⚙",shortcut:","}],he=S.slice(0,5);function te(r,e){const p=e.startsWith(_)?e.slice(_.length)||"/":e;return r==="/graph"?p==="/"||p==="/graph":p.startsWith(r)}let T=X(()=>s(u)?S.filter(r=>r.label.toLowerCase().includes(s(u).toLowerCase())):S);function ae(r){c(d,!1),c(u,""),me(`${_}${r}`)}var se=st(),z=n(xe(se),6),G=a(z),re=a(G),R=n(re,2);Y(R,21,()=>S,Z,(r,e)=>{const p=X(()=>te(s(e).href,M().url.pathname));var i=Ye(),o=a(i),y=a(o,!0);t(o);var x=n(o,2),E=a(x,!0);t(x);var q=n(x,2),l=a(q,!0);t(q),t(i),A(()=>{P(i,"href",`${_??""}${s(e).href??""}`),ee(i,1,`flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 text-sm + ${s(p)?"bg-synapse/15 text-synapse-glow border border-synapse/30 shadow-[0_0_12px_rgba(99,102,241,0.15)] nav-active-border":"text-dim hover:text-text hover:bg-white/[0.03] border border-transparent"}`),v(y,s(e).icon),v(E,s(e).label),v(l,s(e).shortcut)}),b(r,i)}),t(R);var H=n(R,2),_e=a(H);t(H);var ne=n(H,2),O=a(ne),oe=a(O),ie=n(oe,2),ye=a(ie,!0);t(ie),t(O);var V=n(O,2),W=a(V),we=a(W);t(W);var le=n(W,2),$e=a(le);t(le),t(V);var ke=n(V,2);{var Fe=r=>{var e=Ze(),p=a(e);Xe(p),t(e),b(r,e)};N(ke,r=>{D()>0&&r(Fe)})}t(ne),t(G);var Q=n(G,2),de=a(Q),Ce=a(de);ze(Ce,()=>h.children),t(de),t(Q);var pe=n(Q,2),ce=a(pe),ve=a(ce);Y(ve,17,()=>he,Z,(r,e)=>{const p=X(()=>te(s(e).href,M().url.pathname));var i=Pe(),o=a(i),y=a(o,!0);t(o);var x=n(o,2),E=a(x,!0);t(x),t(i),A(()=>{P(i,"href",`${_??""}${s(e).href??""}`),ee(i,1,`flex flex-col items-center gap-0.5 px-3 py-2 rounded-lg transition-all min-w-[3.5rem] + ${s(p)?"text-synapse-glow":"text-muted"}`),v(y,s(e).icon),v(E,s(e).label)}),b(r,i)});var Ee=n(ve,2);t(ce),t(pe),t(z);var Ae=n(z,2);{var Me=r=>{var e=at(),p=a(e),i=a(p),o=n(a(i),2);Ge(o),He(o,l=>c(C,l),()=>s(C)),Ne(2),t(i);var y=n(i,2),x=a(y);Y(x,17,()=>s(T),Z,(l,w)=>{var I=et(),B=a(I),Ke=a(B,!0);t(B);var J=n(B,2),Le=a(J,!0);t(J);var ue=n(J,2),Se=a(ue,!0);t(ue),t(I),A(()=>{v(Ke,s(w).icon),v(Le,s(w).label),v(Se,s(w).shortcut)}),$("click",I,()=>ae(s(w).href)),b(l,I)});var E=n(x,2);{var q=l=>{var w=tt();b(l,w)};N(E,l=>{s(T).length===0&&l(q)})}t(y),t(p),t(e),$("keydown",e,l=>{l.key==="Escape"&&c(d,!1)}),$("click",e,l=>{l.target===l.currentTarget&&c(d,!1)}),$("keydown",o,l=>{l.key==="Enter"&&s(T).length>0&&ae(s(T)[0].href)}),Re(o,()=>s(u),l=>c(u,l)),b(r,e)};N(Ae,r=>{s(d)&&r(Me)})}A(r=>{P(re,"href",`${_??""}/graph`),ee(oe,1,`w-2 h-2 rounded-full ${K()?"bg-recall animate-pulse-glow":"bg-decay"}`),v(ye,K()?"Connected":"Offline"),v(we,`${L()??""} memories`),v($e,`${r??""}% retention`)},[()=>(j()*100).toFixed(0)]),$("click",_e,()=>{c(d,!0),c(u,""),requestAnimationFrame(()=>{var r;return(r=s(C))==null?void 0:r.focus()})}),$("click",Ee,()=>{c(d,!0),c(u,""),requestAnimationFrame(()=>{var r;return(r=s(C))==null?void 0:r.focus()})}),b(m,se),Ie(),F()}je(["click","keydown"]);export{yt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.br b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.br new file mode 100644 index 0000000..4344dfd Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.gz b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.gz new file mode 100644 index 0000000..3d6bcfc Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/0.CrGZHYMq.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js b/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js deleted file mode 100644 index e4ec539..0000000 --- a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js +++ /dev/null @@ -1,3 +0,0 @@ -import"../chunks/Bzak7iHL.js";import{o as Me}from"../chunks/DUC-ssvh.js";import{p as Ke,d as o,f as Le,t as L,a as Te,h as d,g as t,e as s,r as a,s as R,u as H,G as qe}from"../chunks/BBD-8XME.js";import{d as Fe,a as g,s as v}from"../chunks/DNn3Nckx.js";import{i as de}from"../chunks/RaRNNC-y.js";import{e as V,i as W}from"../chunks/C5a--lgk.js";import{a as _,f as y}from"../chunks/CKcqngaU.js";import{s as Se}from"../chunks/DZuEJlJ5.js";import{s as O,r as Ae}from"../chunks/BVZqxpRe.js";import{s as Q}from"../chunks/CBWLjDtu.js";import{b as Ne}from"../chunks/BxfT1SOA.js";import{b as De}from"../chunks/DtXypsxD.js";import{s as Ge,a as T}from"../chunks/BexJutgU.js";import{s as Ie,g as ce}from"../chunks/cIQD_rb4.js";import{b as u}from"../chunks/BeSd-T80.js";import{w as pe,a as je,i as ze,m as Re}from"../chunks/CruZBLYW.js";const He=()=>{const x=Ie;return{page:{subscribe:x.page.subscribe},navigating:{subscribe:x.navigating.subscribe},updated:x.updated}},Ve={subscribe(x){return He().page.subscribe(x)}};var We=y(' '),Oe=y(' '),Qe=y(''),Be=y('
No matches
'),Je=y('
esc
'),Ue=y('
',1);function vt(x,q){Ke(q,!0);const B=()=>T(Ve,"$page",$),J=()=>T(ze,"$isConnected",$),ve=()=>T(Re,"$memoryCount",$),me=()=>T(je,"$avgRetention",$),[$,fe]=Ge();let c=R(!1),f=R(""),w=R(void 0);Me(()=>{pe.connect();function r(e){if((e.metaKey||e.ctrlKey)&&e.key==="k"){e.preventDefault(),d(c,!t(c)),d(f,""),t(c)&&requestAnimationFrame(()=>{var n;return(n=t(w))==null?void 0:n.focus()});return}if(e.key==="Escape"&&t(c)){d(c,!1);return}if(e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement)return;if(e.key==="/"){e.preventDefault();const n=document.querySelector('input[type="text"]');n==null||n.focus();return}const i={g:"/graph",m:"/memories",t:"/timeline",f:"/feed",e:"/explore",i:"/intentions",s:"/stats"}[e.key.toLowerCase()];i&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&(e.preventDefault(),ce(`${u}${i}`))}return window.addEventListener("keydown",r),()=>{pe.disconnect(),window.removeEventListener("keydown",r)}});const C=[{href:"/graph",label:"Graph",icon:"◎",shortcut:"G"},{href:"/memories",label:"Memories",icon:"◈",shortcut:"M"},{href:"/timeline",label:"Timeline",icon:"◷",shortcut:"T"},{href:"/feed",label:"Feed",icon:"◉",shortcut:"F"},{href:"/explore",label:"Explore",icon:"◬",shortcut:"E"},{href:"/intentions",label:"Intentions",icon:"◇",shortcut:"I"},{href:"/stats",label:"Stats",icon:"◫",shortcut:"S"},{href:"/settings",label:"Settings",icon:"⚙",shortcut:","}],xe=C.slice(0,5);function U(r,e){const p=e.startsWith(u)?e.slice(u.length)||"/":e;return r==="/graph"?p==="/"||p==="/graph":p.startsWith(r)}let E=H(()=>t(f)?C.filter(r=>r.label.toLowerCase().includes(t(f).toLowerCase())):C);function X(r){d(c,!1),d(f,""),ce(`${u}${r}`)}var Y=Ue(),F=o(Le(Y),6),S=s(F),Z=s(S),A=o(Z,2);V(A,21,()=>C,W,(r,e)=>{const p=H(()=>U(t(e).href,B().url.pathname));var i=We(),n=s(i),b=s(n,!0);a(n);var m=o(n,2),k=s(m,!0);a(m);var M=o(m,2),l=s(M,!0);a(M),a(i),L(()=>{O(i,"href",`${u??""}${t(e).href??""}`),Q(i,1,`flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 text-sm - ${t(p)?"bg-synapse/15 text-synapse-glow border border-synapse/30 shadow-[0_0_12px_rgba(99,102,241,0.15)] nav-active-border":"text-dim hover:text-text hover:bg-white/[0.03] border border-transparent"}`),v(b,t(e).icon),v(k,t(e).label),v(l,t(e).shortcut)}),_(r,i)}),a(A);var N=o(A,2),ue=s(N);a(N);var P=o(N,2),D=s(P),ee=s(D),te=o(ee,2),be=s(te,!0);a(te),a(D);var ae=o(D,2),G=s(ae),he=s(G);a(G);var se=o(G,2),ge=s(se);a(se),a(ae),a(P),a(S);var I=o(S,2),re=s(I),_e=s(re);Se(_e,()=>q.children),a(re),a(I);var ne=o(I,2),oe=s(ne),ie=s(oe);V(ie,17,()=>xe,W,(r,e)=>{const p=H(()=>U(t(e).href,B().url.pathname));var i=Oe(),n=s(i),b=s(n,!0);a(n);var m=o(n,2),k=s(m,!0);a(m),a(i),L(()=>{O(i,"href",`${u??""}${t(e).href??""}`),Q(i,1,`flex flex-col items-center gap-0.5 px-3 py-2 rounded-lg transition-all min-w-[3.5rem] - ${t(p)?"text-synapse-glow":"text-muted"}`),v(b,t(e).icon),v(k,t(e).label)}),_(r,i)});var ye=o(ie,2);a(oe),a(ne),a(F);var we=o(F,2);{var ke=r=>{var e=Je(),p=s(e),i=s(p),n=o(s(i),2);Ae(n),De(n,l=>d(w,l),()=>t(w)),qe(2),a(i);var b=o(i,2),m=s(b);V(m,17,()=>t(E),W,(l,h)=>{var K=Qe(),j=s(K),$e=s(j,!0);a(j);var z=o(j,2),Ce=s(z,!0);a(z);var le=o(z,2),Ee=s(le,!0);a(le),a(K),L(()=>{v($e,t(h).icon),v(Ce,t(h).label),v(Ee,t(h).shortcut)}),g("click",K,()=>X(t(h).href)),_(l,K)});var k=o(m,2);{var M=l=>{var h=Be();_(l,h)};de(k,l=>{t(E).length===0&&l(M)})}a(b),a(p),a(e),g("keydown",e,l=>{l.key==="Escape"&&d(c,!1)}),g("click",e,l=>{l.target===l.currentTarget&&d(c,!1)}),g("keydown",n,l=>{l.key==="Enter"&&t(E).length>0&&X(t(E)[0].href)}),Ne(n,()=>t(f),l=>d(f,l)),_(r,e)};de(we,r=>{t(c)&&r(ke)})}L(r=>{O(Z,"href",`${u??""}/graph`),Q(ee,1,`w-2 h-2 rounded-full ${J()?"bg-recall animate-pulse-glow":"bg-decay"}`),v(be,J()?"Connected":"Offline"),v(he,`${ve()??""} memories`),v(ge,`${r??""}% retention`)},[()=>(me()*100).toFixed(0)]),g("click",ue,()=>{d(c,!0),d(f,""),requestAnimationFrame(()=>{var r;return(r=t(w))==null?void 0:r.focus()})}),g("click",ye,()=>{d(c,!0),d(f,""),requestAnimationFrame(()=>{var r;return(r=t(w))==null?void 0:r.focus()})}),_(x,Y),Te(),fe()}Fe(["click","keydown"]);export{vt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.br b/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.br deleted file mode 100644 index 15022a7..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.gz b/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.gz deleted file mode 100644 index adf1ff8..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/0.tUYz2cuZ.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js b/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js deleted file mode 100644 index abeb820..0000000 --- a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js +++ /dev/null @@ -1 +0,0 @@ -import"../chunks/Bzak7iHL.js";import{i as h}from"../chunks/D1BK9eoQ.js";import{p as g,f as d,t as l,a as v,d as _,e as s,r as o}from"../chunks/BBD-8XME.js";import{s as p}from"../chunks/DNn3Nckx.js";import{a as x,f as $}from"../chunks/CKcqngaU.js";import{p as m}from"../chunks/BeSd-T80.js";import{s as k}from"../chunks/cIQD_rb4.js";const b={get error(){return m.error},get status(){return m.status}};k.updated.check;const i=b;var E=$("

",1);function C(f,n){g(n,!1),h();var t=E(),r=d(t),c=s(r,!0);o(r);var a=_(r,2),u=s(a,!0);o(a),l(()=>{var e;p(c,i.status),p(u,(e=i.error)==null?void 0:e.message)}),x(f,t),v()}export{C as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.br b/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.br deleted file mode 100644 index 2342405..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.gz b/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.gz deleted file mode 100644 index 925ef2a..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/1.CssKLfNx.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js new file mode 100644 index 0000000..803c235 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js @@ -0,0 +1 @@ +import"../chunks/Bzak7iHL.js";import"../chunks/D_N1HvA5.js";import{p as h,f as g,t as d,a as l,d as v,e as s,r as o}from"../chunks/nyjtQ1Ok.js";import{s as p}from"../chunks/C4L78yoI.js";import{a as _,f as x}from"../chunks/B0IenmM-.js";import{i as $}from"../chunks/Ck7jSX2P.js";import{p as m}from"../chunks/urMNLRPv.js";import{s as k}from"../chunks/DwA4GIGc.js";const b={get error(){return m.error},get status(){return m.status}};k.updated.check;const i=b;var E=x("

",1);function D(f,n){h(n,!1),$();var t=E(),r=g(t),c=s(r,!0);o(r);var a=v(r,2),u=s(a,!0);o(a),d(()=>{var e;p(c,i.status),p(u,(e=i.error)==null?void 0:e.message)}),_(f,t),l()}export{D as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.br b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.br new file mode 100644 index 0000000..dbc94c0 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.gz b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.gz new file mode 100644 index 0000000..04764f6 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/1.DUm1yZ6r.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js new file mode 100644 index 0000000..ab79a6d --- /dev/null +++ b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js @@ -0,0 +1 @@ +import"../chunks/Bzak7iHL.js";import{o as Ft}from"../chunks/DeTA_5mp.js";import{p as $t,a as Ct,d as s,e,j as W,h as y,g as t,r as a,s as E,f as dt,O,t as B,u as P}from"../chunks/nyjtQ1Ok.js";import{d as Rt,s as i,a as At}from"../chunks/C4L78yoI.js";import{i as X}from"../chunks/B17metm1.js";import{e as U,i as q}from"../chunks/BilMa3tw.js";import{a as p,f as u}from"../chunks/B0IenmM-.js";import{s as A}from"../chunks/D2QmVWrb.js";import{a as w}from"../chunks/BcuCGYSa.js";var Dt=u('
'),Mt=u('
'),kt=u('
'),Bt=u('
'),St=u('
'),Tt=u('

'),jt=u('

Retention Distribution

Memory Types

',1),Et=u('
Total Memories
Avg Retention
Due for Review
Embedding Coverage
',1),Ot=u('

System Stats

');function Lt(ot,vt){$t(vt,!0);let n=E(null),m=E(null),l=E(null),Y=E(!0);Ft(async()=>{try{await(async d=>{var r=W(d,3);y(n,r[0],!0),y(m,r[1],!0),y(l,r[2],!0)})(await Promise.all([w.stats(),w.health(),w.retentionDistribution()]))}catch{}finally{y(Y,!1)}});function z(d){return{healthy:"#10b981",degraded:"#f59e0b",critical:"#ef4444",empty:"#6b7280"}[d]||"#6b7280"}async function nt(){try{await w.consolidate(),await(async d=>{var r=W(d,3);y(n,r[0],!0),y(m,r[1],!0),y(l,r[2],!0)})(await Promise.all([w.stats(),w.health(),w.retentionDistribution()]))}catch{}}var G=Ot(),lt=s(e(G),2);{var ct=d=>{var r=Mt();U(r,20,()=>Array(8),q,(F,H)=>{var $=Dt();p(F,$)}),a(r),p(d,r)},xt=d=>{var r=Et(),F=dt(r),H=e(F),$=s(H,2),pt=e($,!0);a($);var Z=s($,2),ut=e(Z);a(Z),a(F);var I=s(F,2),J=e(I),tt=e(J),mt=e(tt,!0);a(tt),O(2),a(J);var K=s(J,2),L=e(K),gt=e(L);a(L),O(2),a(K);var N=s(K,2),at=e(N),_t=e(at,!0);a(at),O(2),a(N);var et=s(N,2),st=e(et),ft=e(st);a(st),O(2),a(et),a(I);var rt=s(I,2);{var bt=D=>{var S=jt(),M=dt(S),T=s(e(M),2);U(T,21,()=>t(l).distribution,q,(g,c,v)=>{const C=P(()=>Math.max(...t(l).distribution.map(V=>V.count),1)),R=P(()=>t(c).count/t(C)*100),_=P(()=>v<3?"#ef4444":v<5?"#f59e0b":v<7?"#10b981":"#6366f1");var x=kt(),o=e(x),f=e(o,!0);a(o);var b=s(o,2),h=s(b,2),Q=e(h,!0);a(h),a(x),B(()=>{i(f,t(c).count),A(b,`height: ${t(R)??""}%; background: ${t(_)??""}; opacity: 0.7; min-height: 2px`),i(Q,t(c).range)}),p(g,x)}),a(T),a(M);var k=s(M,2),j=s(e(k),2);U(j,21,()=>Object.entries(t(l).byType),q,(g,c)=>{var v=P(()=>W(t(c),2));let C=()=>t(v)[0],R=()=>t(v)[1];var _=Bt(),x=e(_),o=s(x,2),f=e(o,!0);a(o);var b=s(o,2),h=e(b,!0);a(b),a(_),B(()=>{A(x,`background: ${({fact:"#00A8FF",concept:"#9D00FF",event:"#FFB800",person:"#00FFD1",note:"#8B95A5",pattern:"#FF3CAC",decision:"#FF4757"}[C()]||"#8B95A5")??""}`),i(f,C()),i(h,R())}),p(g,_)}),a(j),a(k);var yt=s(k,2);{var wt=g=>{var c=Tt(),v=e(c),C=e(v);a(v);var R=s(v,2);U(R,21,()=>t(l).endangered.slice(0,20),q,(_,x)=>{var o=St(),f=e(o),b=e(f);a(f);var h=s(f,2),Q=e(h,!0);a(h),a(o),B(V=>{i(b,`${V??""}%`),i(Q,t(x).content)},[()=>(t(x).retentionStrength*100).toFixed(0)]),p(_,o)}),a(R),a(c),B(()=>i(C,`Endangered Memories (${t(l).endangered.length??""})`)),p(g,c)};X(yt,g=>{t(l).endangered.length>0&&g(wt)})}p(D,S)};X(rt,D=>{t(l)&&D(bt)})}var it=s(rt,2),ht=e(it);a(it),B((D,S,M,T,k,j)=>{A(F,`border-color: ${D??""}30`),A(H,`background: ${S??""}`),A($,`color: ${M??""}`),i(pt,T),i(ut,`v${t(m).version??""}`),i(mt,t(n).totalMemories),A(L,`color: ${t(n).averageRetention>.7?"#10b981":t(n).averageRetention>.4?"#f59e0b":"#ef4444"}`),i(gt,`${k??""}%`),i(_t,t(n).dueForReview),i(ft,`${j??""}%`)},[()=>z(t(m).status),()=>z(t(m).status),()=>z(t(m).status),()=>t(m).status.toUpperCase(),()=>(t(n).averageRetention*100).toFixed(1),()=>t(n).embeddingCoverage.toFixed(0)]),At("click",ht,nt),p(d,r)};X(lt,d=>{t(Y)?d(ct):t(n)&&t(m)&&d(xt,1)})}a(G),p(ot,G),Ct()}Rt(["click"]);export{Lt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.br b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.br new file mode 100644 index 0000000..f593349 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.gz b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.gz new file mode 100644 index 0000000..dcde31b Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/10.CuqTW1-V.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js b/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js deleted file mode 100644 index a26e1cd..0000000 --- a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js +++ /dev/null @@ -1 +0,0 @@ -import"../chunks/Bzak7iHL.js";import{o as Ft}from"../chunks/DUC-ssvh.js";import{p as $t,a as Ct,d as s,e,j as W,h as y,g as t,r as a,s as E,f as dt,G as P,t as B,u as G}from"../chunks/BBD-8XME.js";import{d as Rt,s as i,a as At}from"../chunks/DNn3Nckx.js";import{i as X}from"../chunks/RaRNNC-y.js";import{e as O,i as U}from"../chunks/C5a--lgk.js";import{a as p,f as u}from"../chunks/CKcqngaU.js";import{s as A}from"../chunks/DBfx-YTU.js";import{a as w}from"../chunks/BcuCGYSa.js";var Dt=u('
'),Mt=u('
'),kt=u('
'),Bt=u('
'),St=u('
'),Tt=u('

'),jt=u('

Retention Distribution

Memory Types

',1),Et=u('
Total Memories
Avg Retention
Due for Review
Embedding Coverage
',1),Pt=u('

System Stats

');function Lt(ot,vt){$t(vt,!0);let n=E(null),m=E(null),l=E(null),Y=E(!0);Ft(async()=>{try{await(async d=>{var r=W(d,3);y(n,r[0],!0),y(m,r[1],!0),y(l,r[2],!0)})(await Promise.all([w.stats(),w.health(),w.retentionDistribution()]))}catch{}finally{y(Y,!1)}});function q(d){return{healthy:"#10b981",degraded:"#f59e0b",critical:"#ef4444",empty:"#6b7280"}[d]||"#6b7280"}async function nt(){try{await w.consolidate(),await(async d=>{var r=W(d,3);y(n,r[0],!0),y(m,r[1],!0),y(l,r[2],!0)})(await Promise.all([w.stats(),w.health(),w.retentionDistribution()]))}catch{}}var z=Pt(),lt=s(e(z),2);{var ct=d=>{var r=Mt();O(r,20,()=>Array(8),U,(F,H)=>{var $=Dt();p(F,$)}),a(r),p(d,r)},xt=d=>{var r=Et(),F=dt(r),H=e(F),$=s(H,2),pt=e($,!0);a($);var Z=s($,2),ut=e(Z);a(Z),a(F);var I=s(F,2),J=e(I),tt=e(J),mt=e(tt,!0);a(tt),P(2),a(J);var K=s(J,2),L=e(K),gt=e(L);a(L),P(2),a(K);var N=s(K,2),at=e(N),_t=e(at,!0);a(at),P(2),a(N);var et=s(N,2),st=e(et),ft=e(st);a(st),P(2),a(et),a(I);var rt=s(I,2);{var bt=D=>{var S=jt(),M=dt(S),T=s(e(M),2);O(T,21,()=>t(l).distribution,U,(g,c,v)=>{const C=G(()=>Math.max(...t(l).distribution.map(V=>V.count),1)),R=G(()=>t(c).count/t(C)*100),_=G(()=>v<3?"#ef4444":v<5?"#f59e0b":v<7?"#10b981":"#6366f1");var x=kt(),o=e(x),f=e(o,!0);a(o);var b=s(o,2),h=s(b,2),Q=e(h,!0);a(h),a(x),B(()=>{i(f,t(c).count),A(b,`height: ${t(R)??""}%; background: ${t(_)??""}; opacity: 0.7; min-height: 2px`),i(Q,t(c).range)}),p(g,x)}),a(T),a(M);var k=s(M,2),j=s(e(k),2);O(j,21,()=>Object.entries(t(l).byType),U,(g,c)=>{var v=G(()=>W(t(c),2));let C=()=>t(v)[0],R=()=>t(v)[1];var _=Bt(),x=e(_),o=s(x,2),f=e(o,!0);a(o);var b=s(o,2),h=e(b,!0);a(b),a(_),B(()=>{A(x,`background: ${({fact:"#00A8FF",concept:"#9D00FF",event:"#FFB800",person:"#00FFD1",note:"#8B95A5",pattern:"#FF3CAC",decision:"#FF4757"}[C()]||"#8B95A5")??""}`),i(f,C()),i(h,R())}),p(g,_)}),a(j),a(k);var yt=s(k,2);{var wt=g=>{var c=Tt(),v=e(c),C=e(v);a(v);var R=s(v,2);O(R,21,()=>t(l).endangered.slice(0,20),U,(_,x)=>{var o=St(),f=e(o),b=e(f);a(f);var h=s(f,2),Q=e(h,!0);a(h),a(o),B(V=>{i(b,`${V??""}%`),i(Q,t(x).content)},[()=>(t(x).retentionStrength*100).toFixed(0)]),p(_,o)}),a(R),a(c),B(()=>i(C,`Endangered Memories (${t(l).endangered.length??""})`)),p(g,c)};X(yt,g=>{t(l).endangered.length>0&&g(wt)})}p(D,S)};X(rt,D=>{t(l)&&D(bt)})}var it=s(rt,2),ht=e(it);a(it),B((D,S,M,T,k,j)=>{A(F,`border-color: ${D??""}30`),A(H,`background: ${S??""}`),A($,`color: ${M??""}`),i(pt,T),i(ut,`v${t(m).version??""}`),i(mt,t(n).totalMemories),A(L,`color: ${t(n).averageRetention>.7?"#10b981":t(n).averageRetention>.4?"#f59e0b":"#ef4444"}`),i(gt,`${k??""}%`),i(_t,t(n).dueForReview),i(ft,`${j??""}%`)},[()=>q(t(m).status),()=>q(t(m).status),()=>q(t(m).status),()=>t(m).status.toUpperCase(),()=>(t(n).averageRetention*100).toFixed(1),()=>t(n).embeddingCoverage.toFixed(0)]),At("click",ht,nt),p(d,r)};X(lt,d=>{t(Y)?d(ct):t(n)&&t(m)&&d(xt,1)})}a(z),p(ot,z),Ct()}Rt(["click"]);export{Lt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.br b/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.br deleted file mode 100644 index 59b2c4c..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.gz b/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.gz deleted file mode 100644 index 146020c..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/10.evd80og6.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js similarity index 85% rename from apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js rename to apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js index 99225ce..1588274 100644 --- a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js +++ b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js @@ -1 +1 @@ -import"../chunks/Bzak7iHL.js";import{o as pe}from"../chunks/DUC-ssvh.js";import{p as ce,s as b,c as me,g as e,a as _e,d as i,e as a,h as c,r as t,t as g}from"../chunks/BBD-8XME.js";import{d as ue,a as K,s as m}from"../chunks/DNn3Nckx.js";import{i as M}from"../chunks/RaRNNC-y.js";import{e as h,i as P}from"../chunks/C5a--lgk.js";import{a as l,f as v}from"../chunks/CKcqngaU.js";import{s as Q}from"../chunks/DBfx-YTU.js";import{b as xe}from"../chunks/C-QujEl6.js";import{a as fe}from"../chunks/BcuCGYSa.js";import{N as U}from"../chunks/CZ45jJaw.js";var be=v('
'),ge=v('
'),he=v('

No memories in the selected time range.

'),ye=v('
'),we=v(' '),ke=v('
'),Te=v('
'),je=v('
'),Ae=v('
'),Ne=v('

Timeline

');function Re(V,W){ce(W,!0);let _=b(me([])),y=b(!0),w=b(14),k=b(null);pe(()=>R());async function R(){c(y,!0);try{const s=await fe.timeline(e(w),500);c(_,s.timeline,!0)}catch{c(_,[],!0)}finally{c(y,!1)}}var T=Ne(),j=a(T),u=i(a(j),2),A=a(u);A.value=A.__value=7;var N=i(A);N.value=N.__value=14;var O=i(N);O.value=O.__value=30;var Y=i(O);Y.value=Y.__value=90,t(u),t(j);var X=i(j,2);{var Z=s=>{var d=ge();h(d,20,()=>Array(7),P,(x,f)=>{var r=be();l(x,r)}),t(d),l(s,d)},ee=s=>{var d=he();l(s,d)},te=s=>{var d=Ae(),x=i(a(d),2);h(x,21,()=>e(_),f=>f.date,(f,r)=>{var S=je(),B=i(a(S),2),D=a(B),E=a(D),$=a(E),ae=a($,!0);t($);var q=i($,2),se=a(q);t(q),t(E);var z=i(E,2),G=a(z);h(G,17,()=>e(r).memories.slice(0,10),P,(n,o)=>{var p=ye();g(()=>Q(p,`background: ${(U[e(o).nodeType]||"#8B95A5")??""}; opacity: ${.3+e(o).retentionStrength*.7}`)),l(n,p)});var ie=i(G,2);{var re=n=>{var o=we(),p=a(o);t(o),g(()=>m(p,`+${e(r).memories.length-10}`)),l(n,o)};M(ie,n=>{e(r).memories.length>10&&n(re)})}t(z),t(D);var oe=i(D,2);{var le=n=>{var o=Te();h(o,21,()=>e(r).memories,P,(p,C)=>{var F=ke(),H=a(F),L=i(H,2),I=a(L),ve=a(I,!0);t(I),t(L);var J=i(L,2),de=a(J);t(J),t(F),g(ne=>{Q(H,`background: ${(U[e(C).nodeType]||"#8B95A5")??""}`),m(ve,e(C).content),m(de,`${ne??""}%`)},[()=>(e(C).retentionStrength*100).toFixed(0)]),l(p,F)}),t(o),l(n,o)};M(oe,n=>{e(k)===e(r).date&&n(le)})}t(B),t(S),g(()=>{m(ae,e(r).date),m(se,`${e(r).count??""} memories`)}),K("click",B,()=>c(k,e(k)===e(r).date?null:e(r).date,!0)),l(f,S)}),t(x),t(d),l(s,d)};M(X,s=>{e(y)?s(Z):e(_).length===0?s(ee,1):s(te,!1)})}t(T),K("change",u,R),xe(u,()=>e(w),s=>c(w,s)),l(V,T),_e()}ue(["change","click"]);export{Re as component}; +import"../chunks/Bzak7iHL.js";import{o as pe}from"../chunks/DeTA_5mp.js";import{p as ce,s as b,c as me,g as e,a as _e,d as i,e as a,h as c,r as t,t as g}from"../chunks/nyjtQ1Ok.js";import{d as ue,a as K,s as m}from"../chunks/C4L78yoI.js";import{i as M}from"../chunks/B17metm1.js";import{e as h,i as P}from"../chunks/BilMa3tw.js";import{a as l,f as v}from"../chunks/B0IenmM-.js";import{s as Q}from"../chunks/D2QmVWrb.js";import{b as xe}from"../chunks/J2LZW-kP.js";import{a as fe}from"../chunks/BcuCGYSa.js";import{N as U}from"../chunks/BNytumrp.js";var be=v('
'),ge=v('
'),he=v('

No memories in the selected time range.

'),ye=v('
'),we=v(' '),ke=v('
'),Te=v('
'),je=v('
'),Ae=v('
'),Ne=v('

Timeline

');function Re(V,W){ce(W,!0);let _=b(me([])),y=b(!0),w=b(14),k=b(null);pe(()=>R());async function R(){c(y,!0);try{const s=await fe.timeline(e(w),500);c(_,s.timeline,!0)}catch{c(_,[],!0)}finally{c(y,!1)}}var T=Ne(),j=a(T),u=i(a(j),2),A=a(u);A.value=A.__value=7;var N=i(A);N.value=N.__value=14;var O=i(N);O.value=O.__value=30;var Y=i(O);Y.value=Y.__value=90,t(u),t(j);var X=i(j,2);{var Z=s=>{var d=ge();h(d,20,()=>Array(7),P,(x,f)=>{var r=be();l(x,r)}),t(d),l(s,d)},ee=s=>{var d=he();l(s,d)},te=s=>{var d=Ae(),x=i(a(d),2);h(x,21,()=>e(_),f=>f.date,(f,r)=>{var S=je(),B=i(a(S),2),D=a(B),E=a(D),$=a(E),ae=a($,!0);t($);var q=i($,2),se=a(q);t(q),t(E);var z=i(E,2),G=a(z);h(G,17,()=>e(r).memories.slice(0,10),P,(n,o)=>{var p=ye();g(()=>Q(p,`background: ${(U[e(o).nodeType]||"#8B95A5")??""}; opacity: ${.3+e(o).retentionStrength*.7}`)),l(n,p)});var ie=i(G,2);{var re=n=>{var o=we(),p=a(o);t(o),g(()=>m(p,`+${e(r).memories.length-10}`)),l(n,o)};M(ie,n=>{e(r).memories.length>10&&n(re)})}t(z),t(D);var oe=i(D,2);{var le=n=>{var o=Te();h(o,21,()=>e(r).memories,P,(p,C)=>{var F=ke(),H=a(F),L=i(H,2),I=a(L),ve=a(I,!0);t(I),t(L);var J=i(L,2),de=a(J);t(J),t(F),g(ne=>{Q(H,`background: ${(U[e(C).nodeType]||"#8B95A5")??""}`),m(ve,e(C).content),m(de,`${ne??""}%`)},[()=>(e(C).retentionStrength*100).toFixed(0)]),l(p,F)}),t(o),l(n,o)};M(oe,n=>{e(k)===e(r).date&&n(le)})}t(B),t(S),g(()=>{m(ae,e(r).date),m(se,`${e(r).count??""} memories`)}),K("click",B,()=>c(k,e(k)===e(r).date?null:e(r).date,!0)),l(f,S)}),t(x),t(d),l(s,d)};M(X,s=>{e(y)?s(Z):e(_).length===0?s(ee,1):s(te,!1)})}t(T),K("change",u,R),xe(u,()=>e(w),s=>c(w,s)),l(V,T),_e()}ue(["change","click"]);export{Re as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.br b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.br new file mode 100644 index 0000000..612ece6 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.gz b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.gz new file mode 100644 index 0000000..b0eef24 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/11.C9Q0t9wJ.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.br b/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.br deleted file mode 100644 index bd79ebe..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.gz b/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.gz deleted file mode 100644 index c6a73fb..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/11.gY7s4Ta3.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js b/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js deleted file mode 100644 index 0c29b80..0000000 --- a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js +++ /dev/null @@ -1 +0,0 @@ -import"../chunks/Bzak7iHL.js";import{f as m}from"../chunks/BBD-8XME.js";import{c as n,a as p}from"../chunks/CKcqngaU.js";import{s as i}from"../chunks/DZuEJlJ5.js";function d(r,t){var o=n(),a=m(o);i(a,()=>t.children),p(r,o)}export{d as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.br b/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.br deleted file mode 100644 index e3f8b90..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.gz b/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.gz deleted file mode 100644 index c2a5e41..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/2.1GJQ3fqu.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js new file mode 100644 index 0000000..9029b59 --- /dev/null +++ b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js @@ -0,0 +1 @@ +import"../chunks/Bzak7iHL.js";import{f as m}from"../chunks/nyjtQ1Ok.js";import{c as n,a as p}from"../chunks/B0IenmM-.js";import{s as i}from"../chunks/Ckx7gB9J.js";function d(r,t){var o=n(),a=m(o);i(a,()=>t.children),p(r,o)}export{d as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.br b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.br new file mode 100644 index 0000000..9255360 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.gz b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.gz new file mode 100644 index 0000000..2875335 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/2.CGw3wCmL.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js new file mode 100644 index 0000000..d1b777c --- /dev/null +++ b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js @@ -0,0 +1 @@ +import"../chunks/Bzak7iHL.js";import"../chunks/D_N1HvA5.js";import{o as p}from"../chunks/DeTA_5mp.js";import{p as r,a as t}from"../chunks/nyjtQ1Ok.js";import{i as a}from"../chunks/Ck7jSX2P.js";import{g as m}from"../chunks/DwA4GIGc.js";function u(i,o){r(o,!1),p(()=>m("/graph",{replaceState:!0})),a(),t()}export{u as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.br b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.br new file mode 100644 index 0000000..3b60226 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.gz b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.gz new file mode 100644 index 0000000..c218501 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/3.lMYbfdAF.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js b/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js deleted file mode 100644 index 321be3f..0000000 --- a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js +++ /dev/null @@ -1 +0,0 @@ -import"../chunks/Bzak7iHL.js";import{i as p}from"../chunks/D1BK9eoQ.js";import{o as r}from"../chunks/DUC-ssvh.js";import{p as t,a}from"../chunks/BBD-8XME.js";import{g as m}from"../chunks/cIQD_rb4.js";function g(i,o){t(o,!1),r(()=>m("/graph",{replaceState:!0})),p(),a()}export{g as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.br b/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.br deleted file mode 100644 index 6b4d86c..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.gz b/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.gz deleted file mode 100644 index b979fdd..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/3.qBGkDYYb.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.br b/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.br deleted file mode 100644 index 908dfaf..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.gz b/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.gz deleted file mode 100644 index 627cb49..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js similarity index 95% rename from apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js rename to apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js index 2b88bad..6939247 100644 --- a/apps/dashboard/build/_app/immutable/nodes/4.BYgf5djd.js +++ b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js @@ -1,4 +1,4 @@ -import"../chunks/Bzak7iHL.js";import{p as ze,s as I,c as Ae,g as e,a as Pe,d as a,e as r,h as b,r as t,i as Qe,t as y,f as ge,u as se,j as qe}from"../chunks/BBD-8XME.js";import{d as Be,a as q,s as o}from"../chunks/DNn3Nckx.js";import{a as c,f as m,c as De}from"../chunks/CKcqngaU.js";import{i as k}from"../chunks/RaRNNC-y.js";import{e as ie,i as ne}from"../chunks/C5a--lgk.js";import{r as ye}from"../chunks/BVZqxpRe.js";import{s as oe}from"../chunks/CBWLjDtu.js";import{s as Ke}from"../chunks/DBfx-YTU.js";import{b as de}from"../chunks/BxfT1SOA.js";import{a as X}from"../chunks/BcuCGYSa.js";var Re=m(''),Ue=m('
Source

'),Ve=m('
Target

'),Ge=m(`
Target Memory
'),Ue=m('
Source

'),Ve=m('
Target

'),Ge=m(`
Target Memory
`,1),He=m('

'),Je=m(' '),Le=m(" "),We=m(" "),Xe=m(" "),Ye=m(' '),Ze=m('

'),et=m('

'),tt=m('

No connections found for this query.

'),rt=m('
'),at=m('
'),st=m('
'),it=m(`

Explore Connections

Source Memory

Importance Scorer

4-channel neuroscience scoring: novelty, arousal, reward, attention

`);function ft(he,we){ze(we,!0);let V=I(""),G=I(""),F=I(null),C=I(null),B=I(Ae([])),$=I("associations"),O=I(!1),H=I(""),D=I(null);const le={associations:{icon:"◎",desc:"Spreading activation — find related memories via graph traversal"},chains:{icon:"⟿",desc:"Build reasoning path from source to target memory"},bridges:{icon:"⬡",desc:"Find connecting memories between two concepts"}};async function ve(){if(e(V).trim()){b(O,!0);try{const s=await X.search(e(V),1);s.results.length>0&&(b(F,s.results[0],!0),await Y())}catch{}finally{b(O,!1)}}}async function pe(){if(e(G).trim()){b(O,!0);try{const s=await X.search(e(G),1);s.results.length>0&&(b(C,s.results[0],!0),e(F)&&await Y())}catch{}finally{b(O,!1)}}}async function Y(){if(e(F)){b(O,!0);try{const s=(e($)==="chains"||e($)==="bridges")&&e(C)?e(C).id:void 0,i=await X.explore(e(F).id,e($),s);b(B,i.results||i.nodes||i.chain||i.bridges||[],!0)}catch{b(B,[],!0)}finally{b(O,!1)}}}async function ke(){e(H).trim()&&b(D,await X.importance(e(H)),!0)}function Se(s){b($,s,!0),e(F)&&Y()}var Z=it(),ee=a(r(Z),2);ie(ee,20,()=>["associations","chains","bridges"],ne,(s,i)=>{var d=Re(),_=r(d),h=r(_,!0);t(_);var f=a(_,2),p=r(f,!0);t(f);var n=a(f,2),g=r(n,!0);t(n),t(d),y(w=>{oe(d,1,`flex flex-col items-center gap-1 p-3 rounded-xl text-sm transition diff --git a/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.br b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.br new file mode 100644 index 0000000..b90bff3 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.gz b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.gz new file mode 100644 index 0000000..558793e Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/4.D5K4f9dC.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.br b/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.br deleted file mode 100644 index 4c0992f..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.gz b/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.gz deleted file mode 100644 index 6e8301c..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js similarity index 52% rename from apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js rename to apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js index 9aec708..55e1bf0 100644 --- a/apps/dashboard/build/_app/immutable/nodes/5.DVWNDcwc.js +++ b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js @@ -1,8 +1,8 @@ -import"../chunks/Bzak7iHL.js";import{i as oe}from"../chunks/D1BK9eoQ.js";import{p as ee,ah as ie,g as e,h as M,e as o,d,r as s,f as ne,t as $,a as te,s as K,u as X,C as Z}from"../chunks/BBD-8XME.js";import{s as x,d as de,a as ce}from"../chunks/DNn3Nckx.js";import{a as l,f as m}from"../chunks/CKcqngaU.js";import{i as w}from"../chunks/RaRNNC-y.js";import{e as re,i as ae}from"../chunks/C5a--lgk.js";import{s as C}from"../chunks/DBfx-YTU.js";import{s as le,a as me}from"../chunks/BexJutgU.js";import{w as ve,e as ue}from"../chunks/CruZBLYW.js";import{E as O}from"../chunks/CZ45jJaw.js";import{s as pe}from"../chunks/BVZqxpRe.js";import{s as fe}from"../chunks/CBWLjDtu.js";import{p as Q}from"../chunks/CzkEqL6J.js";var xe=m(' '),_e=m('
'),ge=m('
',1),he=m('
'),ye=m('
'),$e=m('
Cognitive Search Pipeline
');function be(q,F){ee(F,!0);let S=Q(F,"resultCount",3,0),j=Q(F,"durationMs",3,0),I=Q(F,"active",3,!1);const p=[{name:"Overfetch",icon:"◎",color:"#818CF8",desc:"Pull 3x results from hybrid search"},{name:"Rerank",icon:"⟿",color:"#00A8FF",desc:"Re-score by relevance quality"},{name:"Temporal",icon:"◷",color:"#00D4FF",desc:"Recent memories get recency bonus"},{name:"Access",icon:"◇",color:"#00FFD1",desc:"FSRS-6 retention threshold filter"},{name:"Context",icon:"◬",color:"#FFB800",desc:"Encoding specificity matching"},{name:"Compete",icon:"⬡",color:"#FF3CAC",desc:"Retrieval-induced forgetting"},{name:"Activate",icon:"◈",color:"#9D00FF",desc:"Spreading activation cascade"}];let _=K(-1),g=K(!1),u=K(!1);ie(()=>{I()&&!e(g)&&P()});function P(){M(g,!0),M(_,-1),M(u,!1);const t=Math.max(1500,(j()||50)*2),a=t/(p.length+1);p.forEach((i,v)=>{setTimeout(()=>{M(_,v,!0)},a*(v+1))}),setTimeout(()=>{M(u,!0),M(g,!1)},t)}var D=$e(),b=o(D),L=d(o(b),2);{var V=t=>{var a=xe(),i=o(a);s(a),$(()=>x(i,`${S()??""} results in ${j()??""}ms`)),l(t,a)};w(L,t=>{e(u)&&t(V)})}s(b);var A=d(b,2);re(A,21,()=>p,ae,(t,a,i)=>{const v=X(()=>i<=e(_)),E=X(()=>i===e(_)&&e(g));var k=ge(),h=ne(k),y=o(h),J=o(y,!0);s(y);var R=d(y,2),T=o(R,!0);s(R),s(h);var U=d(h,2);{var W=B=>{var c=_e();$(()=>C(c,`background: ${i{i{fe(y,1,`w-8 h-8 rounded-full flex items-center justify-center text-xs transition-all duration-300 +import"../chunks/Bzak7iHL.js";import"../chunks/D_N1HvA5.js";import{p as ee,m as oe,g as e,h as M,e as o,d,r as s,f as ie,t as $,a as te,s as K,u as X,L as Z}from"../chunks/nyjtQ1Ok.js";import{s as x,d as ne,a as de}from"../chunks/C4L78yoI.js";import{a as l,f as m}from"../chunks/B0IenmM-.js";import{i as w}from"../chunks/B17metm1.js";import{e as re,i as ae}from"../chunks/BilMa3tw.js";import{s as C}from"../chunks/D2QmVWrb.js";import{i as ce}from"../chunks/Ck7jSX2P.js";import{s as le,a as me}from"../chunks/C3ZC25l2.js";import{w as ve,e as ue}from"../chunks/B6fk3AxI.js";import{E as L}from"../chunks/BNytumrp.js";import{s as pe}from"../chunks/BBOOwRwQ.js";import{s as fe}from"../chunks/BgOFZ9jq.js";import{p as Q}from"../chunks/BPtVz5jm.js";var xe=m(' '),_e=m('
'),ge=m('
',1),he=m('
'),ye=m('
'),$e=m('
Cognitive Search Pipeline
');function be(O,F){ee(F,!0);let S=Q(F,"resultCount",3,0),j=Q(F,"durationMs",3,0),q=Q(F,"active",3,!1);const p=[{name:"Overfetch",icon:"◎",color:"#818CF8",desc:"Pull 3x results from hybrid search"},{name:"Rerank",icon:"⟿",color:"#00A8FF",desc:"Re-score by relevance quality"},{name:"Temporal",icon:"◷",color:"#00D4FF",desc:"Recent memories get recency bonus"},{name:"Access",icon:"◇",color:"#00FFD1",desc:"FSRS-6 retention threshold filter"},{name:"Context",icon:"◬",color:"#FFB800",desc:"Encoding specificity matching"},{name:"Compete",icon:"⬡",color:"#FF3CAC",desc:"Retrieval-induced forgetting"},{name:"Activate",icon:"◈",color:"#9D00FF",desc:"Spreading activation cascade"}];let _=K(-1),g=K(!1),u=K(!1);oe(()=>{q()&&!e(g)&&P()});function P(){M(g,!0),M(_,-1),M(u,!1);const t=Math.max(1500,(j()||50)*2),a=t/(p.length+1);p.forEach((i,v)=>{setTimeout(()=>{M(_,v,!0)},a*(v+1))}),setTimeout(()=>{M(u,!0),M(g,!1)},t)}var D=$e(),b=o(D),I=d(o(b),2);{var V=t=>{var a=xe(),i=o(a);s(a),$(()=>x(i,`${S()??""} results in ${j()??""}ms`)),l(t,a)};w(I,t=>{e(u)&&t(V)})}s(b);var A=d(b,2);re(A,21,()=>p,ae,(t,a,i)=>{const v=X(()=>i<=e(_)),E=X(()=>i===e(_)&&e(g));var k=ge(),h=ie(k),y=o(h),J=o(y,!0);s(y);var R=d(y,2),T=o(R,!0);s(R),s(h);var U=d(h,2);{var W=B=>{var c=_e();$(()=>C(c,`background: ${i{i{fe(y,1,`w-8 h-8 rounded-full flex items-center justify-center text-xs transition-all duration-300 ${e(E)?"scale-125":""}`),C(y,`background: ${e(v)?e(a).color+"25":"rgba(255,255,255,0.03)"}; border: 1.5px solid ${(e(v)?e(a).color:"rgba(255,255,255,0.06)")??""}; color: ${(e(v)?e(a).color:"#4a4a7a")??""}; box-shadow: ${e(E)?"0 0 12px "+e(a).color+"40":"none"}`),pe(y,"title",e(a).desc),x(J,e(a).icon),C(R,`color: ${(e(v)?e(a).color:"#4a4a7a")??""}`),x(T,e(a).name)}),l(t,k)}),s(A);var N=d(A,2),z=o(N);{var n=t=>{var a=he();$(i=>C(a,`width: ${i??""}%; background: linear-gradient(90deg, #818CF8, #00FFD1, #9D00FF); - transition-duration: ${e(g)?"300ms":"500ms"}`),[()=>e(u)?"100":((e(_)+1)/p.length*100).toFixed(0)]),l(t,a)};w(z,t=>{(e(g)||e(u))&&t(n)})}s(N);var r=d(N,2);{var H=t=>{var a=ye(),i=d(o(a),2),v=o(i);s(i),s(a),$(()=>x(v,`Pipeline complete: ${S()??""} memories surfaced from ${p.length??""}-stage cognitive cascade`)),l(t,a)};w(r,t=>{e(u)&&t(H)})}s(D),l(q,D),te()}var we=m('

Waiting for cognitive events...

Events appear here in real-time as Vestige thinks.

'),Ce=m(' '),Fe=m('
'),Se=m(`

`),De=m('
'),ke=m('

Live Feed

');function ze(q,F){ee(F,!1);const S=()=>me(ue,"$eventFeed",j),[j,I]=le();function p(n){return new Date(n).toLocaleTimeString()}function _(n){return{MemoryCreated:"+",MemoryUpdated:"~",MemoryDeleted:"×",MemoryPromoted:"↑",MemoryDemoted:"↓",SearchPerformed:"◎",DreamStarted:"◈",DreamProgress:"◈",DreamCompleted:"◈",ConsolidationStarted:"◉",ConsolidationCompleted:"◉",RetentionDecayed:"↘",ConnectionDiscovered:"━",ActivationSpread:"◬",ImportanceScored:"◫",Heartbeat:"♡"}[n]||"·"}function g(n){const r=n.data;switch(n.type){case"MemoryCreated":return`New ${r.node_type}: "${String(r.content_preview).slice(0,60)}..."`;case"SearchPerformed":return`Searched "${r.query}" → ${r.result_count} results (${r.duration_ms}ms)`;case"DreamStarted":return`Dream started with ${r.memory_count} memories`;case"DreamCompleted":return`Dream complete: ${r.connections_found} connections, ${r.insights_generated} insights (${r.duration_ms}ms)`;case"ConsolidationStarted":return"Consolidation cycle started";case"ConsolidationCompleted":return`Consolidated ${r.nodes_processed} nodes, ${r.decay_applied} decayed (${r.duration_ms}ms)`;case"ConnectionDiscovered":return`Connection: ${String(r.connection_type)} (weight: ${Number(r.weight).toFixed(2)})`;case"ImportanceScored":return`Scored ${Number(r.composite_score).toFixed(2)}: "${String(r.content_preview).slice(0,50)}..."`;case"MemoryPromoted":return`Promoted → ${(Number(r.new_retention)*100).toFixed(0)}% retention`;case"MemoryDemoted":return`Demoted → ${(Number(r.new_retention)*100).toFixed(0)}% retention`;default:return JSON.stringify(r).slice(0,100)}}oe();var u=ke(),P=o(u),D=d(o(P),2),b=o(D),L=o(b);s(b);var V=d(b,2);s(D),s(P);var A=d(P,2);{var N=n=>{var r=we();l(n,r)},z=n=>{var r=De();re(r,5,S,ae,(H,t)=>{var a=Se(),i=o(a),v=o(i,!0);s(i);var E=d(i,2),k=o(E),h=o(k),y=o(h,!0);s(h);var J=d(h,2);{var R=c=>{var f=Ce(),Y=o(f,!0);s(f),$(G=>x(Y,G),[()=>p(String(e(t).data.timestamp))]),l(c,f)};w(J,c=>{e(t).data.timestamp&&c(R)})}s(k);var T=d(k,2),U=o(T,!0);s(T);var W=d(T,2);{var B=c=>{var f=Fe(),Y=o(f);{let G=Z(()=>Number(e(t).data.result_count)||0),se=Z(()=>Number(e(t).data.duration_ms)||0);be(Y,{get resultCount(){return e(G)},get durationMs(){return e(se)},active:!0})}s(f),l(c,f)};w(W,c=>{e(t).type==="SearchPerformed"&&c(B)})}s(E),s(a),$((c,f)=>{C(a,`border-left: 3px solid ${(O[e(t).type]||"#8B95A5")??""}`),C(i,`background: ${(O[e(t).type]||"#8B95A5")??""}15; color: ${(O[e(t).type]||"#8B95A5")??""}`),x(v,c),C(h,`color: ${(O[e(t).type]||"#8B95A5")??""}`),x(y,e(t).type),x(U,f)},[()=>_(e(t).type),()=>g(e(t))]),l(H,a)}),s(r),l(n,r)};w(A,n=>{S().length===0?n(N):n(z,!1)})}s(u),$(()=>x(L,`${S().length??""} events`)),ce("click",V,()=>ve.clearEvents()),l(q,u),te(),I()}de(["click"]);export{ze as component}; + transition-duration: ${e(g)?"300ms":"500ms"}`),[()=>e(u)?"100":((e(_)+1)/p.length*100).toFixed(0)]),l(t,a)};w(z,t=>{(e(g)||e(u))&&t(n)})}s(N);var r=d(N,2);{var H=t=>{var a=ye(),i=d(o(a),2),v=o(i);s(i),s(a),$(()=>x(v,`Pipeline complete: ${S()??""} memories surfaced from ${p.length??""}-stage cognitive cascade`)),l(t,a)};w(r,t=>{e(u)&&t(H)})}s(D),l(O,D),te()}var we=m('

Waiting for cognitive events...

Events appear here in real-time as Vestige thinks.

'),Ce=m(' '),Fe=m('
'),Se=m(`

`),De=m('
'),ke=m('

Live Feed

');function He(O,F){ee(F,!1);const S=()=>me(ue,"$eventFeed",j),[j,q]=le();function p(n){return new Date(n).toLocaleTimeString()}function _(n){return{MemoryCreated:"+",MemoryUpdated:"~",MemoryDeleted:"×",MemoryPromoted:"↑",MemoryDemoted:"↓",SearchPerformed:"◎",DreamStarted:"◈",DreamProgress:"◈",DreamCompleted:"◈",ConsolidationStarted:"◉",ConsolidationCompleted:"◉",RetentionDecayed:"↘",ConnectionDiscovered:"━",ActivationSpread:"◬",ImportanceScored:"◫",Heartbeat:"♡"}[n]||"·"}function g(n){const r=n.data;switch(n.type){case"MemoryCreated":return`New ${r.node_type}: "${String(r.content_preview).slice(0,60)}..."`;case"SearchPerformed":return`Searched "${r.query}" → ${r.result_count} results (${r.duration_ms}ms)`;case"DreamStarted":return`Dream started with ${r.memory_count} memories`;case"DreamCompleted":return`Dream complete: ${r.connections_found} connections, ${r.insights_generated} insights (${r.duration_ms}ms)`;case"ConsolidationStarted":return"Consolidation cycle started";case"ConsolidationCompleted":return`Consolidated ${r.nodes_processed} nodes, ${r.decay_applied} decayed (${r.duration_ms}ms)`;case"ConnectionDiscovered":return`Connection: ${String(r.connection_type)} (weight: ${Number(r.weight).toFixed(2)})`;case"ImportanceScored":return`Scored ${Number(r.composite_score).toFixed(2)}: "${String(r.content_preview).slice(0,50)}..."`;case"MemoryPromoted":return`Promoted → ${(Number(r.new_retention)*100).toFixed(0)}% retention`;case"MemoryDemoted":return`Demoted → ${(Number(r.new_retention)*100).toFixed(0)}% retention`;default:return JSON.stringify(r).slice(0,100)}}ce();var u=ke(),P=o(u),D=d(o(P),2),b=o(D),I=o(b);s(b);var V=d(b,2);s(D),s(P);var A=d(P,2);{var N=n=>{var r=we();l(n,r)},z=n=>{var r=De();re(r,5,S,ae,(H,t)=>{var a=Se(),i=o(a),v=o(i,!0);s(i);var E=d(i,2),k=o(E),h=o(k),y=o(h,!0);s(h);var J=d(h,2);{var R=c=>{var f=Ce(),Y=o(f,!0);s(f),$(G=>x(Y,G),[()=>p(String(e(t).data.timestamp))]),l(c,f)};w(J,c=>{e(t).data.timestamp&&c(R)})}s(k);var T=d(k,2),U=o(T,!0);s(T);var W=d(T,2);{var B=c=>{var f=Fe(),Y=o(f);{let G=Z(()=>Number(e(t).data.result_count)||0),se=Z(()=>Number(e(t).data.duration_ms)||0);be(Y,{get resultCount(){return e(G)},get durationMs(){return e(se)},active:!0})}s(f),l(c,f)};w(W,c=>{e(t).type==="SearchPerformed"&&c(B)})}s(E),s(a),$((c,f)=>{C(a,`border-left: 3px solid ${(L[e(t).type]||"#8B95A5")??""}`),C(i,`background: ${(L[e(t).type]||"#8B95A5")??""}15; color: ${(L[e(t).type]||"#8B95A5")??""}`),x(v,c),C(h,`color: ${(L[e(t).type]||"#8B95A5")??""}`),x(y,e(t).type),x(U,f)},[()=>_(e(t).type),()=>g(e(t))]),l(H,a)}),s(r),l(n,r)};w(A,n=>{S().length===0?n(N):n(z,!1)})}s(u),$(()=>x(I,`${S().length??""} events`)),de("click",V,()=>ve.clearEvents()),l(O,u),te(),q()}ne(["click"]);export{He as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.br b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.br new file mode 100644 index 0000000..ede5574 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.gz b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.gz new file mode 100644 index 0000000..7660a9a Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/5.DxlkmHN2.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js similarity index 76% rename from apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js rename to apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js index 77c057c..b65d109 100644 --- a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js +++ b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js @@ -1,12 +1,12 @@ -var bc=Object.defineProperty;var Tc=(i,t,e)=>t in i?bc(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var Wt=(i,t,e)=>Tc(i,typeof t!="symbol"?t+"":t,e);import"../chunks/Bzak7iHL.js";import{o as Al,a as Rl}from"../chunks/DUC-ssvh.js";import{p as lr,a as cr,e as Dt,d as Ot,G as wc,r as Rt,t as ln,g as j,u as ti,f as Cl,s as Ie,h as se,c as Ac}from"../chunks/BBD-8XME.js";import{s as _e,d as Pl,a as Je}from"../chunks/DNn3Nckx.js";import{i as wi}from"../chunks/RaRNNC-y.js";import{e as $r,i as Jr}from"../chunks/C5a--lgk.js";import{a as ze,f as je,c as Rc}from"../chunks/CKcqngaU.js";import{s as Be,r as Dl}from"../chunks/BVZqxpRe.js";import{s as Cc}from"../chunks/CBWLjDtu.js";import{s as Ll}from"../chunks/DBfx-YTU.js";import{b as Ul}from"../chunks/BxfT1SOA.js";import{b as Il}from"../chunks/C-QujEl6.js";import{s as Pc,a as Dc}from"../chunks/BexJutgU.js";import{b as Lc}from"../chunks/BeSd-T80.js";import{b as Uc}from"../chunks/DtXypsxD.js";import{p as Qs}from"../chunks/CzkEqL6J.js";import{N as Nl}from"../chunks/CZ45jJaw.js";import{a as Yi}from"../chunks/BcuCGYSa.js";import{e as Ic}from"../chunks/CruZBLYW.js";/** +var wc=Object.defineProperty;var Ac=(i,t,e)=>t in i?wc(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var Wt=(i,t,e)=>Ac(i,typeof t!="symbol"?t+"":t,e);import"../chunks/Bzak7iHL.js";import{o as Rl,a as Cl}from"../chunks/DeTA_5mp.js";import{p as ur,a as dr,e as Dt,d as Ot,O as Rc,r as Rt,t as ln,g as j,u as ti,f as Pl,s as Ie,h as ie,c as Cc}from"../chunks/nyjtQ1Ok.js";import{s as _e,d as Dl,a as Je}from"../chunks/C4L78yoI.js";import{i as Ai}from"../chunks/B17metm1.js";import{e as Qr,i as ta}from"../chunks/BilMa3tw.js";import{a as He,f as je,c as Pc}from"../chunks/B0IenmM-.js";import{s as ze,r as Ll}from"../chunks/BBOOwRwQ.js";import{s as Dc}from"../chunks/BgOFZ9jq.js";import{s as Ul}from"../chunks/D2QmVWrb.js";import{b as Il}from"../chunks/BOVu8he9.js";import{b as Nl}from"../chunks/J2LZW-kP.js";import{s as Lc,a as Uc}from"../chunks/C3ZC25l2.js";import{b as Ic}from"../chunks/urMNLRPv.js";import{b as Nc}from"../chunks/DAhpUNCK.js";import{p as nr}from"../chunks/BPtVz5jm.js";import{N as Fl}from"../chunks/BNytumrp.js";import{a as qi}from"../chunks/BcuCGYSa.js";import{e as Fc}from"../chunks/B6fk3AxI.js";/** * @license * Copyright 2010-2024 Three.js Authors * SPDX-License-Identifier: MIT - */const Xa="172",Di={ROTATE:0,DOLLY:1,PAN:2},Ri={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},Nc=0,uo=1,Fc=2,Fl=1,Oc=2,yn=3,zn=0,ke=1,hn=2,bn=0,Li=1,He=2,fo=3,po=4,Bc=5,Kn=100,zc=101,Hc=102,kc=103,Vc=104,Gc=200,Wc=201,Xc=202,Yc=203,Qr=204,ta=205,qc=206,jc=207,Zc=208,Kc=209,$c=210,Jc=211,Qc=212,th=213,eh=214,ea=0,na=1,ia=2,Fi=3,sa=4,ra=5,aa=6,oa=7,Ol=0,nh=1,ih=2,On=0,sh=1,rh=2,ah=3,Bl=4,oh=5,lh=6,ch=7,zl=300,Oi=301,Bi=302,la=303,ca=304,hr=306,ha=1e3,Jn=1001,ua=1002,qe=1003,hh=1004,ms=1005,dn=1006,gr=1007,Qn=1008,An=1009,Hl=1010,kl=1011,os=1012,Ya=1013,ei=1014,fn=1015,Tn=1016,qa=1017,ja=1018,zi=1020,Vl=35902,Gl=1021,Wl=1022,an=1023,Xl=1024,Yl=1025,Ui=1026,Hi=1027,Za=1028,Ka=1029,ql=1030,$a=1031,Ja=1033,Xs=33776,Ys=33777,qs=33778,js=33779,da=35840,fa=35841,pa=35842,ma=35843,ga=36196,_a=37492,va=37496,xa=37808,Ma=37809,Sa=37810,ya=37811,Ea=37812,ba=37813,Ta=37814,wa=37815,Aa=37816,Ra=37817,Ca=37818,Pa=37819,Da=37820,La=37821,Zs=36492,Ua=36494,Ia=36495,jl=36283,Na=36284,Fa=36285,Oa=36286,uh=3200,dh=3201,Zl=0,fh=1,Fn="",Qe="srgb",ki="srgb-linear",tr="linear",re="srgb",oi=7680,mo=519,ph=512,mh=513,gh=514,Kl=515,_h=516,vh=517,xh=518,Mh=519,Ba=35044,go="300 es",En=2e3,er=2001;class ii{addEventListener(t,e){this._listeners===void 0&&(this._listeners={});const n=this._listeners;n[t]===void 0&&(n[t]=[]),n[t].indexOf(e)===-1&&n[t].push(e)}hasEventListener(t,e){if(this._listeners===void 0)return!1;const n=this._listeners;return n[t]!==void 0&&n[t].indexOf(e)!==-1}removeEventListener(t,e){if(this._listeners===void 0)return;const s=this._listeners[t];if(s!==void 0){const r=s.indexOf(e);r!==-1&&s.splice(r,1)}}dispatchEvent(t){if(this._listeners===void 0)return;const n=this._listeners[t.type];if(n!==void 0){t.target=this;const s=n.slice(0);for(let r=0,a=s.length;r>8&255]+Ae[i>>16&255]+Ae[i>>24&255]+"-"+Ae[t&255]+Ae[t>>8&255]+"-"+Ae[t>>16&15|64]+Ae[t>>24&255]+"-"+Ae[e&63|128]+Ae[e>>8&255]+"-"+Ae[e>>16&255]+Ae[e>>24&255]+Ae[n&255]+Ae[n>>8&255]+Ae[n>>16&255]+Ae[n>>24&255]).toLowerCase()}function Yt(i,t,e){return Math.max(t,Math.min(e,i))}function Sh(i,t){return(i%t+t)%t}function _r(i,t,e){return(1-e)*i+e*t}function un(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return i/4294967295;case Uint16Array:return i/65535;case Uint8Array:return i/255;case Int32Array:return Math.max(i/2147483647,-1);case Int16Array:return Math.max(i/32767,-1);case Int8Array:return Math.max(i/127,-1);default:throw new Error("Invalid component type.")}}function ae(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return Math.round(i*4294967295);case Uint16Array:return Math.round(i*65535);case Uint8Array:return Math.round(i*255);case Int32Array:return Math.round(i*2147483647);case Int16Array:return Math.round(i*32767);case Int8Array:return Math.round(i*127);default:throw new Error("Invalid component type.")}}const yh={DEG2RAD:Ks};class vt{constructor(t=0,e=0){vt.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,s=t.elements;return this.x=s[0]*e+s[3]*n+s[6],this.y=s[1]*e+s[4]*n+s[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),s=Math.sin(e),r=this.x-t.x,a=this.y-t.y;return this.x=r*n-a*s+t.x,this.y=r*s+a*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Ht{constructor(t,e,n,s,r,a,o,l,c){Ht.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c)}set(t,e,n,s,r,a,o,l,c){const h=this.elements;return h[0]=t,h[1]=s,h[2]=o,h[3]=e,h[4]=r,h[5]=l,h[6]=n,h[7]=a,h[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[3],l=n[6],c=n[1],h=n[4],d=n[7],f=n[2],p=n[5],g=n[8],v=s[0],m=s[3],u=s[6],T=s[1],b=s[4],y=s[7],L=s[2],R=s[5],A=s[8];return r[0]=a*v+o*T+l*L,r[3]=a*m+o*b+l*R,r[6]=a*u+o*y+l*A,r[1]=c*v+h*T+d*L,r[4]=c*m+h*b+d*R,r[7]=c*u+h*y+d*A,r[2]=f*v+p*T+g*L,r[5]=f*m+p*b+g*R,r[8]=f*u+p*y+g*A,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8];return e*a*h-e*o*c-n*r*h+n*o*l+s*r*c-s*a*l}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],d=h*a-o*c,f=o*l-h*r,p=c*r-a*l,g=e*d+n*f+s*p;if(g===0)return this.set(0,0,0,0,0,0,0,0,0);const v=1/g;return t[0]=d*v,t[1]=(s*c-h*n)*v,t[2]=(o*n-s*a)*v,t[3]=f*v,t[4]=(h*e-s*l)*v,t[5]=(s*r-o*e)*v,t[6]=p*v,t[7]=(n*l-c*e)*v,t[8]=(a*e-n*r)*v,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,s,r,a,o){const l=Math.cos(r),c=Math.sin(r);return this.set(n*l,n*c,-n*(l*a+c*o)+a+t,-s*c,s*l,-s*(-c*a+l*o)+o+e,0,0,1),this}scale(t,e){return this.premultiply(vr.makeScale(t,e)),this}rotate(t){return this.premultiply(vr.makeRotation(-t)),this}translate(t,e){return this.premultiply(vr.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<9;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return new this.constructor().fromArray(this.elements)}}const vr=new Ht;function $l(i){for(let t=i.length-1;t>=0;--t)if(i[t]>=65535)return!0;return!1}function nr(i){return document.createElementNS("http://www.w3.org/1999/xhtml",i)}function Eh(){const i=nr("canvas");return i.style.display="block",i}const _o={};function Ai(i){i in _o||(_o[i]=!0,console.warn(i))}function bh(i,t,e){return new Promise(function(n,s){function r(){switch(i.clientWaitSync(t,i.SYNC_FLUSH_COMMANDS_BIT,0)){case i.WAIT_FAILED:s();break;case i.TIMEOUT_EXPIRED:setTimeout(r,e);break;default:n()}}setTimeout(r,e)})}function Th(i){const t=i.elements;t[2]=.5*t[2]+.5*t[3],t[6]=.5*t[6]+.5*t[7],t[10]=.5*t[10]+.5*t[11],t[14]=.5*t[14]+.5*t[15]}function wh(i){const t=i.elements;t[11]===-1?(t[10]=-t[10]-1,t[14]=-t[14]):(t[10]=-t[10],t[14]=-t[14]+1)}const vo=new Ht().set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),xo=new Ht().set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function Ah(){const i={enabled:!0,workingColorSpace:ki,spaces:{},convert:function(s,r,a){return this.enabled===!1||r===a||!r||!a||(this.spaces[r].transfer===re&&(s.r=wn(s.r),s.g=wn(s.g),s.b=wn(s.b)),this.spaces[r].primaries!==this.spaces[a].primaries&&(s.applyMatrix3(this.spaces[r].toXYZ),s.applyMatrix3(this.spaces[a].fromXYZ)),this.spaces[a].transfer===re&&(s.r=Ii(s.r),s.g=Ii(s.g),s.b=Ii(s.b))),s},fromWorkingColorSpace:function(s,r){return this.convert(s,this.workingColorSpace,r)},toWorkingColorSpace:function(s,r){return this.convert(s,r,this.workingColorSpace)},getPrimaries:function(s){return this.spaces[s].primaries},getTransfer:function(s){return s===Fn?tr:this.spaces[s].transfer},getLuminanceCoefficients:function(s,r=this.workingColorSpace){return s.fromArray(this.spaces[r].luminanceCoefficients)},define:function(s){Object.assign(this.spaces,s)},_getMatrix:function(s,r,a){return s.copy(this.spaces[r].toXYZ).multiply(this.spaces[a].fromXYZ)},_getDrawingBufferColorSpace:function(s){return this.spaces[s].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(s=this.workingColorSpace){return this.spaces[s].workingColorSpaceConfig.unpackColorSpace}},t=[.64,.33,.3,.6,.15,.06],e=[.2126,.7152,.0722],n=[.3127,.329];return i.define({[ki]:{primaries:t,whitePoint:n,transfer:tr,toXYZ:vo,fromXYZ:xo,luminanceCoefficients:e,workingColorSpaceConfig:{unpackColorSpace:Qe},outputColorSpaceConfig:{drawingBufferColorSpace:Qe}},[Qe]:{primaries:t,whitePoint:n,transfer:re,toXYZ:vo,fromXYZ:xo,luminanceCoefficients:e,outputColorSpaceConfig:{drawingBufferColorSpace:Qe}}}),i}const $t=Ah();function wn(i){return i<.04045?i*.0773993808:Math.pow(i*.9478672986+.0521327014,2.4)}function Ii(i){return i<.0031308?i*12.92:1.055*Math.pow(i,.41666)-.055}let li;class Rh{static getDataURL(t){if(/^data:/i.test(t.src)||typeof HTMLCanvasElement>"u")return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{li===void 0&&(li=nr("canvas")),li.width=t.width,li.height=t.height;const n=li.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=li}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if(typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&t instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&t instanceof ImageBitmap){const e=nr("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const s=n.getImageData(0,0,t.width,t.height),r=s.data;for(let a=0;a0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==zl)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case ha:t.x=t.x-Math.floor(t.x);break;case Jn:t.x=t.x<0?0:1;break;case ua:Math.abs(Math.floor(t.x)%2)===1?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x);break}if(t.y<0||t.y>1)switch(this.wrapT){case ha:t.y=t.y-Math.floor(t.y);break;case Jn:t.y=t.y<0?0:1;break;case ua:Math.abs(Math.floor(t.y)%2)===1?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y);break}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){t===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(t){t===!0&&this.pmremVersion++}}Ce.DEFAULT_IMAGE=null;Ce.DEFAULT_MAPPING=zl;Ce.DEFAULT_ANISOTROPY=1;class le{constructor(t=0,e=0,n=0,s=1){le.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=s}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,s){return this.x=t,this.y=e,this.z=n,this.w=s,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=t.w!==void 0?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=this.w,a=t.elements;return this.x=a[0]*e+a[4]*n+a[8]*s+a[12]*r,this.y=a[1]*e+a[5]*n+a[9]*s+a[13]*r,this.z=a[2]*e+a[6]*n+a[10]*s+a[14]*r,this.w=a[3]*e+a[7]*n+a[11]*s+a[15]*r,this}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this.w/=t.w,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,s,r;const l=t.elements,c=l[0],h=l[4],d=l[8],f=l[1],p=l[5],g=l[9],v=l[2],m=l[6],u=l[10];if(Math.abs(h-f)<.01&&Math.abs(d-v)<.01&&Math.abs(g-m)<.01){if(Math.abs(h+f)<.1&&Math.abs(d+v)<.1&&Math.abs(g+m)<.1&&Math.abs(c+p+u-3)<.1)return this.set(1,0,0,0),this;e=Math.PI;const b=(c+1)/2,y=(p+1)/2,L=(u+1)/2,R=(h+f)/4,A=(d+v)/4,U=(g+m)/4;return b>y&&b>L?b<.01?(n=0,s=.707106781,r=.707106781):(n=Math.sqrt(b),s=R/n,r=A/n):y>L?y<.01?(n=.707106781,s=0,r=.707106781):(s=Math.sqrt(y),n=R/s,r=U/s):L<.01?(n=.707106781,s=.707106781,r=0):(r=Math.sqrt(L),n=A/r,s=U/r),this.set(n,s,r,e),this}let T=Math.sqrt((m-g)*(m-g)+(d-v)*(d-v)+(f-h)*(f-h));return Math.abs(T)<.001&&(T=1),this.x=(m-g)/T,this.y=(d-v)/T,this.z=(f-h)/T,this.w=Math.acos((c+p+u-1)/2),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this.w=e[15],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this.z=Yt(this.z,t.z,e.z),this.w=Yt(this.w,t.w,e.w),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this.z=Yt(this.z,t,e),this.w=Yt(this.w,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this.w=t.w+(e.w-t.w)*n,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z&&t.w===this.w}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class Dh extends ii{constructor(t=1,e=1,n={}){super(),this.isRenderTarget=!0,this.width=t,this.height=e,this.depth=1,this.scissor=new le(0,0,t,e),this.scissorTest=!1,this.viewport=new le(0,0,t,e);const s={width:t,height:e,depth:1};n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:dn,depthBuffer:!0,stencilBuffer:!1,resolveDepthBuffer:!0,resolveStencilBuffer:!0,depthTexture:null,samples:0,count:1},n);const r=new Ce(s,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.colorSpace);r.flipY=!1,r.generateMipmaps=n.generateMipmaps,r.internalFormat=n.internalFormat,this.textures=[];const a=n.count;for(let o=0;o=0?1:-1,b=1-u*u;if(b>Number.EPSILON){const L=Math.sqrt(b),R=Math.atan2(L,u*T);m=Math.sin(m*R)/L,o=Math.sin(o*R)/L}const y=o*T;if(l=l*m+f*y,c=c*m+p*y,h=h*m+g*y,d=d*m+v*y,m===1-o){const L=1/Math.sqrt(l*l+c*c+h*h+d*d);l*=L,c*=L,h*=L,d*=L}}t[e]=l,t[e+1]=c,t[e+2]=h,t[e+3]=d}static multiplyQuaternionsFlat(t,e,n,s,r,a){const o=n[s],l=n[s+1],c=n[s+2],h=n[s+3],d=r[a],f=r[a+1],p=r[a+2],g=r[a+3];return t[e]=o*g+h*d+l*p-c*f,t[e+1]=l*g+h*f+c*d-o*p,t[e+2]=c*g+h*p+o*f-l*d,t[e+3]=h*g-o*d-l*f-c*p,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,s){return this._x=t,this._y=e,this._z=n,this._w=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const n=t._x,s=t._y,r=t._z,a=t._order,o=Math.cos,l=Math.sin,c=o(n/2),h=o(s/2),d=o(r/2),f=l(n/2),p=l(s/2),g=l(r/2);switch(a){case"XYZ":this._x=f*h*d+c*p*g,this._y=c*p*d-f*h*g,this._z=c*h*g+f*p*d,this._w=c*h*d-f*p*g;break;case"YXZ":this._x=f*h*d+c*p*g,this._y=c*p*d-f*h*g,this._z=c*h*g-f*p*d,this._w=c*h*d+f*p*g;break;case"ZXY":this._x=f*h*d-c*p*g,this._y=c*p*d+f*h*g,this._z=c*h*g+f*p*d,this._w=c*h*d-f*p*g;break;case"ZYX":this._x=f*h*d-c*p*g,this._y=c*p*d+f*h*g,this._z=c*h*g-f*p*d,this._w=c*h*d+f*p*g;break;case"YZX":this._x=f*h*d+c*p*g,this._y=c*p*d+f*h*g,this._z=c*h*g-f*p*d,this._w=c*h*d-f*p*g;break;case"XZY":this._x=f*h*d-c*p*g,this._y=c*p*d-f*h*g,this._z=c*h*g+f*p*d,this._w=c*h*d+f*p*g;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return e===!0&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,s=Math.sin(n);return this._x=t.x*s,this._y=t.y*s,this._z=t.z*s,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],s=e[4],r=e[8],a=e[1],o=e[5],l=e[9],c=e[2],h=e[6],d=e[10],f=n+o+d;if(f>0){const p=.5/Math.sqrt(f+1);this._w=.25/p,this._x=(h-l)*p,this._y=(r-c)*p,this._z=(a-s)*p}else if(n>o&&n>d){const p=2*Math.sqrt(1+n-o-d);this._w=(h-l)/p,this._x=.25*p,this._y=(s+a)/p,this._z=(r+c)/p}else if(o>d){const p=2*Math.sqrt(1+o-n-d);this._w=(r-c)/p,this._x=(s+a)/p,this._y=.25*p,this._z=(l+h)/p}else{const p=2*Math.sqrt(1+d-n-o);this._w=(a-s)/p,this._x=(r+c)/p,this._y=(l+h)/p,this._z=.25*p}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Yt(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(n===0)return this;const s=Math.min(1,e/n);return this.slerp(t,s),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return t===0?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,s=t._y,r=t._z,a=t._w,o=e._x,l=e._y,c=e._z,h=e._w;return this._x=n*h+a*o+s*c-r*l,this._y=s*h+a*l+r*o-n*c,this._z=r*h+a*c+n*l-s*o,this._w=a*h-n*o-s*l-r*c,this._onChangeCallback(),this}slerp(t,e){if(e===0)return this;if(e===1)return this.copy(t);const n=this._x,s=this._y,r=this._z,a=this._w;let o=a*t._w+n*t._x+s*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=a,this._x=n,this._y=s,this._z=r,this;const l=1-o*o;if(l<=Number.EPSILON){const p=1-e;return this._w=p*a+e*this._w,this._x=p*n+e*this._x,this._y=p*s+e*this._y,this._z=p*r+e*this._z,this.normalize(),this}const c=Math.sqrt(l),h=Math.atan2(c,o),d=Math.sin((1-e)*h)/c,f=Math.sin(e*h)/c;return this._w=a*d+this._w*f,this._x=n*d+this._x*f,this._y=s*d+this._y*f,this._z=r*d+this._z*f,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),n=Math.random(),s=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(s*Math.sin(t),s*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class P{constructor(t=0,e=0,n=0){P.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return n===void 0&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(Mo.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Mo.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*s,this.y=r[1]*e+r[4]*n+r[7]*s,this.z=r[2]*e+r[5]*n+r[8]*s,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=t.elements,a=1/(r[3]*e+r[7]*n+r[11]*s+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*s+r[12])*a,this.y=(r[1]*e+r[5]*n+r[9]*s+r[13])*a,this.z=(r[2]*e+r[6]*n+r[10]*s+r[14])*a,this}applyQuaternion(t){const e=this.x,n=this.y,s=this.z,r=t.x,a=t.y,o=t.z,l=t.w,c=2*(a*s-o*n),h=2*(o*e-r*s),d=2*(r*n-a*e);return this.x=e+l*c+a*d-o*h,this.y=n+l*h+o*c-r*d,this.z=s+l*d+r*h-a*c,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*s,this.y=r[1]*e+r[5]*n+r[9]*s,this.z=r[2]*e+r[6]*n+r[10]*s,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this.z=Yt(this.z,t.z,e.z),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this.z=Yt(this.z,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,s=t.y,r=t.z,a=e.x,o=e.y,l=e.z;return this.x=s*l-r*o,this.y=r*a-n*l,this.z=n*o-s*a,this}projectOnVector(t){const e=t.lengthSq();if(e===0)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Mr.copy(this).projectOnVector(t),this.sub(Mr)}reflect(t){return this.sub(Mr.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,s=this.z-t.z;return e*e+n*n+s*s}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const s=Math.sin(e)*t;return this.x=s*Math.sin(n),this.y=Math.cos(e)*t,this.z=s*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),s=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=s,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,e*4)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,e*3)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=Math.random()*Math.PI*2,e=Math.random()*2-1,n=Math.sqrt(1-e*e);return this.x=n*Math.cos(t),this.y=e,this.z=n*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Mr=new P,Mo=new ni;class si{constructor(t=new P(1/0,1/0,1/0),e=new P(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,nn),nn.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(qi),_s.subVectors(this.max,qi),ci.subVectors(t.a,qi),hi.subVectors(t.b,qi),ui.subVectors(t.c,qi),Rn.subVectors(hi,ci),Cn.subVectors(ui,hi),Gn.subVectors(ci,ui);let e=[0,-Rn.z,Rn.y,0,-Cn.z,Cn.y,0,-Gn.z,Gn.y,Rn.z,0,-Rn.x,Cn.z,0,-Cn.x,Gn.z,0,-Gn.x,-Rn.y,Rn.x,0,-Cn.y,Cn.x,0,-Gn.y,Gn.x,0];return!Sr(e,ci,hi,ui,_s)||(e=[1,0,0,0,1,0,0,0,1],!Sr(e,ci,hi,ui,_s))?!1:(vs.crossVectors(Rn,Cn),e=[vs.x,vs.y,vs.z],Sr(e,ci,hi,ui,_s))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,nn).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=this.getSize(nn).length()*.5),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()?this:(gn[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),gn[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),gn[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),gn[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),gn[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),gn[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),gn[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),gn[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(gn),this)}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const gn=[new P,new P,new P,new P,new P,new P,new P,new P],nn=new P,gs=new si,ci=new P,hi=new P,ui=new P,Rn=new P,Cn=new P,Gn=new P,qi=new P,_s=new P,vs=new P,Wn=new P;function Sr(i,t,e,n,s){for(let r=0,a=i.length-3;r<=a;r+=3){Wn.fromArray(i,r);const o=s.x*Math.abs(Wn.x)+s.y*Math.abs(Wn.y)+s.z*Math.abs(Wn.z),l=t.dot(Wn),c=e.dot(Wn),h=n.dot(Wn);if(Math.max(-Math.max(l,c,h),Math.min(l,c,h))>o)return!1}return!0}const Uh=new si,ji=new P,yr=new P;class ri{constructor(t=new P,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;e!==void 0?n.copy(e):Uh.setFromPoints(t).getCenter(n);let s=0;for(let r=0,a=t.length;rthis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;ji.subVectors(t,this.center);const e=ji.lengthSq();if(e>this.radius*this.radius){const n=Math.sqrt(e),s=(n-this.radius)*.5;this.center.addScaledVector(ji,s/n),this.radius+=s}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(this.center.equals(t.center)===!0?this.radius=Math.max(this.radius,t.radius):(yr.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(ji.copy(t.center).add(yr)),this.expandByPoint(ji.copy(t.center).sub(yr))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return new this.constructor().copy(this)}}const _n=new P,Er=new P,xs=new P,Pn=new P,br=new P,Ms=new P,Tr=new P;class cs{constructor(t=new P,e=new P(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,_n)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=_n.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(_n.copy(this.origin).addScaledVector(this.direction,e),_n.distanceToSquared(t))}distanceSqToSegment(t,e,n,s){Er.copy(t).add(e).multiplyScalar(.5),xs.copy(e).sub(t).normalize(),Pn.copy(this.origin).sub(Er);const r=t.distanceTo(e)*.5,a=-this.direction.dot(xs),o=Pn.dot(this.direction),l=-Pn.dot(xs),c=Pn.lengthSq(),h=Math.abs(1-a*a);let d,f,p,g;if(h>0)if(d=a*l-o,f=a*o-l,g=r*h,d>=0)if(f>=-g)if(f<=g){const v=1/h;d*=v,f*=v,p=d*(d+a*f+2*o)+f*(a*d+f+2*l)+c}else f=r,d=Math.max(0,-(a*f+o)),p=-d*d+f*(f+2*l)+c;else f=-r,d=Math.max(0,-(a*f+o)),p=-d*d+f*(f+2*l)+c;else f<=-g?(d=Math.max(0,-(-a*r+o)),f=d>0?-r:Math.min(Math.max(-r,-l),r),p=-d*d+f*(f+2*l)+c):f<=g?(d=0,f=Math.min(Math.max(-r,-l),r),p=f*(f+2*l)+c):(d=Math.max(0,-(a*r+o)),f=d>0?r:Math.min(Math.max(-r,-l),r),p=-d*d+f*(f+2*l)+c);else f=a>0?-r:r,d=Math.max(0,-(a*f+o)),p=-d*d+f*(f+2*l)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,d),s&&s.copy(Er).addScaledVector(xs,f),p}intersectSphere(t,e){_n.subVectors(t.center,this.origin);const n=_n.dot(this.direction),s=_n.dot(_n)-n*n,r=t.radius*t.radius;if(s>r)return null;const a=Math.sqrt(r-s),o=n-a,l=n+a;return l<0?null:o<0?this.at(l,e):this.at(o,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(e===0)return t.distanceToPoint(this.origin)===0?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return n===null?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);return e===0||t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,s,r,a,o,l;const c=1/this.direction.x,h=1/this.direction.y,d=1/this.direction.z,f=this.origin;return c>=0?(n=(t.min.x-f.x)*c,s=(t.max.x-f.x)*c):(n=(t.max.x-f.x)*c,s=(t.min.x-f.x)*c),h>=0?(r=(t.min.y-f.y)*h,a=(t.max.y-f.y)*h):(r=(t.max.y-f.y)*h,a=(t.min.y-f.y)*h),n>a||r>s||((r>n||isNaN(n))&&(n=r),(a=0?(o=(t.min.z-f.z)*d,l=(t.max.z-f.z)*d):(o=(t.max.z-f.z)*d,l=(t.min.z-f.z)*d),n>l||o>s)||((o>n||n!==n)&&(n=o),(l=0?n:s,e)}intersectsBox(t){return this.intersectBox(t,_n)!==null}intersectTriangle(t,e,n,s,r){br.subVectors(e,t),Ms.subVectors(n,t),Tr.crossVectors(br,Ms);let a=this.direction.dot(Tr),o;if(a>0){if(s)return null;o=1}else if(a<0)o=-1,a=-a;else return null;Pn.subVectors(this.origin,t);const l=o*this.direction.dot(Ms.crossVectors(Pn,Ms));if(l<0)return null;const c=o*this.direction.dot(br.cross(Pn));if(c<0||l+c>a)return null;const h=-o*Pn.dot(Tr);return h<0?null:this.at(h/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}}class ee{constructor(t,e,n,s,r,a,o,l,c,h,d,f,p,g,v,m){ee.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c,h,d,f,p,g,v,m)}set(t,e,n,s,r,a,o,l,c,h,d,f,p,g,v,m){const u=this.elements;return u[0]=t,u[4]=e,u[8]=n,u[12]=s,u[1]=r,u[5]=a,u[9]=o,u[13]=l,u[2]=c,u[6]=h,u[10]=d,u[14]=f,u[3]=p,u[7]=g,u[11]=v,u[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new ee().fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,s=1/di.setFromMatrixColumn(t,0).length(),r=1/di.setFromMatrixColumn(t,1).length(),a=1/di.setFromMatrixColumn(t,2).length();return e[0]=n[0]*s,e[1]=n[1]*s,e[2]=n[2]*s,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*a,e[9]=n[9]*a,e[10]=n[10]*a,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,s=t.y,r=t.z,a=Math.cos(n),o=Math.sin(n),l=Math.cos(s),c=Math.sin(s),h=Math.cos(r),d=Math.sin(r);if(t.order==="XYZ"){const f=a*h,p=a*d,g=o*h,v=o*d;e[0]=l*h,e[4]=-l*d,e[8]=c,e[1]=p+g*c,e[5]=f-v*c,e[9]=-o*l,e[2]=v-f*c,e[6]=g+p*c,e[10]=a*l}else if(t.order==="YXZ"){const f=l*h,p=l*d,g=c*h,v=c*d;e[0]=f+v*o,e[4]=g*o-p,e[8]=a*c,e[1]=a*d,e[5]=a*h,e[9]=-o,e[2]=p*o-g,e[6]=v+f*o,e[10]=a*l}else if(t.order==="ZXY"){const f=l*h,p=l*d,g=c*h,v=c*d;e[0]=f-v*o,e[4]=-a*d,e[8]=g+p*o,e[1]=p+g*o,e[5]=a*h,e[9]=v-f*o,e[2]=-a*c,e[6]=o,e[10]=a*l}else if(t.order==="ZYX"){const f=a*h,p=a*d,g=o*h,v=o*d;e[0]=l*h,e[4]=g*c-p,e[8]=f*c+v,e[1]=l*d,e[5]=v*c+f,e[9]=p*c-g,e[2]=-c,e[6]=o*l,e[10]=a*l}else if(t.order==="YZX"){const f=a*l,p=a*c,g=o*l,v=o*c;e[0]=l*h,e[4]=v-f*d,e[8]=g*d+p,e[1]=d,e[5]=a*h,e[9]=-o*h,e[2]=-c*h,e[6]=p*d+g,e[10]=f-v*d}else if(t.order==="XZY"){const f=a*l,p=a*c,g=o*l,v=o*c;e[0]=l*h,e[4]=-d,e[8]=c*h,e[1]=f*d+v,e[5]=a*h,e[9]=p*d-g,e[2]=g*d-p,e[6]=o*h,e[10]=v*d+f}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Ih,t,Nh)}lookAt(t,e,n){const s=this.elements;return We.subVectors(t,e),We.lengthSq()===0&&(We.z=1),We.normalize(),Dn.crossVectors(n,We),Dn.lengthSq()===0&&(Math.abs(n.z)===1?We.x+=1e-4:We.z+=1e-4,We.normalize(),Dn.crossVectors(n,We)),Dn.normalize(),Ss.crossVectors(We,Dn),s[0]=Dn.x,s[4]=Ss.x,s[8]=We.x,s[1]=Dn.y,s[5]=Ss.y,s[9]=We.y,s[2]=Dn.z,s[6]=Ss.z,s[10]=We.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[4],l=n[8],c=n[12],h=n[1],d=n[5],f=n[9],p=n[13],g=n[2],v=n[6],m=n[10],u=n[14],T=n[3],b=n[7],y=n[11],L=n[15],R=s[0],A=s[4],U=s[8],S=s[12],M=s[1],D=s[5],W=s[9],z=s[13],V=s[2],$=s[6],G=s[10],J=s[14],k=s[3],it=s[7],ut=s[11],yt=s[15];return r[0]=a*R+o*M+l*V+c*k,r[4]=a*A+o*D+l*$+c*it,r[8]=a*U+o*W+l*G+c*ut,r[12]=a*S+o*z+l*J+c*yt,r[1]=h*R+d*M+f*V+p*k,r[5]=h*A+d*D+f*$+p*it,r[9]=h*U+d*W+f*G+p*ut,r[13]=h*S+d*z+f*J+p*yt,r[2]=g*R+v*M+m*V+u*k,r[6]=g*A+v*D+m*$+u*it,r[10]=g*U+v*W+m*G+u*ut,r[14]=g*S+v*z+m*J+u*yt,r[3]=T*R+b*M+y*V+L*k,r[7]=T*A+b*D+y*$+L*it,r[11]=T*U+b*W+y*G+L*ut,r[15]=T*S+b*z+y*J+L*yt,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],s=t[8],r=t[12],a=t[1],o=t[5],l=t[9],c=t[13],h=t[2],d=t[6],f=t[10],p=t[14],g=t[3],v=t[7],m=t[11],u=t[15];return g*(+r*l*d-s*c*d-r*o*f+n*c*f+s*o*p-n*l*p)+v*(+e*l*p-e*c*f+r*a*f-s*a*p+s*c*h-r*l*h)+m*(+e*c*d-e*o*p-r*a*d+n*a*p+r*o*h-n*c*h)+u*(-s*o*h-e*l*d+e*o*f+s*a*d-n*a*f+n*l*h)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const s=this.elements;return t.isVector3?(s[12]=t.x,s[13]=t.y,s[14]=t.z):(s[12]=t,s[13]=e,s[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],d=t[9],f=t[10],p=t[11],g=t[12],v=t[13],m=t[14],u=t[15],T=d*m*c-v*f*c+v*l*p-o*m*p-d*l*u+o*f*u,b=g*f*c-h*m*c-g*l*p+a*m*p+h*l*u-a*f*u,y=h*v*c-g*d*c+g*o*p-a*v*p-h*o*u+a*d*u,L=g*d*l-h*v*l-g*o*f+a*v*f+h*o*m-a*d*m,R=e*T+n*b+s*y+r*L;if(R===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const A=1/R;return t[0]=T*A,t[1]=(v*f*r-d*m*r-v*s*p+n*m*p+d*s*u-n*f*u)*A,t[2]=(o*m*r-v*l*r+v*s*c-n*m*c-o*s*u+n*l*u)*A,t[3]=(d*l*r-o*f*r-d*s*c+n*f*c+o*s*p-n*l*p)*A,t[4]=b*A,t[5]=(h*m*r-g*f*r+g*s*p-e*m*p-h*s*u+e*f*u)*A,t[6]=(g*l*r-a*m*r-g*s*c+e*m*c+a*s*u-e*l*u)*A,t[7]=(a*f*r-h*l*r+h*s*c-e*f*c-a*s*p+e*l*p)*A,t[8]=y*A,t[9]=(g*d*r-h*v*r-g*n*p+e*v*p+h*n*u-e*d*u)*A,t[10]=(a*v*r-g*o*r+g*n*c-e*v*c-a*n*u+e*o*u)*A,t[11]=(h*o*r-a*d*r-h*n*c+e*d*c+a*n*p-e*o*p)*A,t[12]=L*A,t[13]=(h*v*s-g*d*s+g*n*f-e*v*f-h*n*m+e*d*m)*A,t[14]=(g*o*s-a*v*s-g*n*l+e*v*l+a*n*m-e*o*m)*A,t[15]=(a*d*s-h*o*s+h*n*l-e*d*l-a*n*f+e*o*f)*A,this}scale(t){const e=this.elements,n=t.x,s=t.y,r=t.z;return e[0]*=n,e[4]*=s,e[8]*=r,e[1]*=n,e[5]*=s,e[9]*=r,e[2]*=n,e[6]*=s,e[10]*=r,e[3]*=n,e[7]*=s,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],s=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,s))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),s=Math.sin(e),r=1-n,a=t.x,o=t.y,l=t.z,c=r*a,h=r*o;return this.set(c*a+n,c*o-s*l,c*l+s*o,0,c*o+s*l,h*o+n,h*l-s*a,0,c*l-s*o,h*l+s*a,r*l*l+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,s,r,a){return this.set(1,n,r,0,t,1,a,0,e,s,1,0,0,0,0,1),this}compose(t,e,n){const s=this.elements,r=e._x,a=e._y,o=e._z,l=e._w,c=r+r,h=a+a,d=o+o,f=r*c,p=r*h,g=r*d,v=a*h,m=a*d,u=o*d,T=l*c,b=l*h,y=l*d,L=n.x,R=n.y,A=n.z;return s[0]=(1-(v+u))*L,s[1]=(p+y)*L,s[2]=(g-b)*L,s[3]=0,s[4]=(p-y)*R,s[5]=(1-(f+u))*R,s[6]=(m+T)*R,s[7]=0,s[8]=(g+b)*A,s[9]=(m-T)*A,s[10]=(1-(f+v))*A,s[11]=0,s[12]=t.x,s[13]=t.y,s[14]=t.z,s[15]=1,this}decompose(t,e,n){const s=this.elements;let r=di.set(s[0],s[1],s[2]).length();const a=di.set(s[4],s[5],s[6]).length(),o=di.set(s[8],s[9],s[10]).length();this.determinant()<0&&(r=-r),t.x=s[12],t.y=s[13],t.z=s[14],sn.copy(this);const c=1/r,h=1/a,d=1/o;return sn.elements[0]*=c,sn.elements[1]*=c,sn.elements[2]*=c,sn.elements[4]*=h,sn.elements[5]*=h,sn.elements[6]*=h,sn.elements[8]*=d,sn.elements[9]*=d,sn.elements[10]*=d,e.setFromRotationMatrix(sn),n.x=r,n.y=a,n.z=o,this}makePerspective(t,e,n,s,r,a,o=En){const l=this.elements,c=2*r/(e-t),h=2*r/(n-s),d=(e+t)/(e-t),f=(n+s)/(n-s);let p,g;if(o===En)p=-(a+r)/(a-r),g=-2*a*r/(a-r);else if(o===er)p=-a/(a-r),g=-a*r/(a-r);else throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);return l[0]=c,l[4]=0,l[8]=d,l[12]=0,l[1]=0,l[5]=h,l[9]=f,l[13]=0,l[2]=0,l[6]=0,l[10]=p,l[14]=g,l[3]=0,l[7]=0,l[11]=-1,l[15]=0,this}makeOrthographic(t,e,n,s,r,a,o=En){const l=this.elements,c=1/(e-t),h=1/(n-s),d=1/(a-r),f=(e+t)*c,p=(n+s)*h;let g,v;if(o===En)g=(a+r)*d,v=-2*d;else if(o===er)g=r*d,v=-1*d;else throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);return l[0]=2*c,l[4]=0,l[8]=0,l[12]=-f,l[1]=0,l[5]=2*h,l[9]=0,l[13]=-p,l[2]=0,l[6]=0,l[10]=v,l[14]=-g,l[3]=0,l[7]=0,l[11]=0,l[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<16;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const di=new P,sn=new ee,Ih=new P(0,0,0),Nh=new P(1,1,1),Dn=new P,Ss=new P,We=new P,So=new ee,yo=new ni;class pn{constructor(t=0,e=0,n=0,s=pn.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=s}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,s=this._order){return this._x=t,this._y=e,this._z=n,this._order=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const s=t.elements,r=s[0],a=s[4],o=s[8],l=s[1],c=s[5],h=s[9],d=s[2],f=s[6],p=s[10];switch(e){case"XYZ":this._y=Math.asin(Yt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-h,p),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(f,c),this._z=0);break;case"YXZ":this._x=Math.asin(-Yt(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(o,p),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-d,r),this._z=0);break;case"ZXY":this._x=Math.asin(Yt(f,-1,1)),Math.abs(f)<.9999999?(this._y=Math.atan2(-d,p),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(l,r));break;case"ZYX":this._y=Math.asin(-Yt(d,-1,1)),Math.abs(d)<.9999999?(this._x=Math.atan2(f,p),this._z=Math.atan2(l,r)):(this._x=0,this._z=Math.atan2(-a,c));break;case"YZX":this._z=Math.asin(Yt(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-d,r)):(this._x=0,this._y=Math.atan2(o,p));break;case"XZY":this._z=Math.asin(-Yt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(f,c),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-h,p),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,n===!0&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return So.makeRotationFromQuaternion(t),this.setFromRotationMatrix(So,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return yo.setFromEuler(this),this.setFromQuaternion(yo,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],t[3]!==void 0&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}pn.DEFAULT_ORDER="XYZ";class Qa{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let e=0;e1){for(let n=0;n0&&(s.userData=this.userData),s.layers=this.layers.mask,s.matrix=this.matrix.toArray(),s.up=this.up.toArray(),this.matrixAutoUpdate===!1&&(s.matrixAutoUpdate=!1),this.isInstancedMesh&&(s.type="InstancedMesh",s.count=this.count,s.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(s.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(s.type="BatchedMesh",s.perObjectFrustumCulled=this.perObjectFrustumCulled,s.sortObjects=this.sortObjects,s.drawRanges=this._drawRanges,s.reservedRanges=this._reservedRanges,s.visibility=this._visibility,s.active=this._active,s.bounds=this._bounds.map(o=>({boxInitialized:o.boxInitialized,boxMin:o.box.min.toArray(),boxMax:o.box.max.toArray(),sphereInitialized:o.sphereInitialized,sphereRadius:o.sphere.radius,sphereCenter:o.sphere.center.toArray()})),s.maxInstanceCount=this._maxInstanceCount,s.maxVertexCount=this._maxVertexCount,s.maxIndexCount=this._maxIndexCount,s.geometryInitialized=this._geometryInitialized,s.geometryCount=this._geometryCount,s.matricesTexture=this._matricesTexture.toJSON(t),this._colorsTexture!==null&&(s.colorsTexture=this._colorsTexture.toJSON(t)),this.boundingSphere!==null&&(s.boundingSphere={center:s.boundingSphere.center.toArray(),radius:s.boundingSphere.radius}),this.boundingBox!==null&&(s.boundingBox={min:s.boundingBox.min.toArray(),max:s.boundingBox.max.toArray()}));function r(o,l){return o[l.uuid]===void 0&&(o[l.uuid]=l.toJSON(t)),l.uuid}if(this.isScene)this.background&&(this.background.isColor?s.background=this.background.toJSON():this.background.isTexture&&(s.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(s.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){s.geometry=r(t.geometries,this.geometry);const o=this.geometry.parameters;if(o!==void 0&&o.shapes!==void 0){const l=o.shapes;if(Array.isArray(l))for(let c=0,h=l.length;c0){s.children=[];for(let o=0;o0){s.animations=[];for(let o=0;o0&&(n.geometries=o),l.length>0&&(n.materials=l),c.length>0&&(n.textures=c),h.length>0&&(n.images=h),d.length>0&&(n.shapes=d),f.length>0&&(n.skeletons=f),p.length>0&&(n.animations=p),g.length>0&&(n.nodes=g)}return n.object=s,n;function a(o){const l=[];for(const c in o){const h=o[c];delete h.metadata,l.push(h)}return l}}clone(t){return new this.constructor().copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),e===!0)for(let n=0;n0?s.multiplyScalar(1/Math.sqrt(r)):s.set(0,0,0)}static getBarycoord(t,e,n,s,r){rn.subVectors(s,e),xn.subVectors(n,e),Ar.subVectors(t,e);const a=rn.dot(rn),o=rn.dot(xn),l=rn.dot(Ar),c=xn.dot(xn),h=xn.dot(Ar),d=a*c-o*o;if(d===0)return r.set(0,0,0),null;const f=1/d,p=(c*l-o*h)*f,g=(a*h-o*l)*f;return r.set(1-p-g,g,p)}static containsPoint(t,e,n,s){return this.getBarycoord(t,e,n,s,Mn)===null?!1:Mn.x>=0&&Mn.y>=0&&Mn.x+Mn.y<=1}static getInterpolation(t,e,n,s,r,a,o,l){return this.getBarycoord(t,e,n,s,Mn)===null?(l.x=0,l.y=0,"z"in l&&(l.z=0),"w"in l&&(l.w=0),null):(l.setScalar(0),l.addScaledVector(r,Mn.x),l.addScaledVector(a,Mn.y),l.addScaledVector(o,Mn.z),l)}static getInterpolatedAttribute(t,e,n,s,r,a){return Dr.setScalar(0),Lr.setScalar(0),Ur.setScalar(0),Dr.fromBufferAttribute(t,e),Lr.fromBufferAttribute(t,n),Ur.fromBufferAttribute(t,s),a.setScalar(0),a.addScaledVector(Dr,r.x),a.addScaledVector(Lr,r.y),a.addScaledVector(Ur,r.z),a}static isFrontFacing(t,e,n,s){return rn.subVectors(n,e),xn.subVectors(t,e),rn.cross(xn).dot(s)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,s){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[s]),this}setFromAttributeAndIndices(t,e,n,s){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,s),this}clone(){return new this.constructor().copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return rn.subVectors(this.c,this.b),xn.subVectors(this.a,this.b),rn.cross(xn).length()*.5}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return tn.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return tn.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,n,s,r){return tn.getInterpolation(t,this.a,this.b,this.c,e,n,s,r)}containsPoint(t){return tn.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return tn.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,s=this.b,r=this.c;let a,o;mi.subVectors(s,n),gi.subVectors(r,n),Rr.subVectors(t,n);const l=mi.dot(Rr),c=gi.dot(Rr);if(l<=0&&c<=0)return e.copy(n);Cr.subVectors(t,s);const h=mi.dot(Cr),d=gi.dot(Cr);if(h>=0&&d<=h)return e.copy(s);const f=l*d-h*c;if(f<=0&&l>=0&&h<=0)return a=l/(l-h),e.copy(n).addScaledVector(mi,a);Pr.subVectors(t,r);const p=mi.dot(Pr),g=gi.dot(Pr);if(g>=0&&p<=g)return e.copy(r);const v=p*c-l*g;if(v<=0&&c>=0&&g<=0)return o=c/(c-g),e.copy(n).addScaledVector(gi,o);const m=h*g-p*d;if(m<=0&&d-h>=0&&p-g>=0)return Ro.subVectors(r,s),o=(d-h)/(d-h+(p-g)),e.copy(s).addScaledVector(Ro,o);const u=1/(m+v+f);return a=v*u,o=f*u,e.copy(n).addScaledVector(mi,a).addScaledVector(gi,o)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const tc={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Ln={h:0,s:0,l:0},Es={h:0,s:0,l:0};function Ir(i,t,e){return e<0&&(e+=1),e>1&&(e-=1),e<1/6?i+(t-i)*6*e:e<1/2?t:e<2/3?i+(t-i)*6*(2/3-e):i}class pt{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(e===void 0&&n===void 0){const s=t;s&&s.isColor?this.copy(s):typeof s=="number"?this.setHex(s):typeof s=="string"&&this.setStyle(s)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Qe){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(t&255)/255,$t.toWorkingColorSpace(this,e),this}setRGB(t,e,n,s=$t.workingColorSpace){return this.r=t,this.g=e,this.b=n,$t.toWorkingColorSpace(this,s),this}setHSL(t,e,n,s=$t.workingColorSpace){if(t=Sh(t,1),e=Yt(e,0,1),n=Yt(n,0,1),e===0)this.r=this.g=this.b=n;else{const r=n<=.5?n*(1+e):n+e-n*e,a=2*n-r;this.r=Ir(a,r,t+1/3),this.g=Ir(a,r,t),this.b=Ir(a,r,t-1/3)}return $t.toWorkingColorSpace(this,s),this}setStyle(t,e=Qe){function n(r){r!==void 0&&parseFloat(r)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let s;if(s=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const a=s[1],o=s[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(s=/^\#([A-Fa-f\d]+)$/.exec(t)){const r=s[1],a=r.length;if(a===3)return this.setRGB(parseInt(r.charAt(0),16)/15,parseInt(r.charAt(1),16)/15,parseInt(r.charAt(2),16)/15,e);if(a===6)return this.setHex(parseInt(r,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Qe){const n=tc[t.toLowerCase()];return n!==void 0?this.setHex(n,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=wn(t.r),this.g=wn(t.g),this.b=wn(t.b),this}copyLinearToSRGB(t){return this.r=Ii(t.r),this.g=Ii(t.g),this.b=Ii(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Qe){return $t.fromWorkingColorSpace(Re.copy(this),t),Math.round(Yt(Re.r*255,0,255))*65536+Math.round(Yt(Re.g*255,0,255))*256+Math.round(Yt(Re.b*255,0,255))}getHexString(t=Qe){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=$t.workingColorSpace){$t.fromWorkingColorSpace(Re.copy(this),e);const n=Re.r,s=Re.g,r=Re.b,a=Math.max(n,s,r),o=Math.min(n,s,r);let l,c;const h=(o+a)/2;if(o===a)l=0,c=0;else{const d=a-o;switch(c=h<=.5?d/(a+o):d/(2-a-o),a){case n:l=(s-r)/d+(s0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(t!==void 0)for(const e in t){const n=t[e];if(n===void 0){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const s=this[e];if(s===void 0){console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`);continue}s&&s.isColor?s.set(n):s&&s.isVector3&&n&&n.isVector3?s.copy(n):this[e]=n}}toJSON(t){const e=t===void 0||typeof t=="string";e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};n.uuid=this.uuid,n.type=this.type,this.name!==""&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==Li&&(n.blending=this.blending),this.side!==zn&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==Qr&&(n.blendSrc=this.blendSrc),this.blendDst!==ta&&(n.blendDst=this.blendDst),this.blendEquation!==Kn&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==Fi&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==mo&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==oi&&(n.stencilFail=this.stencilFail),this.stencilZFail!==oi&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==oi&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!=="round"&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!=="round"&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function s(r){const a=[];for(const o in r){const l=r[o];delete l.metadata,a.push(l)}return a}if(e){const r=s(t.textures),a=s(t.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n}clone(){return new this.constructor().copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(e!==null){const s=e.length;n=new Array(s);for(let r=0;r!==s;++r)n[r]=e[r].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){t===!0&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class ls extends Hn{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new pt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new pn,this.combine=Ol,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const ge=new P,bs=new vt;class de{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=t!==void 0?t.length/e:0,this.normalized=n,this.usage=Ba,this.updateRanges=[],this.gpuType=fn,this.version=0}onUploadCallback(){}set needsUpdate(t){t===!0&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let s=0,r=this.itemSize;se.count&&console.warn("THREE.BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),e.needsUpdate=!0}return this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new si);const t=this.attributes.position,e=this.morphAttributes.position;if(t&&t.isGLBufferAttribute){console.error("THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),this.boundingBox.set(new P(-1/0,-1/0,-1/0),new P(1/0,1/0,1/0));return}if(t!==void 0){if(this.boundingBox.setFromBufferAttribute(t),e)for(let n=0,s=e.length;n0&&(t.userData=this.userData),this.parameters!==void 0){const l=this.parameters;for(const c in l)l[c]!==void 0&&(t[c]=l[c]);return t}t.data={attributes:{}};const e=this.index;e!==null&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const l in n){const c=n[l];t.data.attributes[l]=c.toJSON(t.data)}const s={};let r=!1;for(const l in this.morphAttributes){const c=this.morphAttributes[l],h=[];for(let d=0,f=c.length;d0&&(s[l]=h,r=!0)}r&&(t.data.morphAttributes=s,t.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(t.data.groups=JSON.parse(JSON.stringify(a)));const o=this.boundingSphere;return o!==null&&(t.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),t}clone(){return new this.constructor().copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;n!==null&&this.setIndex(n.clone(e));const s=t.attributes;for(const c in s){const h=s[c];this.setAttribute(c,h.clone(e))}const r=t.morphAttributes;for(const c in r){const h=[],d=r[c];for(let f=0,p=d.length;f0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;r(t.far-t.near)**2))&&(Co.copy(r).invert(),Xn.copy(t.ray).applyMatrix4(Co),!(n.boundingBox!==null&&Xn.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(t,e,Xn)))}_computeIntersections(t,e,n){let s;const r=this.geometry,a=this.material,o=r.index,l=r.attributes.position,c=r.attributes.uv,h=r.attributes.uv1,d=r.attributes.normal,f=r.groups,p=r.drawRange;if(o!==null)if(Array.isArray(a))for(let g=0,v=f.length;ge.far?null:{distance:c,point:Ps.clone(),object:i}}function Ds(i,t,e,n,s,r,a,o,l,c){i.getVertexPosition(o,ws),i.getVertexPosition(l,As),i.getVertexPosition(c,Rs);const h=Vh(i,t,e,n,ws,As,Rs,Do);if(h){const d=new P;tn.getBarycoord(Do,ws,As,Rs,d),s&&(h.uv=tn.getInterpolatedAttribute(s,o,l,c,d,new vt)),r&&(h.uv1=tn.getInterpolatedAttribute(r,o,l,c,d,new vt)),a&&(h.normal=tn.getInterpolatedAttribute(a,o,l,c,d,new P),h.normal.dot(n.direction)>0&&h.normal.multiplyScalar(-1));const f={a:o,b:l,c,normal:new P,materialIndex:0};tn.getNormal(ws,As,Rs,f.normal),h.face=f,h.barycoord=d}return h}class hs extends pe{constructor(t=1,e=1,n=1,s=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:s,heightSegments:r,depthSegments:a};const o=this;s=Math.floor(s),r=Math.floor(r),a=Math.floor(a);const l=[],c=[],h=[],d=[];let f=0,p=0;g("z","y","x",-1,-1,n,e,t,a,r,0),g("z","y","x",1,-1,n,e,-t,a,r,1),g("x","z","y",1,1,t,n,e,s,a,2),g("x","z","y",1,-1,t,n,-e,s,a,3),g("x","y","z",1,-1,t,e,n,s,r,4),g("x","y","z",-1,-1,t,e,-n,s,r,5),this.setIndex(l),this.setAttribute("position",new Pe(c,3)),this.setAttribute("normal",new Pe(h,3)),this.setAttribute("uv",new Pe(d,2));function g(v,m,u,T,b,y,L,R,A,U,S){const M=y/A,D=L/U,W=y/2,z=L/2,V=R/2,$=A+1,G=U+1;let J=0,k=0;const it=new P;for(let ut=0;ut0?1:-1,h.push(it.x,it.y,it.z),d.push(Lt/A),d.push(1-ut/U),J+=1}}for(let ut=0;ut>8&255]+Re[i>>16&255]+Re[i>>24&255]+"-"+Re[t&255]+Re[t>>8&255]+"-"+Re[t>>16&15|64]+Re[t>>24&255]+"-"+Re[e&63|128]+Re[e>>8&255]+"-"+Re[e>>16&255]+Re[e>>24&255]+Re[n&255]+Re[n>>8&255]+Re[n>>16&255]+Re[n>>24&255]).toLowerCase()}function Yt(i,t,e){return Math.max(t,Math.min(e,i))}function Eh(i,t){return(i%t+t)%t}function Mr(i,t,e){return(1-e)*i+e*t}function un(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return i/4294967295;case Uint16Array:return i/65535;case Uint8Array:return i/255;case Int32Array:return Math.max(i/2147483647,-1);case Int16Array:return Math.max(i/32767,-1);case Int8Array:return Math.max(i/127,-1);default:throw new Error("Invalid component type.")}}function ae(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return Math.round(i*4294967295);case Uint16Array:return Math.round(i*65535);case Uint8Array:return Math.round(i*255);case Int32Array:return Math.round(i*2147483647);case Int16Array:return Math.round(i*32767);case Int8Array:return Math.round(i*127);default:throw new Error("Invalid component type.")}}const bh={DEG2RAD:Js};class vt{constructor(t=0,e=0){vt.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,s=t.elements;return this.x=s[0]*e+s[3]*n+s[6],this.y=s[1]*e+s[4]*n+s[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),s=Math.sin(e),r=this.x-t.x,a=this.y-t.y;return this.x=r*n-a*s+t.x,this.y=r*s+a*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Ht{constructor(t,e,n,s,r,a,o,l,c){Ht.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c)}set(t,e,n,s,r,a,o,l,c){const h=this.elements;return h[0]=t,h[1]=s,h[2]=o,h[3]=e,h[4]=r,h[5]=l,h[6]=n,h[7]=a,h[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[3],l=n[6],c=n[1],h=n[4],d=n[7],p=n[2],f=n[5],g=n[8],v=s[0],m=s[3],u=s[6],T=s[1],b=s[4],y=s[7],L=s[2],R=s[5],A=s[8];return r[0]=a*v+o*T+l*L,r[3]=a*m+o*b+l*R,r[6]=a*u+o*y+l*A,r[1]=c*v+h*T+d*L,r[4]=c*m+h*b+d*R,r[7]=c*u+h*y+d*A,r[2]=p*v+f*T+g*L,r[5]=p*m+f*b+g*R,r[8]=p*u+f*y+g*A,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8];return e*a*h-e*o*c-n*r*h+n*o*l+s*r*c-s*a*l}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],d=h*a-o*c,p=o*l-h*r,f=c*r-a*l,g=e*d+n*p+s*f;if(g===0)return this.set(0,0,0,0,0,0,0,0,0);const v=1/g;return t[0]=d*v,t[1]=(s*c-h*n)*v,t[2]=(o*n-s*a)*v,t[3]=p*v,t[4]=(h*e-s*l)*v,t[5]=(s*r-o*e)*v,t[6]=f*v,t[7]=(n*l-c*e)*v,t[8]=(a*e-n*r)*v,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,s,r,a,o){const l=Math.cos(r),c=Math.sin(r);return this.set(n*l,n*c,-n*(l*a+c*o)+a+t,-s*c,s*l,-s*(-c*a+l*o)+o+e,0,0,1),this}scale(t,e){return this.premultiply(Sr.makeScale(t,e)),this}rotate(t){return this.premultiply(Sr.makeRotation(-t)),this}translate(t,e){return this.premultiply(Sr.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<9;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return new this.constructor().fromArray(this.elements)}}const Sr=new Ht;function Jl(i){for(let t=i.length-1;t>=0;--t)if(i[t]>=65535)return!0;return!1}function rr(i){return document.createElementNS("http://www.w3.org/1999/xhtml",i)}function Th(){const i=rr("canvas");return i.style.display="block",i}const vo={};function Ri(i){i in vo||(vo[i]=!0,console.warn(i))}function wh(i,t,e){return new Promise(function(n,s){function r(){switch(i.clientWaitSync(t,i.SYNC_FLUSH_COMMANDS_BIT,0)){case i.WAIT_FAILED:s();break;case i.TIMEOUT_EXPIRED:setTimeout(r,e);break;default:n()}}setTimeout(r,e)})}function Ah(i){const t=i.elements;t[2]=.5*t[2]+.5*t[3],t[6]=.5*t[6]+.5*t[7],t[10]=.5*t[10]+.5*t[11],t[14]=.5*t[14]+.5*t[15]}function Rh(i){const t=i.elements;t[11]===-1?(t[10]=-t[10]-1,t[14]=-t[14]):(t[10]=-t[10],t[14]=-t[14]+1)}const xo=new Ht().set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),Mo=new Ht().set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function Ch(){const i={enabled:!0,workingColorSpace:Vi,spaces:{},convert:function(s,r,a){return this.enabled===!1||r===a||!r||!a||(this.spaces[r].transfer===re&&(s.r=wn(s.r),s.g=wn(s.g),s.b=wn(s.b)),this.spaces[r].primaries!==this.spaces[a].primaries&&(s.applyMatrix3(this.spaces[r].toXYZ),s.applyMatrix3(this.spaces[a].fromXYZ)),this.spaces[a].transfer===re&&(s.r=Ni(s.r),s.g=Ni(s.g),s.b=Ni(s.b))),s},fromWorkingColorSpace:function(s,r){return this.convert(s,this.workingColorSpace,r)},toWorkingColorSpace:function(s,r){return this.convert(s,r,this.workingColorSpace)},getPrimaries:function(s){return this.spaces[s].primaries},getTransfer:function(s){return s===Fn?ir:this.spaces[s].transfer},getLuminanceCoefficients:function(s,r=this.workingColorSpace){return s.fromArray(this.spaces[r].luminanceCoefficients)},define:function(s){Object.assign(this.spaces,s)},_getMatrix:function(s,r,a){return s.copy(this.spaces[r].toXYZ).multiply(this.spaces[a].fromXYZ)},_getDrawingBufferColorSpace:function(s){return this.spaces[s].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(s=this.workingColorSpace){return this.spaces[s].workingColorSpaceConfig.unpackColorSpace}},t=[.64,.33,.3,.6,.15,.06],e=[.2126,.7152,.0722],n=[.3127,.329];return i.define({[Vi]:{primaries:t,whitePoint:n,transfer:ir,toXYZ:xo,fromXYZ:Mo,luminanceCoefficients:e,workingColorSpaceConfig:{unpackColorSpace:Qe},outputColorSpaceConfig:{drawingBufferColorSpace:Qe}},[Qe]:{primaries:t,whitePoint:n,transfer:re,toXYZ:xo,fromXYZ:Mo,luminanceCoefficients:e,outputColorSpaceConfig:{drawingBufferColorSpace:Qe}}}),i}const $t=Ch();function wn(i){return i<.04045?i*.0773993808:Math.pow(i*.9478672986+.0521327014,2.4)}function Ni(i){return i<.0031308?i*12.92:1.055*Math.pow(i,.41666)-.055}let ci;class Ph{static getDataURL(t){if(/^data:/i.test(t.src)||typeof HTMLCanvasElement>"u")return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{ci===void 0&&(ci=rr("canvas")),ci.width=t.width,ci.height=t.height;const n=ci.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=ci}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if(typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&t instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&t instanceof ImageBitmap){const e=rr("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const s=n.getImageData(0,0,t.width,t.height),r=s.data;for(let a=0;a0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==Hl)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case da:t.x=t.x-Math.floor(t.x);break;case Jn:t.x=t.x<0?0:1;break;case fa:Math.abs(Math.floor(t.x)%2)===1?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x);break}if(t.y<0||t.y>1)switch(this.wrapT){case da:t.y=t.y-Math.floor(t.y);break;case Jn:t.y=t.y<0?0:1;break;case fa:Math.abs(Math.floor(t.y)%2)===1?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y);break}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){t===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(t){t===!0&&this.pmremVersion++}}Te.DEFAULT_IMAGE=null;Te.DEFAULT_MAPPING=Hl;Te.DEFAULT_ANISOTROPY=1;class le{constructor(t=0,e=0,n=0,s=1){le.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=s}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,s){return this.x=t,this.y=e,this.z=n,this.w=s,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=t.w!==void 0?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=this.w,a=t.elements;return this.x=a[0]*e+a[4]*n+a[8]*s+a[12]*r,this.y=a[1]*e+a[5]*n+a[9]*s+a[13]*r,this.z=a[2]*e+a[6]*n+a[10]*s+a[14]*r,this.w=a[3]*e+a[7]*n+a[11]*s+a[15]*r,this}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this.w/=t.w,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,s,r;const l=t.elements,c=l[0],h=l[4],d=l[8],p=l[1],f=l[5],g=l[9],v=l[2],m=l[6],u=l[10];if(Math.abs(h-p)<.01&&Math.abs(d-v)<.01&&Math.abs(g-m)<.01){if(Math.abs(h+p)<.1&&Math.abs(d+v)<.1&&Math.abs(g+m)<.1&&Math.abs(c+f+u-3)<.1)return this.set(1,0,0,0),this;e=Math.PI;const b=(c+1)/2,y=(f+1)/2,L=(u+1)/2,R=(h+p)/4,A=(d+v)/4,U=(g+m)/4;return b>y&&b>L?b<.01?(n=0,s=.707106781,r=.707106781):(n=Math.sqrt(b),s=R/n,r=A/n):y>L?y<.01?(n=.707106781,s=0,r=.707106781):(s=Math.sqrt(y),n=R/s,r=U/s):L<.01?(n=.707106781,s=.707106781,r=0):(r=Math.sqrt(L),n=A/r,s=U/r),this.set(n,s,r,e),this}let T=Math.sqrt((m-g)*(m-g)+(d-v)*(d-v)+(p-h)*(p-h));return Math.abs(T)<.001&&(T=1),this.x=(m-g)/T,this.y=(d-v)/T,this.z=(p-h)/T,this.w=Math.acos((c+f+u-1)/2),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this.w=e[15],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this.z=Yt(this.z,t.z,e.z),this.w=Yt(this.w,t.w,e.w),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this.z=Yt(this.z,t,e),this.w=Yt(this.w,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this.w=t.w+(e.w-t.w)*n,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z&&t.w===this.w}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class Uh extends si{constructor(t=1,e=1,n={}){super(),this.isRenderTarget=!0,this.width=t,this.height=e,this.depth=1,this.scissor=new le(0,0,t,e),this.scissorTest=!1,this.viewport=new le(0,0,t,e);const s={width:t,height:e,depth:1};n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:dn,depthBuffer:!0,stencilBuffer:!1,resolveDepthBuffer:!0,resolveStencilBuffer:!0,depthTexture:null,samples:0,count:1},n);const r=new Te(s,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.colorSpace);r.flipY=!1,r.generateMipmaps=n.generateMipmaps,r.internalFormat=n.internalFormat,this.textures=[];const a=n.count;for(let o=0;o=0?1:-1,b=1-u*u;if(b>Number.EPSILON){const L=Math.sqrt(b),R=Math.atan2(L,u*T);m=Math.sin(m*R)/L,o=Math.sin(o*R)/L}const y=o*T;if(l=l*m+p*y,c=c*m+f*y,h=h*m+g*y,d=d*m+v*y,m===1-o){const L=1/Math.sqrt(l*l+c*c+h*h+d*d);l*=L,c*=L,h*=L,d*=L}}t[e]=l,t[e+1]=c,t[e+2]=h,t[e+3]=d}static multiplyQuaternionsFlat(t,e,n,s,r,a){const o=n[s],l=n[s+1],c=n[s+2],h=n[s+3],d=r[a],p=r[a+1],f=r[a+2],g=r[a+3];return t[e]=o*g+h*d+l*f-c*p,t[e+1]=l*g+h*p+c*d-o*f,t[e+2]=c*g+h*f+o*p-l*d,t[e+3]=h*g-o*d-l*p-c*f,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,s){return this._x=t,this._y=e,this._z=n,this._w=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const n=t._x,s=t._y,r=t._z,a=t._order,o=Math.cos,l=Math.sin,c=o(n/2),h=o(s/2),d=o(r/2),p=l(n/2),f=l(s/2),g=l(r/2);switch(a){case"XYZ":this._x=p*h*d+c*f*g,this._y=c*f*d-p*h*g,this._z=c*h*g+p*f*d,this._w=c*h*d-p*f*g;break;case"YXZ":this._x=p*h*d+c*f*g,this._y=c*f*d-p*h*g,this._z=c*h*g-p*f*d,this._w=c*h*d+p*f*g;break;case"ZXY":this._x=p*h*d-c*f*g,this._y=c*f*d+p*h*g,this._z=c*h*g+p*f*d,this._w=c*h*d-p*f*g;break;case"ZYX":this._x=p*h*d-c*f*g,this._y=c*f*d+p*h*g,this._z=c*h*g-p*f*d,this._w=c*h*d+p*f*g;break;case"YZX":this._x=p*h*d+c*f*g,this._y=c*f*d+p*h*g,this._z=c*h*g-p*f*d,this._w=c*h*d-p*f*g;break;case"XZY":this._x=p*h*d-c*f*g,this._y=c*f*d-p*h*g,this._z=c*h*g+p*f*d,this._w=c*h*d+p*f*g;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return e===!0&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,s=Math.sin(n);return this._x=t.x*s,this._y=t.y*s,this._z=t.z*s,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],s=e[4],r=e[8],a=e[1],o=e[5],l=e[9],c=e[2],h=e[6],d=e[10],p=n+o+d;if(p>0){const f=.5/Math.sqrt(p+1);this._w=.25/f,this._x=(h-l)*f,this._y=(r-c)*f,this._z=(a-s)*f}else if(n>o&&n>d){const f=2*Math.sqrt(1+n-o-d);this._w=(h-l)/f,this._x=.25*f,this._y=(s+a)/f,this._z=(r+c)/f}else if(o>d){const f=2*Math.sqrt(1+o-n-d);this._w=(r-c)/f,this._x=(s+a)/f,this._y=.25*f,this._z=(l+h)/f}else{const f=2*Math.sqrt(1+d-n-o);this._w=(a-s)/f,this._x=(r+c)/f,this._y=(l+h)/f,this._z=.25*f}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Yt(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(n===0)return this;const s=Math.min(1,e/n);return this.slerp(t,s),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return t===0?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,s=t._y,r=t._z,a=t._w,o=e._x,l=e._y,c=e._z,h=e._w;return this._x=n*h+a*o+s*c-r*l,this._y=s*h+a*l+r*o-n*c,this._z=r*h+a*c+n*l-s*o,this._w=a*h-n*o-s*l-r*c,this._onChangeCallback(),this}slerp(t,e){if(e===0)return this;if(e===1)return this.copy(t);const n=this._x,s=this._y,r=this._z,a=this._w;let o=a*t._w+n*t._x+s*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=a,this._x=n,this._y=s,this._z=r,this;const l=1-o*o;if(l<=Number.EPSILON){const f=1-e;return this._w=f*a+e*this._w,this._x=f*n+e*this._x,this._y=f*s+e*this._y,this._z=f*r+e*this._z,this.normalize(),this}const c=Math.sqrt(l),h=Math.atan2(c,o),d=Math.sin((1-e)*h)/c,p=Math.sin(e*h)/c;return this._w=a*d+this._w*p,this._x=n*d+this._x*p,this._y=s*d+this._y*p,this._z=r*d+this._z*p,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),n=Math.random(),s=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(s*Math.sin(t),s*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class P{constructor(t=0,e=0,n=0){P.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return n===void 0&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(So.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(So.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*s,this.y=r[1]*e+r[4]*n+r[7]*s,this.z=r[2]*e+r[5]*n+r[8]*s,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=t.elements,a=1/(r[3]*e+r[7]*n+r[11]*s+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*s+r[12])*a,this.y=(r[1]*e+r[5]*n+r[9]*s+r[13])*a,this.z=(r[2]*e+r[6]*n+r[10]*s+r[14])*a,this}applyQuaternion(t){const e=this.x,n=this.y,s=this.z,r=t.x,a=t.y,o=t.z,l=t.w,c=2*(a*s-o*n),h=2*(o*e-r*s),d=2*(r*n-a*e);return this.x=e+l*c+a*d-o*h,this.y=n+l*h+o*c-r*d,this.z=s+l*d+r*h-a*c,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*s,this.y=r[1]*e+r[5]*n+r[9]*s,this.z=r[2]*e+r[6]*n+r[10]*s,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Yt(this.x,t.x,e.x),this.y=Yt(this.y,t.y,e.y),this.z=Yt(this.z,t.z,e.z),this}clampScalar(t,e){return this.x=Yt(this.x,t,e),this.y=Yt(this.y,t,e),this.z=Yt(this.z,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Yt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,s=t.y,r=t.z,a=e.x,o=e.y,l=e.z;return this.x=s*l-r*o,this.y=r*a-n*l,this.z=n*o-s*a,this}projectOnVector(t){const e=t.lengthSq();if(e===0)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Er.copy(this).projectOnVector(t),this.sub(Er)}reflect(t){return this.sub(Er.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,s=this.z-t.z;return e*e+n*n+s*s}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const s=Math.sin(e)*t;return this.x=s*Math.sin(n),this.y=Math.cos(e)*t,this.z=s*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),s=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=s,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,e*4)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,e*3)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=Math.random()*Math.PI*2,e=Math.random()*2-1,n=Math.sqrt(1-e*e);return this.x=n*Math.cos(t),this.y=e,this.z=n*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Er=new P,So=new ii;class ri{constructor(t=new P(1/0,1/0,1/0),e=new P(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,nn),nn.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ji),vs.subVectors(this.max,ji),hi.subVectors(t.a,ji),ui.subVectors(t.b,ji),di.subVectors(t.c,ji),Rn.subVectors(ui,hi),Cn.subVectors(di,ui),Gn.subVectors(hi,di);let e=[0,-Rn.z,Rn.y,0,-Cn.z,Cn.y,0,-Gn.z,Gn.y,Rn.z,0,-Rn.x,Cn.z,0,-Cn.x,Gn.z,0,-Gn.x,-Rn.y,Rn.x,0,-Cn.y,Cn.x,0,-Gn.y,Gn.x,0];return!br(e,hi,ui,di,vs)||(e=[1,0,0,0,1,0,0,0,1],!br(e,hi,ui,di,vs))?!1:(xs.crossVectors(Rn,Cn),e=[xs.x,xs.y,xs.z],br(e,hi,ui,di,vs))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,nn).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=this.getSize(nn).length()*.5),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()?this:(gn[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),gn[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),gn[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),gn[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),gn[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),gn[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),gn[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),gn[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(gn),this)}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const gn=[new P,new P,new P,new P,new P,new P,new P,new P],nn=new P,_s=new ri,hi=new P,ui=new P,di=new P,Rn=new P,Cn=new P,Gn=new P,ji=new P,vs=new P,xs=new P,Wn=new P;function br(i,t,e,n,s){for(let r=0,a=i.length-3;r<=a;r+=3){Wn.fromArray(i,r);const o=s.x*Math.abs(Wn.x)+s.y*Math.abs(Wn.y)+s.z*Math.abs(Wn.z),l=t.dot(Wn),c=e.dot(Wn),h=n.dot(Wn);if(Math.max(-Math.max(l,c,h),Math.min(l,c,h))>o)return!1}return!0}const Nh=new ri,Zi=new P,Tr=new P;class ai{constructor(t=new P,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;e!==void 0?n.copy(e):Nh.setFromPoints(t).getCenter(n);let s=0;for(let r=0,a=t.length;rthis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Zi.subVectors(t,this.center);const e=Zi.lengthSq();if(e>this.radius*this.radius){const n=Math.sqrt(e),s=(n-this.radius)*.5;this.center.addScaledVector(Zi,s/n),this.radius+=s}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(this.center.equals(t.center)===!0?this.radius=Math.max(this.radius,t.radius):(Tr.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Zi.copy(t.center).add(Tr)),this.expandByPoint(Zi.copy(t.center).sub(Tr))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return new this.constructor().copy(this)}}const _n=new P,wr=new P,Ms=new P,Pn=new P,Ar=new P,Ss=new P,Rr=new P;class hs{constructor(t=new P,e=new P(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,_n)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=_n.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(_n.copy(this.origin).addScaledVector(this.direction,e),_n.distanceToSquared(t))}distanceSqToSegment(t,e,n,s){wr.copy(t).add(e).multiplyScalar(.5),Ms.copy(e).sub(t).normalize(),Pn.copy(this.origin).sub(wr);const r=t.distanceTo(e)*.5,a=-this.direction.dot(Ms),o=Pn.dot(this.direction),l=-Pn.dot(Ms),c=Pn.lengthSq(),h=Math.abs(1-a*a);let d,p,f,g;if(h>0)if(d=a*l-o,p=a*o-l,g=r*h,d>=0)if(p>=-g)if(p<=g){const v=1/h;d*=v,p*=v,f=d*(d+a*p+2*o)+p*(a*d+p+2*l)+c}else p=r,d=Math.max(0,-(a*p+o)),f=-d*d+p*(p+2*l)+c;else p=-r,d=Math.max(0,-(a*p+o)),f=-d*d+p*(p+2*l)+c;else p<=-g?(d=Math.max(0,-(-a*r+o)),p=d>0?-r:Math.min(Math.max(-r,-l),r),f=-d*d+p*(p+2*l)+c):p<=g?(d=0,p=Math.min(Math.max(-r,-l),r),f=p*(p+2*l)+c):(d=Math.max(0,-(a*r+o)),p=d>0?r:Math.min(Math.max(-r,-l),r),f=-d*d+p*(p+2*l)+c);else p=a>0?-r:r,d=Math.max(0,-(a*p+o)),f=-d*d+p*(p+2*l)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,d),s&&s.copy(wr).addScaledVector(Ms,p),f}intersectSphere(t,e){_n.subVectors(t.center,this.origin);const n=_n.dot(this.direction),s=_n.dot(_n)-n*n,r=t.radius*t.radius;if(s>r)return null;const a=Math.sqrt(r-s),o=n-a,l=n+a;return l<0?null:o<0?this.at(l,e):this.at(o,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(e===0)return t.distanceToPoint(this.origin)===0?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return n===null?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);return e===0||t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,s,r,a,o,l;const c=1/this.direction.x,h=1/this.direction.y,d=1/this.direction.z,p=this.origin;return c>=0?(n=(t.min.x-p.x)*c,s=(t.max.x-p.x)*c):(n=(t.max.x-p.x)*c,s=(t.min.x-p.x)*c),h>=0?(r=(t.min.y-p.y)*h,a=(t.max.y-p.y)*h):(r=(t.max.y-p.y)*h,a=(t.min.y-p.y)*h),n>a||r>s||((r>n||isNaN(n))&&(n=r),(a=0?(o=(t.min.z-p.z)*d,l=(t.max.z-p.z)*d):(o=(t.max.z-p.z)*d,l=(t.min.z-p.z)*d),n>l||o>s)||((o>n||n!==n)&&(n=o),(l=0?n:s,e)}intersectsBox(t){return this.intersectBox(t,_n)!==null}intersectTriangle(t,e,n,s,r){Ar.subVectors(e,t),Ss.subVectors(n,t),Rr.crossVectors(Ar,Ss);let a=this.direction.dot(Rr),o;if(a>0){if(s)return null;o=1}else if(a<0)o=-1,a=-a;else return null;Pn.subVectors(this.origin,t);const l=o*this.direction.dot(Ss.crossVectors(Pn,Ss));if(l<0)return null;const c=o*this.direction.dot(Ar.cross(Pn));if(c<0||l+c>a)return null;const h=-o*Pn.dot(Rr);return h<0?null:this.at(h/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}}class ee{constructor(t,e,n,s,r,a,o,l,c,h,d,p,f,g,v,m){ee.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c,h,d,p,f,g,v,m)}set(t,e,n,s,r,a,o,l,c,h,d,p,f,g,v,m){const u=this.elements;return u[0]=t,u[4]=e,u[8]=n,u[12]=s,u[1]=r,u[5]=a,u[9]=o,u[13]=l,u[2]=c,u[6]=h,u[10]=d,u[14]=p,u[3]=f,u[7]=g,u[11]=v,u[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new ee().fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,s=1/fi.setFromMatrixColumn(t,0).length(),r=1/fi.setFromMatrixColumn(t,1).length(),a=1/fi.setFromMatrixColumn(t,2).length();return e[0]=n[0]*s,e[1]=n[1]*s,e[2]=n[2]*s,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*a,e[9]=n[9]*a,e[10]=n[10]*a,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,s=t.y,r=t.z,a=Math.cos(n),o=Math.sin(n),l=Math.cos(s),c=Math.sin(s),h=Math.cos(r),d=Math.sin(r);if(t.order==="XYZ"){const p=a*h,f=a*d,g=o*h,v=o*d;e[0]=l*h,e[4]=-l*d,e[8]=c,e[1]=f+g*c,e[5]=p-v*c,e[9]=-o*l,e[2]=v-p*c,e[6]=g+f*c,e[10]=a*l}else if(t.order==="YXZ"){const p=l*h,f=l*d,g=c*h,v=c*d;e[0]=p+v*o,e[4]=g*o-f,e[8]=a*c,e[1]=a*d,e[5]=a*h,e[9]=-o,e[2]=f*o-g,e[6]=v+p*o,e[10]=a*l}else if(t.order==="ZXY"){const p=l*h,f=l*d,g=c*h,v=c*d;e[0]=p-v*o,e[4]=-a*d,e[8]=g+f*o,e[1]=f+g*o,e[5]=a*h,e[9]=v-p*o,e[2]=-a*c,e[6]=o,e[10]=a*l}else if(t.order==="ZYX"){const p=a*h,f=a*d,g=o*h,v=o*d;e[0]=l*h,e[4]=g*c-f,e[8]=p*c+v,e[1]=l*d,e[5]=v*c+p,e[9]=f*c-g,e[2]=-c,e[6]=o*l,e[10]=a*l}else if(t.order==="YZX"){const p=a*l,f=a*c,g=o*l,v=o*c;e[0]=l*h,e[4]=v-p*d,e[8]=g*d+f,e[1]=d,e[5]=a*h,e[9]=-o*h,e[2]=-c*h,e[6]=f*d+g,e[10]=p-v*d}else if(t.order==="XZY"){const p=a*l,f=a*c,g=o*l,v=o*c;e[0]=l*h,e[4]=-d,e[8]=c*h,e[1]=p*d+v,e[5]=a*h,e[9]=f*d-g,e[2]=g*d-f,e[6]=o*h,e[10]=v*d+p}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Fh,t,Oh)}lookAt(t,e,n){const s=this.elements;return We.subVectors(t,e),We.lengthSq()===0&&(We.z=1),We.normalize(),Dn.crossVectors(n,We),Dn.lengthSq()===0&&(Math.abs(n.z)===1?We.x+=1e-4:We.z+=1e-4,We.normalize(),Dn.crossVectors(n,We)),Dn.normalize(),ys.crossVectors(We,Dn),s[0]=Dn.x,s[4]=ys.x,s[8]=We.x,s[1]=Dn.y,s[5]=ys.y,s[9]=We.y,s[2]=Dn.z,s[6]=ys.z,s[10]=We.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[4],l=n[8],c=n[12],h=n[1],d=n[5],p=n[9],f=n[13],g=n[2],v=n[6],m=n[10],u=n[14],T=n[3],b=n[7],y=n[11],L=n[15],R=s[0],A=s[4],U=s[8],S=s[12],M=s[1],D=s[5],W=s[9],z=s[13],V=s[2],$=s[6],G=s[10],J=s[14],k=s[3],it=s[7],ut=s[11],yt=s[15];return r[0]=a*R+o*M+l*V+c*k,r[4]=a*A+o*D+l*$+c*it,r[8]=a*U+o*W+l*G+c*ut,r[12]=a*S+o*z+l*J+c*yt,r[1]=h*R+d*M+p*V+f*k,r[5]=h*A+d*D+p*$+f*it,r[9]=h*U+d*W+p*G+f*ut,r[13]=h*S+d*z+p*J+f*yt,r[2]=g*R+v*M+m*V+u*k,r[6]=g*A+v*D+m*$+u*it,r[10]=g*U+v*W+m*G+u*ut,r[14]=g*S+v*z+m*J+u*yt,r[3]=T*R+b*M+y*V+L*k,r[7]=T*A+b*D+y*$+L*it,r[11]=T*U+b*W+y*G+L*ut,r[15]=T*S+b*z+y*J+L*yt,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],s=t[8],r=t[12],a=t[1],o=t[5],l=t[9],c=t[13],h=t[2],d=t[6],p=t[10],f=t[14],g=t[3],v=t[7],m=t[11],u=t[15];return g*(+r*l*d-s*c*d-r*o*p+n*c*p+s*o*f-n*l*f)+v*(+e*l*f-e*c*p+r*a*p-s*a*f+s*c*h-r*l*h)+m*(+e*c*d-e*o*f-r*a*d+n*a*f+r*o*h-n*c*h)+u*(-s*o*h-e*l*d+e*o*p+s*a*d-n*a*p+n*l*h)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const s=this.elements;return t.isVector3?(s[12]=t.x,s[13]=t.y,s[14]=t.z):(s[12]=t,s[13]=e,s[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],d=t[9],p=t[10],f=t[11],g=t[12],v=t[13],m=t[14],u=t[15],T=d*m*c-v*p*c+v*l*f-o*m*f-d*l*u+o*p*u,b=g*p*c-h*m*c-g*l*f+a*m*f+h*l*u-a*p*u,y=h*v*c-g*d*c+g*o*f-a*v*f-h*o*u+a*d*u,L=g*d*l-h*v*l-g*o*p+a*v*p+h*o*m-a*d*m,R=e*T+n*b+s*y+r*L;if(R===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const A=1/R;return t[0]=T*A,t[1]=(v*p*r-d*m*r-v*s*f+n*m*f+d*s*u-n*p*u)*A,t[2]=(o*m*r-v*l*r+v*s*c-n*m*c-o*s*u+n*l*u)*A,t[3]=(d*l*r-o*p*r-d*s*c+n*p*c+o*s*f-n*l*f)*A,t[4]=b*A,t[5]=(h*m*r-g*p*r+g*s*f-e*m*f-h*s*u+e*p*u)*A,t[6]=(g*l*r-a*m*r-g*s*c+e*m*c+a*s*u-e*l*u)*A,t[7]=(a*p*r-h*l*r+h*s*c-e*p*c-a*s*f+e*l*f)*A,t[8]=y*A,t[9]=(g*d*r-h*v*r-g*n*f+e*v*f+h*n*u-e*d*u)*A,t[10]=(a*v*r-g*o*r+g*n*c-e*v*c-a*n*u+e*o*u)*A,t[11]=(h*o*r-a*d*r-h*n*c+e*d*c+a*n*f-e*o*f)*A,t[12]=L*A,t[13]=(h*v*s-g*d*s+g*n*p-e*v*p-h*n*m+e*d*m)*A,t[14]=(g*o*s-a*v*s-g*n*l+e*v*l+a*n*m-e*o*m)*A,t[15]=(a*d*s-h*o*s+h*n*l-e*d*l-a*n*p+e*o*p)*A,this}scale(t){const e=this.elements,n=t.x,s=t.y,r=t.z;return e[0]*=n,e[4]*=s,e[8]*=r,e[1]*=n,e[5]*=s,e[9]*=r,e[2]*=n,e[6]*=s,e[10]*=r,e[3]*=n,e[7]*=s,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],s=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,s))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),s=Math.sin(e),r=1-n,a=t.x,o=t.y,l=t.z,c=r*a,h=r*o;return this.set(c*a+n,c*o-s*l,c*l+s*o,0,c*o+s*l,h*o+n,h*l-s*a,0,c*l-s*o,h*l+s*a,r*l*l+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,s,r,a){return this.set(1,n,r,0,t,1,a,0,e,s,1,0,0,0,0,1),this}compose(t,e,n){const s=this.elements,r=e._x,a=e._y,o=e._z,l=e._w,c=r+r,h=a+a,d=o+o,p=r*c,f=r*h,g=r*d,v=a*h,m=a*d,u=o*d,T=l*c,b=l*h,y=l*d,L=n.x,R=n.y,A=n.z;return s[0]=(1-(v+u))*L,s[1]=(f+y)*L,s[2]=(g-b)*L,s[3]=0,s[4]=(f-y)*R,s[5]=(1-(p+u))*R,s[6]=(m+T)*R,s[7]=0,s[8]=(g+b)*A,s[9]=(m-T)*A,s[10]=(1-(p+v))*A,s[11]=0,s[12]=t.x,s[13]=t.y,s[14]=t.z,s[15]=1,this}decompose(t,e,n){const s=this.elements;let r=fi.set(s[0],s[1],s[2]).length();const a=fi.set(s[4],s[5],s[6]).length(),o=fi.set(s[8],s[9],s[10]).length();this.determinant()<0&&(r=-r),t.x=s[12],t.y=s[13],t.z=s[14],sn.copy(this);const c=1/r,h=1/a,d=1/o;return sn.elements[0]*=c,sn.elements[1]*=c,sn.elements[2]*=c,sn.elements[4]*=h,sn.elements[5]*=h,sn.elements[6]*=h,sn.elements[8]*=d,sn.elements[9]*=d,sn.elements[10]*=d,e.setFromRotationMatrix(sn),n.x=r,n.y=a,n.z=o,this}makePerspective(t,e,n,s,r,a,o=En){const l=this.elements,c=2*r/(e-t),h=2*r/(n-s),d=(e+t)/(e-t),p=(n+s)/(n-s);let f,g;if(o===En)f=-(a+r)/(a-r),g=-2*a*r/(a-r);else if(o===sr)f=-a/(a-r),g=-a*r/(a-r);else throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);return l[0]=c,l[4]=0,l[8]=d,l[12]=0,l[1]=0,l[5]=h,l[9]=p,l[13]=0,l[2]=0,l[6]=0,l[10]=f,l[14]=g,l[3]=0,l[7]=0,l[11]=-1,l[15]=0,this}makeOrthographic(t,e,n,s,r,a,o=En){const l=this.elements,c=1/(e-t),h=1/(n-s),d=1/(a-r),p=(e+t)*c,f=(n+s)*h;let g,v;if(o===En)g=(a+r)*d,v=-2*d;else if(o===sr)g=r*d,v=-1*d;else throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);return l[0]=2*c,l[4]=0,l[8]=0,l[12]=-p,l[1]=0,l[5]=2*h,l[9]=0,l[13]=-f,l[2]=0,l[6]=0,l[10]=v,l[14]=-g,l[3]=0,l[7]=0,l[11]=0,l[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<16;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const fi=new P,sn=new ee,Fh=new P(0,0,0),Oh=new P(1,1,1),Dn=new P,ys=new P,We=new P,yo=new ee,Eo=new ii;class pn{constructor(t=0,e=0,n=0,s=pn.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=s}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,s=this._order){return this._x=t,this._y=e,this._z=n,this._order=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const s=t.elements,r=s[0],a=s[4],o=s[8],l=s[1],c=s[5],h=s[9],d=s[2],p=s[6],f=s[10];switch(e){case"XYZ":this._y=Math.asin(Yt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-h,f),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(p,c),this._z=0);break;case"YXZ":this._x=Math.asin(-Yt(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(o,f),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-d,r),this._z=0);break;case"ZXY":this._x=Math.asin(Yt(p,-1,1)),Math.abs(p)<.9999999?(this._y=Math.atan2(-d,f),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(l,r));break;case"ZYX":this._y=Math.asin(-Yt(d,-1,1)),Math.abs(d)<.9999999?(this._x=Math.atan2(p,f),this._z=Math.atan2(l,r)):(this._x=0,this._z=Math.atan2(-a,c));break;case"YZX":this._z=Math.asin(Yt(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-d,r)):(this._x=0,this._y=Math.atan2(o,f));break;case"XZY":this._z=Math.asin(-Yt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(p,c),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-h,f),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,n===!0&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return yo.makeRotationFromQuaternion(t),this.setFromRotationMatrix(yo,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return Eo.setFromEuler(this),this.setFromQuaternion(Eo,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],t[3]!==void 0&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}pn.DEFAULT_ORDER="XYZ";class to{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let e=0;e1){for(let n=0;n0&&(s.userData=this.userData),s.layers=this.layers.mask,s.matrix=this.matrix.toArray(),s.up=this.up.toArray(),this.matrixAutoUpdate===!1&&(s.matrixAutoUpdate=!1),this.isInstancedMesh&&(s.type="InstancedMesh",s.count=this.count,s.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(s.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(s.type="BatchedMesh",s.perObjectFrustumCulled=this.perObjectFrustumCulled,s.sortObjects=this.sortObjects,s.drawRanges=this._drawRanges,s.reservedRanges=this._reservedRanges,s.visibility=this._visibility,s.active=this._active,s.bounds=this._bounds.map(o=>({boxInitialized:o.boxInitialized,boxMin:o.box.min.toArray(),boxMax:o.box.max.toArray(),sphereInitialized:o.sphereInitialized,sphereRadius:o.sphere.radius,sphereCenter:o.sphere.center.toArray()})),s.maxInstanceCount=this._maxInstanceCount,s.maxVertexCount=this._maxVertexCount,s.maxIndexCount=this._maxIndexCount,s.geometryInitialized=this._geometryInitialized,s.geometryCount=this._geometryCount,s.matricesTexture=this._matricesTexture.toJSON(t),this._colorsTexture!==null&&(s.colorsTexture=this._colorsTexture.toJSON(t)),this.boundingSphere!==null&&(s.boundingSphere={center:s.boundingSphere.center.toArray(),radius:s.boundingSphere.radius}),this.boundingBox!==null&&(s.boundingBox={min:s.boundingBox.min.toArray(),max:s.boundingBox.max.toArray()}));function r(o,l){return o[l.uuid]===void 0&&(o[l.uuid]=l.toJSON(t)),l.uuid}if(this.isScene)this.background&&(this.background.isColor?s.background=this.background.toJSON():this.background.isTexture&&(s.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(s.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){s.geometry=r(t.geometries,this.geometry);const o=this.geometry.parameters;if(o!==void 0&&o.shapes!==void 0){const l=o.shapes;if(Array.isArray(l))for(let c=0,h=l.length;c0){s.children=[];for(let o=0;o0){s.animations=[];for(let o=0;o0&&(n.geometries=o),l.length>0&&(n.materials=l),c.length>0&&(n.textures=c),h.length>0&&(n.images=h),d.length>0&&(n.shapes=d),p.length>0&&(n.skeletons=p),f.length>0&&(n.animations=f),g.length>0&&(n.nodes=g)}return n.object=s,n;function a(o){const l=[];for(const c in o){const h=o[c];delete h.metadata,l.push(h)}return l}}clone(t){return new this.constructor().copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),e===!0)for(let n=0;n0?s.multiplyScalar(1/Math.sqrt(r)):s.set(0,0,0)}static getBarycoord(t,e,n,s,r){rn.subVectors(s,e),xn.subVectors(n,e),Pr.subVectors(t,e);const a=rn.dot(rn),o=rn.dot(xn),l=rn.dot(Pr),c=xn.dot(xn),h=xn.dot(Pr),d=a*c-o*o;if(d===0)return r.set(0,0,0),null;const p=1/d,f=(c*l-o*h)*p,g=(a*h-o*l)*p;return r.set(1-f-g,g,f)}static containsPoint(t,e,n,s){return this.getBarycoord(t,e,n,s,Mn)===null?!1:Mn.x>=0&&Mn.y>=0&&Mn.x+Mn.y<=1}static getInterpolation(t,e,n,s,r,a,o,l){return this.getBarycoord(t,e,n,s,Mn)===null?(l.x=0,l.y=0,"z"in l&&(l.z=0),"w"in l&&(l.w=0),null):(l.setScalar(0),l.addScaledVector(r,Mn.x),l.addScaledVector(a,Mn.y),l.addScaledVector(o,Mn.z),l)}static getInterpolatedAttribute(t,e,n,s,r,a){return Ir.setScalar(0),Nr.setScalar(0),Fr.setScalar(0),Ir.fromBufferAttribute(t,e),Nr.fromBufferAttribute(t,n),Fr.fromBufferAttribute(t,s),a.setScalar(0),a.addScaledVector(Ir,r.x),a.addScaledVector(Nr,r.y),a.addScaledVector(Fr,r.z),a}static isFrontFacing(t,e,n,s){return rn.subVectors(n,e),xn.subVectors(t,e),rn.cross(xn).dot(s)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,s){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[s]),this}setFromAttributeAndIndices(t,e,n,s){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,s),this}clone(){return new this.constructor().copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return rn.subVectors(this.c,this.b),xn.subVectors(this.a,this.b),rn.cross(xn).length()*.5}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return tn.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return tn.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,n,s,r){return tn.getInterpolation(t,this.a,this.b,this.c,e,n,s,r)}containsPoint(t){return tn.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return tn.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,s=this.b,r=this.c;let a,o;gi.subVectors(s,n),_i.subVectors(r,n),Dr.subVectors(t,n);const l=gi.dot(Dr),c=_i.dot(Dr);if(l<=0&&c<=0)return e.copy(n);Lr.subVectors(t,s);const h=gi.dot(Lr),d=_i.dot(Lr);if(h>=0&&d<=h)return e.copy(s);const p=l*d-h*c;if(p<=0&&l>=0&&h<=0)return a=l/(l-h),e.copy(n).addScaledVector(gi,a);Ur.subVectors(t,r);const f=gi.dot(Ur),g=_i.dot(Ur);if(g>=0&&f<=g)return e.copy(r);const v=f*c-l*g;if(v<=0&&c>=0&&g<=0)return o=c/(c-g),e.copy(n).addScaledVector(_i,o);const m=h*g-f*d;if(m<=0&&d-h>=0&&f-g>=0)return Co.subVectors(r,s),o=(d-h)/(d-h+(f-g)),e.copy(s).addScaledVector(Co,o);const u=1/(m+v+p);return a=v*u,o=p*u,e.copy(n).addScaledVector(gi,a).addScaledVector(_i,o)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const ec={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Ln={h:0,s:0,l:0},bs={h:0,s:0,l:0};function Or(i,t,e){return e<0&&(e+=1),e>1&&(e-=1),e<1/6?i+(t-i)*6*e:e<1/2?t:e<2/3?i+(t-i)*6*(2/3-e):i}class pt{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(e===void 0&&n===void 0){const s=t;s&&s.isColor?this.copy(s):typeof s=="number"?this.setHex(s):typeof s=="string"&&this.setStyle(s)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Qe){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(t&255)/255,$t.toWorkingColorSpace(this,e),this}setRGB(t,e,n,s=$t.workingColorSpace){return this.r=t,this.g=e,this.b=n,$t.toWorkingColorSpace(this,s),this}setHSL(t,e,n,s=$t.workingColorSpace){if(t=Eh(t,1),e=Yt(e,0,1),n=Yt(n,0,1),e===0)this.r=this.g=this.b=n;else{const r=n<=.5?n*(1+e):n+e-n*e,a=2*n-r;this.r=Or(a,r,t+1/3),this.g=Or(a,r,t),this.b=Or(a,r,t-1/3)}return $t.toWorkingColorSpace(this,s),this}setStyle(t,e=Qe){function n(r){r!==void 0&&parseFloat(r)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let s;if(s=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const a=s[1],o=s[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(s=/^\#([A-Fa-f\d]+)$/.exec(t)){const r=s[1],a=r.length;if(a===3)return this.setRGB(parseInt(r.charAt(0),16)/15,parseInt(r.charAt(1),16)/15,parseInt(r.charAt(2),16)/15,e);if(a===6)return this.setHex(parseInt(r,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Qe){const n=ec[t.toLowerCase()];return n!==void 0?this.setHex(n,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=wn(t.r),this.g=wn(t.g),this.b=wn(t.b),this}copyLinearToSRGB(t){return this.r=Ni(t.r),this.g=Ni(t.g),this.b=Ni(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Qe){return $t.fromWorkingColorSpace(Ce.copy(this),t),Math.round(Yt(Ce.r*255,0,255))*65536+Math.round(Yt(Ce.g*255,0,255))*256+Math.round(Yt(Ce.b*255,0,255))}getHexString(t=Qe){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=$t.workingColorSpace){$t.fromWorkingColorSpace(Ce.copy(this),e);const n=Ce.r,s=Ce.g,r=Ce.b,a=Math.max(n,s,r),o=Math.min(n,s,r);let l,c;const h=(o+a)/2;if(o===a)l=0,c=0;else{const d=a-o;switch(c=h<=.5?d/(a+o):d/(2-a-o),a){case n:l=(s-r)/d+(s0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(t!==void 0)for(const e in t){const n=t[e];if(n===void 0){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const s=this[e];if(s===void 0){console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`);continue}s&&s.isColor?s.set(n):s&&s.isVector3&&n&&n.isVector3?s.copy(n):this[e]=n}}toJSON(t){const e=t===void 0||typeof t=="string";e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};n.uuid=this.uuid,n.type=this.type,this.name!==""&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==Ui&&(n.blending=this.blending),this.side!==zn&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==ea&&(n.blendSrc=this.blendSrc),this.blendDst!==na&&(n.blendDst=this.blendDst),this.blendEquation!==Kn&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==Oi&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==go&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==li&&(n.stencilFail=this.stencilFail),this.stencilZFail!==li&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==li&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!=="round"&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!=="round"&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function s(r){const a=[];for(const o in r){const l=r[o];delete l.metadata,a.push(l)}return a}if(e){const r=s(t.textures),a=s(t.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n}clone(){return new this.constructor().copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(e!==null){const s=e.length;n=new Array(s);for(let r=0;r!==s;++r)n[r]=e[r].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){t===!0&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class cs extends Hn{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new pt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new pn,this.combine=Bl,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const ge=new P,Ts=new vt;class he{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=t!==void 0?t.length/e:0,this.normalized=n,this.usage=Ha,this.updateRanges=[],this.gpuType=fn,this.version=0}onUploadCallback(){}set needsUpdate(t){t===!0&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let s=0,r=this.itemSize;se.count&&console.warn("THREE.BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),e.needsUpdate=!0}return this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new ri);const t=this.attributes.position,e=this.morphAttributes.position;if(t&&t.isGLBufferAttribute){console.error("THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),this.boundingBox.set(new P(-1/0,-1/0,-1/0),new P(1/0,1/0,1/0));return}if(t!==void 0){if(this.boundingBox.setFromBufferAttribute(t),e)for(let n=0,s=e.length;n0&&(t.userData=this.userData),this.parameters!==void 0){const l=this.parameters;for(const c in l)l[c]!==void 0&&(t[c]=l[c]);return t}t.data={attributes:{}};const e=this.index;e!==null&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const l in n){const c=n[l];t.data.attributes[l]=c.toJSON(t.data)}const s={};let r=!1;for(const l in this.morphAttributes){const c=this.morphAttributes[l],h=[];for(let d=0,p=c.length;d0&&(s[l]=h,r=!0)}r&&(t.data.morphAttributes=s,t.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(t.data.groups=JSON.parse(JSON.stringify(a)));const o=this.boundingSphere;return o!==null&&(t.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),t}clone(){return new this.constructor().copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;n!==null&&this.setIndex(n.clone(e));const s=t.attributes;for(const c in s){const h=s[c];this.setAttribute(c,h.clone(e))}const r=t.morphAttributes;for(const c in r){const h=[],d=r[c];for(let p=0,f=d.length;p0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;r(t.far-t.near)**2))&&(Po.copy(r).invert(),Xn.copy(t.ray).applyMatrix4(Po),!(n.boundingBox!==null&&Xn.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(t,e,Xn)))}_computeIntersections(t,e,n){let s;const r=this.geometry,a=this.material,o=r.index,l=r.attributes.position,c=r.attributes.uv,h=r.attributes.uv1,d=r.attributes.normal,p=r.groups,f=r.drawRange;if(o!==null)if(Array.isArray(a))for(let g=0,v=p.length;ge.far?null:{distance:c,point:Ds.clone(),object:i}}function Ls(i,t,e,n,s,r,a,o,l,c){i.getVertexPosition(o,As),i.getVertexPosition(l,Rs),i.getVertexPosition(c,Cs);const h=Wh(i,t,e,n,As,Rs,Cs,Lo);if(h){const d=new P;tn.getBarycoord(Lo,As,Rs,Cs,d),s&&(h.uv=tn.getInterpolatedAttribute(s,o,l,c,d,new vt)),r&&(h.uv1=tn.getInterpolatedAttribute(r,o,l,c,d,new vt)),a&&(h.normal=tn.getInterpolatedAttribute(a,o,l,c,d,new P),h.normal.dot(n.direction)>0&&h.normal.multiplyScalar(-1));const p={a:o,b:l,c,normal:new P,materialIndex:0};tn.getNormal(As,Rs,Cs,p.normal),h.face=p,h.barycoord=d}return h}class us extends pe{constructor(t=1,e=1,n=1,s=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:s,heightSegments:r,depthSegments:a};const o=this;s=Math.floor(s),r=Math.floor(r),a=Math.floor(a);const l=[],c=[],h=[],d=[];let p=0,f=0;g("z","y","x",-1,-1,n,e,t,a,r,0),g("z","y","x",1,-1,n,e,-t,a,r,1),g("x","z","y",1,1,t,n,e,s,a,2),g("x","z","y",1,-1,t,n,-e,s,a,3),g("x","y","z",1,-1,t,e,n,s,r,4),g("x","y","z",-1,-1,t,e,-n,s,r,5),this.setIndex(l),this.setAttribute("position",new Pe(c,3)),this.setAttribute("normal",new Pe(h,3)),this.setAttribute("uv",new Pe(d,2));function g(v,m,u,T,b,y,L,R,A,U,S){const M=y/A,D=L/U,W=y/2,z=L/2,V=R/2,$=A+1,G=U+1;let J=0,k=0;const it=new P;for(let ut=0;ut0?1:-1,h.push(it.x,it.y,it.z),d.push(Lt/A),d.push(1-ut/U),J+=1}}for(let ut=0;ut0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const s in this.extensions)this.extensions[s]===!0&&(n[s]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class sc extends we{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ee,this.projectionMatrix=new ee,this.projectionMatrixInverse=new ee,this.coordinateSystem=En}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}const Un=new P,Lo=new vt,Uo=new vt;class Ye extends sc{constructor(t=50,e=1,n=.1,s=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=s,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=t.view===null?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=za*2*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(Ks*.5*this.fov);return .5*this.getFilmHeight()/t}getEffectiveFOV(){return za*2*Math.atan(Math.tan(Ks*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,n){Un.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Un.x,Un.y).multiplyScalar(-t/Un.z),Un.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Un.x,Un.y).multiplyScalar(-t/Un.z)}getViewSize(t,e){return this.getViewBounds(t,Lo,Uo),e.subVectors(Uo,Lo)}setViewOffset(t,e,n,s,r,a){this.aspect=t/e,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=s,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(Ks*.5*this.fov)/this.zoom,n=2*e,s=this.aspect*n,r=-.5*s;const a=this.view;if(this.view!==null&&this.view.enabled){const l=a.fullWidth,c=a.fullHeight;r+=a.offsetX*s/l,e-=a.offsetY*n/c,s*=a.width/l,n*=a.height/c}const o=this.filmOffset;o!==0&&(r+=t*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+s,e,e-n,t,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,this.view!==null&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const vi=-90,xi=1;class Yh extends we{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const s=new Ye(vi,xi,t,e);s.layers=this.layers,this.add(s);const r=new Ye(vi,xi,t,e);r.layers=this.layers,this.add(r);const a=new Ye(vi,xi,t,e);a.layers=this.layers,this.add(a);const o=new Ye(vi,xi,t,e);o.layers=this.layers,this.add(o);const l=new Ye(vi,xi,t,e);l.layers=this.layers,this.add(l);const c=new Ye(vi,xi,t,e);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,s,r,a,o,l]=e;for(const c of e)this.remove(c);if(t===En)n.up.set(0,1,0),n.lookAt(1,0,0),s.up.set(0,1,0),s.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),l.up.set(0,1,0),l.lookAt(0,0,-1);else if(t===er)n.up.set(0,-1,0),n.lookAt(-1,0,0),s.up.set(0,-1,0),s.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),l.up.set(0,-1,0),l.lookAt(0,0,-1);else throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);for(const c of e)this.add(c),c.updateMatrixWorld()}update(t,e){this.parent===null&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:s}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,a,o,l,c,h]=this.children,d=t.getRenderTarget(),f=t.getActiveCubeFace(),p=t.getActiveMipmapLevel(),g=t.xr.enabled;t.xr.enabled=!1;const v=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,s),t.render(e,r),t.setRenderTarget(n,1,s),t.render(e,a),t.setRenderTarget(n,2,s),t.render(e,o),t.setRenderTarget(n,3,s),t.render(e,l),t.setRenderTarget(n,4,s),t.render(e,c),n.texture.generateMipmaps=v,t.setRenderTarget(n,5,s),t.render(e,h),t.setRenderTarget(d,f,p),t.xr.enabled=g,n.texture.needsPMREMUpdate=!0}}class rc extends Ce{constructor(t,e,n,s,r,a,o,l,c,h){t=t!==void 0?t:[],e=e!==void 0?e:Oi,super(t,e,n,s,r,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class qh extends on{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},s=[n,n,n,n,n,n];this.texture=new rc(s,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=e.generateMipmaps!==void 0?e.generateMipmaps:!1,this.texture.minFilter=e.minFilter!==void 0?e.minFilter:dn}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:` +}`;class Fe extends Hn{constructor(t){super(),this.isShaderMaterial=!0,this.type="ShaderMaterial",this.defines={},this.uniforms={},this.uniformsGroups=[],this.vertexShader=Yh,this.fragmentShader=qh,this.linewidth=1,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.clipping=!1,this.forceSinglePass=!0,this.extensions={clipCullDistance:!1,multiDraw:!1},this.defaultAttributeValues={color:[1,1,1],uv:[0,0],uv1:[0,0]},this.index0AttributeName=void 0,this.uniformsNeedUpdate=!1,this.glslVersion=null,t!==void 0&&this.setValues(t)}copy(t){return super.copy(t),this.fragmentShader=t.fragmentShader,this.vertexShader=t.vertexShader,this.uniforms=Gi(t.uniforms),this.uniformsGroups=Xh(t.uniformsGroups),this.defines=Object.assign({},t.defines),this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.fog=t.fog,this.lights=t.lights,this.clipping=t.clipping,this.extensions=Object.assign({},t.extensions),this.glslVersion=t.glslVersion,this}toJSON(t){const e=super.toJSON(t);e.glslVersion=this.glslVersion,e.uniforms={};for(const s in this.uniforms){const a=this.uniforms[s].value;a&&a.isTexture?e.uniforms[s]={type:"t",value:a.toJSON(t).uuid}:a&&a.isColor?e.uniforms[s]={type:"c",value:a.getHex()}:a&&a.isVector2?e.uniforms[s]={type:"v2",value:a.toArray()}:a&&a.isVector3?e.uniforms[s]={type:"v3",value:a.toArray()}:a&&a.isVector4?e.uniforms[s]={type:"v4",value:a.toArray()}:a&&a.isMatrix3?e.uniforms[s]={type:"m3",value:a.toArray()}:a&&a.isMatrix4?e.uniforms[s]={type:"m4",value:a.toArray()}:e.uniforms[s]={value:a}}Object.keys(this.defines).length>0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const s in this.extensions)this.extensions[s]===!0&&(n[s]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class rc extends Ae{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ee,this.projectionMatrix=new ee,this.projectionMatrixInverse=new ee,this.coordinateSystem=En}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}const Un=new P,Uo=new vt,Io=new vt;class Ye extends rc{constructor(t=50,e=1,n=.1,s=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=s,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=t.view===null?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=ka*2*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(Js*.5*this.fov);return .5*this.getFilmHeight()/t}getEffectiveFOV(){return ka*2*Math.atan(Math.tan(Js*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,n){Un.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Un.x,Un.y).multiplyScalar(-t/Un.z),Un.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Un.x,Un.y).multiplyScalar(-t/Un.z)}getViewSize(t,e){return this.getViewBounds(t,Uo,Io),e.subVectors(Io,Uo)}setViewOffset(t,e,n,s,r,a){this.aspect=t/e,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=s,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(Js*.5*this.fov)/this.zoom,n=2*e,s=this.aspect*n,r=-.5*s;const a=this.view;if(this.view!==null&&this.view.enabled){const l=a.fullWidth,c=a.fullHeight;r+=a.offsetX*s/l,e-=a.offsetY*n/c,s*=a.width/l,n*=a.height/c}const o=this.filmOffset;o!==0&&(r+=t*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+s,e,e-n,t,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,this.view!==null&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const xi=-90,Mi=1;class jh extends Ae{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const s=new Ye(xi,Mi,t,e);s.layers=this.layers,this.add(s);const r=new Ye(xi,Mi,t,e);r.layers=this.layers,this.add(r);const a=new Ye(xi,Mi,t,e);a.layers=this.layers,this.add(a);const o=new Ye(xi,Mi,t,e);o.layers=this.layers,this.add(o);const l=new Ye(xi,Mi,t,e);l.layers=this.layers,this.add(l);const c=new Ye(xi,Mi,t,e);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,s,r,a,o,l]=e;for(const c of e)this.remove(c);if(t===En)n.up.set(0,1,0),n.lookAt(1,0,0),s.up.set(0,1,0),s.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),l.up.set(0,1,0),l.lookAt(0,0,-1);else if(t===sr)n.up.set(0,-1,0),n.lookAt(-1,0,0),s.up.set(0,-1,0),s.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),l.up.set(0,-1,0),l.lookAt(0,0,-1);else throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);for(const c of e)this.add(c),c.updateMatrixWorld()}update(t,e){this.parent===null&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:s}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,a,o,l,c,h]=this.children,d=t.getRenderTarget(),p=t.getActiveCubeFace(),f=t.getActiveMipmapLevel(),g=t.xr.enabled;t.xr.enabled=!1;const v=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,s),t.render(e,r),t.setRenderTarget(n,1,s),t.render(e,a),t.setRenderTarget(n,2,s),t.render(e,o),t.setRenderTarget(n,3,s),t.render(e,l),t.setRenderTarget(n,4,s),t.render(e,c),n.texture.generateMipmaps=v,t.setRenderTarget(n,5,s),t.render(e,h),t.setRenderTarget(d,p,f),t.xr.enabled=g,n.texture.needsPMREMUpdate=!0}}class ac extends Te{constructor(t,e,n,s,r,a,o,l,c,h){t=t!==void 0?t:[],e=e!==void 0?e:Bi,super(t,e,n,s,r,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class Zh extends on{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},s=[n,n,n,n,n,n];this.texture=new ac(s,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=e.generateMipmaps!==void 0?e.generateMipmaps:!1,this.texture.minFilter=e.minFilter!==void 0?e.minFilter:dn}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:` varying vec3 vWorldDirection; @@ -41,13 +41,13 @@ var bc=Object.defineProperty;var Tc=(i,t,e)=>t in i?bc(i,t,{enumerable:!0,config gl_FragColor = texture2D( tEquirect, sampleUV ); } - `},s=new hs(5,5,5),r=new Ne({name:"CubemapFromEquirect",uniforms:Vi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:ke,blending:bn});r.uniforms.tEquirect.value=e;const a=new Se(s,r),o=e.minFilter;return e.minFilter===Qn&&(e.minFilter=dn),new Yh(1,10,this).update(t,a),e.minFilter=o,a.geometry.dispose(),a.material.dispose(),this}clear(t,e,n,s){const r=t.getRenderTarget();for(let a=0;a<6;a++)t.setRenderTarget(this,a),t.clear(e,n,s);t.setRenderTarget(r)}}class ur{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new pt(t),this.density=e}clone(){return new ur(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class jh extends we{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new pn,this.environmentIntensity=1,this.environmentRotation=new pn,this.overrideMaterial=null,typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),t.background!==null&&(this.background=t.background.clone()),t.environment!==null&&(this.environment=t.environment.clone()),t.fog!==null&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),t.overrideMaterial!==null&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return this.fog!==null&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class Zh{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=t!==void 0?t.length/e:0,this.usage=Ba,this.updateRanges=[],this.version=0,this.uuid=Bn()}onUploadCallback(){}set needsUpdate(t){t===!0&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let s=0,r=this.stride;st.far||e.push({distance:l,point:$i.clone(),uv:tn.getInterpolation($i,Ls,Qi,Us,Io,Or,No,new vt),face:null,object:this})}copy(t,e){return super.copy(t,e),t.center!==void 0&&this.center.copy(t.center),this.material=t.material,this}}function Is(i,t,e,n,s,r){Ei.subVectors(i,e).addScalar(.5).multiply(n),s!==void 0?(Ji.x=r*Ei.x-s*Ei.y,Ji.y=s*Ei.x+r*Ei.y):Ji.copy(Ei),i.copy(t),i.x+=Ji.x,i.y+=Ji.y,i.applyMatrix4(ac)}class Kh extends Ce{constructor(t=null,e=1,n=1,s,r,a,o,l,c=qe,h=qe,d,f){super(null,a,o,l,c,h,s,r,d,f),this.isDataTexture=!0,this.image={data:t,width:e,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class Fo extends de{constructor(t,e,n,s=1){super(t,e,n),this.isInstancedBufferAttribute=!0,this.meshPerAttribute=s}copy(t){return super.copy(t),this.meshPerAttribute=t.meshPerAttribute,this}toJSON(){const t=super.toJSON();return t.meshPerAttribute=this.meshPerAttribute,t.isInstancedBufferAttribute=!0,t}}const bi=new ee,Oo=new ee,Ns=[],Bo=new si,$h=new ee,ts=new Se,es=new ri;class Jh extends Se{constructor(t,e,n){super(t,e),this.isInstancedMesh=!0,this.instanceMatrix=new Fo(new Float32Array(n*16),16),this.instanceColor=null,this.morphTexture=null,this.count=n,this.boundingBox=null,this.boundingSphere=null;for(let s=0;s1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||tu.getNormalMatrix(t),s=this.coplanarPoint(zr).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-s.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return new this.constructor().copy(this)}}const Yn=new ri,Fs=new P;class to{constructor(t=new Nn,e=new Nn,n=new Nn,s=new Nn,r=new Nn,a=new Nn){this.planes=[t,e,n,s,r,a]}set(t,e,n,s,r,a){const o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(n),o[3].copy(s),o[4].copy(r),o[5].copy(a),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=En){const n=this.planes,s=t.elements,r=s[0],a=s[1],o=s[2],l=s[3],c=s[4],h=s[5],d=s[6],f=s[7],p=s[8],g=s[9],v=s[10],m=s[11],u=s[12],T=s[13],b=s[14],y=s[15];if(n[0].setComponents(l-r,f-c,m-p,y-u).normalize(),n[1].setComponents(l+r,f+c,m+p,y+u).normalize(),n[2].setComponents(l+a,f+h,m+g,y+T).normalize(),n[3].setComponents(l-a,f-h,m-g,y-T).normalize(),n[4].setComponents(l-o,f-d,m-v,y-b).normalize(),e===En)n[5].setComponents(l+o,f+d,m+v,y+b).normalize();else if(e===er)n[5].setComponents(o,d,v,b).normalize();else throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);return this}intersectsObject(t){if(t.boundingSphere!==void 0)t.boundingSphere===null&&t.computeBoundingSphere(),Yn.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;e.boundingSphere===null&&e.computeBoundingSphere(),Yn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(Yn)}intersectsSprite(t){return Yn.center.set(0,0,0),Yn.radius=.7071067811865476,Yn.applyMatrix4(t.matrixWorld),this.intersectsSphere(Yn)}intersectsSphere(t){const e=this.planes,n=t.center,s=-t.radius;for(let r=0;r<6;r++)if(e[r].distanceToPoint(n)0?t.max.x:t.min.x,Fs.y=s.normal.y>0?t.max.y:t.min.y,Fs.z=s.normal.z>0?t.max.z:t.min.z,s.distanceToPoint(Fs)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}}class rr extends Hn{constructor(t){super(),this.isLineBasicMaterial=!0,this.type="LineBasicMaterial",this.color=new pt(16777215),this.map=null,this.linewidth=1,this.linecap="round",this.linejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.linewidth=t.linewidth,this.linecap=t.linecap,this.linejoin=t.linejoin,this.fog=t.fog,this}}const ar=new P,or=new P,zo=new ee,ns=new cs,Os=new ri,Hr=new P,Ho=new P;class ka extends we{constructor(t=new pe,e=new rr){super(),this.isLine=!0,this.type="Line",this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}computeLineDistances(){const t=this.geometry;if(t.index===null){const e=t.attributes.position,n=[0];for(let s=1,r=e.count;s0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;rn)return;Hr.applyMatrix4(i.matrixWorld);const l=t.ray.origin.distanceTo(Hr);if(!(lt.far))return{distance:l,point:Ho.clone().applyMatrix4(i.matrixWorld),index:s,face:null,faceIndex:null,barycoord:null,object:i}}class Ni extends Hn{constructor(t){super(),this.isPointsMaterial=!0,this.type="PointsMaterial",this.color=new pt(16777215),this.map=null,this.alphaMap=null,this.size=1,this.sizeAttenuation=!0,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.alphaMap=t.alphaMap,this.size=t.size,this.sizeAttenuation=t.sizeAttenuation,this.fog=t.fog,this}}const ko=new ee,Va=new cs,zs=new ri,Hs=new P;class rs extends we{constructor(t=new pe,e=new Ni){super(),this.isPoints=!0,this.type="Points",this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}raycast(t,e){const n=this.geometry,s=this.matrixWorld,r=t.params.Points.threshold,a=n.drawRange;if(n.boundingSphere===null&&n.computeBoundingSphere(),zs.copy(n.boundingSphere),zs.applyMatrix4(s),zs.radius+=r,t.ray.intersectsSphere(zs)===!1)return;ko.copy(s).invert(),Va.copy(t.ray).applyMatrix4(ko);const o=r/((this.scale.x+this.scale.y+this.scale.z)/3),l=o*o,c=n.index,d=n.attributes.position;if(c!==null){const f=Math.max(0,a.start),p=Math.min(c.count,a.start+a.count);for(let g=f,v=p;g0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;rs.far)return;r.push({distance:c,distanceToRay:Math.sqrt(o),point:l,index:t,face:null,faceIndex:null,barycoord:null,object:a})}}class Ci extends we{constructor(){super(),this.isGroup=!0,this.type="Group"}}class eu extends Ce{constructor(t,e,n,s,r,a,o,l,c){super(t,e,n,s,r,a,o,l,c),this.isCanvasTexture=!0,this.needsUpdate=!0}}class oc extends Ce{constructor(t,e,n,s,r,a,o,l,c,h=Ui){if(h!==Ui&&h!==Hi)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");n===void 0&&h===Ui&&(n=ei),n===void 0&&h===Hi&&(n=zi),super(null,s,r,a,o,l,h,n,c),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=o!==void 0?o:qe,this.minFilter=l!==void 0?l:qe,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return this.compareFunction!==null&&(e.compareFunction=this.compareFunction),e}}class us extends pe{constructor(t=1,e=1,n=1,s=1){super(),this.type="PlaneGeometry",this.parameters={width:t,height:e,widthSegments:n,heightSegments:s};const r=t/2,a=e/2,o=Math.floor(n),l=Math.floor(s),c=o+1,h=l+1,d=t/o,f=e/l,p=[],g=[],v=[],m=[];for(let u=0;u0)&&p.push(b,y,R),(u!==n-1||l0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class $h{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=t!==void 0?t.length/e:0,this.usage=Ha,this.updateRanges=[],this.version=0,this.uuid=Bn()}onUploadCallback(){}set needsUpdate(t){t===!0&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let s=0,r=this.stride;st.far||e.push({distance:l,point:Ji.clone(),uv:tn.getInterpolation(Ji,Us,ts,Is,No,Hr,Fo,new vt),face:null,object:this})}copy(t,e){return super.copy(t,e),t.center!==void 0&&this.center.copy(t.center),this.material=t.material,this}}function Fs(i,t,e,n,s,r){bi.subVectors(i,e).addScalar(.5).multiply(n),s!==void 0?(Qi.x=r*bi.x-s*bi.y,Qi.y=s*bi.x+r*bi.y):Qi.copy(bi),i.copy(t),i.x+=Qi.x,i.y+=Qi.y,i.applyMatrix4(oc)}class Jh extends Te{constructor(t=null,e=1,n=1,s,r,a,o,l,c=qe,h=qe,d,p){super(null,a,o,l,c,h,s,r,d,p),this.isDataTexture=!0,this.image={data:t,width:e,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class Oo extends he{constructor(t,e,n,s=1){super(t,e,n),this.isInstancedBufferAttribute=!0,this.meshPerAttribute=s}copy(t){return super.copy(t),this.meshPerAttribute=t.meshPerAttribute,this}toJSON(){const t=super.toJSON();return t.meshPerAttribute=this.meshPerAttribute,t.isInstancedBufferAttribute=!0,t}}const Ti=new ee,Bo=new ee,Os=[],zo=new ri,Qh=new ee,es=new Se,ns=new ai;class tu extends Se{constructor(t,e,n){super(t,e),this.isInstancedMesh=!0,this.instanceMatrix=new Oo(new Float32Array(n*16),16),this.instanceColor=null,this.morphTexture=null,this.count=n,this.boundingBox=null,this.boundingSphere=null;for(let s=0;s1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||nu.getNormalMatrix(t),s=this.coplanarPoint(kr).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-s.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return new this.constructor().copy(this)}}const Yn=new ai,Bs=new P;class eo{constructor(t=new Nn,e=new Nn,n=new Nn,s=new Nn,r=new Nn,a=new Nn){this.planes=[t,e,n,s,r,a]}set(t,e,n,s,r,a){const o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(n),o[3].copy(s),o[4].copy(r),o[5].copy(a),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=En){const n=this.planes,s=t.elements,r=s[0],a=s[1],o=s[2],l=s[3],c=s[4],h=s[5],d=s[6],p=s[7],f=s[8],g=s[9],v=s[10],m=s[11],u=s[12],T=s[13],b=s[14],y=s[15];if(n[0].setComponents(l-r,p-c,m-f,y-u).normalize(),n[1].setComponents(l+r,p+c,m+f,y+u).normalize(),n[2].setComponents(l+a,p+h,m+g,y+T).normalize(),n[3].setComponents(l-a,p-h,m-g,y-T).normalize(),n[4].setComponents(l-o,p-d,m-v,y-b).normalize(),e===En)n[5].setComponents(l+o,p+d,m+v,y+b).normalize();else if(e===sr)n[5].setComponents(o,d,v,b).normalize();else throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);return this}intersectsObject(t){if(t.boundingSphere!==void 0)t.boundingSphere===null&&t.computeBoundingSphere(),Yn.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;e.boundingSphere===null&&e.computeBoundingSphere(),Yn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(Yn)}intersectsSprite(t){return Yn.center.set(0,0,0),Yn.radius=.7071067811865476,Yn.applyMatrix4(t.matrixWorld),this.intersectsSphere(Yn)}intersectsSphere(t){const e=this.planes,n=t.center,s=-t.radius;for(let r=0;r<6;r++)if(e[r].distanceToPoint(n)0?t.max.x:t.min.x,Bs.y=s.normal.y>0?t.max.y:t.min.y,Bs.z=s.normal.z>0?t.max.z:t.min.z,s.distanceToPoint(Bs)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}}class lr extends Hn{constructor(t){super(),this.isLineBasicMaterial=!0,this.type="LineBasicMaterial",this.color=new pt(16777215),this.map=null,this.linewidth=1,this.linecap="round",this.linejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.linewidth=t.linewidth,this.linecap=t.linecap,this.linejoin=t.linejoin,this.fog=t.fog,this}}const cr=new P,hr=new P,Ho=new ee,is=new hs,zs=new ai,Vr=new P,ko=new P;class Va extends Ae{constructor(t=new pe,e=new lr){super(),this.isLine=!0,this.type="Line",this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}computeLineDistances(){const t=this.geometry;if(t.index===null){const e=t.attributes.position,n=[0];for(let s=1,r=e.count;s0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;rn)return;Vr.applyMatrix4(i.matrixWorld);const l=t.ray.origin.distanceTo(Vr);if(!(lt.far))return{distance:l,point:ko.clone().applyMatrix4(i.matrixWorld),index:s,face:null,faceIndex:null,barycoord:null,object:i}}class ei extends Hn{constructor(t){super(),this.isPointsMaterial=!0,this.type="PointsMaterial",this.color=new pt(16777215),this.map=null,this.alphaMap=null,this.size=1,this.sizeAttenuation=!0,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.alphaMap=t.alphaMap,this.size=t.size,this.sizeAttenuation=t.sizeAttenuation,this.fog=t.fog,this}}const Vo=new ee,Ga=new hs,ks=new ai,Vs=new P;class Fi extends Ae{constructor(t=new pe,e=new ei){super(),this.isPoints=!0,this.type="Points",this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}raycast(t,e){const n=this.geometry,s=this.matrixWorld,r=t.params.Points.threshold,a=n.drawRange;if(n.boundingSphere===null&&n.computeBoundingSphere(),ks.copy(n.boundingSphere),ks.applyMatrix4(s),ks.radius+=r,t.ray.intersectsSphere(ks)===!1)return;Vo.copy(s).invert(),Ga.copy(t.ray).applyMatrix4(Vo);const o=r/((this.scale.x+this.scale.y+this.scale.z)/3),l=o*o,c=n.index,d=n.attributes.position;if(c!==null){const p=Math.max(0,a.start),f=Math.min(c.count,a.start+a.count);for(let g=p,v=f;g0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;rs.far)return;r.push({distance:c,distanceToRay:Math.sqrt(o),point:l,index:t,face:null,faceIndex:null,barycoord:null,object:a})}}class Pi extends Ae{constructor(){super(),this.isGroup=!0,this.type="Group"}}class lc extends Te{constructor(t,e,n,s,r,a,o,l,c){super(t,e,n,s,r,a,o,l,c),this.isCanvasTexture=!0,this.needsUpdate=!0}}class cc extends Te{constructor(t,e,n,s,r,a,o,l,c,h=Ii){if(h!==Ii&&h!==ki)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");n===void 0&&h===Ii&&(n=ni),n===void 0&&h===ki&&(n=Hi),super(null,s,r,a,o,l,h,n,c),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=o!==void 0?o:qe,this.minFilter=l!==void 0?l:qe,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return this.compareFunction!==null&&(e.compareFunction=this.compareFunction),e}}class ds extends pe{constructor(t=1,e=1,n=1,s=1){super(),this.type="PlaneGeometry",this.parameters={width:t,height:e,widthSegments:n,heightSegments:s};const r=t/2,a=e/2,o=Math.floor(n),l=Math.floor(s),c=o+1,h=l+1,d=t/o,p=e/l,f=[],g=[],v=[],m=[];for(let u=0;u0)&&f.push(b,y,R),(u!==n-1||lp.start-g.start);let f=0;for(let p=1;pf.start-g.start);let p=0;for(let f=1;ft in i?bc(i,t,{enumerable:!0,config : cases.z; return clamp( threshold , 1.0e-6, 1.0 ); } -#endif`,gu=`#ifdef USE_ALPHAMAP - diffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g; #endif`,_u=`#ifdef USE_ALPHAMAP + diffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g; +#endif`,vu=`#ifdef USE_ALPHAMAP uniform sampler2D alphaMap; -#endif`,vu=`#ifdef USE_ALPHATEST +#endif`,xu=`#ifdef USE_ALPHATEST #ifdef ALPHA_TO_COVERAGE diffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a ); if ( diffuseColor.a == 0.0 ) discard; #else if ( diffuseColor.a < alphaTest ) discard; #endif -#endif`,xu=`#ifdef USE_ALPHATEST +#endif`,Mu=`#ifdef USE_ALPHATEST uniform float alphaTest; -#endif`,Mu=`#ifdef USE_AOMAP +#endif`,Su=`#ifdef USE_AOMAP float ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0; reflectedLight.indirectDiffuse *= ambientOcclusion; #if defined( USE_CLEARCOAT ) @@ -108,10 +108,10 @@ var bc=Object.defineProperty;var Tc=(i,t,e)=>t in i?bc(i,t,{enumerable:!0,config float dotNV = saturate( dot( geometryNormal, geometryViewDir ) ); reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness ); #endif -#endif`,Su=`#ifdef USE_AOMAP +#endif`,yu=`#ifdef USE_AOMAP uniform sampler2D aoMap; uniform float aoMapIntensity; -#endif`,yu=`#ifdef USE_BATCHING +#endif`,Eu=`#ifdef USE_BATCHING #if ! defined( GL_ANGLE_multi_draw ) #define gl_DrawID _gl_DrawID uniform int _gl_DrawID; @@ -145,15 +145,15 @@ var bc=Object.defineProperty;var Tc=(i,t,e)=>t in i?bc(i,t,{enumerable:!0,config int y = j / size; return texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb; } -#endif`,Eu=`#ifdef USE_BATCHING +#endif`,bu=`#ifdef USE_BATCHING mat4 batchingMatrix = getBatchingMatrix( getIndirectIndex( gl_DrawID ) ); -#endif`,bu=`vec3 transformed = vec3( position ); +#endif`,Tu=`vec3 transformed = vec3( position ); #ifdef USE_ALPHAHASH vPosition = vec3( position ); -#endif`,Tu=`vec3 objectNormal = vec3( normal ); +#endif`,wu=`vec3 objectNormal = vec3( normal ); #ifdef USE_TANGENT vec3 objectTangent = vec3( tangent.xyz ); -#endif`,wu=`float G_BlinnPhong_Implicit( ) { +#endif`,Au=`float G_BlinnPhong_Implicit( ) { return 0.25; } float D_BlinnPhong( const in float shininess, const in float dotNH ) { @@ -167,7 +167,7 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve float G = G_BlinnPhong_Implicit( ); float D = D_BlinnPhong( shininess, dotNH ); return F * ( G * D ); -} // validated`,Au=`#ifdef USE_IRIDESCENCE +} // validated`,Ru=`#ifdef USE_IRIDESCENCE const mat3 XYZ_TO_REC709 = mat3( 3.2404542, -0.9692660, 0.0556434, -1.5371385, 1.8760108, -0.2040259, @@ -230,7 +230,7 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve } return max( I, vec3( 0.0 ) ); } -#endif`,Ru=`#ifdef USE_BUMPMAP +#endif`,Cu=`#ifdef USE_BUMPMAP uniform sampler2D bumpMap; uniform float bumpScale; vec2 dHdxy_fwd() { @@ -251,7 +251,7 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 ); return normalize( abs( fDet ) * surf_norm - vGrad ); } -#endif`,Cu=`#if NUM_CLIPPING_PLANES > 0 +#endif`,Pu=`#if NUM_CLIPPING_PLANES > 0 vec4 plane; #ifdef ALPHA_TO_COVERAGE float distanceToPlane, distanceGradient; @@ -297,26 +297,26 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve if ( clipped ) discard; #endif #endif -#endif`,Pu=`#if NUM_CLIPPING_PLANES > 0 - varying vec3 vClipPosition; - uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; #endif`,Du=`#if NUM_CLIPPING_PLANES > 0 varying vec3 vClipPosition; + uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; #endif`,Lu=`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; +#endif`,Uu=`#if NUM_CLIPPING_PLANES > 0 vClipPosition = - mvPosition.xyz; -#endif`,Uu=`#if defined( USE_COLOR_ALPHA ) +#endif`,Iu=`#if defined( USE_COLOR_ALPHA ) diffuseColor *= vColor; #elif defined( USE_COLOR ) diffuseColor.rgb *= vColor; -#endif`,Iu=`#if defined( USE_COLOR_ALPHA ) +#endif`,Nu=`#if defined( USE_COLOR_ALPHA ) varying vec4 vColor; #elif defined( USE_COLOR ) varying vec3 vColor; -#endif`,Nu=`#if defined( USE_COLOR_ALPHA ) +#endif`,Fu=`#if defined( USE_COLOR_ALPHA ) varying vec4 vColor; #elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) varying vec3 vColor; -#endif`,Fu=`#if defined( USE_COLOR_ALPHA ) +#endif`,Ou=`#if defined( USE_COLOR_ALPHA ) vColor = vec4( 1.0 ); #elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) vColor = vec3( 1.0 ); @@ -330,7 +330,7 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve #ifdef USE_BATCHING_COLOR vec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) ); vColor.xyz *= batchingColor.xyz; -#endif`,Ou=`#define PI 3.141592653589793 +#endif`,Bu=`#define PI 3.141592653589793 #define PI2 6.283185307179586 #define PI_HALF 1.5707963267948966 #define RECIPROCAL_PI 0.3183098861837907 @@ -404,7 +404,7 @@ vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); -} // validated`,Bu=`#ifdef ENVMAP_TYPE_CUBE_UV +} // validated`,zu=`#ifdef ENVMAP_TYPE_CUBE_UV #define cubeUV_minMipLevel 4.0 #define cubeUV_minTileSize 16.0 float getFace( vec3 direction ) { @@ -497,7 +497,7 @@ float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { return vec4( mix( color0, color1, mipF ), 1.0 ); } } -#endif`,zu=`vec3 transformedNormal = objectNormal; +#endif`,Hu=`vec3 transformedNormal = objectNormal; #ifdef USE_TANGENT vec3 transformedTangent = objectTangent; #endif @@ -526,21 +526,21 @@ transformedNormal = normalMatrix * transformedNormal; #ifdef FLIP_SIDED transformedTangent = - transformedTangent; #endif -#endif`,Hu=`#ifdef USE_DISPLACEMENTMAP +#endif`,ku=`#ifdef USE_DISPLACEMENTMAP uniform sampler2D displacementMap; uniform float displacementScale; uniform float displacementBias; -#endif`,ku=`#ifdef USE_DISPLACEMENTMAP +#endif`,Vu=`#ifdef USE_DISPLACEMENTMAP transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); -#endif`,Vu=`#ifdef USE_EMISSIVEMAP +#endif`,Gu=`#ifdef USE_EMISSIVEMAP vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); #ifdef DECODE_VIDEO_TEXTURE_EMISSIVE emissiveColor = sRGBTransferEOTF( emissiveColor ); #endif totalEmissiveRadiance *= emissiveColor.rgb; -#endif`,Gu=`#ifdef USE_EMISSIVEMAP +#endif`,Wu=`#ifdef USE_EMISSIVEMAP uniform sampler2D emissiveMap; -#endif`,Wu="gl_FragColor = linearToOutputTexel( gl_FragColor );",Xu=`vec4 LinearTransferOETF( in vec4 value ) { +#endif`,Xu="gl_FragColor = linearToOutputTexel( gl_FragColor );",Yu=`vec4 LinearTransferOETF( in vec4 value ) { return value; } vec4 sRGBTransferEOTF( in vec4 value ) { @@ -548,7 +548,7 @@ vec4 sRGBTransferEOTF( in vec4 value ) { } vec4 sRGBTransferOETF( in vec4 value ) { return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); -}`,Yu=`#ifdef USE_ENVMAP +}`,qu=`#ifdef USE_ENVMAP #ifdef ENV_WORLDPOS vec3 cameraToFrag; if ( isOrthographic ) { @@ -577,7 +577,7 @@ vec4 sRGBTransferOETF( in vec4 value ) { #elif defined( ENVMAP_BLENDING_ADD ) outgoingLight += envColor.xyz * specularStrength * reflectivity; #endif -#endif`,qu=`#ifdef USE_ENVMAP +#endif`,ju=`#ifdef USE_ENVMAP uniform float envMapIntensity; uniform float flipEnvMap; uniform mat3 envMapRotation; @@ -587,7 +587,7 @@ vec4 sRGBTransferOETF( in vec4 value ) { uniform sampler2D envMap; #endif -#endif`,ju=`#ifdef USE_ENVMAP +#endif`,Zu=`#ifdef USE_ENVMAP uniform float reflectivity; #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) #define ENV_WORLDPOS @@ -598,7 +598,7 @@ vec4 sRGBTransferOETF( in vec4 value ) { #else varying vec3 vReflect; #endif -#endif`,Zu=`#ifdef USE_ENVMAP +#endif`,Ku=`#ifdef USE_ENVMAP #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) #define ENV_WORLDPOS #endif @@ -609,7 +609,7 @@ vec4 sRGBTransferOETF( in vec4 value ) { varying vec3 vReflect; uniform float refractionRatio; #endif -#endif`,Ku=`#ifdef USE_ENVMAP +#endif`,$u=`#ifdef USE_ENVMAP #ifdef ENV_WORLDPOS vWorldPosition = worldPosition.xyz; #else @@ -626,18 +626,18 @@ vec4 sRGBTransferOETF( in vec4 value ) { vReflect = refract( cameraToVertex, worldNormal, refractionRatio ); #endif #endif -#endif`,$u=`#ifdef USE_FOG - vFogDepth = - mvPosition.z; #endif`,Ju=`#ifdef USE_FOG - varying float vFogDepth; + vFogDepth = - mvPosition.z; #endif`,Qu=`#ifdef USE_FOG + varying float vFogDepth; +#endif`,td=`#ifdef USE_FOG #ifdef FOG_EXP2 float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth ); #else float fogFactor = smoothstep( fogNear, fogFar, vFogDepth ); #endif gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); -#endif`,td=`#ifdef USE_FOG +#endif`,ed=`#ifdef USE_FOG uniform vec3 fogColor; varying float vFogDepth; #ifdef FOG_EXP2 @@ -646,7 +646,7 @@ vec4 sRGBTransferOETF( in vec4 value ) { uniform float fogNear; uniform float fogFar; #endif -#endif`,ed=`#ifdef USE_GRADIENTMAP +#endif`,nd=`#ifdef USE_GRADIENTMAP uniform sampler2D gradientMap; #endif vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { @@ -658,12 +658,12 @@ vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { vec2 fw = fwidth( coord ) * 0.5; return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) ); #endif -}`,nd=`#ifdef USE_LIGHTMAP +}`,id=`#ifdef USE_LIGHTMAP uniform sampler2D lightMap; uniform float lightMapIntensity; -#endif`,id=`LambertMaterial material; +#endif`,sd=`LambertMaterial material; material.diffuseColor = diffuseColor.rgb; -material.specularStrength = specularStrength;`,sd=`varying vec3 vViewPosition; +material.specularStrength = specularStrength;`,rd=`varying vec3 vViewPosition; struct LambertMaterial { vec3 diffuseColor; float specularStrength; @@ -677,7 +677,7 @@ void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometr reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); } #define RE_Direct RE_Direct_Lambert -#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,rd=`uniform bool receiveShadow; +#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,ad=`uniform bool receiveShadow; uniform vec3 ambientLightColor; #if defined( USE_LIGHT_PROBES ) uniform vec3 lightProbe[ 9 ]; @@ -793,7 +793,7 @@ float getSpotAttenuation( const in float coneCosine, const in float penumbraCosi vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight ); return irradiance; } -#endif`,ad=`#ifdef USE_ENVMAP +#endif`,od=`#ifdef USE_ENVMAP vec3 getIBLIrradiance( const in vec3 normal ) { #ifdef ENVMAP_TYPE_CUBE_UV vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); @@ -826,8 +826,8 @@ float getSpotAttenuation( const in float coneCosine, const in float penumbraCosi #endif } #endif -#endif`,od=`ToonMaterial material; -material.diffuseColor = diffuseColor.rgb;`,ld=`varying vec3 vViewPosition; +#endif`,ld=`ToonMaterial material; +material.diffuseColor = diffuseColor.rgb;`,cd=`varying vec3 vViewPosition; struct ToonMaterial { vec3 diffuseColor; }; @@ -839,11 +839,11 @@ void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPo reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); } #define RE_Direct RE_Direct_Toon -#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,cd=`BlinnPhongMaterial material; +#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,hd=`BlinnPhongMaterial material; material.diffuseColor = diffuseColor.rgb; material.specularColor = specular; material.specularShininess = shininess; -material.specularStrength = specularStrength;`,hd=`varying vec3 vViewPosition; +material.specularStrength = specularStrength;`,ud=`varying vec3 vViewPosition; struct BlinnPhongMaterial { vec3 diffuseColor; vec3 specularColor; @@ -860,7 +860,7 @@ void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geom reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); } #define RE_Direct RE_Direct_BlinnPhong -#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,ud=`PhysicalMaterial material; +#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,dd=`PhysicalMaterial material; material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor ); vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) ); float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); @@ -946,7 +946,7 @@ material.roughness = min( material.roughness, 1.0 ); material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y; material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y; -#endif`,dd=`struct PhysicalMaterial { +#endif`,fd=`struct PhysicalMaterial { vec3 diffuseColor; float roughness; vec3 specularColor; @@ -1247,7 +1247,7 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia #define RE_IndirectSpecular RE_IndirectSpecular_Physical float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); -}`,fd=` +}`,pd=` vec3 geometryPosition = - vViewPosition; vec3 geometryNormal = normal; vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); @@ -1362,7 +1362,7 @@ IncidentLight directLight; #if defined( RE_IndirectSpecular ) vec3 radiance = vec3( 0.0 ); vec3 clearcoatRadiance = vec3( 0.0 ); -#endif`,pd=`#if defined( RE_IndirectDiffuse ) +#endif`,md=`#if defined( RE_IndirectDiffuse ) #ifdef USE_LIGHTMAP vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; @@ -1381,32 +1381,32 @@ IncidentLight directLight; #ifdef USE_CLEARCOAT clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness ); #endif -#endif`,md=`#if defined( RE_IndirectDiffuse ) +#endif`,gd=`#if defined( RE_IndirectDiffuse ) RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); #endif #if defined( RE_IndirectSpecular ) RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); -#endif`,gd=`#if defined( USE_LOGDEPTHBUF ) - gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; #endif`,_d=`#if defined( USE_LOGDEPTHBUF ) + gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; +#endif`,vd=`#if defined( USE_LOGDEPTHBUF ) uniform float logDepthBufFC; varying float vFragDepth; varying float vIsPerspective; -#endif`,vd=`#ifdef USE_LOGDEPTHBUF +#endif`,xd=`#ifdef USE_LOGDEPTHBUF varying float vFragDepth; varying float vIsPerspective; -#endif`,xd=`#ifdef USE_LOGDEPTHBUF +#endif`,Md=`#ifdef USE_LOGDEPTHBUF vFragDepth = 1.0 + gl_Position.w; vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) ); -#endif`,Md=`#ifdef USE_MAP +#endif`,Sd=`#ifdef USE_MAP vec4 sampledDiffuseColor = texture2D( map, vMapUv ); #ifdef DECODE_VIDEO_TEXTURE sampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor ); #endif diffuseColor *= sampledDiffuseColor; -#endif`,Sd=`#ifdef USE_MAP +#endif`,yd=`#ifdef USE_MAP uniform sampler2D map; -#endif`,yd=`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) +#endif`,Ed=`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) #if defined( USE_POINTS_UV ) vec2 uv = vUv; #else @@ -1418,7 +1418,7 @@ IncidentLight directLight; #endif #ifdef USE_ALPHAMAP diffuseColor.a *= texture2D( alphaMap, uv ).g; -#endif`,Ed=`#if defined( USE_POINTS_UV ) +#endif`,bd=`#if defined( USE_POINTS_UV ) varying vec2 vUv; #else #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) @@ -1430,19 +1430,19 @@ IncidentLight directLight; #endif #ifdef USE_ALPHAMAP uniform sampler2D alphaMap; -#endif`,bd=`float metalnessFactor = metalness; +#endif`,Td=`float metalnessFactor = metalness; #ifdef USE_METALNESSMAP vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); metalnessFactor *= texelMetalness.b; -#endif`,Td=`#ifdef USE_METALNESSMAP +#endif`,wd=`#ifdef USE_METALNESSMAP uniform sampler2D metalnessMap; -#endif`,wd=`#ifdef USE_INSTANCING_MORPH +#endif`,Ad=`#ifdef USE_INSTANCING_MORPH float morphTargetInfluences[ MORPHTARGETS_COUNT ]; float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r; for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r; } -#endif`,Ad=`#if defined( USE_MORPHCOLORS ) +#endif`,Rd=`#if defined( USE_MORPHCOLORS ) vColor *= morphTargetBaseInfluence; for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { #if defined( USE_COLOR_ALPHA ) @@ -1451,12 +1451,12 @@ IncidentLight directLight; if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ]; #endif } -#endif`,Rd=`#ifdef USE_MORPHNORMALS +#endif`,Cd=`#ifdef USE_MORPHNORMALS objectNormal *= morphTargetBaseInfluence; for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ]; } -#endif`,Cd=`#ifdef USE_MORPHTARGETS +#endif`,Pd=`#ifdef USE_MORPHTARGETS #ifndef USE_INSTANCING_MORPH uniform float morphTargetBaseInfluence; uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; @@ -1470,12 +1470,12 @@ IncidentLight directLight; ivec3 morphUV = ivec3( x, y, morphTargetIndex ); return texelFetch( morphTargetsTexture, morphUV, 0 ); } -#endif`,Pd=`#ifdef USE_MORPHTARGETS +#endif`,Dd=`#ifdef USE_MORPHTARGETS transformed *= morphTargetBaseInfluence; for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ]; } -#endif`,Dd=`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; +#endif`,Ld=`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; #ifdef FLAT_SHADED vec3 fdx = dFdx( vViewPosition ); vec3 fdy = dFdy( vViewPosition ); @@ -1516,7 +1516,7 @@ IncidentLight directLight; tbn2[1] *= faceDirection; #endif #endif -vec3 nonPerturbedNormal = normal;`,Ld=`#ifdef USE_NORMALMAP_OBJECTSPACE +vec3 nonPerturbedNormal = normal;`,Ud=`#ifdef USE_NORMALMAP_OBJECTSPACE normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; #ifdef FLIP_SIDED normal = - normal; @@ -1531,12 +1531,6 @@ vec3 nonPerturbedNormal = normal;`,Ld=`#ifdef USE_NORMALMAP_OBJECTSPACE normal = normalize( tbn * mapN ); #elif defined( USE_BUMPMAP ) normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); -#endif`,Ud=`#ifndef FLAT_SHADED - varying vec3 vNormal; - #ifdef USE_TANGENT - varying vec3 vTangent; - varying vec3 vBitangent; - #endif #endif`,Id=`#ifndef FLAT_SHADED varying vec3 vNormal; #ifdef USE_TANGENT @@ -1544,12 +1538,18 @@ vec3 nonPerturbedNormal = normal;`,Ld=`#ifdef USE_NORMALMAP_OBJECTSPACE varying vec3 vBitangent; #endif #endif`,Nd=`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,Fd=`#ifndef FLAT_SHADED vNormal = normalize( transformedNormal ); #ifdef USE_TANGENT vTangent = normalize( transformedTangent ); vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w ); #endif -#endif`,Fd=`#ifdef USE_NORMALMAP +#endif`,Od=`#ifdef USE_NORMALMAP uniform sampler2D normalMap; uniform vec2 normalScale; #endif @@ -1571,13 +1571,13 @@ vec3 nonPerturbedNormal = normal;`,Ld=`#ifdef USE_NORMALMAP_OBJECTSPACE float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); return mat3( T * scale, B * scale, N ); } -#endif`,Od=`#ifdef USE_CLEARCOAT +#endif`,Bd=`#ifdef USE_CLEARCOAT vec3 clearcoatNormal = nonPerturbedNormal; -#endif`,Bd=`#ifdef USE_CLEARCOAT_NORMALMAP +#endif`,zd=`#ifdef USE_CLEARCOAT_NORMALMAP vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; clearcoatMapN.xy *= clearcoatNormalScale; clearcoatNormal = normalize( tbn2 * clearcoatMapN ); -#endif`,zd=`#ifdef USE_CLEARCOATMAP +#endif`,Hd=`#ifdef USE_CLEARCOATMAP uniform sampler2D clearcoatMap; #endif #ifdef USE_CLEARCOAT_NORMALMAP @@ -1586,18 +1586,18 @@ vec3 nonPerturbedNormal = normal;`,Ld=`#ifdef USE_NORMALMAP_OBJECTSPACE #endif #ifdef USE_CLEARCOAT_ROUGHNESSMAP uniform sampler2D clearcoatRoughnessMap; -#endif`,Hd=`#ifdef USE_IRIDESCENCEMAP +#endif`,kd=`#ifdef USE_IRIDESCENCEMAP uniform sampler2D iridescenceMap; #endif #ifdef USE_IRIDESCENCE_THICKNESSMAP uniform sampler2D iridescenceThicknessMap; -#endif`,kd=`#ifdef OPAQUE +#endif`,Vd=`#ifdef OPAQUE diffuseColor.a = 1.0; #endif #ifdef USE_TRANSMISSION diffuseColor.a *= material.transmissionAlpha; #endif -gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,Vd=`vec3 packNormalToRGB( const in vec3 normal ) { +gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,Gd=`vec3 packNormalToRGB( const in vec3 normal ) { return normalize( normal ) * 0.5 + 0.5; } vec3 unpackRGBToNormal( const in vec3 rgb ) { @@ -1666,9 +1666,9 @@ float viewZToPerspectiveDepth( const in float viewZ, const in float near, const } float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { return ( near * far ) / ( ( far - near ) * depth - far ); -}`,Gd=`#ifdef PREMULTIPLIED_ALPHA +}`,Wd=`#ifdef PREMULTIPLIED_ALPHA gl_FragColor.rgb *= gl_FragColor.a; -#endif`,Wd=`vec4 mvPosition = vec4( transformed, 1.0 ); +#endif`,Xd=`vec4 mvPosition = vec4( transformed, 1.0 ); #ifdef USE_BATCHING mvPosition = batchingMatrix * mvPosition; #endif @@ -1676,22 +1676,22 @@ float perspectiveDepthToViewZ( const in float depth, const in float near, const mvPosition = instanceMatrix * mvPosition; #endif mvPosition = modelViewMatrix * mvPosition; -gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING +gl_Position = projectionMatrix * mvPosition;`,Yd=`#ifdef DITHERING gl_FragColor.rgb = dithering( gl_FragColor.rgb ); -#endif`,Yd=`#ifdef DITHERING +#endif`,qd=`#ifdef DITHERING vec3 dithering( vec3 color ) { float grid_position = rand( gl_FragCoord.xy ); vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 ); dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position ); return color + dither_shift_RGB; } -#endif`,qd=`float roughnessFactor = roughness; +#endif`,jd=`float roughnessFactor = roughness; #ifdef USE_ROUGHNESSMAP vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); roughnessFactor *= texelRoughness.g; -#endif`,jd=`#ifdef USE_ROUGHNESSMAP +#endif`,Zd=`#ifdef USE_ROUGHNESSMAP uniform sampler2D roughnessMap; -#endif`,Zd=`#if NUM_SPOT_LIGHT_COORDS > 0 +#endif`,Kd=`#if NUM_SPOT_LIGHT_COORDS > 0 varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; #endif #if NUM_SPOT_LIGHT_MAPS > 0 @@ -1877,7 +1877,7 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING } return mix( 1.0, shadow, shadowIntensity ); } -#endif`,Kd=`#if NUM_SPOT_LIGHT_COORDS > 0 +#endif`,$d=`#if NUM_SPOT_LIGHT_COORDS > 0 uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; #endif @@ -1918,7 +1918,7 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING }; uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; #endif -#endif`,$d=`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) +#endif`,Jd=`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); vec4 shadowWorldPosition; #endif @@ -1950,7 +1950,7 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition; } #pragma unroll_loop_end -#endif`,Jd=`float getShadowMask() { +#endif`,Qd=`float getShadowMask() { float shadow = 1.0; #ifdef USE_SHADOWMAP #if NUM_DIR_LIGHT_SHADOWS > 0 @@ -1982,12 +1982,12 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING #endif #endif return shadow; -}`,Qd=`#ifdef USE_SKINNING +}`,tf=`#ifdef USE_SKINNING mat4 boneMatX = getBoneMatrix( skinIndex.x ); mat4 boneMatY = getBoneMatrix( skinIndex.y ); mat4 boneMatZ = getBoneMatrix( skinIndex.z ); mat4 boneMatW = getBoneMatrix( skinIndex.w ); -#endif`,tf=`#ifdef USE_SKINNING +#endif`,ef=`#ifdef USE_SKINNING uniform mat4 bindMatrix; uniform mat4 bindMatrixInverse; uniform highp sampler2D boneTexture; @@ -2002,7 +2002,7 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 ); return mat4( v1, v2, v3, v4 ); } -#endif`,ef=`#ifdef USE_SKINNING +#endif`,nf=`#ifdef USE_SKINNING vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 ); vec4 skinned = vec4( 0.0 ); skinned += boneMatX * skinVertex * skinWeight.x; @@ -2010,7 +2010,7 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING skinned += boneMatZ * skinVertex * skinWeight.z; skinned += boneMatW * skinVertex * skinWeight.w; transformed = ( bindMatrixInverse * skinned ).xyz; -#endif`,nf=`#ifdef USE_SKINNING +#endif`,sf=`#ifdef USE_SKINNING mat4 skinMatrix = mat4( 0.0 ); skinMatrix += skinWeight.x * boneMatX; skinMatrix += skinWeight.y * boneMatY; @@ -2021,17 +2021,17 @@ gl_Position = projectionMatrix * mvPosition;`,Xd=`#ifdef DITHERING #ifdef USE_TANGENT objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz; #endif -#endif`,sf=`float specularStrength; +#endif`,rf=`float specularStrength; #ifdef USE_SPECULARMAP vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); specularStrength = texelSpecular.r; #else specularStrength = 1.0; -#endif`,rf=`#ifdef USE_SPECULARMAP +#endif`,af=`#ifdef USE_SPECULARMAP uniform sampler2D specularMap; -#endif`,af=`#if defined( TONE_MAPPING ) +#endif`,of=`#if defined( TONE_MAPPING ) gl_FragColor.rgb = toneMapping( gl_FragColor.rgb ); -#endif`,of=`#ifndef saturate +#endif`,lf=`#ifndef saturate #define saturate( a ) clamp( a, 0.0, 1.0 ) #endif uniform float toneMappingExposure; @@ -2128,7 +2128,7 @@ vec3 NeutralToneMapping( vec3 color ) { float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); return mix( color, vec3( newPeak ), g ); } -vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISSION +vec3 CustomToneMapping( vec3 color ) { return color; }`,cf=`#ifdef USE_TRANSMISSION material.transmission = transmission; material.transmissionAlpha = 1.0; material.thickness = thickness; @@ -2149,7 +2149,7 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS material.attenuationColor, material.attenuationDistance ); material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); -#endif`,cf=`#ifdef USE_TRANSMISSION +#endif`,hf=`#ifdef USE_TRANSMISSION uniform float transmission; uniform float thickness; uniform float attenuationDistance; @@ -2275,7 +2275,7 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); } -#endif`,hf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) +#endif`,uf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) varying vec2 vUv; #endif #ifdef USE_MAP @@ -2345,7 +2345,7 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS #ifdef USE_THICKNESSMAP uniform mat3 thicknessMapTransform; varying vec2 vThicknessMapUv; -#endif`,uf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) +#endif`,df=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) varying vec2 vUv; #endif #ifdef USE_MAP @@ -2439,7 +2439,7 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS #ifdef USE_THICKNESSMAP uniform mat3 thicknessMapTransform; varying vec2 vThicknessMapUv; -#endif`,df=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) +#endif`,ff=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) vUv = vec3( uv, 1 ).xy; #endif #ifdef USE_MAP @@ -2510,7 +2510,7 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS #endif #ifdef USE_THICKNESSMAP vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; -#endif`,ff=`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 +#endif`,pf=`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 vec4 worldPosition = vec4( transformed, 1.0 ); #ifdef USE_BATCHING worldPosition = batchingMatrix * worldPosition; @@ -2519,12 +2519,12 @@ vec3 CustomToneMapping( vec3 color ) { return color; }`,lf=`#ifdef USE_TRANSMISS worldPosition = instanceMatrix * worldPosition; #endif worldPosition = modelMatrix * worldPosition; -#endif`;const pf=`varying vec2 vUv; +#endif`;const mf=`varying vec2 vUv; uniform mat3 uvTransform; void main() { vUv = ( uvTransform * vec3( uv, 1 ) ).xy; gl_Position = vec4( position.xy, 1.0, 1.0 ); -}`,mf=`uniform sampler2D t2D; +}`,gf=`uniform sampler2D t2D; uniform float backgroundIntensity; varying vec2 vUv; void main() { @@ -2536,14 +2536,14 @@ void main() { gl_FragColor = texColor; #include #include -}`,gf=`varying vec3 vWorldDirection; +}`,_f=`varying vec3 vWorldDirection; #include void main() { vWorldDirection = transformDirection( position, modelMatrix ); #include #include gl_Position.z = gl_Position.w; -}`,_f=`#ifdef ENVMAP_TYPE_CUBE +}`,vf=`#ifdef ENVMAP_TYPE_CUBE uniform samplerCube envMap; #elif defined( ENVMAP_TYPE_CUBE_UV ) uniform sampler2D envMap; @@ -2566,14 +2566,14 @@ void main() { gl_FragColor = texColor; #include #include -}`,vf=`varying vec3 vWorldDirection; +}`,xf=`varying vec3 vWorldDirection; #include void main() { vWorldDirection = transformDirection( position, modelMatrix ); #include #include gl_Position.z = gl_Position.w; -}`,xf=`uniform samplerCube tCube; +}`,Mf=`uniform samplerCube tCube; uniform float tFlip; uniform float opacity; varying vec3 vWorldDirection; @@ -2583,7 +2583,7 @@ void main() { gl_FragColor.a *= opacity; #include #include -}`,Mf=`#include +}`,Sf=`#include #include #include #include @@ -2610,7 +2610,7 @@ void main() { #include #include vHighPrecisionZW = gl_Position.zw; -}`,Sf=`#if DEPTH_PACKING == 3200 +}`,yf=`#if DEPTH_PACKING == 3200 uniform float opacity; #endif #include @@ -2644,7 +2644,7 @@ void main() { #elif DEPTH_PACKING == 3203 gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 ); #endif -}`,yf=`#define DISTANCE +}`,Ef=`#define DISTANCE varying vec3 vWorldPosition; #include #include @@ -2671,7 +2671,7 @@ void main() { #include #include vWorldPosition = worldPosition.xyz; -}`,Ef=`#define DISTANCE +}`,bf=`#define DISTANCE uniform vec3 referencePosition; uniform float nearDistance; uniform float farDistance; @@ -2695,13 +2695,13 @@ void main () { dist = ( dist - nearDistance ) / ( farDistance - nearDistance ); dist = saturate( dist ); gl_FragColor = packDepthToRGBA( dist ); -}`,bf=`varying vec3 vWorldDirection; +}`,Tf=`varying vec3 vWorldDirection; #include void main() { vWorldDirection = transformDirection( position, modelMatrix ); #include #include -}`,Tf=`uniform sampler2D tEquirect; +}`,wf=`uniform sampler2D tEquirect; varying vec3 vWorldDirection; #include void main() { @@ -2710,7 +2710,7 @@ void main() { gl_FragColor = texture2D( tEquirect, sampleUV ); #include #include -}`,wf=`uniform float scale; +}`,Af=`uniform float scale; attribute float lineDistance; varying float vLineDistance; #include @@ -2732,7 +2732,7 @@ void main() { #include #include #include -}`,Af=`uniform vec3 diffuse; +}`,Rf=`uniform vec3 diffuse; uniform float opacity; uniform float dashSize; uniform float totalSize; @@ -2760,7 +2760,7 @@ void main() { #include #include #include -}`,Rf=`#include +}`,Cf=`#include #include #include #include @@ -2792,7 +2792,7 @@ void main() { #include #include #include -}`,Cf=`uniform vec3 diffuse; +}`,Pf=`uniform vec3 diffuse; uniform float opacity; #ifndef FLAT_SHADED varying vec3 vNormal; @@ -2840,7 +2840,7 @@ void main() { #include #include #include -}`,Pf=`#define LAMBERT +}`,Df=`#define LAMBERT varying vec3 vViewPosition; #include #include @@ -2879,7 +2879,7 @@ void main() { #include #include #include -}`,Df=`#define LAMBERT +}`,Lf=`#define LAMBERT uniform vec3 diffuse; uniform vec3 emissive; uniform float opacity; @@ -2936,7 +2936,7 @@ void main() { #include #include #include -}`,Lf=`#define MATCAP +}`,Uf=`#define MATCAP varying vec3 vViewPosition; #include #include @@ -2970,7 +2970,7 @@ void main() { #include #include vViewPosition = - mvPosition.xyz; -}`,Uf=`#define MATCAP +}`,If=`#define MATCAP uniform vec3 diffuse; uniform float opacity; uniform sampler2D matcap; @@ -3016,7 +3016,7 @@ void main() { #include #include #include -}`,If=`#define NORMAL +}`,Nf=`#define NORMAL #if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) varying vec3 vViewPosition; #endif @@ -3049,7 +3049,7 @@ void main() { #if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) vViewPosition = - mvPosition.xyz; #endif -}`,Nf=`#define NORMAL +}`,Ff=`#define NORMAL uniform float opacity; #if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) varying vec3 vViewPosition; @@ -3071,7 +3071,7 @@ void main() { #ifdef OPAQUE gl_FragColor.a = 1.0; #endif -}`,Ff=`#define PHONG +}`,Of=`#define PHONG varying vec3 vViewPosition; #include #include @@ -3110,7 +3110,7 @@ void main() { #include #include #include -}`,Of=`#define PHONG +}`,Bf=`#define PHONG uniform vec3 diffuse; uniform vec3 emissive; uniform vec3 specular; @@ -3169,7 +3169,7 @@ void main() { #include #include #include -}`,Bf=`#define STANDARD +}`,zf=`#define STANDARD varying vec3 vViewPosition; #ifdef USE_TRANSMISSION varying vec3 vWorldPosition; @@ -3212,7 +3212,7 @@ void main() { #ifdef USE_TRANSMISSION vWorldPosition = worldPosition.xyz; #endif -}`,zf=`#define STANDARD +}`,Hf=`#define STANDARD #ifdef PHYSICAL #define IOR #define USE_SPECULAR @@ -3337,7 +3337,7 @@ void main() { #include #include #include -}`,Hf=`#define TOON +}`,kf=`#define TOON varying vec3 vViewPosition; #include #include @@ -3374,7 +3374,7 @@ void main() { #include #include #include -}`,kf=`#define TOON +}`,Vf=`#define TOON uniform vec3 diffuse; uniform vec3 emissive; uniform float opacity; @@ -3427,7 +3427,7 @@ void main() { #include #include #include -}`,Vf=`uniform float size; +}`,Gf=`uniform float size; uniform float scale; #include #include @@ -3458,7 +3458,7 @@ void main() { #include #include #include -}`,Gf=`uniform vec3 diffuse; +}`,Wf=`uniform vec3 diffuse; uniform float opacity; #include #include @@ -3483,7 +3483,7 @@ void main() { #include #include #include -}`,Wf=`#include +}`,Xf=`#include #include #include #include @@ -3506,7 +3506,7 @@ void main() { #include #include #include -}`,Xf=`uniform vec3 color; +}`,Yf=`uniform vec3 color; uniform float opacity; #include #include @@ -3522,7 +3522,7 @@ void main() { #include #include #include -}`,Yf=`uniform float rotation; +}`,qf=`uniform float rotation; uniform vec2 center; #include #include @@ -3546,7 +3546,7 @@ void main() { #include #include #include -}`,qf=`uniform vec3 diffuse; +}`,jf=`uniform vec3 diffuse; uniform float opacity; #include #include @@ -3571,7 +3571,7 @@ void main() { #include #include #include -}`,Vt={alphahash_fragment:pu,alphahash_pars_fragment:mu,alphamap_fragment:gu,alphamap_pars_fragment:_u,alphatest_fragment:vu,alphatest_pars_fragment:xu,aomap_fragment:Mu,aomap_pars_fragment:Su,batching_pars_vertex:yu,batching_vertex:Eu,begin_vertex:bu,beginnormal_vertex:Tu,bsdfs:wu,iridescence_fragment:Au,bumpmap_pars_fragment:Ru,clipping_planes_fragment:Cu,clipping_planes_pars_fragment:Pu,clipping_planes_pars_vertex:Du,clipping_planes_vertex:Lu,color_fragment:Uu,color_pars_fragment:Iu,color_pars_vertex:Nu,color_vertex:Fu,common:Ou,cube_uv_reflection_fragment:Bu,defaultnormal_vertex:zu,displacementmap_pars_vertex:Hu,displacementmap_vertex:ku,emissivemap_fragment:Vu,emissivemap_pars_fragment:Gu,colorspace_fragment:Wu,colorspace_pars_fragment:Xu,envmap_fragment:Yu,envmap_common_pars_fragment:qu,envmap_pars_fragment:ju,envmap_pars_vertex:Zu,envmap_physical_pars_fragment:ad,envmap_vertex:Ku,fog_vertex:$u,fog_pars_vertex:Ju,fog_fragment:Qu,fog_pars_fragment:td,gradientmap_pars_fragment:ed,lightmap_pars_fragment:nd,lights_lambert_fragment:id,lights_lambert_pars_fragment:sd,lights_pars_begin:rd,lights_toon_fragment:od,lights_toon_pars_fragment:ld,lights_phong_fragment:cd,lights_phong_pars_fragment:hd,lights_physical_fragment:ud,lights_physical_pars_fragment:dd,lights_fragment_begin:fd,lights_fragment_maps:pd,lights_fragment_end:md,logdepthbuf_fragment:gd,logdepthbuf_pars_fragment:_d,logdepthbuf_pars_vertex:vd,logdepthbuf_vertex:xd,map_fragment:Md,map_pars_fragment:Sd,map_particle_fragment:yd,map_particle_pars_fragment:Ed,metalnessmap_fragment:bd,metalnessmap_pars_fragment:Td,morphinstance_vertex:wd,morphcolor_vertex:Ad,morphnormal_vertex:Rd,morphtarget_pars_vertex:Cd,morphtarget_vertex:Pd,normal_fragment_begin:Dd,normal_fragment_maps:Ld,normal_pars_fragment:Ud,normal_pars_vertex:Id,normal_vertex:Nd,normalmap_pars_fragment:Fd,clearcoat_normal_fragment_begin:Od,clearcoat_normal_fragment_maps:Bd,clearcoat_pars_fragment:zd,iridescence_pars_fragment:Hd,opaque_fragment:kd,packing:Vd,premultiplied_alpha_fragment:Gd,project_vertex:Wd,dithering_fragment:Xd,dithering_pars_fragment:Yd,roughnessmap_fragment:qd,roughnessmap_pars_fragment:jd,shadowmap_pars_fragment:Zd,shadowmap_pars_vertex:Kd,shadowmap_vertex:$d,shadowmask_pars_fragment:Jd,skinbase_vertex:Qd,skinning_pars_vertex:tf,skinning_vertex:ef,skinnormal_vertex:nf,specularmap_fragment:sf,specularmap_pars_fragment:rf,tonemapping_fragment:af,tonemapping_pars_fragment:of,transmission_fragment:lf,transmission_pars_fragment:cf,uv_pars_fragment:hf,uv_pars_vertex:uf,uv_vertex:df,worldpos_vertex:ff,background_vert:pf,background_frag:mf,backgroundCube_vert:gf,backgroundCube_frag:_f,cube_vert:vf,cube_frag:xf,depth_vert:Mf,depth_frag:Sf,distanceRGBA_vert:yf,distanceRGBA_frag:Ef,equirect_vert:bf,equirect_frag:Tf,linedashed_vert:wf,linedashed_frag:Af,meshbasic_vert:Rf,meshbasic_frag:Cf,meshlambert_vert:Pf,meshlambert_frag:Df,meshmatcap_vert:Lf,meshmatcap_frag:Uf,meshnormal_vert:If,meshnormal_frag:Nf,meshphong_vert:Ff,meshphong_frag:Of,meshphysical_vert:Bf,meshphysical_frag:zf,meshtoon_vert:Hf,meshtoon_frag:kf,points_vert:Vf,points_frag:Gf,shadow_vert:Wf,shadow_frag:Xf,sprite_vert:Yf,sprite_frag:qf},st={common:{diffuse:{value:new pt(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Ht}},envmap:{envMap:{value:null},envMapRotation:{value:new Ht},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Ht}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Ht}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Ht},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Ht},normalScale:{value:new vt(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Ht},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Ht}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Ht}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Ht}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new pt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new pt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0},uvTransform:{value:new Ht}},sprite:{diffuse:{value:new pt(16777215)},opacity:{value:1},center:{value:new vt(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}}},cn={basic:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.fog]),vertexShader:Vt.meshbasic_vert,fragmentShader:Vt.meshbasic_frag},lambert:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.fog,st.lights,{emissive:{value:new pt(0)}}]),vertexShader:Vt.meshlambert_vert,fragmentShader:Vt.meshlambert_frag},phong:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.fog,st.lights,{emissive:{value:new pt(0)},specular:{value:new pt(1118481)},shininess:{value:30}}]),vertexShader:Vt.meshphong_vert,fragmentShader:Vt.meshphong_frag},standard:{uniforms:Ue([st.common,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.roughnessmap,st.metalnessmap,st.fog,st.lights,{emissive:{value:new pt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Vt.meshphysical_vert,fragmentShader:Vt.meshphysical_frag},toon:{uniforms:Ue([st.common,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.gradientmap,st.fog,st.lights,{emissive:{value:new pt(0)}}]),vertexShader:Vt.meshtoon_vert,fragmentShader:Vt.meshtoon_frag},matcap:{uniforms:Ue([st.common,st.bumpmap,st.normalmap,st.displacementmap,st.fog,{matcap:{value:null}}]),vertexShader:Vt.meshmatcap_vert,fragmentShader:Vt.meshmatcap_frag},points:{uniforms:Ue([st.points,st.fog]),vertexShader:Vt.points_vert,fragmentShader:Vt.points_frag},dashed:{uniforms:Ue([st.common,st.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Vt.linedashed_vert,fragmentShader:Vt.linedashed_frag},depth:{uniforms:Ue([st.common,st.displacementmap]),vertexShader:Vt.depth_vert,fragmentShader:Vt.depth_frag},normal:{uniforms:Ue([st.common,st.bumpmap,st.normalmap,st.displacementmap,{opacity:{value:1}}]),vertexShader:Vt.meshnormal_vert,fragmentShader:Vt.meshnormal_frag},sprite:{uniforms:Ue([st.sprite,st.fog]),vertexShader:Vt.sprite_vert,fragmentShader:Vt.sprite_frag},background:{uniforms:{uvTransform:{value:new Ht},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Vt.background_vert,fragmentShader:Vt.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new Ht}},vertexShader:Vt.backgroundCube_vert,fragmentShader:Vt.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Vt.cube_vert,fragmentShader:Vt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Vt.equirect_vert,fragmentShader:Vt.equirect_frag},distanceRGBA:{uniforms:Ue([st.common,st.displacementmap,{referencePosition:{value:new P},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Vt.distanceRGBA_vert,fragmentShader:Vt.distanceRGBA_frag},shadow:{uniforms:Ue([st.lights,st.fog,{color:{value:new pt(0)},opacity:{value:1}}]),vertexShader:Vt.shadow_vert,fragmentShader:Vt.shadow_frag}};cn.physical={uniforms:Ue([cn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new Ht},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new Ht},clearcoatNormalScale:{value:new vt(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new Ht},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new Ht},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new Ht},sheen:{value:0},sheenColor:{value:new pt(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new Ht},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new Ht},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new Ht},transmissionSamplerSize:{value:new vt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new Ht},attenuationDistance:{value:0},attenuationColor:{value:new pt(0)},specularColor:{value:new pt(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new Ht},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new Ht},anisotropyVector:{value:new vt},anisotropyMap:{value:null},anisotropyMapTransform:{value:new Ht}}]),vertexShader:Vt.meshphysical_vert,fragmentShader:Vt.meshphysical_frag};const ks={r:0,b:0,g:0},qn=new pn,jf=new ee;function Zf(i,t,e,n,s,r,a){const o=new pt(0);let l=r===!0?0:1,c,h,d=null,f=0,p=null;function g(b){let y=b.isScene===!0?b.background:null;return y&&y.isTexture&&(y=(b.backgroundBlurriness>0?e:t).get(y)),y}function v(b){let y=!1;const L=g(b);L===null?u(o,l):L&&L.isColor&&(u(L,1),y=!0);const R=i.xr.getEnvironmentBlendMode();R==="additive"?n.buffers.color.setClear(0,0,0,1,a):R==="alpha-blend"&&n.buffers.color.setClear(0,0,0,0,a),(i.autoClear||y)&&(n.buffers.depth.setTest(!0),n.buffers.depth.setMask(!0),n.buffers.color.setMask(!0),i.clear(i.autoClearColor,i.autoClearDepth,i.autoClearStencil))}function m(b,y){const L=g(y);L&&(L.isCubeTexture||L.mapping===hr)?(h===void 0&&(h=new Se(new hs(1,1,1),new Ne({name:"BackgroundCubeMaterial",uniforms:Vi(cn.backgroundCube.uniforms),vertexShader:cn.backgroundCube.vertexShader,fragmentShader:cn.backgroundCube.fragmentShader,side:ke,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(R,A,U){this.matrixWorld.copyPosition(U.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),s.update(h)),qn.copy(y.backgroundRotation),qn.x*=-1,qn.y*=-1,qn.z*=-1,L.isCubeTexture&&L.isRenderTargetTexture===!1&&(qn.y*=-1,qn.z*=-1),h.material.uniforms.envMap.value=L,h.material.uniforms.flipEnvMap.value=L.isCubeTexture&&L.isRenderTargetTexture===!1?-1:1,h.material.uniforms.backgroundBlurriness.value=y.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,h.material.uniforms.backgroundRotation.value.setFromMatrix4(jf.makeRotationFromEuler(qn)),h.material.toneMapped=$t.getTransfer(L.colorSpace)!==re,(d!==L||f!==L.version||p!==i.toneMapping)&&(h.material.needsUpdate=!0,d=L,f=L.version,p=i.toneMapping),h.layers.enableAll(),b.unshift(h,h.geometry,h.material,0,0,null)):L&&L.isTexture&&(c===void 0&&(c=new Se(new us(2,2),new Ne({name:"BackgroundMaterial",uniforms:Vi(cn.background.uniforms),vertexShader:cn.background.vertexShader,fragmentShader:cn.background.fragmentShader,side:zn,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),s.update(c)),c.material.uniforms.t2D.value=L,c.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,c.material.toneMapped=$t.getTransfer(L.colorSpace)!==re,L.matrixAutoUpdate===!0&&L.updateMatrix(),c.material.uniforms.uvTransform.value.copy(L.matrix),(d!==L||f!==L.version||p!==i.toneMapping)&&(c.material.needsUpdate=!0,d=L,f=L.version,p=i.toneMapping),c.layers.enableAll(),b.unshift(c,c.geometry,c.material,0,0,null))}function u(b,y){b.getRGB(ks,ic(i)),n.buffers.color.setClear(ks.r,ks.g,ks.b,y,a)}function T(){h!==void 0&&(h.geometry.dispose(),h.material.dispose()),c!==void 0&&(c.geometry.dispose(),c.material.dispose())}return{getClearColor:function(){return o},setClearColor:function(b,y=1){o.set(b),l=y,u(o,l)},getClearAlpha:function(){return l},setClearAlpha:function(b){l=b,u(o,l)},render:v,addToRenderList:m,dispose:T}}function Kf(i,t){const e=i.getParameter(i.MAX_VERTEX_ATTRIBS),n={},s=f(null);let r=s,a=!1;function o(M,D,W,z,V){let $=!1;const G=d(z,W,D);r!==G&&(r=G,c(r.object)),$=p(M,z,W,V),$&&g(M,z,W,V),V!==null&&t.update(V,i.ELEMENT_ARRAY_BUFFER),($||a)&&(a=!1,y(M,D,W,z),V!==null&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,t.get(V).buffer))}function l(){return i.createVertexArray()}function c(M){return i.bindVertexArray(M)}function h(M){return i.deleteVertexArray(M)}function d(M,D,W){const z=W.wireframe===!0;let V=n[M.id];V===void 0&&(V={},n[M.id]=V);let $=V[D.id];$===void 0&&($={},V[D.id]=$);let G=$[z];return G===void 0&&(G=f(l()),$[z]=G),G}function f(M){const D=[],W=[],z=[];for(let V=0;V=0){const ut=V[k];let yt=$[k];if(yt===void 0&&(k==="instanceMatrix"&&M.instanceMatrix&&(yt=M.instanceMatrix),k==="instanceColor"&&M.instanceColor&&(yt=M.instanceColor)),ut===void 0||ut.attribute!==yt||yt&&ut.data!==yt.data)return!0;G++}return r.attributesNum!==G||r.index!==z}function g(M,D,W,z){const V={},$=D.attributes;let G=0;const J=W.getAttributes();for(const k in J)if(J[k].location>=0){let ut=$[k];ut===void 0&&(k==="instanceMatrix"&&M.instanceMatrix&&(ut=M.instanceMatrix),k==="instanceColor"&&M.instanceColor&&(ut=M.instanceColor));const yt={};yt.attribute=ut,ut&&ut.data&&(yt.data=ut.data),V[k]=yt,G++}r.attributes=V,r.attributesNum=G,r.index=z}function v(){const M=r.newAttributes;for(let D=0,W=M.length;D=0){let it=V[J];if(it===void 0&&(J==="instanceMatrix"&&M.instanceMatrix&&(it=M.instanceMatrix),J==="instanceColor"&&M.instanceColor&&(it=M.instanceColor)),it!==void 0){const ut=it.normalized,yt=it.itemSize,Lt=t.get(it);if(Lt===void 0)continue;const qt=Lt.buffer,Y=Lt.type,nt=Lt.bytesPerElement,xt=Y===i.INT||Y===i.UNSIGNED_INT||it.gpuType===Ya;if(it.isInterleavedBufferAttribute){const at=it.data,wt=at.stride,Ut=it.offset;if(at.isInstancedInterleavedBuffer){for(let Gt=0;Gt0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.HIGH_FLOAT).precision>0)return"highp";A="mediump"}return A==="mediump"&&i.getShaderPrecisionFormat(i.VERTEX_SHADER,i.MEDIUM_FLOAT).precision>0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let c=e.precision!==void 0?e.precision:"highp";const h=l(c);h!==c&&(console.warn("THREE.WebGLRenderer:",c,"not supported, using",h,"instead."),c=h);const d=e.logarithmicDepthBuffer===!0,f=e.reverseDepthBuffer===!0&&t.has("EXT_clip_control"),p=i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS),g=i.getParameter(i.MAX_VERTEX_TEXTURE_IMAGE_UNITS),v=i.getParameter(i.MAX_TEXTURE_SIZE),m=i.getParameter(i.MAX_CUBE_MAP_TEXTURE_SIZE),u=i.getParameter(i.MAX_VERTEX_ATTRIBS),T=i.getParameter(i.MAX_VERTEX_UNIFORM_VECTORS),b=i.getParameter(i.MAX_VARYING_VECTORS),y=i.getParameter(i.MAX_FRAGMENT_UNIFORM_VECTORS),L=g>0,R=i.getParameter(i.MAX_SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:r,getMaxPrecision:l,textureFormatReadable:a,textureTypeReadable:o,precision:c,logarithmicDepthBuffer:d,reverseDepthBuffer:f,maxTextures:p,maxVertexTextures:g,maxTextureSize:v,maxCubemapSize:m,maxAttributes:u,maxVertexUniforms:T,maxVaryings:b,maxFragmentUniforms:y,vertexTextures:L,maxSamples:R}}function Qf(i){const t=this;let e=null,n=0,s=!1,r=!1;const a=new Nn,o=new Ht,l={value:null,needsUpdate:!1};this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(d,f){const p=d.length!==0||f||n!==0||s;return s=f,n=d.length,p},this.beginShadows=function(){r=!0,h(null)},this.endShadows=function(){r=!1},this.setGlobalState=function(d,f){e=h(d,f,0)},this.setState=function(d,f,p){const g=d.clippingPlanes,v=d.clipIntersection,m=d.clipShadows,u=i.get(d);if(!s||g===null||g.length===0||r&&!m)r?h(null):c();else{const T=r?0:n,b=T*4;let y=u.clippingState||null;l.value=y,y=h(g,f,b,p);for(let L=0;L!==b;++L)y[L]=e[L];u.clippingState=y,this.numIntersection=v?this.numPlanes:0,this.numPlanes+=T}};function c(){l.value!==e&&(l.value=e,l.needsUpdate=n>0),t.numPlanes=n,t.numIntersection=0}function h(d,f,p,g){const v=d!==null?d.length:0;let m=null;if(v!==0){if(m=l.value,g!==!0||m===null){const u=p+v*4,T=f.matrixWorldInverse;o.getNormalMatrix(T),(m===null||m.length0){const c=new qh(l.height);return c.fromEquirectangularTexture(i,a),t.set(a,c),a.addEventListener("dispose",s),e(c.texture,a.mapping)}else return null}}return a}function s(a){const o=a.target;o.removeEventListener("dispose",s);const l=t.get(o);l!==void 0&&(t.delete(o),l.dispose())}function r(){t=new WeakMap}return{get:n,dispose:r}}const Pi=4,Jo=[.125,.215,.35,.446,.526,.582],$n=20,Gr=new cc,Qo=new pt;let Wr=null,Xr=0,Yr=0,qr=!1;const Zn=(1+Math.sqrt(5))/2,Ti=1/Zn,tl=[new P(-Zn,Ti,0),new P(Zn,Ti,0),new P(-Ti,0,Zn),new P(Ti,0,Zn),new P(0,Zn,-Ti),new P(0,Zn,Ti),new P(-1,1,-1),new P(1,1,-1),new P(-1,1,1),new P(1,1,1)];class el{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,s=100){Wr=this._renderer.getRenderTarget(),Xr=this._renderer.getActiveCubeFace(),Yr=this._renderer.getActiveMipmapLevel(),qr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,s,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=sl(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=il(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let t=0;t2?b:0,b,b),h.setRenderTarget(s),v&&h.render(g,o),h.render(t,o)}g.geometry.dispose(),g.material.dispose(),h.toneMapping=f,h.autoClear=d,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,s=t.mapping===Oi||t.mapping===Bi;s?(this._cubemapMaterial===null&&(this._cubemapMaterial=sl()),this._cubemapMaterial.uniforms.flipEnvMap.value=t.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=il());const r=s?this._cubemapMaterial:this._equirectMaterial,a=new Se(this._lodPlanes[0],r),o=r.uniforms;o.envMap.value=t;const l=this._cubeSize;Vs(e,0,0,3*l,2*l),n.setRenderTarget(e),n.render(a,Gr)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;const s=this._lodPlanes.length;for(let r=1;r$n&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${$n}`);const u=[];let T=0;for(let A=0;A<$n;++A){const U=A/v,S=Math.exp(-U*U/2);u.push(S),A===0?T+=S:Ab-Pi?s-b+Pi:0),R=4*(this._cubeSize-y);Vs(e,L,R,3*y,2*y),l.setRenderTarget(e),l.render(d,Gr)}}function ep(i){const t=[],e=[],n=[];let s=i;const r=i-Pi+1+Jo.length;for(let a=0;ai-Pi?l=Jo[a-i+Pi-1]:a===0&&(l=0),n.push(l);const c=1/(o-2),h=-c,d=1+c,f=[h,h,d,h,d,d,h,h,d,d,h,d],p=6,g=6,v=3,m=2,u=1,T=new Float32Array(v*g*p),b=new Float32Array(m*g*p),y=new Float32Array(u*g*p);for(let R=0;R2?0:-1,S=[A,U,0,A+2/3,U,0,A+2/3,U+1,0,A,U,0,A+2/3,U+1,0,A,U+1,0];T.set(S,v*g*R),b.set(f,m*g*R);const M=[R,R,R,R,R,R];y.set(M,u*g*R)}const L=new pe;L.setAttribute("position",new de(T,v)),L.setAttribute("uv",new de(b,m)),L.setAttribute("faceIndex",new de(y,u)),t.push(L),s>Pi&&s--}return{lodPlanes:t,sizeLods:e,sigmas:n}}function nl(i,t,e){const n=new on(i,t,e);return n.texture.mapping=hr,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Vs(i,t,e,n,s){i.viewport.set(t,e,n,s),i.scissor.set(t,e,n,s)}function np(i,t,e){const n=new Float32Array($n),s=new P(0,1,0);return new Ne({name:"SphericalGaussianBlur",defines:{n:$n,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/e,CUBEUV_MAX_MIP:`${i}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:s}},vertexShader:no(),fragmentShader:` +}`,Vt={alphahash_fragment:mu,alphahash_pars_fragment:gu,alphamap_fragment:_u,alphamap_pars_fragment:vu,alphatest_fragment:xu,alphatest_pars_fragment:Mu,aomap_fragment:Su,aomap_pars_fragment:yu,batching_pars_vertex:Eu,batching_vertex:bu,begin_vertex:Tu,beginnormal_vertex:wu,bsdfs:Au,iridescence_fragment:Ru,bumpmap_pars_fragment:Cu,clipping_planes_fragment:Pu,clipping_planes_pars_fragment:Du,clipping_planes_pars_vertex:Lu,clipping_planes_vertex:Uu,color_fragment:Iu,color_pars_fragment:Nu,color_pars_vertex:Fu,color_vertex:Ou,common:Bu,cube_uv_reflection_fragment:zu,defaultnormal_vertex:Hu,displacementmap_pars_vertex:ku,displacementmap_vertex:Vu,emissivemap_fragment:Gu,emissivemap_pars_fragment:Wu,colorspace_fragment:Xu,colorspace_pars_fragment:Yu,envmap_fragment:qu,envmap_common_pars_fragment:ju,envmap_pars_fragment:Zu,envmap_pars_vertex:Ku,envmap_physical_pars_fragment:od,envmap_vertex:$u,fog_vertex:Ju,fog_pars_vertex:Qu,fog_fragment:td,fog_pars_fragment:ed,gradientmap_pars_fragment:nd,lightmap_pars_fragment:id,lights_lambert_fragment:sd,lights_lambert_pars_fragment:rd,lights_pars_begin:ad,lights_toon_fragment:ld,lights_toon_pars_fragment:cd,lights_phong_fragment:hd,lights_phong_pars_fragment:ud,lights_physical_fragment:dd,lights_physical_pars_fragment:fd,lights_fragment_begin:pd,lights_fragment_maps:md,lights_fragment_end:gd,logdepthbuf_fragment:_d,logdepthbuf_pars_fragment:vd,logdepthbuf_pars_vertex:xd,logdepthbuf_vertex:Md,map_fragment:Sd,map_pars_fragment:yd,map_particle_fragment:Ed,map_particle_pars_fragment:bd,metalnessmap_fragment:Td,metalnessmap_pars_fragment:wd,morphinstance_vertex:Ad,morphcolor_vertex:Rd,morphnormal_vertex:Cd,morphtarget_pars_vertex:Pd,morphtarget_vertex:Dd,normal_fragment_begin:Ld,normal_fragment_maps:Ud,normal_pars_fragment:Id,normal_pars_vertex:Nd,normal_vertex:Fd,normalmap_pars_fragment:Od,clearcoat_normal_fragment_begin:Bd,clearcoat_normal_fragment_maps:zd,clearcoat_pars_fragment:Hd,iridescence_pars_fragment:kd,opaque_fragment:Vd,packing:Gd,premultiplied_alpha_fragment:Wd,project_vertex:Xd,dithering_fragment:Yd,dithering_pars_fragment:qd,roughnessmap_fragment:jd,roughnessmap_pars_fragment:Zd,shadowmap_pars_fragment:Kd,shadowmap_pars_vertex:$d,shadowmap_vertex:Jd,shadowmask_pars_fragment:Qd,skinbase_vertex:tf,skinning_pars_vertex:ef,skinning_vertex:nf,skinnormal_vertex:sf,specularmap_fragment:rf,specularmap_pars_fragment:af,tonemapping_fragment:of,tonemapping_pars_fragment:lf,transmission_fragment:cf,transmission_pars_fragment:hf,uv_pars_fragment:uf,uv_pars_vertex:df,uv_vertex:ff,worldpos_vertex:pf,background_vert:mf,background_frag:gf,backgroundCube_vert:_f,backgroundCube_frag:vf,cube_vert:xf,cube_frag:Mf,depth_vert:Sf,depth_frag:yf,distanceRGBA_vert:Ef,distanceRGBA_frag:bf,equirect_vert:Tf,equirect_frag:wf,linedashed_vert:Af,linedashed_frag:Rf,meshbasic_vert:Cf,meshbasic_frag:Pf,meshlambert_vert:Df,meshlambert_frag:Lf,meshmatcap_vert:Uf,meshmatcap_frag:If,meshnormal_vert:Nf,meshnormal_frag:Ff,meshphong_vert:Of,meshphong_frag:Bf,meshphysical_vert:zf,meshphysical_frag:Hf,meshtoon_vert:kf,meshtoon_frag:Vf,points_vert:Gf,points_frag:Wf,shadow_vert:Xf,shadow_frag:Yf,sprite_vert:qf,sprite_frag:jf},st={common:{diffuse:{value:new pt(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Ht}},envmap:{envMap:{value:null},envMapRotation:{value:new Ht},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Ht}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Ht}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Ht},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Ht},normalScale:{value:new vt(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Ht},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Ht}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Ht}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Ht}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new pt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new pt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0},uvTransform:{value:new Ht}},sprite:{diffuse:{value:new pt(16777215)},opacity:{value:1},center:{value:new vt(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}}},cn={basic:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.fog]),vertexShader:Vt.meshbasic_vert,fragmentShader:Vt.meshbasic_frag},lambert:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.fog,st.lights,{emissive:{value:new pt(0)}}]),vertexShader:Vt.meshlambert_vert,fragmentShader:Vt.meshlambert_frag},phong:{uniforms:Ue([st.common,st.specularmap,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.fog,st.lights,{emissive:{value:new pt(0)},specular:{value:new pt(1118481)},shininess:{value:30}}]),vertexShader:Vt.meshphong_vert,fragmentShader:Vt.meshphong_frag},standard:{uniforms:Ue([st.common,st.envmap,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.roughnessmap,st.metalnessmap,st.fog,st.lights,{emissive:{value:new pt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Vt.meshphysical_vert,fragmentShader:Vt.meshphysical_frag},toon:{uniforms:Ue([st.common,st.aomap,st.lightmap,st.emissivemap,st.bumpmap,st.normalmap,st.displacementmap,st.gradientmap,st.fog,st.lights,{emissive:{value:new pt(0)}}]),vertexShader:Vt.meshtoon_vert,fragmentShader:Vt.meshtoon_frag},matcap:{uniforms:Ue([st.common,st.bumpmap,st.normalmap,st.displacementmap,st.fog,{matcap:{value:null}}]),vertexShader:Vt.meshmatcap_vert,fragmentShader:Vt.meshmatcap_frag},points:{uniforms:Ue([st.points,st.fog]),vertexShader:Vt.points_vert,fragmentShader:Vt.points_frag},dashed:{uniforms:Ue([st.common,st.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Vt.linedashed_vert,fragmentShader:Vt.linedashed_frag},depth:{uniforms:Ue([st.common,st.displacementmap]),vertexShader:Vt.depth_vert,fragmentShader:Vt.depth_frag},normal:{uniforms:Ue([st.common,st.bumpmap,st.normalmap,st.displacementmap,{opacity:{value:1}}]),vertexShader:Vt.meshnormal_vert,fragmentShader:Vt.meshnormal_frag},sprite:{uniforms:Ue([st.sprite,st.fog]),vertexShader:Vt.sprite_vert,fragmentShader:Vt.sprite_frag},background:{uniforms:{uvTransform:{value:new Ht},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Vt.background_vert,fragmentShader:Vt.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new Ht}},vertexShader:Vt.backgroundCube_vert,fragmentShader:Vt.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Vt.cube_vert,fragmentShader:Vt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Vt.equirect_vert,fragmentShader:Vt.equirect_frag},distanceRGBA:{uniforms:Ue([st.common,st.displacementmap,{referencePosition:{value:new P},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Vt.distanceRGBA_vert,fragmentShader:Vt.distanceRGBA_frag},shadow:{uniforms:Ue([st.lights,st.fog,{color:{value:new pt(0)},opacity:{value:1}}]),vertexShader:Vt.shadow_vert,fragmentShader:Vt.shadow_frag}};cn.physical={uniforms:Ue([cn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new Ht},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new Ht},clearcoatNormalScale:{value:new vt(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new Ht},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new Ht},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new Ht},sheen:{value:0},sheenColor:{value:new pt(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new Ht},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new Ht},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new Ht},transmissionSamplerSize:{value:new vt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new Ht},attenuationDistance:{value:0},attenuationColor:{value:new pt(0)},specularColor:{value:new pt(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new Ht},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new Ht},anisotropyVector:{value:new vt},anisotropyMap:{value:null},anisotropyMapTransform:{value:new Ht}}]),vertexShader:Vt.meshphysical_vert,fragmentShader:Vt.meshphysical_frag};const Gs={r:0,b:0,g:0},qn=new pn,Zf=new ee;function Kf(i,t,e,n,s,r,a){const o=new pt(0);let l=r===!0?0:1,c,h,d=null,p=0,f=null;function g(b){let y=b.isScene===!0?b.background:null;return y&&y.isTexture&&(y=(b.backgroundBlurriness>0?e:t).get(y)),y}function v(b){let y=!1;const L=g(b);L===null?u(o,l):L&&L.isColor&&(u(L,1),y=!0);const R=i.xr.getEnvironmentBlendMode();R==="additive"?n.buffers.color.setClear(0,0,0,1,a):R==="alpha-blend"&&n.buffers.color.setClear(0,0,0,0,a),(i.autoClear||y)&&(n.buffers.depth.setTest(!0),n.buffers.depth.setMask(!0),n.buffers.color.setMask(!0),i.clear(i.autoClearColor,i.autoClearDepth,i.autoClearStencil))}function m(b,y){const L=g(y);L&&(L.isCubeTexture||L.mapping===fr)?(h===void 0&&(h=new Se(new us(1,1,1),new Fe({name:"BackgroundCubeMaterial",uniforms:Gi(cn.backgroundCube.uniforms),vertexShader:cn.backgroundCube.vertexShader,fragmentShader:cn.backgroundCube.fragmentShader,side:ke,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(R,A,U){this.matrixWorld.copyPosition(U.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),s.update(h)),qn.copy(y.backgroundRotation),qn.x*=-1,qn.y*=-1,qn.z*=-1,L.isCubeTexture&&L.isRenderTargetTexture===!1&&(qn.y*=-1,qn.z*=-1),h.material.uniforms.envMap.value=L,h.material.uniforms.flipEnvMap.value=L.isCubeTexture&&L.isRenderTargetTexture===!1?-1:1,h.material.uniforms.backgroundBlurriness.value=y.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,h.material.uniforms.backgroundRotation.value.setFromMatrix4(Zf.makeRotationFromEuler(qn)),h.material.toneMapped=$t.getTransfer(L.colorSpace)!==re,(d!==L||p!==L.version||f!==i.toneMapping)&&(h.material.needsUpdate=!0,d=L,p=L.version,f=i.toneMapping),h.layers.enableAll(),b.unshift(h,h.geometry,h.material,0,0,null)):L&&L.isTexture&&(c===void 0&&(c=new Se(new ds(2,2),new Fe({name:"BackgroundMaterial",uniforms:Gi(cn.background.uniforms),vertexShader:cn.background.vertexShader,fragmentShader:cn.background.fragmentShader,side:zn,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),s.update(c)),c.material.uniforms.t2D.value=L,c.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,c.material.toneMapped=$t.getTransfer(L.colorSpace)!==re,L.matrixAutoUpdate===!0&&L.updateMatrix(),c.material.uniforms.uvTransform.value.copy(L.matrix),(d!==L||p!==L.version||f!==i.toneMapping)&&(c.material.needsUpdate=!0,d=L,p=L.version,f=i.toneMapping),c.layers.enableAll(),b.unshift(c,c.geometry,c.material,0,0,null))}function u(b,y){b.getRGB(Gs,sc(i)),n.buffers.color.setClear(Gs.r,Gs.g,Gs.b,y,a)}function T(){h!==void 0&&(h.geometry.dispose(),h.material.dispose()),c!==void 0&&(c.geometry.dispose(),c.material.dispose())}return{getClearColor:function(){return o},setClearColor:function(b,y=1){o.set(b),l=y,u(o,l)},getClearAlpha:function(){return l},setClearAlpha:function(b){l=b,u(o,l)},render:v,addToRenderList:m,dispose:T}}function $f(i,t){const e=i.getParameter(i.MAX_VERTEX_ATTRIBS),n={},s=p(null);let r=s,a=!1;function o(M,D,W,z,V){let $=!1;const G=d(z,W,D);r!==G&&(r=G,c(r.object)),$=f(M,z,W,V),$&&g(M,z,W,V),V!==null&&t.update(V,i.ELEMENT_ARRAY_BUFFER),($||a)&&(a=!1,y(M,D,W,z),V!==null&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,t.get(V).buffer))}function l(){return i.createVertexArray()}function c(M){return i.bindVertexArray(M)}function h(M){return i.deleteVertexArray(M)}function d(M,D,W){const z=W.wireframe===!0;let V=n[M.id];V===void 0&&(V={},n[M.id]=V);let $=V[D.id];$===void 0&&($={},V[D.id]=$);let G=$[z];return G===void 0&&(G=p(l()),$[z]=G),G}function p(M){const D=[],W=[],z=[];for(let V=0;V=0){const ut=V[k];let yt=$[k];if(yt===void 0&&(k==="instanceMatrix"&&M.instanceMatrix&&(yt=M.instanceMatrix),k==="instanceColor"&&M.instanceColor&&(yt=M.instanceColor)),ut===void 0||ut.attribute!==yt||yt&&ut.data!==yt.data)return!0;G++}return r.attributesNum!==G||r.index!==z}function g(M,D,W,z){const V={},$=D.attributes;let G=0;const J=W.getAttributes();for(const k in J)if(J[k].location>=0){let ut=$[k];ut===void 0&&(k==="instanceMatrix"&&M.instanceMatrix&&(ut=M.instanceMatrix),k==="instanceColor"&&M.instanceColor&&(ut=M.instanceColor));const yt={};yt.attribute=ut,ut&&ut.data&&(yt.data=ut.data),V[k]=yt,G++}r.attributes=V,r.attributesNum=G,r.index=z}function v(){const M=r.newAttributes;for(let D=0,W=M.length;D=0){let it=V[J];if(it===void 0&&(J==="instanceMatrix"&&M.instanceMatrix&&(it=M.instanceMatrix),J==="instanceColor"&&M.instanceColor&&(it=M.instanceColor)),it!==void 0){const ut=it.normalized,yt=it.itemSize,Lt=t.get(it);if(Lt===void 0)continue;const qt=Lt.buffer,Y=Lt.type,nt=Lt.bytesPerElement,xt=Y===i.INT||Y===i.UNSIGNED_INT||it.gpuType===qa;if(it.isInterleavedBufferAttribute){const at=it.data,wt=at.stride,Ut=it.offset;if(at.isInstancedInterleavedBuffer){for(let Gt=0;Gt0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.HIGH_FLOAT).precision>0)return"highp";A="mediump"}return A==="mediump"&&i.getShaderPrecisionFormat(i.VERTEX_SHADER,i.MEDIUM_FLOAT).precision>0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let c=e.precision!==void 0?e.precision:"highp";const h=l(c);h!==c&&(console.warn("THREE.WebGLRenderer:",c,"not supported, using",h,"instead."),c=h);const d=e.logarithmicDepthBuffer===!0,p=e.reverseDepthBuffer===!0&&t.has("EXT_clip_control"),f=i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS),g=i.getParameter(i.MAX_VERTEX_TEXTURE_IMAGE_UNITS),v=i.getParameter(i.MAX_TEXTURE_SIZE),m=i.getParameter(i.MAX_CUBE_MAP_TEXTURE_SIZE),u=i.getParameter(i.MAX_VERTEX_ATTRIBS),T=i.getParameter(i.MAX_VERTEX_UNIFORM_VECTORS),b=i.getParameter(i.MAX_VARYING_VECTORS),y=i.getParameter(i.MAX_FRAGMENT_UNIFORM_VECTORS),L=g>0,R=i.getParameter(i.MAX_SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:r,getMaxPrecision:l,textureFormatReadable:a,textureTypeReadable:o,precision:c,logarithmicDepthBuffer:d,reverseDepthBuffer:p,maxTextures:f,maxVertexTextures:g,maxTextureSize:v,maxCubemapSize:m,maxAttributes:u,maxVertexUniforms:T,maxVaryings:b,maxFragmentUniforms:y,vertexTextures:L,maxSamples:R}}function tp(i){const t=this;let e=null,n=0,s=!1,r=!1;const a=new Nn,o=new Ht,l={value:null,needsUpdate:!1};this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(d,p){const f=d.length!==0||p||n!==0||s;return s=p,n=d.length,f},this.beginShadows=function(){r=!0,h(null)},this.endShadows=function(){r=!1},this.setGlobalState=function(d,p){e=h(d,p,0)},this.setState=function(d,p,f){const g=d.clippingPlanes,v=d.clipIntersection,m=d.clipShadows,u=i.get(d);if(!s||g===null||g.length===0||r&&!m)r?h(null):c();else{const T=r?0:n,b=T*4;let y=u.clippingState||null;l.value=y,y=h(g,p,b,f);for(let L=0;L!==b;++L)y[L]=e[L];u.clippingState=y,this.numIntersection=v?this.numPlanes:0,this.numPlanes+=T}};function c(){l.value!==e&&(l.value=e,l.needsUpdate=n>0),t.numPlanes=n,t.numIntersection=0}function h(d,p,f,g){const v=d!==null?d.length:0;let m=null;if(v!==0){if(m=l.value,g!==!0||m===null){const u=f+v*4,T=p.matrixWorldInverse;o.getNormalMatrix(T),(m===null||m.length0){const c=new Zh(l.height);return c.fromEquirectangularTexture(i,a),t.set(a,c),a.addEventListener("dispose",s),e(c.texture,a.mapping)}else return null}}return a}function s(a){const o=a.target;o.removeEventListener("dispose",s);const l=t.get(o);l!==void 0&&(t.delete(o),l.dispose())}function r(){t=new WeakMap}return{get:n,dispose:r}}const Di=4,Qo=[.125,.215,.35,.446,.526,.582],$n=20,Xr=new uc,tl=new pt;let Yr=null,qr=0,jr=0,Zr=!1;const Zn=(1+Math.sqrt(5))/2,wi=1/Zn,el=[new P(-Zn,wi,0),new P(Zn,wi,0),new P(-wi,0,Zn),new P(wi,0,Zn),new P(0,Zn,-wi),new P(0,Zn,wi),new P(-1,1,-1),new P(1,1,-1),new P(-1,1,1),new P(1,1,1)];class nl{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,s=100){Yr=this._renderer.getRenderTarget(),qr=this._renderer.getActiveCubeFace(),jr=this._renderer.getActiveMipmapLevel(),Zr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,s,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=rl(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=sl(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let t=0;t2?b:0,b,b),h.setRenderTarget(s),v&&h.render(g,o),h.render(t,o)}g.geometry.dispose(),g.material.dispose(),h.toneMapping=p,h.autoClear=d,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,s=t.mapping===Bi||t.mapping===zi;s?(this._cubemapMaterial===null&&(this._cubemapMaterial=rl()),this._cubemapMaterial.uniforms.flipEnvMap.value=t.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=sl());const r=s?this._cubemapMaterial:this._equirectMaterial,a=new Se(this._lodPlanes[0],r),o=r.uniforms;o.envMap.value=t;const l=this._cubeSize;Ws(e,0,0,3*l,2*l),n.setRenderTarget(e),n.render(a,Xr)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;const s=this._lodPlanes.length;for(let r=1;r$n&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${$n}`);const u=[];let T=0;for(let A=0;A<$n;++A){const U=A/v,S=Math.exp(-U*U/2);u.push(S),A===0?T+=S:Ab-Di?s-b+Di:0),R=4*(this._cubeSize-y);Ws(e,L,R,3*y,2*y),l.setRenderTarget(e),l.render(d,Xr)}}function np(i){const t=[],e=[],n=[];let s=i;const r=i-Di+1+Qo.length;for(let a=0;ai-Di?l=Qo[a-i+Di-1]:a===0&&(l=0),n.push(l);const c=1/(o-2),h=-c,d=1+c,p=[h,h,d,h,d,d,h,h,d,d,h,d],f=6,g=6,v=3,m=2,u=1,T=new Float32Array(v*g*f),b=new Float32Array(m*g*f),y=new Float32Array(u*g*f);for(let R=0;R2?0:-1,S=[A,U,0,A+2/3,U,0,A+2/3,U+1,0,A,U,0,A+2/3,U+1,0,A,U+1,0];T.set(S,v*g*R),b.set(p,m*g*R);const M=[R,R,R,R,R,R];y.set(M,u*g*R)}const L=new pe;L.setAttribute("position",new he(T,v)),L.setAttribute("uv",new he(b,m)),L.setAttribute("faceIndex",new he(y,u)),t.push(L),s>Di&&s--}return{lodPlanes:t,sizeLods:e,sigmas:n}}function il(i,t,e){const n=new on(i,t,e);return n.texture.mapping=fr,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Ws(i,t,e,n,s){i.viewport.set(t,e,n,s),i.scissor.set(t,e,n,s)}function ip(i,t,e){const n=new Float32Array($n),s=new P(0,1,0);return new Fe({name:"SphericalGaussianBlur",defines:{n:$n,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/e,CUBEUV_MAX_MIP:`${i}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:s}},vertexShader:io(),fragmentShader:` precision mediump float; precision mediump int; @@ -3631,7 +3631,7 @@ void main() { } } - `,blending:bn,depthTest:!1,depthWrite:!1})}function il(){return new Ne({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:no(),fragmentShader:` + `,blending:bn,depthTest:!1,depthWrite:!1})}function sl(){return new Fe({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:io(),fragmentShader:` precision mediump float; precision mediump int; @@ -3650,7 +3650,7 @@ void main() { gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); } - `,blending:bn,depthTest:!1,depthWrite:!1})}function sl(){return new Ne({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:no(),fragmentShader:` + `,blending:bn,depthTest:!1,depthWrite:!1})}function rl(){return new Fe({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:io(),fragmentShader:` precision mediump float; precision mediump int; @@ -3666,7 +3666,7 @@ void main() { gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); } - `,blending:bn,depthTest:!1,depthWrite:!1})}function no(){return` + `,blending:bn,depthTest:!1,depthWrite:!1})}function io(){return` precision mediump float; precision mediump int; @@ -3721,17 +3721,17 @@ void main() { gl_Position = vec4( position, 1.0 ); } - `}function ip(i){let t=new WeakMap,e=null;function n(o){if(o&&o.isTexture){const l=o.mapping,c=l===la||l===ca,h=l===Oi||l===Bi;if(c||h){let d=t.get(o);const f=d!==void 0?d.texture.pmremVersion:0;if(o.isRenderTargetTexture&&o.pmremVersion!==f)return e===null&&(e=new el(i)),d=c?e.fromEquirectangular(o,d):e.fromCubemap(o,d),d.texture.pmremVersion=o.pmremVersion,t.set(o,d),d.texture;if(d!==void 0)return d.texture;{const p=o.image;return c&&p&&p.height>0||h&&p&&s(p)?(e===null&&(e=new el(i)),d=c?e.fromEquirectangular(o):e.fromCubemap(o),d.texture.pmremVersion=o.pmremVersion,t.set(o,d),o.addEventListener("dispose",r),d.texture):null}}}return o}function s(o){let l=0;const c=6;for(let h=0;ht.maxTextureSize&&(L=Math.ceil(y/t.maxTextureSize),y=t.maxTextureSize);const R=new Float32Array(y*L*4*d),A=new Ql(R,y,L,d);A.type=fn,A.needsUpdate=!0;const U=b*4;for(let M=0;M0)return i;const s=t*e;let r=al[s];if(r===void 0&&(r=new Float32Array(s),al[s]=r),t!==0){n.toArray(r,0);for(let a=1,o=0;a!==t;++a)o+=e,i[a].toArray(r,o)}return r}function ye(i,t){if(i.length!==t.length)return!1;for(let e=0,n=i.length;e0||h&&f&&s(f)?(e===null&&(e=new nl(i)),d=c?e.fromEquirectangular(o):e.fromCubemap(o),d.texture.pmremVersion=o.pmremVersion,t.set(o,d),o.addEventListener("dispose",r),d.texture):null}}}return o}function s(o){let l=0;const c=6;for(let h=0;ht.maxTextureSize&&(L=Math.ceil(y/t.maxTextureSize),y=t.maxTextureSize);const R=new Float32Array(y*L*4*d),A=new tc(R,y,L,d);A.type=fn,A.needsUpdate=!0;const U=b*4;for(let M=0;M0)return i;const s=t*e;let r=ol[s];if(r===void 0&&(r=new Float32Array(s),ol[s]=r),t!==0){n.toArray(r,0);for(let a=1,o=0;a!==t;++a)o+=e,i[a].toArray(r,o)}return r}function ye(i,t){if(i.length!==t.length)return!1;for(let e=0,n=i.length;e":" "} ${o}: ${e[a]}`)}return n.join(` -`)}const fl=new Ht;function im(i){$t._getMatrix(fl,$t.workingColorSpace,i);const t=`mat3( ${fl.elements.map(e=>e.toFixed(4))} )`;switch($t.getTransfer(i)){case tr:return[t,"LinearTransferOETF"];case re:return[t,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space: ",i),[t,"LinearTransferOETF"]}}function pl(i,t,e){const n=i.getShaderParameter(t,i.COMPILE_STATUS),s=i.getShaderInfoLog(t).trim();if(n&&s==="")return"";const r=/ERROR: 0:(\d+)/.exec(s);if(r){const a=parseInt(r[1]);return e.toUpperCase()+` +`)}const pl=new Ht;function sm(i){$t._getMatrix(pl,$t.workingColorSpace,i);const t=`mat3( ${pl.elements.map(e=>e.toFixed(4))} )`;switch($t.getTransfer(i)){case ir:return[t,"LinearTransferOETF"];case re:return[t,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space: ",i),[t,"LinearTransferOETF"]}}function ml(i,t,e){const n=i.getShaderParameter(t,i.COMPILE_STATUS),s=i.getShaderInfoLog(t).trim();if(n&&s==="")return"";const r=/ERROR: 0:(\d+)/.exec(s);if(r){const a=parseInt(r[1]);return e.toUpperCase()+` `+s+` -`+nm(i.getShaderSource(t),a)}else return s}function sm(i,t){const e=im(t);return[`vec4 ${i}( vec4 value ) {`,` return ${e[1]}( vec4( value.rgb * ${e[0]}, value.a ) );`,"}"].join(` -`)}function rm(i,t){let e;switch(t){case sh:e="Linear";break;case rh:e="Reinhard";break;case ah:e="Cineon";break;case Bl:e="ACESFilmic";break;case lh:e="AgX";break;case ch:e="Neutral";break;case oh:e="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),e="Linear"}return"vec3 "+i+"( vec3 color ) { return "+e+"ToneMapping( color ); }"}const Gs=new P;function am(){$t.getLuminanceCoefficients(Gs);const i=Gs.x.toFixed(4),t=Gs.y.toFixed(4),e=Gs.z.toFixed(4);return["float luminance( const in vec3 rgb ) {",` const vec3 weights = vec3( ${i}, ${t}, ${e} );`," return dot( weights, rgb );","}"].join(` -`)}function om(i){return[i.extensionClipCullDistance?"#extension GL_ANGLE_clip_cull_distance : require":"",i.extensionMultiDraw?"#extension GL_ANGLE_multi_draw : require":""].filter(ss).join(` -`)}function lm(i){const t=[];for(const e in i){const n=i[e];n!==!1&&t.push("#define "+e+" "+n)}return t.join(` -`)}function cm(i,t){const e={},n=i.getProgramParameter(t,i.ACTIVE_ATTRIBUTES);for(let s=0;s/gm;function Wa(i){return i.replace(hm,dm)}const um=new Map;function dm(i,t){let e=Vt[t];if(e===void 0){const n=um.get(t);if(n!==void 0)e=Vt[n],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,n);else throw new Error("Can not resolve #include <"+t+">")}return Wa(e)}const fm=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function _l(i){return i.replace(fm,pm)}function pm(i,t,e,n){let s="";for(let r=parseInt(t);r/gm;function Xa(i){return i.replace(um,fm)}const dm=new Map;function fm(i,t){let e=Vt[t];if(e===void 0){const n=dm.get(t);if(n!==void 0)e=Vt[n],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,n);else throw new Error("Can not resolve #include <"+t+">")}return Xa(e)}const pm=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function vl(i){return i.replace(pm,mm)}function mm(i,t,e,n){let s="";for(let r=parseInt(t);r0&&(m+=` -`),u=["#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g].filter(ss).join(` +`),u=["#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g].filter(as).join(` `),u.length>0&&(u+=` -`)):(m=[vl(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g,e.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",e.batching?"#define USE_BATCHING":"",e.batchingColor?"#define USE_BATCHING_COLOR":"",e.instancing?"#define USE_INSTANCING":"",e.instancingColor?"#define USE_INSTANCING_COLOR":"",e.instancingMorph?"#define USE_INSTANCING_MORPH":"",e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.map?"#define USE_MAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+h:"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.displacementMap?"#define USE_DISPLACEMENTMAP":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.mapUv?"#define MAP_UV "+e.mapUv:"",e.alphaMapUv?"#define ALPHAMAP_UV "+e.alphaMapUv:"",e.lightMapUv?"#define LIGHTMAP_UV "+e.lightMapUv:"",e.aoMapUv?"#define AOMAP_UV "+e.aoMapUv:"",e.emissiveMapUv?"#define EMISSIVEMAP_UV "+e.emissiveMapUv:"",e.bumpMapUv?"#define BUMPMAP_UV "+e.bumpMapUv:"",e.normalMapUv?"#define NORMALMAP_UV "+e.normalMapUv:"",e.displacementMapUv?"#define DISPLACEMENTMAP_UV "+e.displacementMapUv:"",e.metalnessMapUv?"#define METALNESSMAP_UV "+e.metalnessMapUv:"",e.roughnessMapUv?"#define ROUGHNESSMAP_UV "+e.roughnessMapUv:"",e.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+e.anisotropyMapUv:"",e.clearcoatMapUv?"#define CLEARCOATMAP_UV "+e.clearcoatMapUv:"",e.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+e.clearcoatNormalMapUv:"",e.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+e.clearcoatRoughnessMapUv:"",e.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+e.iridescenceMapUv:"",e.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+e.iridescenceThicknessMapUv:"",e.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+e.sheenColorMapUv:"",e.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+e.sheenRoughnessMapUv:"",e.specularMapUv?"#define SPECULARMAP_UV "+e.specularMapUv:"",e.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+e.specularColorMapUv:"",e.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+e.specularIntensityMapUv:"",e.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+e.transmissionMapUv:"",e.thicknessMapUv?"#define THICKNESSMAP_UV "+e.thicknessMapUv:"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.flatShading?"#define FLAT_SHADED":"",e.skinning?"#define USE_SKINNING":"",e.morphTargets?"#define USE_MORPHTARGETS":"",e.morphNormals&&e.flatShading===!1?"#define USE_MORPHNORMALS":"",e.morphColors?"#define USE_MORPHCOLORS":"",e.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+e.morphTextureStride:"",e.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+e.morphTargetsCount:"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.sizeAttenuation?"#define USE_SIZEATTENUATION":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",e.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH"," uniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif",` -`].filter(ss).join(` -`),u=[vl(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g,e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",e.map?"#define USE_MAP":"",e.matcap?"#define USE_MATCAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+c:"",e.envMap?"#define "+h:"",e.envMap?"#define "+d:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoat?"#define USE_CLEARCOAT":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.dispersion?"#define USE_DISPERSION":"",e.iridescence?"#define USE_IRIDESCENCE":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaTest?"#define USE_ALPHATEST":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.sheen?"#define USE_SHEEN":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors||e.instancingColor||e.batchingColor?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.gradientMap?"#define USE_GRADIENTMAP":"",e.flatShading?"#define FLAT_SHADED":"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",e.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",e.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",e.toneMapping!==On?"#define TONE_MAPPING":"",e.toneMapping!==On?Vt.tonemapping_pars_fragment:"",e.toneMapping!==On?rm("toneMapping",e.toneMapping):"",e.dithering?"#define DITHERING":"",e.opaque?"#define OPAQUE":"",Vt.colorspace_pars_fragment,sm("linearToOutputTexel",e.outputColorSpace),am(),e.useDepthPacking?"#define DEPTH_PACKING "+e.depthPacking:"",` -`].filter(ss).join(` -`)),a=Wa(a),a=ml(a,e),a=gl(a,e),o=Wa(o),o=ml(o,e),o=gl(o,e),a=_l(a),o=_l(o),e.isRawShaderMaterial!==!0&&(T=`#version 300 es -`,m=[p,"#define attribute in","#define varying out","#define texture2D texture"].join(` +`)):(m=[xl(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g,e.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",e.batching?"#define USE_BATCHING":"",e.batchingColor?"#define USE_BATCHING_COLOR":"",e.instancing?"#define USE_INSTANCING":"",e.instancingColor?"#define USE_INSTANCING_COLOR":"",e.instancingMorph?"#define USE_INSTANCING_MORPH":"",e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.map?"#define USE_MAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+h:"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.displacementMap?"#define USE_DISPLACEMENTMAP":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.mapUv?"#define MAP_UV "+e.mapUv:"",e.alphaMapUv?"#define ALPHAMAP_UV "+e.alphaMapUv:"",e.lightMapUv?"#define LIGHTMAP_UV "+e.lightMapUv:"",e.aoMapUv?"#define AOMAP_UV "+e.aoMapUv:"",e.emissiveMapUv?"#define EMISSIVEMAP_UV "+e.emissiveMapUv:"",e.bumpMapUv?"#define BUMPMAP_UV "+e.bumpMapUv:"",e.normalMapUv?"#define NORMALMAP_UV "+e.normalMapUv:"",e.displacementMapUv?"#define DISPLACEMENTMAP_UV "+e.displacementMapUv:"",e.metalnessMapUv?"#define METALNESSMAP_UV "+e.metalnessMapUv:"",e.roughnessMapUv?"#define ROUGHNESSMAP_UV "+e.roughnessMapUv:"",e.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+e.anisotropyMapUv:"",e.clearcoatMapUv?"#define CLEARCOATMAP_UV "+e.clearcoatMapUv:"",e.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+e.clearcoatNormalMapUv:"",e.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+e.clearcoatRoughnessMapUv:"",e.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+e.iridescenceMapUv:"",e.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+e.iridescenceThicknessMapUv:"",e.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+e.sheenColorMapUv:"",e.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+e.sheenRoughnessMapUv:"",e.specularMapUv?"#define SPECULARMAP_UV "+e.specularMapUv:"",e.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+e.specularColorMapUv:"",e.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+e.specularIntensityMapUv:"",e.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+e.transmissionMapUv:"",e.thicknessMapUv?"#define THICKNESSMAP_UV "+e.thicknessMapUv:"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.flatShading?"#define FLAT_SHADED":"",e.skinning?"#define USE_SKINNING":"",e.morphTargets?"#define USE_MORPHTARGETS":"",e.morphNormals&&e.flatShading===!1?"#define USE_MORPHNORMALS":"",e.morphColors?"#define USE_MORPHCOLORS":"",e.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+e.morphTextureStride:"",e.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+e.morphTargetsCount:"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.sizeAttenuation?"#define USE_SIZEATTENUATION":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",e.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH"," uniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif",` +`].filter(as).join(` +`),u=[xl(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,g,e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",e.map?"#define USE_MAP":"",e.matcap?"#define USE_MATCAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+c:"",e.envMap?"#define "+h:"",e.envMap?"#define "+d:"",p?"#define CUBEUV_TEXEL_WIDTH "+p.texelWidth:"",p?"#define CUBEUV_TEXEL_HEIGHT "+p.texelHeight:"",p?"#define CUBEUV_MAX_MIP "+p.maxMip+".0":"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoat?"#define USE_CLEARCOAT":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.dispersion?"#define USE_DISPERSION":"",e.iridescence?"#define USE_IRIDESCENCE":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaTest?"#define USE_ALPHATEST":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.sheen?"#define USE_SHEEN":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors||e.instancingColor||e.batchingColor?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.gradientMap?"#define USE_GRADIENTMAP":"",e.flatShading?"#define FLAT_SHADED":"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",e.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",e.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",e.toneMapping!==On?"#define TONE_MAPPING":"",e.toneMapping!==On?Vt.tonemapping_pars_fragment:"",e.toneMapping!==On?am("toneMapping",e.toneMapping):"",e.dithering?"#define DITHERING":"",e.opaque?"#define OPAQUE":"",Vt.colorspace_pars_fragment,rm("linearToOutputTexel",e.outputColorSpace),om(),e.useDepthPacking?"#define DEPTH_PACKING "+e.depthPacking:"",` +`].filter(as).join(` +`)),a=Xa(a),a=gl(a,e),a=_l(a,e),o=Xa(o),o=gl(o,e),o=_l(o,e),a=vl(a),o=vl(o),e.isRawShaderMaterial!==!0&&(T=`#version 300 es +`,m=[f,"#define attribute in","#define varying out","#define texture2D texture"].join(` `)+` -`+m,u=["#define varying in",e.glslVersion===go?"":"layout(location = 0) out highp vec4 pc_fragColor;",e.glslVersion===go?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join(` +`+m,u=["#define varying in",e.glslVersion===_o?"":"layout(location = 0) out highp vec4 pc_fragColor;",e.glslVersion===_o?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join(` `)+` -`+u);const b=T+m+a,y=T+u+o,L=dl(s,s.VERTEX_SHADER,b),R=dl(s,s.FRAGMENT_SHADER,y);s.attachShader(v,L),s.attachShader(v,R),e.index0AttributeName!==void 0?s.bindAttribLocation(v,0,e.index0AttributeName):e.morphTargets===!0&&s.bindAttribLocation(v,0,"position"),s.linkProgram(v);function A(D){if(i.debug.checkShaderErrors){const W=s.getProgramInfoLog(v).trim(),z=s.getShaderInfoLog(L).trim(),V=s.getShaderInfoLog(R).trim();let $=!0,G=!0;if(s.getProgramParameter(v,s.LINK_STATUS)===!1)if($=!1,typeof i.debug.onShaderError=="function")i.debug.onShaderError(s,v,L,R);else{const J=pl(s,L,"vertex"),k=pl(s,R,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(v,s.VALIDATE_STATUS)+` +`+u);const b=T+m+a,y=T+u+o,L=fl(s,s.VERTEX_SHADER,b),R=fl(s,s.FRAGMENT_SHADER,y);s.attachShader(v,L),s.attachShader(v,R),e.index0AttributeName!==void 0?s.bindAttribLocation(v,0,e.index0AttributeName):e.morphTargets===!0&&s.bindAttribLocation(v,0,"position"),s.linkProgram(v);function A(D){if(i.debug.checkShaderErrors){const W=s.getProgramInfoLog(v).trim(),z=s.getShaderInfoLog(L).trim(),V=s.getShaderInfoLog(R).trim();let $=!0,G=!0;if(s.getProgramParameter(v,s.LINK_STATUS)===!1)if($=!1,typeof i.debug.onShaderError=="function")i.debug.onShaderError(s,v,L,R);else{const J=ml(s,L,"vertex"),k=ml(s,R,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(v,s.VALIDATE_STATUS)+` Material Name: `+D.name+` Material Type: `+D.type+` Program Info Log: `+W+` `+J+` -`+k)}else W!==""?console.warn("THREE.WebGLProgram: Program Info Log:",W):(z===""||V==="")&&(G=!1);G&&(D.diagnostics={runnable:$,programLog:W,vertexShader:{log:z,prefix:m},fragmentShader:{log:V,prefix:u}})}s.deleteShader(L),s.deleteShader(R),U=new $s(s,v),S=cm(s,v)}let U;this.getUniforms=function(){return U===void 0&&A(this),U};let S;this.getAttributes=function(){return S===void 0&&A(this),S};let M=e.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return M===!1&&(M=s.getProgramParameter(v,tm)),M},this.destroy=function(){n.releaseStatesOfProgram(this),s.deleteProgram(v),this.program=void 0},this.type=e.shaderType,this.name=e.shaderName,this.id=em++,this.cacheKey=t,this.usedTimes=1,this.program=v,this.vertexShader=L,this.fragmentShader=R,this}let Sm=0;class ym{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(t){const e=t.vertexShader,n=t.fragmentShader,s=this._getShaderStage(e),r=this._getShaderStage(n),a=this._getShaderCacheForMaterial(t);return a.has(s)===!1&&(a.add(s),s.usedTimes++),a.has(r)===!1&&(a.add(r),r.usedTimes++),this}remove(t){const e=this.materialCache.get(t);for(const n of e)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(t),this}getVertexShaderID(t){return this._getShaderStage(t.vertexShader).id}getFragmentShaderID(t){return this._getShaderStage(t.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(t){const e=this.materialCache;let n=e.get(t);return n===void 0&&(n=new Set,e.set(t,n)),n}_getShaderStage(t){const e=this.shaderCache;let n=e.get(t);return n===void 0&&(n=new Em(t),e.set(t,n)),n}}class Em{constructor(t){this.id=Sm++,this.code=t,this.usedTimes=0}}function bm(i,t,e,n,s,r,a){const o=new Qa,l=new ym,c=new Set,h=[],d=s.logarithmicDepthBuffer,f=s.vertexTextures;let p=s.precision;const g={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function v(S){return c.add(S),S===0?"uv":`uv${S}`}function m(S,M,D,W,z){const V=W.fog,$=z.geometry,G=S.isMeshStandardMaterial?W.environment:null,J=(S.isMeshStandardMaterial?e:t).get(S.envMap||G),k=J&&J.mapping===hr?J.image.height:null,it=g[S.type];S.precision!==null&&(p=s.getMaxPrecision(S.precision),p!==S.precision&&console.warn("THREE.WebGLProgram.getParameters:",S.precision,"not supported, using",p,"instead."));const ut=$.morphAttributes.position||$.morphAttributes.normal||$.morphAttributes.color,yt=ut!==void 0?ut.length:0;let Lt=0;$.morphAttributes.position!==void 0&&(Lt=1),$.morphAttributes.normal!==void 0&&(Lt=2),$.morphAttributes.color!==void 0&&(Lt=3);let qt,Y,nt,xt;if(it){const Jt=cn[it];qt=Jt.vertexShader,Y=Jt.fragmentShader}else qt=S.vertexShader,Y=S.fragmentShader,l.update(S),nt=l.getVertexShaderID(S),xt=l.getFragmentShaderID(S);const at=i.getRenderTarget(),wt=i.state.buffers.depth.getReversed(),Ut=z.isInstancedMesh===!0,Gt=z.isBatchedMesh===!0,ce=!!S.map,rt=!!S.matcap,Ct=!!J,w=!!S.aoMap,ve=!!S.lightMap,Bt=!!S.bumpMap,kt=!!S.normalMap,Mt=!!S.displacementMap,ne=!!S.emissiveMap,Et=!!S.metalnessMap,E=!!S.roughnessMap,_=S.anisotropy>0,F=S.clearcoat>0,Z=S.dispersion>0,K=S.iridescence>0,X=S.sheen>0,St=S.transmission>0,ot=_&&!!S.anisotropyMap,dt=F&&!!S.clearcoatMap,jt=F&&!!S.clearcoatNormalMap,tt=F&&!!S.clearcoatRoughnessMap,mt=K&&!!S.iridescenceMap,bt=K&&!!S.iridescenceThicknessMap,Pt=X&&!!S.sheenColorMap,ft=X&&!!S.sheenRoughnessMap,Xt=!!S.specularMap,zt=!!S.specularColorMap,ie=!!S.specularIntensityMap,C=St&&!!S.transmissionMap,et=St&&!!S.thicknessMap,H=!!S.gradientMap,q=!!S.alphaMap,lt=S.alphaTest>0,ct=!!S.alphaHash,Nt=!!S.extensions;let he=On;S.toneMapped&&(at===null||at.isXRRenderTarget===!0)&&(he=i.toneMapping);const xe={shaderID:it,shaderType:S.type,shaderName:S.name,vertexShader:qt,fragmentShader:Y,defines:S.defines,customVertexShaderID:nt,customFragmentShaderID:xt,isRawShaderMaterial:S.isRawShaderMaterial===!0,glslVersion:S.glslVersion,precision:p,batching:Gt,batchingColor:Gt&&z._colorsTexture!==null,instancing:Ut,instancingColor:Ut&&z.instanceColor!==null,instancingMorph:Ut&&z.morphTexture!==null,supportsVertexTextures:f,outputColorSpace:at===null?i.outputColorSpace:at.isXRRenderTarget===!0?at.texture.colorSpace:ki,alphaToCoverage:!!S.alphaToCoverage,map:ce,matcap:rt,envMap:Ct,envMapMode:Ct&&J.mapping,envMapCubeUVHeight:k,aoMap:w,lightMap:ve,bumpMap:Bt,normalMap:kt,displacementMap:f&&Mt,emissiveMap:ne,normalMapObjectSpace:kt&&S.normalMapType===fh,normalMapTangentSpace:kt&&S.normalMapType===Zl,metalnessMap:Et,roughnessMap:E,anisotropy:_,anisotropyMap:ot,clearcoat:F,clearcoatMap:dt,clearcoatNormalMap:jt,clearcoatRoughnessMap:tt,dispersion:Z,iridescence:K,iridescenceMap:mt,iridescenceThicknessMap:bt,sheen:X,sheenColorMap:Pt,sheenRoughnessMap:ft,specularMap:Xt,specularColorMap:zt,specularIntensityMap:ie,transmission:St,transmissionMap:C,thicknessMap:et,gradientMap:H,opaque:S.transparent===!1&&S.blending===Li&&S.alphaToCoverage===!1,alphaMap:q,alphaTest:lt,alphaHash:ct,combine:S.combine,mapUv:ce&&v(S.map.channel),aoMapUv:w&&v(S.aoMap.channel),lightMapUv:ve&&v(S.lightMap.channel),bumpMapUv:Bt&&v(S.bumpMap.channel),normalMapUv:kt&&v(S.normalMap.channel),displacementMapUv:Mt&&v(S.displacementMap.channel),emissiveMapUv:ne&&v(S.emissiveMap.channel),metalnessMapUv:Et&&v(S.metalnessMap.channel),roughnessMapUv:E&&v(S.roughnessMap.channel),anisotropyMapUv:ot&&v(S.anisotropyMap.channel),clearcoatMapUv:dt&&v(S.clearcoatMap.channel),clearcoatNormalMapUv:jt&&v(S.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:tt&&v(S.clearcoatRoughnessMap.channel),iridescenceMapUv:mt&&v(S.iridescenceMap.channel),iridescenceThicknessMapUv:bt&&v(S.iridescenceThicknessMap.channel),sheenColorMapUv:Pt&&v(S.sheenColorMap.channel),sheenRoughnessMapUv:ft&&v(S.sheenRoughnessMap.channel),specularMapUv:Xt&&v(S.specularMap.channel),specularColorMapUv:zt&&v(S.specularColorMap.channel),specularIntensityMapUv:ie&&v(S.specularIntensityMap.channel),transmissionMapUv:C&&v(S.transmissionMap.channel),thicknessMapUv:et&&v(S.thicknessMap.channel),alphaMapUv:q&&v(S.alphaMap.channel),vertexTangents:!!$.attributes.tangent&&(kt||_),vertexColors:S.vertexColors,vertexAlphas:S.vertexColors===!0&&!!$.attributes.color&&$.attributes.color.itemSize===4,pointsUvs:z.isPoints===!0&&!!$.attributes.uv&&(ce||q),fog:!!V,useFog:S.fog===!0,fogExp2:!!V&&V.isFogExp2,flatShading:S.flatShading===!0,sizeAttenuation:S.sizeAttenuation===!0,logarithmicDepthBuffer:d,reverseDepthBuffer:wt,skinning:z.isSkinnedMesh===!0,morphTargets:$.morphAttributes.position!==void 0,morphNormals:$.morphAttributes.normal!==void 0,morphColors:$.morphAttributes.color!==void 0,morphTargetsCount:yt,morphTextureStride:Lt,numDirLights:M.directional.length,numPointLights:M.point.length,numSpotLights:M.spot.length,numSpotLightMaps:M.spotLightMap.length,numRectAreaLights:M.rectArea.length,numHemiLights:M.hemi.length,numDirLightShadows:M.directionalShadowMap.length,numPointLightShadows:M.pointShadowMap.length,numSpotLightShadows:M.spotShadowMap.length,numSpotLightShadowsWithMaps:M.numSpotLightShadowsWithMaps,numLightProbes:M.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:S.dithering,shadowMapEnabled:i.shadowMap.enabled&&D.length>0,shadowMapType:i.shadowMap.type,toneMapping:he,decodeVideoTexture:ce&&S.map.isVideoTexture===!0&&$t.getTransfer(S.map.colorSpace)===re,decodeVideoTextureEmissive:ne&&S.emissiveMap.isVideoTexture===!0&&$t.getTransfer(S.emissiveMap.colorSpace)===re,premultipliedAlpha:S.premultipliedAlpha,doubleSided:S.side===hn,flipSided:S.side===ke,useDepthPacking:S.depthPacking>=0,depthPacking:S.depthPacking||0,index0AttributeName:S.index0AttributeName,extensionClipCullDistance:Nt&&S.extensions.clipCullDistance===!0&&n.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(Nt&&S.extensions.multiDraw===!0||Gt)&&n.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:n.has("KHR_parallel_shader_compile"),customProgramCacheKey:S.customProgramCacheKey()};return xe.vertexUv1s=c.has(1),xe.vertexUv2s=c.has(2),xe.vertexUv3s=c.has(3),c.clear(),xe}function u(S){const M=[];if(S.shaderID?M.push(S.shaderID):(M.push(S.customVertexShaderID),M.push(S.customFragmentShaderID)),S.defines!==void 0)for(const D in S.defines)M.push(D),M.push(S.defines[D]);return S.isRawShaderMaterial===!1&&(T(M,S),b(M,S),M.push(i.outputColorSpace)),M.push(S.customProgramCacheKey),M.join()}function T(S,M){S.push(M.precision),S.push(M.outputColorSpace),S.push(M.envMapMode),S.push(M.envMapCubeUVHeight),S.push(M.mapUv),S.push(M.alphaMapUv),S.push(M.lightMapUv),S.push(M.aoMapUv),S.push(M.bumpMapUv),S.push(M.normalMapUv),S.push(M.displacementMapUv),S.push(M.emissiveMapUv),S.push(M.metalnessMapUv),S.push(M.roughnessMapUv),S.push(M.anisotropyMapUv),S.push(M.clearcoatMapUv),S.push(M.clearcoatNormalMapUv),S.push(M.clearcoatRoughnessMapUv),S.push(M.iridescenceMapUv),S.push(M.iridescenceThicknessMapUv),S.push(M.sheenColorMapUv),S.push(M.sheenRoughnessMapUv),S.push(M.specularMapUv),S.push(M.specularColorMapUv),S.push(M.specularIntensityMapUv),S.push(M.transmissionMapUv),S.push(M.thicknessMapUv),S.push(M.combine),S.push(M.fogExp2),S.push(M.sizeAttenuation),S.push(M.morphTargetsCount),S.push(M.morphAttributeCount),S.push(M.numDirLights),S.push(M.numPointLights),S.push(M.numSpotLights),S.push(M.numSpotLightMaps),S.push(M.numHemiLights),S.push(M.numRectAreaLights),S.push(M.numDirLightShadows),S.push(M.numPointLightShadows),S.push(M.numSpotLightShadows),S.push(M.numSpotLightShadowsWithMaps),S.push(M.numLightProbes),S.push(M.shadowMapType),S.push(M.toneMapping),S.push(M.numClippingPlanes),S.push(M.numClipIntersection),S.push(M.depthPacking)}function b(S,M){o.disableAll(),M.supportsVertexTextures&&o.enable(0),M.instancing&&o.enable(1),M.instancingColor&&o.enable(2),M.instancingMorph&&o.enable(3),M.matcap&&o.enable(4),M.envMap&&o.enable(5),M.normalMapObjectSpace&&o.enable(6),M.normalMapTangentSpace&&o.enable(7),M.clearcoat&&o.enable(8),M.iridescence&&o.enable(9),M.alphaTest&&o.enable(10),M.vertexColors&&o.enable(11),M.vertexAlphas&&o.enable(12),M.vertexUv1s&&o.enable(13),M.vertexUv2s&&o.enable(14),M.vertexUv3s&&o.enable(15),M.vertexTangents&&o.enable(16),M.anisotropy&&o.enable(17),M.alphaHash&&o.enable(18),M.batching&&o.enable(19),M.dispersion&&o.enable(20),M.batchingColor&&o.enable(21),S.push(o.mask),o.disableAll(),M.fog&&o.enable(0),M.useFog&&o.enable(1),M.flatShading&&o.enable(2),M.logarithmicDepthBuffer&&o.enable(3),M.reverseDepthBuffer&&o.enable(4),M.skinning&&o.enable(5),M.morphTargets&&o.enable(6),M.morphNormals&&o.enable(7),M.morphColors&&o.enable(8),M.premultipliedAlpha&&o.enable(9),M.shadowMapEnabled&&o.enable(10),M.doubleSided&&o.enable(11),M.flipSided&&o.enable(12),M.useDepthPacking&&o.enable(13),M.dithering&&o.enable(14),M.transmission&&o.enable(15),M.sheen&&o.enable(16),M.opaque&&o.enable(17),M.pointsUvs&&o.enable(18),M.decodeVideoTexture&&o.enable(19),M.decodeVideoTextureEmissive&&o.enable(20),M.alphaToCoverage&&o.enable(21),S.push(o.mask)}function y(S){const M=g[S.type];let D;if(M){const W=cn[M];D=ir.clone(W.uniforms)}else D=S.uniforms;return D}function L(S,M){let D;for(let W=0,z=h.length;W0?n.push(u):p.transparent===!0?s.push(u):e.push(u)}function l(d,f,p,g,v,m){const u=a(d,f,p,g,v,m);p.transmission>0?n.unshift(u):p.transparent===!0?s.unshift(u):e.unshift(u)}function c(d,f){e.length>1&&e.sort(d||wm),n.length>1&&n.sort(f||xl),s.length>1&&s.sort(f||xl)}function h(){for(let d=t,f=i.length;d=r.length?(a=new Ml,r.push(a)):a=r[s],a}function e(){i=new WeakMap}return{get:t,dispose:e}}function Rm(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={direction:new P,color:new pt};break;case"SpotLight":e={position:new P,direction:new P,color:new pt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":e={position:new P,color:new pt,distance:0,decay:0};break;case"HemisphereLight":e={direction:new P,skyColor:new pt,groundColor:new pt};break;case"RectAreaLight":e={color:new pt,position:new P,halfWidth:new P,halfHeight:new P};break}return i[t.id]=e,e}}}function Cm(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt};break;case"SpotLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt};break;case"PointLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt,shadowCameraNear:1,shadowCameraFar:1e3};break}return i[t.id]=e,e}}}let Pm=0;function Dm(i,t){return(t.castShadow?2:0)-(i.castShadow?2:0)+(t.map?1:0)-(i.map?1:0)}function Lm(i){const t=new Rm,e=Cm(),n={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let c=0;c<9;c++)n.probe.push(new P);const s=new P,r=new ee,a=new ee;function o(c){let h=0,d=0,f=0;for(let S=0;S<9;S++)n.probe[S].set(0,0,0);let p=0,g=0,v=0,m=0,u=0,T=0,b=0,y=0,L=0,R=0,A=0;c.sort(Dm);for(let S=0,M=c.length;S0&&(i.has("OES_texture_float_linear")===!0?(n.rectAreaLTC1=st.LTC_FLOAT_1,n.rectAreaLTC2=st.LTC_FLOAT_2):(n.rectAreaLTC1=st.LTC_HALF_1,n.rectAreaLTC2=st.LTC_HALF_2)),n.ambient[0]=h,n.ambient[1]=d,n.ambient[2]=f;const U=n.hash;(U.directionalLength!==p||U.pointLength!==g||U.spotLength!==v||U.rectAreaLength!==m||U.hemiLength!==u||U.numDirectionalShadows!==T||U.numPointShadows!==b||U.numSpotShadows!==y||U.numSpotMaps!==L||U.numLightProbes!==A)&&(n.directional.length=p,n.spot.length=v,n.rectArea.length=m,n.point.length=g,n.hemi.length=u,n.directionalShadow.length=T,n.directionalShadowMap.length=T,n.pointShadow.length=b,n.pointShadowMap.length=b,n.spotShadow.length=y,n.spotShadowMap.length=y,n.directionalShadowMatrix.length=T,n.pointShadowMatrix.length=b,n.spotLightMatrix.length=y+L-R,n.spotLightMap.length=L,n.numSpotLightShadowsWithMaps=R,n.numLightProbes=A,U.directionalLength=p,U.pointLength=g,U.spotLength=v,U.rectAreaLength=m,U.hemiLength=u,U.numDirectionalShadows=T,U.numPointShadows=b,U.numSpotShadows=y,U.numSpotMaps=L,U.numLightProbes=A,n.version=Pm++)}function l(c,h){let d=0,f=0,p=0,g=0,v=0;const m=h.matrixWorldInverse;for(let u=0,T=c.length;u=a.length?(o=new Sl(i),a.push(o)):o=a[r],o}function n(){t=new WeakMap}return{get:e,dispose:n}}const Im=`void main() { +`+k)}else W!==""?console.warn("THREE.WebGLProgram: Program Info Log:",W):(z===""||V==="")&&(G=!1);G&&(D.diagnostics={runnable:$,programLog:W,vertexShader:{log:z,prefix:m},fragmentShader:{log:V,prefix:u}})}s.deleteShader(L),s.deleteShader(R),U=new tr(s,v),S=hm(s,v)}let U;this.getUniforms=function(){return U===void 0&&A(this),U};let S;this.getAttributes=function(){return S===void 0&&A(this),S};let M=e.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return M===!1&&(M=s.getProgramParameter(v,em)),M},this.destroy=function(){n.releaseStatesOfProgram(this),s.deleteProgram(v),this.program=void 0},this.type=e.shaderType,this.name=e.shaderName,this.id=nm++,this.cacheKey=t,this.usedTimes=1,this.program=v,this.vertexShader=L,this.fragmentShader=R,this}let ym=0;class Em{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(t){const e=t.vertexShader,n=t.fragmentShader,s=this._getShaderStage(e),r=this._getShaderStage(n),a=this._getShaderCacheForMaterial(t);return a.has(s)===!1&&(a.add(s),s.usedTimes++),a.has(r)===!1&&(a.add(r),r.usedTimes++),this}remove(t){const e=this.materialCache.get(t);for(const n of e)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(t),this}getVertexShaderID(t){return this._getShaderStage(t.vertexShader).id}getFragmentShaderID(t){return this._getShaderStage(t.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(t){const e=this.materialCache;let n=e.get(t);return n===void 0&&(n=new Set,e.set(t,n)),n}_getShaderStage(t){const e=this.shaderCache;let n=e.get(t);return n===void 0&&(n=new bm(t),e.set(t,n)),n}}class bm{constructor(t){this.id=ym++,this.code=t,this.usedTimes=0}}function Tm(i,t,e,n,s,r,a){const o=new to,l=new Em,c=new Set,h=[],d=s.logarithmicDepthBuffer,p=s.vertexTextures;let f=s.precision;const g={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function v(S){return c.add(S),S===0?"uv":`uv${S}`}function m(S,M,D,W,z){const V=W.fog,$=z.geometry,G=S.isMeshStandardMaterial?W.environment:null,J=(S.isMeshStandardMaterial?e:t).get(S.envMap||G),k=J&&J.mapping===fr?J.image.height:null,it=g[S.type];S.precision!==null&&(f=s.getMaxPrecision(S.precision),f!==S.precision&&console.warn("THREE.WebGLProgram.getParameters:",S.precision,"not supported, using",f,"instead."));const ut=$.morphAttributes.position||$.morphAttributes.normal||$.morphAttributes.color,yt=ut!==void 0?ut.length:0;let Lt=0;$.morphAttributes.position!==void 0&&(Lt=1),$.morphAttributes.normal!==void 0&&(Lt=2),$.morphAttributes.color!==void 0&&(Lt=3);let qt,Y,nt,xt;if(it){const Jt=cn[it];qt=Jt.vertexShader,Y=Jt.fragmentShader}else qt=S.vertexShader,Y=S.fragmentShader,l.update(S),nt=l.getVertexShaderID(S),xt=l.getFragmentShaderID(S);const at=i.getRenderTarget(),wt=i.state.buffers.depth.getReversed(),Ut=z.isInstancedMesh===!0,Gt=z.isBatchedMesh===!0,ce=!!S.map,rt=!!S.matcap,Ct=!!J,w=!!S.aoMap,ve=!!S.lightMap,Bt=!!S.bumpMap,kt=!!S.normalMap,Mt=!!S.displacementMap,ne=!!S.emissiveMap,Et=!!S.metalnessMap,E=!!S.roughnessMap,_=S.anisotropy>0,F=S.clearcoat>0,Z=S.dispersion>0,K=S.iridescence>0,X=S.sheen>0,St=S.transmission>0,ot=_&&!!S.anisotropyMap,dt=F&&!!S.clearcoatMap,jt=F&&!!S.clearcoatNormalMap,tt=F&&!!S.clearcoatRoughnessMap,mt=K&&!!S.iridescenceMap,bt=K&&!!S.iridescenceThicknessMap,Pt=X&&!!S.sheenColorMap,ft=X&&!!S.sheenRoughnessMap,Xt=!!S.specularMap,zt=!!S.specularColorMap,se=!!S.specularIntensityMap,C=St&&!!S.transmissionMap,et=St&&!!S.thicknessMap,H=!!S.gradientMap,q=!!S.alphaMap,lt=S.alphaTest>0,ct=!!S.alphaHash,Nt=!!S.extensions;let ue=On;S.toneMapped&&(at===null||at.isXRRenderTarget===!0)&&(ue=i.toneMapping);const xe={shaderID:it,shaderType:S.type,shaderName:S.name,vertexShader:qt,fragmentShader:Y,defines:S.defines,customVertexShaderID:nt,customFragmentShaderID:xt,isRawShaderMaterial:S.isRawShaderMaterial===!0,glslVersion:S.glslVersion,precision:f,batching:Gt,batchingColor:Gt&&z._colorsTexture!==null,instancing:Ut,instancingColor:Ut&&z.instanceColor!==null,instancingMorph:Ut&&z.morphTexture!==null,supportsVertexTextures:p,outputColorSpace:at===null?i.outputColorSpace:at.isXRRenderTarget===!0?at.texture.colorSpace:Vi,alphaToCoverage:!!S.alphaToCoverage,map:ce,matcap:rt,envMap:Ct,envMapMode:Ct&&J.mapping,envMapCubeUVHeight:k,aoMap:w,lightMap:ve,bumpMap:Bt,normalMap:kt,displacementMap:p&&Mt,emissiveMap:ne,normalMapObjectSpace:kt&&S.normalMapType===mh,normalMapTangentSpace:kt&&S.normalMapType===Kl,metalnessMap:Et,roughnessMap:E,anisotropy:_,anisotropyMap:ot,clearcoat:F,clearcoatMap:dt,clearcoatNormalMap:jt,clearcoatRoughnessMap:tt,dispersion:Z,iridescence:K,iridescenceMap:mt,iridescenceThicknessMap:bt,sheen:X,sheenColorMap:Pt,sheenRoughnessMap:ft,specularMap:Xt,specularColorMap:zt,specularIntensityMap:se,transmission:St,transmissionMap:C,thicknessMap:et,gradientMap:H,opaque:S.transparent===!1&&S.blending===Ui&&S.alphaToCoverage===!1,alphaMap:q,alphaTest:lt,alphaHash:ct,combine:S.combine,mapUv:ce&&v(S.map.channel),aoMapUv:w&&v(S.aoMap.channel),lightMapUv:ve&&v(S.lightMap.channel),bumpMapUv:Bt&&v(S.bumpMap.channel),normalMapUv:kt&&v(S.normalMap.channel),displacementMapUv:Mt&&v(S.displacementMap.channel),emissiveMapUv:ne&&v(S.emissiveMap.channel),metalnessMapUv:Et&&v(S.metalnessMap.channel),roughnessMapUv:E&&v(S.roughnessMap.channel),anisotropyMapUv:ot&&v(S.anisotropyMap.channel),clearcoatMapUv:dt&&v(S.clearcoatMap.channel),clearcoatNormalMapUv:jt&&v(S.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:tt&&v(S.clearcoatRoughnessMap.channel),iridescenceMapUv:mt&&v(S.iridescenceMap.channel),iridescenceThicknessMapUv:bt&&v(S.iridescenceThicknessMap.channel),sheenColorMapUv:Pt&&v(S.sheenColorMap.channel),sheenRoughnessMapUv:ft&&v(S.sheenRoughnessMap.channel),specularMapUv:Xt&&v(S.specularMap.channel),specularColorMapUv:zt&&v(S.specularColorMap.channel),specularIntensityMapUv:se&&v(S.specularIntensityMap.channel),transmissionMapUv:C&&v(S.transmissionMap.channel),thicknessMapUv:et&&v(S.thicknessMap.channel),alphaMapUv:q&&v(S.alphaMap.channel),vertexTangents:!!$.attributes.tangent&&(kt||_),vertexColors:S.vertexColors,vertexAlphas:S.vertexColors===!0&&!!$.attributes.color&&$.attributes.color.itemSize===4,pointsUvs:z.isPoints===!0&&!!$.attributes.uv&&(ce||q),fog:!!V,useFog:S.fog===!0,fogExp2:!!V&&V.isFogExp2,flatShading:S.flatShading===!0,sizeAttenuation:S.sizeAttenuation===!0,logarithmicDepthBuffer:d,reverseDepthBuffer:wt,skinning:z.isSkinnedMesh===!0,morphTargets:$.morphAttributes.position!==void 0,morphNormals:$.morphAttributes.normal!==void 0,morphColors:$.morphAttributes.color!==void 0,morphTargetsCount:yt,morphTextureStride:Lt,numDirLights:M.directional.length,numPointLights:M.point.length,numSpotLights:M.spot.length,numSpotLightMaps:M.spotLightMap.length,numRectAreaLights:M.rectArea.length,numHemiLights:M.hemi.length,numDirLightShadows:M.directionalShadowMap.length,numPointLightShadows:M.pointShadowMap.length,numSpotLightShadows:M.spotShadowMap.length,numSpotLightShadowsWithMaps:M.numSpotLightShadowsWithMaps,numLightProbes:M.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:S.dithering,shadowMapEnabled:i.shadowMap.enabled&&D.length>0,shadowMapType:i.shadowMap.type,toneMapping:ue,decodeVideoTexture:ce&&S.map.isVideoTexture===!0&&$t.getTransfer(S.map.colorSpace)===re,decodeVideoTextureEmissive:ne&&S.emissiveMap.isVideoTexture===!0&&$t.getTransfer(S.emissiveMap.colorSpace)===re,premultipliedAlpha:S.premultipliedAlpha,doubleSided:S.side===hn,flipSided:S.side===ke,useDepthPacking:S.depthPacking>=0,depthPacking:S.depthPacking||0,index0AttributeName:S.index0AttributeName,extensionClipCullDistance:Nt&&S.extensions.clipCullDistance===!0&&n.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(Nt&&S.extensions.multiDraw===!0||Gt)&&n.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:n.has("KHR_parallel_shader_compile"),customProgramCacheKey:S.customProgramCacheKey()};return xe.vertexUv1s=c.has(1),xe.vertexUv2s=c.has(2),xe.vertexUv3s=c.has(3),c.clear(),xe}function u(S){const M=[];if(S.shaderID?M.push(S.shaderID):(M.push(S.customVertexShaderID),M.push(S.customFragmentShaderID)),S.defines!==void 0)for(const D in S.defines)M.push(D),M.push(S.defines[D]);return S.isRawShaderMaterial===!1&&(T(M,S),b(M,S),M.push(i.outputColorSpace)),M.push(S.customProgramCacheKey),M.join()}function T(S,M){S.push(M.precision),S.push(M.outputColorSpace),S.push(M.envMapMode),S.push(M.envMapCubeUVHeight),S.push(M.mapUv),S.push(M.alphaMapUv),S.push(M.lightMapUv),S.push(M.aoMapUv),S.push(M.bumpMapUv),S.push(M.normalMapUv),S.push(M.displacementMapUv),S.push(M.emissiveMapUv),S.push(M.metalnessMapUv),S.push(M.roughnessMapUv),S.push(M.anisotropyMapUv),S.push(M.clearcoatMapUv),S.push(M.clearcoatNormalMapUv),S.push(M.clearcoatRoughnessMapUv),S.push(M.iridescenceMapUv),S.push(M.iridescenceThicknessMapUv),S.push(M.sheenColorMapUv),S.push(M.sheenRoughnessMapUv),S.push(M.specularMapUv),S.push(M.specularColorMapUv),S.push(M.specularIntensityMapUv),S.push(M.transmissionMapUv),S.push(M.thicknessMapUv),S.push(M.combine),S.push(M.fogExp2),S.push(M.sizeAttenuation),S.push(M.morphTargetsCount),S.push(M.morphAttributeCount),S.push(M.numDirLights),S.push(M.numPointLights),S.push(M.numSpotLights),S.push(M.numSpotLightMaps),S.push(M.numHemiLights),S.push(M.numRectAreaLights),S.push(M.numDirLightShadows),S.push(M.numPointLightShadows),S.push(M.numSpotLightShadows),S.push(M.numSpotLightShadowsWithMaps),S.push(M.numLightProbes),S.push(M.shadowMapType),S.push(M.toneMapping),S.push(M.numClippingPlanes),S.push(M.numClipIntersection),S.push(M.depthPacking)}function b(S,M){o.disableAll(),M.supportsVertexTextures&&o.enable(0),M.instancing&&o.enable(1),M.instancingColor&&o.enable(2),M.instancingMorph&&o.enable(3),M.matcap&&o.enable(4),M.envMap&&o.enable(5),M.normalMapObjectSpace&&o.enable(6),M.normalMapTangentSpace&&o.enable(7),M.clearcoat&&o.enable(8),M.iridescence&&o.enable(9),M.alphaTest&&o.enable(10),M.vertexColors&&o.enable(11),M.vertexAlphas&&o.enable(12),M.vertexUv1s&&o.enable(13),M.vertexUv2s&&o.enable(14),M.vertexUv3s&&o.enable(15),M.vertexTangents&&o.enable(16),M.anisotropy&&o.enable(17),M.alphaHash&&o.enable(18),M.batching&&o.enable(19),M.dispersion&&o.enable(20),M.batchingColor&&o.enable(21),S.push(o.mask),o.disableAll(),M.fog&&o.enable(0),M.useFog&&o.enable(1),M.flatShading&&o.enable(2),M.logarithmicDepthBuffer&&o.enable(3),M.reverseDepthBuffer&&o.enable(4),M.skinning&&o.enable(5),M.morphTargets&&o.enable(6),M.morphNormals&&o.enable(7),M.morphColors&&o.enable(8),M.premultipliedAlpha&&o.enable(9),M.shadowMapEnabled&&o.enable(10),M.doubleSided&&o.enable(11),M.flipSided&&o.enable(12),M.useDepthPacking&&o.enable(13),M.dithering&&o.enable(14),M.transmission&&o.enable(15),M.sheen&&o.enable(16),M.opaque&&o.enable(17),M.pointsUvs&&o.enable(18),M.decodeVideoTexture&&o.enable(19),M.decodeVideoTextureEmissive&&o.enable(20),M.alphaToCoverage&&o.enable(21),S.push(o.mask)}function y(S){const M=g[S.type];let D;if(M){const W=cn[M];D=ar.clone(W.uniforms)}else D=S.uniforms;return D}function L(S,M){let D;for(let W=0,z=h.length;W0?n.push(u):f.transparent===!0?s.push(u):e.push(u)}function l(d,p,f,g,v,m){const u=a(d,p,f,g,v,m);f.transmission>0?n.unshift(u):f.transparent===!0?s.unshift(u):e.unshift(u)}function c(d,p){e.length>1&&e.sort(d||Am),n.length>1&&n.sort(p||Ml),s.length>1&&s.sort(p||Ml)}function h(){for(let d=t,p=i.length;d=r.length?(a=new Sl,r.push(a)):a=r[s],a}function e(){i=new WeakMap}return{get:t,dispose:e}}function Cm(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={direction:new P,color:new pt};break;case"SpotLight":e={position:new P,direction:new P,color:new pt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":e={position:new P,color:new pt,distance:0,decay:0};break;case"HemisphereLight":e={direction:new P,skyColor:new pt,groundColor:new pt};break;case"RectAreaLight":e={color:new pt,position:new P,halfWidth:new P,halfHeight:new P};break}return i[t.id]=e,e}}}function Pm(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt};break;case"SpotLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt};break;case"PointLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt,shadowCameraNear:1,shadowCameraFar:1e3};break}return i[t.id]=e,e}}}let Dm=0;function Lm(i,t){return(t.castShadow?2:0)-(i.castShadow?2:0)+(t.map?1:0)-(i.map?1:0)}function Um(i){const t=new Cm,e=Pm(),n={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let c=0;c<9;c++)n.probe.push(new P);const s=new P,r=new ee,a=new ee;function o(c){let h=0,d=0,p=0;for(let S=0;S<9;S++)n.probe[S].set(0,0,0);let f=0,g=0,v=0,m=0,u=0,T=0,b=0,y=0,L=0,R=0,A=0;c.sort(Lm);for(let S=0,M=c.length;S0&&(i.has("OES_texture_float_linear")===!0?(n.rectAreaLTC1=st.LTC_FLOAT_1,n.rectAreaLTC2=st.LTC_FLOAT_2):(n.rectAreaLTC1=st.LTC_HALF_1,n.rectAreaLTC2=st.LTC_HALF_2)),n.ambient[0]=h,n.ambient[1]=d,n.ambient[2]=p;const U=n.hash;(U.directionalLength!==f||U.pointLength!==g||U.spotLength!==v||U.rectAreaLength!==m||U.hemiLength!==u||U.numDirectionalShadows!==T||U.numPointShadows!==b||U.numSpotShadows!==y||U.numSpotMaps!==L||U.numLightProbes!==A)&&(n.directional.length=f,n.spot.length=v,n.rectArea.length=m,n.point.length=g,n.hemi.length=u,n.directionalShadow.length=T,n.directionalShadowMap.length=T,n.pointShadow.length=b,n.pointShadowMap.length=b,n.spotShadow.length=y,n.spotShadowMap.length=y,n.directionalShadowMatrix.length=T,n.pointShadowMatrix.length=b,n.spotLightMatrix.length=y+L-R,n.spotLightMap.length=L,n.numSpotLightShadowsWithMaps=R,n.numLightProbes=A,U.directionalLength=f,U.pointLength=g,U.spotLength=v,U.rectAreaLength=m,U.hemiLength=u,U.numDirectionalShadows=T,U.numPointShadows=b,U.numSpotShadows=y,U.numSpotMaps=L,U.numLightProbes=A,n.version=Dm++)}function l(c,h){let d=0,p=0,f=0,g=0,v=0;const m=h.matrixWorldInverse;for(let u=0,T=c.length;u=a.length?(o=new yl(i),a.push(o)):o=a[r],o}function n(){t=new WeakMap}return{get:e,dispose:n}}const Nm=`void main() { gl_Position = vec4( position, 1.0 ); -}`,Nm=`uniform sampler2D shadow_pass; +}`,Fm=`uniform sampler2D shadow_pass; uniform vec2 resolution; uniform float radius; #include @@ -3800,12 +3800,12 @@ void main() { squared_mean = squared_mean / samples; float std_dev = sqrt( squared_mean - mean * mean ); gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) ); -}`;function Fm(i,t,e){let n=new to;const s=new vt,r=new vt,a=new le,o=new iu({depthPacking:dh}),l=new su,c={},h=e.maxTextureSize,d={[zn]:ke,[ke]:zn,[hn]:hn},f=new Ne({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new vt},radius:{value:4}},vertexShader:Im,fragmentShader:Nm}),p=f.clone();p.defines.HORIZONTAL_PASS=1;const g=new pe;g.setAttribute("position",new de(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new Se(g,f),m=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=Fl;let u=this.type;this.render=function(R,A,U){if(m.enabled===!1||m.autoUpdate===!1&&m.needsUpdate===!1||R.length===0)return;const S=i.getRenderTarget(),M=i.getActiveCubeFace(),D=i.getActiveMipmapLevel(),W=i.state;W.setBlending(bn),W.buffers.color.setClear(1,1,1,1),W.buffers.depth.setTest(!0),W.setScissorTest(!1);const z=u!==yn&&this.type===yn,V=u===yn&&this.type!==yn;for(let $=0,G=R.length;$h||s.y>h)&&(s.x>h&&(r.x=Math.floor(h/it.x),s.x=r.x*it.x,k.mapSize.x=r.x),s.y>h&&(r.y=Math.floor(h/it.y),s.y=r.y*it.y,k.mapSize.y=r.y)),k.map===null||z===!0||V===!0){const yt=this.type!==yn?{minFilter:qe,magFilter:qe}:{};k.map!==null&&k.map.dispose(),k.map=new on(s.x,s.y,yt),k.map.texture.name=J.name+".shadowMap",k.camera.updateProjectionMatrix()}i.setRenderTarget(k.map),i.clear();const ut=k.getViewportCount();for(let yt=0;yt0||A.map&&A.alphaTest>0){const W=M.uuid,z=A.uuid;let V=c[W];V===void 0&&(V={},c[W]=V);let $=V[z];$===void 0&&($=M.clone(),V[z]=$,A.addEventListener("dispose",L)),M=$}if(M.visible=A.visible,M.wireframe=A.wireframe,S===yn?M.side=A.shadowSide!==null?A.shadowSide:A.side:M.side=A.shadowSide!==null?A.shadowSide:d[A.side],M.alphaMap=A.alphaMap,M.alphaTest=A.alphaTest,M.map=A.map,M.clipShadows=A.clipShadows,M.clippingPlanes=A.clippingPlanes,M.clipIntersection=A.clipIntersection,M.displacementMap=A.displacementMap,M.displacementScale=A.displacementScale,M.displacementBias=A.displacementBias,M.wireframeLinewidth=A.wireframeLinewidth,M.linewidth=A.linewidth,U.isPointLight===!0&&M.isMeshDistanceMaterial===!0){const W=i.properties.get(M);W.light=U}return M}function y(R,A,U,S,M){if(R.visible===!1)return;if(R.layers.test(A.layers)&&(R.isMesh||R.isLine||R.isPoints)&&(R.castShadow||R.receiveShadow&&M===yn)&&(!R.frustumCulled||n.intersectsObject(R))){R.modelViewMatrix.multiplyMatrices(U.matrixWorldInverse,R.matrixWorld);const z=t.update(R),V=R.material;if(Array.isArray(V)){const $=z.groups;for(let G=0,J=$.length;G=1):k.indexOf("OpenGL ES")!==-1&&(J=parseFloat(/^OpenGL ES (\d)/.exec(k)[1]),G=J>=2);let it=null,ut={};const yt=i.getParameter(i.SCISSOR_BOX),Lt=i.getParameter(i.VIEWPORT),qt=new le().fromArray(yt),Y=new le().fromArray(Lt);function nt(C,et,H,q){const lt=new Uint8Array(4),ct=i.createTexture();i.bindTexture(C,ct),i.texParameteri(C,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(C,i.TEXTURE_MAG_FILTER,i.NEAREST);for(let Nt=0;Nt"u"?!1:/OculusBrowser/g.test(navigator.userAgent),c=new vt,h=new WeakMap;let d;const f=new WeakMap;let p=!1;try{p=typeof OffscreenCanvas<"u"&&new OffscreenCanvas(1,1).getContext("2d")!==null}catch{}function g(E,_){return p?new OffscreenCanvas(E,_):nr("canvas")}function v(E,_,F){let Z=1;const K=Et(E);if((K.width>F||K.height>F)&&(Z=F/Math.max(K.width,K.height)),Z<1)if(typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&E instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&E instanceof ImageBitmap||typeof VideoFrame<"u"&&E instanceof VideoFrame){const X=Math.floor(Z*K.width),St=Math.floor(Z*K.height);d===void 0&&(d=g(X,St));const ot=_?g(X,St):d;return ot.width=X,ot.height=St,ot.getContext("2d").drawImage(E,0,0,X,St),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+K.width+"x"+K.height+") to ("+X+"x"+St+")."),ot}else return"data"in E&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+K.width+"x"+K.height+")."),E;return E}function m(E){return E.generateMipmaps}function u(E){i.generateMipmap(E)}function T(E){return E.isWebGLCubeRenderTarget?i.TEXTURE_CUBE_MAP:E.isWebGL3DRenderTarget?i.TEXTURE_3D:E.isWebGLArrayRenderTarget||E.isCompressedArrayTexture?i.TEXTURE_2D_ARRAY:i.TEXTURE_2D}function b(E,_,F,Z,K=!1){if(E!==null){if(i[E]!==void 0)return i[E];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+E+"'")}let X=_;if(_===i.RED&&(F===i.FLOAT&&(X=i.R32F),F===i.HALF_FLOAT&&(X=i.R16F),F===i.UNSIGNED_BYTE&&(X=i.R8)),_===i.RED_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.R8UI),F===i.UNSIGNED_SHORT&&(X=i.R16UI),F===i.UNSIGNED_INT&&(X=i.R32UI),F===i.BYTE&&(X=i.R8I),F===i.SHORT&&(X=i.R16I),F===i.INT&&(X=i.R32I)),_===i.RG&&(F===i.FLOAT&&(X=i.RG32F),F===i.HALF_FLOAT&&(X=i.RG16F),F===i.UNSIGNED_BYTE&&(X=i.RG8)),_===i.RG_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RG8UI),F===i.UNSIGNED_SHORT&&(X=i.RG16UI),F===i.UNSIGNED_INT&&(X=i.RG32UI),F===i.BYTE&&(X=i.RG8I),F===i.SHORT&&(X=i.RG16I),F===i.INT&&(X=i.RG32I)),_===i.RGB_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RGB8UI),F===i.UNSIGNED_SHORT&&(X=i.RGB16UI),F===i.UNSIGNED_INT&&(X=i.RGB32UI),F===i.BYTE&&(X=i.RGB8I),F===i.SHORT&&(X=i.RGB16I),F===i.INT&&(X=i.RGB32I)),_===i.RGBA_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RGBA8UI),F===i.UNSIGNED_SHORT&&(X=i.RGBA16UI),F===i.UNSIGNED_INT&&(X=i.RGBA32UI),F===i.BYTE&&(X=i.RGBA8I),F===i.SHORT&&(X=i.RGBA16I),F===i.INT&&(X=i.RGBA32I)),_===i.RGB&&F===i.UNSIGNED_INT_5_9_9_9_REV&&(X=i.RGB9_E5),_===i.RGBA){const St=K?tr:$t.getTransfer(Z);F===i.FLOAT&&(X=i.RGBA32F),F===i.HALF_FLOAT&&(X=i.RGBA16F),F===i.UNSIGNED_BYTE&&(X=St===re?i.SRGB8_ALPHA8:i.RGBA8),F===i.UNSIGNED_SHORT_4_4_4_4&&(X=i.RGBA4),F===i.UNSIGNED_SHORT_5_5_5_1&&(X=i.RGB5_A1)}return(X===i.R16F||X===i.R32F||X===i.RG16F||X===i.RG32F||X===i.RGBA16F||X===i.RGBA32F)&&t.get("EXT_color_buffer_float"),X}function y(E,_){let F;return E?_===null||_===ei||_===zi?F=i.DEPTH24_STENCIL8:_===fn?F=i.DEPTH32F_STENCIL8:_===os&&(F=i.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):_===null||_===ei||_===zi?F=i.DEPTH_COMPONENT24:_===fn?F=i.DEPTH_COMPONENT32F:_===os&&(F=i.DEPTH_COMPONENT16),F}function L(E,_){return m(E)===!0||E.isFramebufferTexture&&E.minFilter!==qe&&E.minFilter!==dn?Math.log2(Math.max(_.width,_.height))+1:E.mipmaps!==void 0&&E.mipmaps.length>0?E.mipmaps.length:E.isCompressedTexture&&Array.isArray(E.image)?_.mipmaps.length:1}function R(E){const _=E.target;_.removeEventListener("dispose",R),U(_),_.isVideoTexture&&h.delete(_)}function A(E){const _=E.target;_.removeEventListener("dispose",A),M(_)}function U(E){const _=n.get(E);if(_.__webglInit===void 0)return;const F=E.source,Z=f.get(F);if(Z){const K=Z[_.__cacheKey];K.usedTimes--,K.usedTimes===0&&S(E),Object.keys(Z).length===0&&f.delete(F)}n.remove(E)}function S(E){const _=n.get(E);i.deleteTexture(_.__webglTexture);const F=E.source,Z=f.get(F);delete Z[_.__cacheKey],a.memory.textures--}function M(E){const _=n.get(E);if(E.depthTexture&&(E.depthTexture.dispose(),n.remove(E.depthTexture)),E.isWebGLCubeRenderTarget)for(let Z=0;Z<6;Z++){if(Array.isArray(_.__webglFramebuffer[Z]))for(let K=0;K<_.__webglFramebuffer[Z].length;K++)i.deleteFramebuffer(_.__webglFramebuffer[Z][K]);else i.deleteFramebuffer(_.__webglFramebuffer[Z]);_.__webglDepthbuffer&&i.deleteRenderbuffer(_.__webglDepthbuffer[Z])}else{if(Array.isArray(_.__webglFramebuffer))for(let Z=0;Z<_.__webglFramebuffer.length;Z++)i.deleteFramebuffer(_.__webglFramebuffer[Z]);else i.deleteFramebuffer(_.__webglFramebuffer);if(_.__webglDepthbuffer&&i.deleteRenderbuffer(_.__webglDepthbuffer),_.__webglMultisampledFramebuffer&&i.deleteFramebuffer(_.__webglMultisampledFramebuffer),_.__webglColorRenderbuffer)for(let Z=0;Z<_.__webglColorRenderbuffer.length;Z++)_.__webglColorRenderbuffer[Z]&&i.deleteRenderbuffer(_.__webglColorRenderbuffer[Z]);_.__webglDepthRenderbuffer&&i.deleteRenderbuffer(_.__webglDepthRenderbuffer)}const F=E.textures;for(let Z=0,K=F.length;Z=s.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+E+" texture units while this GPU supports only "+s.maxTextures),D+=1,E}function V(E){const _=[];return _.push(E.wrapS),_.push(E.wrapT),_.push(E.wrapR||0),_.push(E.magFilter),_.push(E.minFilter),_.push(E.anisotropy),_.push(E.internalFormat),_.push(E.format),_.push(E.type),_.push(E.generateMipmaps),_.push(E.premultiplyAlpha),_.push(E.flipY),_.push(E.unpackAlignment),_.push(E.colorSpace),_.join()}function $(E,_){const F=n.get(E);if(E.isVideoTexture&&Mt(E),E.isRenderTargetTexture===!1&&E.version>0&&F.__version!==E.version){const Z=E.image;if(Z===null)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else if(Z.complete===!1)console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");else{Y(F,E,_);return}}e.bindTexture(i.TEXTURE_2D,F.__webglTexture,i.TEXTURE0+_)}function G(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){Y(F,E,_);return}e.bindTexture(i.TEXTURE_2D_ARRAY,F.__webglTexture,i.TEXTURE0+_)}function J(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){Y(F,E,_);return}e.bindTexture(i.TEXTURE_3D,F.__webglTexture,i.TEXTURE0+_)}function k(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){nt(F,E,_);return}e.bindTexture(i.TEXTURE_CUBE_MAP,F.__webglTexture,i.TEXTURE0+_)}const it={[ha]:i.REPEAT,[Jn]:i.CLAMP_TO_EDGE,[ua]:i.MIRRORED_REPEAT},ut={[qe]:i.NEAREST,[hh]:i.NEAREST_MIPMAP_NEAREST,[ms]:i.NEAREST_MIPMAP_LINEAR,[dn]:i.LINEAR,[gr]:i.LINEAR_MIPMAP_NEAREST,[Qn]:i.LINEAR_MIPMAP_LINEAR},yt={[ph]:i.NEVER,[Mh]:i.ALWAYS,[mh]:i.LESS,[Kl]:i.LEQUAL,[gh]:i.EQUAL,[xh]:i.GEQUAL,[_h]:i.GREATER,[vh]:i.NOTEQUAL};function Lt(E,_){if(_.type===fn&&t.has("OES_texture_float_linear")===!1&&(_.magFilter===dn||_.magFilter===gr||_.magFilter===ms||_.magFilter===Qn||_.minFilter===dn||_.minFilter===gr||_.minFilter===ms||_.minFilter===Qn)&&console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),i.texParameteri(E,i.TEXTURE_WRAP_S,it[_.wrapS]),i.texParameteri(E,i.TEXTURE_WRAP_T,it[_.wrapT]),(E===i.TEXTURE_3D||E===i.TEXTURE_2D_ARRAY)&&i.texParameteri(E,i.TEXTURE_WRAP_R,it[_.wrapR]),i.texParameteri(E,i.TEXTURE_MAG_FILTER,ut[_.magFilter]),i.texParameteri(E,i.TEXTURE_MIN_FILTER,ut[_.minFilter]),_.compareFunction&&(i.texParameteri(E,i.TEXTURE_COMPARE_MODE,i.COMPARE_REF_TO_TEXTURE),i.texParameteri(E,i.TEXTURE_COMPARE_FUNC,yt[_.compareFunction])),t.has("EXT_texture_filter_anisotropic")===!0){if(_.magFilter===qe||_.minFilter!==ms&&_.minFilter!==Qn||_.type===fn&&t.has("OES_texture_float_linear")===!1)return;if(_.anisotropy>1||n.get(_).__currentAnisotropy){const F=t.get("EXT_texture_filter_anisotropic");i.texParameterf(E,F.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(_.anisotropy,s.getMaxAnisotropy())),n.get(_).__currentAnisotropy=_.anisotropy}}}function qt(E,_){let F=!1;E.__webglInit===void 0&&(E.__webglInit=!0,_.addEventListener("dispose",R));const Z=_.source;let K=f.get(Z);K===void 0&&(K={},f.set(Z,K));const X=V(_);if(X!==E.__cacheKey){K[X]===void 0&&(K[X]={texture:i.createTexture(),usedTimes:0},a.memory.textures++,F=!0),K[X].usedTimes++;const St=K[E.__cacheKey];St!==void 0&&(K[E.__cacheKey].usedTimes--,St.usedTimes===0&&S(_)),E.__cacheKey=X,E.__webglTexture=K[X].texture}return F}function Y(E,_,F){let Z=i.TEXTURE_2D;(_.isDataArrayTexture||_.isCompressedArrayTexture)&&(Z=i.TEXTURE_2D_ARRAY),_.isData3DTexture&&(Z=i.TEXTURE_3D);const K=qt(E,_),X=_.source;e.bindTexture(Z,E.__webglTexture,i.TEXTURE0+F);const St=n.get(X);if(X.version!==St.__version||K===!0){e.activeTexture(i.TEXTURE0+F);const ot=$t.getPrimaries($t.workingColorSpace),dt=_.colorSpace===Fn?null:$t.getPrimaries(_.colorSpace),jt=_.colorSpace===Fn||ot===dt?i.NONE:i.BROWSER_DEFAULT_WEBGL;i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,_.flipY),i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL,_.premultiplyAlpha),i.pixelStorei(i.UNPACK_ALIGNMENT,_.unpackAlignment),i.pixelStorei(i.UNPACK_COLORSPACE_CONVERSION_WEBGL,jt);let tt=v(_.image,!1,s.maxTextureSize);tt=ne(_,tt);const mt=r.convert(_.format,_.colorSpace),bt=r.convert(_.type);let Pt=b(_.internalFormat,mt,bt,_.colorSpace,_.isVideoTexture);Lt(Z,_);let ft;const Xt=_.mipmaps,zt=_.isVideoTexture!==!0,ie=St.__version===void 0||K===!0,C=X.dataReady,et=L(_,tt);if(_.isDepthTexture)Pt=y(_.format===Hi,_.type),ie&&(zt?e.texStorage2D(i.TEXTURE_2D,1,Pt,tt.width,tt.height):e.texImage2D(i.TEXTURE_2D,0,Pt,tt.width,tt.height,0,mt,bt,null));else if(_.isDataTexture)if(Xt.length>0){zt&&ie&&e.texStorage2D(i.TEXTURE_2D,et,Pt,Xt[0].width,Xt[0].height);for(let H=0,q=Xt.length;H0){const lt=$o(ft.width,ft.height,_.format,_.type);for(const ct of _.layerUpdates){const Nt=ft.data.subarray(ct*lt/ft.data.BYTES_PER_ELEMENT,(ct+1)*lt/ft.data.BYTES_PER_ELEMENT);e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,ct,ft.width,ft.height,1,mt,Nt)}_.clearLayerUpdates()}else e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,ft.width,ft.height,tt.depth,mt,ft.data)}else e.compressedTexImage3D(i.TEXTURE_2D_ARRAY,H,Pt,ft.width,ft.height,tt.depth,0,ft.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else zt?C&&e.texSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,ft.width,ft.height,tt.depth,mt,bt,ft.data):e.texImage3D(i.TEXTURE_2D_ARRAY,H,Pt,ft.width,ft.height,tt.depth,0,mt,bt,ft.data)}else{zt&&ie&&e.texStorage2D(i.TEXTURE_2D,et,Pt,Xt[0].width,Xt[0].height);for(let H=0,q=Xt.length;H0){const H=$o(tt.width,tt.height,_.format,_.type);for(const q of _.layerUpdates){const lt=tt.data.subarray(q*H/tt.data.BYTES_PER_ELEMENT,(q+1)*H/tt.data.BYTES_PER_ELEMENT);e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,q,tt.width,tt.height,1,mt,bt,lt)}_.clearLayerUpdates()}else e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,0,tt.width,tt.height,tt.depth,mt,bt,tt.data)}else e.texImage3D(i.TEXTURE_2D_ARRAY,0,Pt,tt.width,tt.height,tt.depth,0,mt,bt,tt.data);else if(_.isData3DTexture)zt?(ie&&e.texStorage3D(i.TEXTURE_3D,et,Pt,tt.width,tt.height,tt.depth),C&&e.texSubImage3D(i.TEXTURE_3D,0,0,0,0,tt.width,tt.height,tt.depth,mt,bt,tt.data)):e.texImage3D(i.TEXTURE_3D,0,Pt,tt.width,tt.height,tt.depth,0,mt,bt,tt.data);else if(_.isFramebufferTexture){if(ie)if(zt)e.texStorage2D(i.TEXTURE_2D,et,Pt,tt.width,tt.height);else{let H=tt.width,q=tt.height;for(let lt=0;lt>=1,q>>=1}}else if(Xt.length>0){if(zt&&ie){const H=Et(Xt[0]);e.texStorage2D(i.TEXTURE_2D,et,Pt,H.width,H.height)}for(let H=0,q=Xt.length;H0&&et++;const q=Et(mt[0]);e.texStorage2D(i.TEXTURE_CUBE_MAP,et,Xt,q.width,q.height)}for(let q=0;q<6;q++)if(tt){zt?C&&e.texSubImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+q,0,0,0,mt[q].width,mt[q].height,Pt,ft,mt[q].data):e.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+q,0,Xt,mt[q].width,mt[q].height,0,Pt,ft,mt[q].data);for(let lt=0;lt>X),bt=Math.max(1,_.height>>X);K===i.TEXTURE_3D||K===i.TEXTURE_2D_ARRAY?e.texImage3D(K,X,dt,mt,bt,_.depth,0,St,ot,null):e.texImage2D(K,X,dt,mt,bt,0,St,ot,null)}e.bindFramebuffer(i.FRAMEBUFFER,E),kt(_)?o.framebufferTexture2DMultisampleEXT(i.FRAMEBUFFER,Z,K,tt.__webglTexture,0,Bt(_)):(K===i.TEXTURE_2D||K>=i.TEXTURE_CUBE_MAP_POSITIVE_X&&K<=i.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&i.framebufferTexture2D(i.FRAMEBUFFER,Z,K,tt.__webglTexture,X),e.bindFramebuffer(i.FRAMEBUFFER,null)}function at(E,_,F){if(i.bindRenderbuffer(i.RENDERBUFFER,E),_.depthBuffer){const Z=_.depthTexture,K=Z&&Z.isDepthTexture?Z.type:null,X=y(_.stencilBuffer,K),St=_.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,ot=Bt(_);kt(_)?o.renderbufferStorageMultisampleEXT(i.RENDERBUFFER,ot,X,_.width,_.height):F?i.renderbufferStorageMultisample(i.RENDERBUFFER,ot,X,_.width,_.height):i.renderbufferStorage(i.RENDERBUFFER,X,_.width,_.height),i.framebufferRenderbuffer(i.FRAMEBUFFER,St,i.RENDERBUFFER,E)}else{const Z=_.textures;for(let K=0;K{delete _.__boundDepthTexture,delete _.__depthDisposeCallback,Z.removeEventListener("dispose",K)};Z.addEventListener("dispose",K),_.__depthDisposeCallback=K}_.__boundDepthTexture=Z}if(E.depthTexture&&!_.__autoAllocateDepthBuffer){if(F)throw new Error("target.depthTexture not supported in Cube render targets");wt(_.__webglFramebuffer,E)}else if(F){_.__webglDepthbuffer=[];for(let Z=0;Z<6;Z++)if(e.bindFramebuffer(i.FRAMEBUFFER,_.__webglFramebuffer[Z]),_.__webglDepthbuffer[Z]===void 0)_.__webglDepthbuffer[Z]=i.createRenderbuffer(),at(_.__webglDepthbuffer[Z],E,!1);else{const K=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,X=_.__webglDepthbuffer[Z];i.bindRenderbuffer(i.RENDERBUFFER,X),i.framebufferRenderbuffer(i.FRAMEBUFFER,K,i.RENDERBUFFER,X)}}else if(e.bindFramebuffer(i.FRAMEBUFFER,_.__webglFramebuffer),_.__webglDepthbuffer===void 0)_.__webglDepthbuffer=i.createRenderbuffer(),at(_.__webglDepthbuffer,E,!1);else{const Z=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,K=_.__webglDepthbuffer;i.bindRenderbuffer(i.RENDERBUFFER,K),i.framebufferRenderbuffer(i.FRAMEBUFFER,Z,i.RENDERBUFFER,K)}e.bindFramebuffer(i.FRAMEBUFFER,null)}function Gt(E,_,F){const Z=n.get(E);_!==void 0&&xt(Z.__webglFramebuffer,E,E.texture,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,0),F!==void 0&&Ut(E)}function ce(E){const _=E.texture,F=n.get(E),Z=n.get(_);E.addEventListener("dispose",A);const K=E.textures,X=E.isWebGLCubeRenderTarget===!0,St=K.length>1;if(St||(Z.__webglTexture===void 0&&(Z.__webglTexture=i.createTexture()),Z.__version=_.version,a.memory.textures++),X){F.__webglFramebuffer=[];for(let ot=0;ot<6;ot++)if(_.mipmaps&&_.mipmaps.length>0){F.__webglFramebuffer[ot]=[];for(let dt=0;dt<_.mipmaps.length;dt++)F.__webglFramebuffer[ot][dt]=i.createFramebuffer()}else F.__webglFramebuffer[ot]=i.createFramebuffer()}else{if(_.mipmaps&&_.mipmaps.length>0){F.__webglFramebuffer=[];for(let ot=0;ot<_.mipmaps.length;ot++)F.__webglFramebuffer[ot]=i.createFramebuffer()}else F.__webglFramebuffer=i.createFramebuffer();if(St)for(let ot=0,dt=K.length;ot0&&kt(E)===!1){F.__webglMultisampledFramebuffer=i.createFramebuffer(),F.__webglColorRenderbuffer=[],e.bindFramebuffer(i.FRAMEBUFFER,F.__webglMultisampledFramebuffer);for(let ot=0;ot0)for(let dt=0;dt<_.mipmaps.length;dt++)xt(F.__webglFramebuffer[ot][dt],E,_,i.COLOR_ATTACHMENT0,i.TEXTURE_CUBE_MAP_POSITIVE_X+ot,dt);else xt(F.__webglFramebuffer[ot],E,_,i.COLOR_ATTACHMENT0,i.TEXTURE_CUBE_MAP_POSITIVE_X+ot,0);m(_)&&u(i.TEXTURE_CUBE_MAP),e.unbindTexture()}else if(St){for(let ot=0,dt=K.length;ot0)for(let dt=0;dt<_.mipmaps.length;dt++)xt(F.__webglFramebuffer[dt],E,_,i.COLOR_ATTACHMENT0,ot,dt);else xt(F.__webglFramebuffer,E,_,i.COLOR_ATTACHMENT0,ot,0);m(_)&&u(ot),e.unbindTexture()}E.depthBuffer&&Ut(E)}function rt(E){const _=E.textures;for(let F=0,Z=_.length;F0){if(kt(E)===!1){const _=E.textures,F=E.width,Z=E.height;let K=i.COLOR_BUFFER_BIT;const X=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,St=n.get(E),ot=_.length>1;if(ot)for(let dt=0;dt<_.length;dt++)e.bindFramebuffer(i.FRAMEBUFFER,St.__webglMultisampledFramebuffer),i.framebufferRenderbuffer(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.RENDERBUFFER,null),e.bindFramebuffer(i.FRAMEBUFFER,St.__webglFramebuffer),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.TEXTURE_2D,null,0);e.bindFramebuffer(i.READ_FRAMEBUFFER,St.__webglMultisampledFramebuffer),e.bindFramebuffer(i.DRAW_FRAMEBUFFER,St.__webglFramebuffer);for(let dt=0;dt<_.length;dt++){if(E.resolveDepthBuffer&&(E.depthBuffer&&(K|=i.DEPTH_BUFFER_BIT),E.stencilBuffer&&E.resolveStencilBuffer&&(K|=i.STENCIL_BUFFER_BIT)),ot){i.framebufferRenderbuffer(i.READ_FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.RENDERBUFFER,St.__webglColorRenderbuffer[dt]);const jt=n.get(_[dt]).__webglTexture;i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,jt,0)}i.blitFramebuffer(0,0,F,Z,0,0,F,Z,K,i.NEAREST),l===!0&&(Ct.length=0,w.length=0,Ct.push(i.COLOR_ATTACHMENT0+dt),E.depthBuffer&&E.resolveDepthBuffer===!1&&(Ct.push(X),w.push(X),i.invalidateFramebuffer(i.DRAW_FRAMEBUFFER,w)),i.invalidateFramebuffer(i.READ_FRAMEBUFFER,Ct))}if(e.bindFramebuffer(i.READ_FRAMEBUFFER,null),e.bindFramebuffer(i.DRAW_FRAMEBUFFER,null),ot)for(let dt=0;dt<_.length;dt++){e.bindFramebuffer(i.FRAMEBUFFER,St.__webglMultisampledFramebuffer),i.framebufferRenderbuffer(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.RENDERBUFFER,St.__webglColorRenderbuffer[dt]);const jt=n.get(_[dt]).__webglTexture;e.bindFramebuffer(i.FRAMEBUFFER,St.__webglFramebuffer),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.TEXTURE_2D,jt,0)}e.bindFramebuffer(i.DRAW_FRAMEBUFFER,St.__webglMultisampledFramebuffer)}else if(E.depthBuffer&&E.resolveDepthBuffer===!1&&l){const _=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT;i.invalidateFramebuffer(i.DRAW_FRAMEBUFFER,[_])}}}function Bt(E){return Math.min(s.maxSamples,E.samples)}function kt(E){const _=n.get(E);return E.samples>0&&t.has("WEBGL_multisampled_render_to_texture")===!0&&_.__useRenderToTexture!==!1}function Mt(E){const _=a.render.frame;h.get(E)!==_&&(h.set(E,_),E.update())}function ne(E,_){const F=E.colorSpace,Z=E.format,K=E.type;return E.isCompressedTexture===!0||E.isVideoTexture===!0||F!==ki&&F!==Fn&&($t.getTransfer(F)===re?(Z!==an||K!==An)&&console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",F)),_}function Et(E){return typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement?(c.width=E.naturalWidth||E.width,c.height=E.naturalHeight||E.height):typeof VideoFrame<"u"&&E instanceof VideoFrame?(c.width=E.displayWidth,c.height=E.displayHeight):(c.width=E.width,c.height=E.height),c}this.allocateTextureUnit=z,this.resetTextureUnits=W,this.setTexture2D=$,this.setTexture2DArray=G,this.setTexture3D=J,this.setTextureCube=k,this.rebindTextures=Gt,this.setupRenderTarget=ce,this.updateRenderTargetMipmap=rt,this.updateMultisampleRenderTarget=ve,this.setupDepthRenderbuffer=Ut,this.setupFrameBufferTexture=xt,this.useMultisampledRTT=kt}function Hm(i,t){function e(n,s=Fn){let r;const a=$t.getTransfer(s);if(n===An)return i.UNSIGNED_BYTE;if(n===qa)return i.UNSIGNED_SHORT_4_4_4_4;if(n===ja)return i.UNSIGNED_SHORT_5_5_5_1;if(n===Vl)return i.UNSIGNED_INT_5_9_9_9_REV;if(n===Hl)return i.BYTE;if(n===kl)return i.SHORT;if(n===os)return i.UNSIGNED_SHORT;if(n===Ya)return i.INT;if(n===ei)return i.UNSIGNED_INT;if(n===fn)return i.FLOAT;if(n===Tn)return i.HALF_FLOAT;if(n===Gl)return i.ALPHA;if(n===Wl)return i.RGB;if(n===an)return i.RGBA;if(n===Xl)return i.LUMINANCE;if(n===Yl)return i.LUMINANCE_ALPHA;if(n===Ui)return i.DEPTH_COMPONENT;if(n===Hi)return i.DEPTH_STENCIL;if(n===Za)return i.RED;if(n===Ka)return i.RED_INTEGER;if(n===ql)return i.RG;if(n===$a)return i.RG_INTEGER;if(n===Ja)return i.RGBA_INTEGER;if(n===Xs||n===Ys||n===qs||n===js)if(a===re)if(r=t.get("WEBGL_compressed_texture_s3tc_srgb"),r!==null){if(n===Xs)return r.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===Ys)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===qs)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===js)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null;else if(r=t.get("WEBGL_compressed_texture_s3tc"),r!==null){if(n===Xs)return r.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===Ys)return r.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===qs)return r.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===js)return r.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null;if(n===da||n===fa||n===pa||n===ma)if(r=t.get("WEBGL_compressed_texture_pvrtc"),r!==null){if(n===da)return r.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===fa)return r.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===pa)return r.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===ma)return r.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null;if(n===ga||n===_a||n===va)if(r=t.get("WEBGL_compressed_texture_etc"),r!==null){if(n===ga||n===_a)return a===re?r.COMPRESSED_SRGB8_ETC2:r.COMPRESSED_RGB8_ETC2;if(n===va)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:r.COMPRESSED_RGBA8_ETC2_EAC}else return null;if(n===xa||n===Ma||n===Sa||n===ya||n===Ea||n===ba||n===Ta||n===wa||n===Aa||n===Ra||n===Ca||n===Pa||n===Da||n===La)if(r=t.get("WEBGL_compressed_texture_astc"),r!==null){if(n===xa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:r.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===Ma)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:r.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===Sa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:r.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===ya)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:r.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===Ea)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:r.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===ba)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:r.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===Ta)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:r.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===wa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:r.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===Aa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:r.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===Ra)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:r.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===Ca)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:r.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===Pa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:r.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===Da)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:r.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===La)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:r.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null;if(n===Zs||n===Ua||n===Ia)if(r=t.get("EXT_texture_compression_bptc"),r!==null){if(n===Zs)return a===re?r.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:r.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===Ua)return r.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===Ia)return r.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null;if(n===jl||n===Na||n===Fa||n===Oa)if(r=t.get("EXT_texture_compression_rgtc"),r!==null){if(n===Zs)return r.COMPRESSED_RED_RGTC1_EXT;if(n===Na)return r.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===Fa)return r.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===Oa)return r.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null;return n===zi?i.UNSIGNED_INT_24_8:i[n]!==void 0?i[n]:null}return{convert:e}}const km={type:"move"};class Zr{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new Ci,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new Ci,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new P,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new P),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new Ci,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new P,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new P),this._grip}dispatchEvent(t){return this._targetRay!==null&&this._targetRay.dispatchEvent(t),this._grip!==null&&this._grip.dispatchEvent(t),this._hand!==null&&this._hand.dispatchEvent(t),this}connect(t){if(t&&t.hand){const e=this._hand;if(e)for(const n of t.hand.values())this._getHandJoint(e,n)}return this.dispatchEvent({type:"connected",data:t}),this}disconnect(t){return this.dispatchEvent({type:"disconnected",data:t}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(t,e,n){let s=null,r=null,a=null;const o=this._targetRay,l=this._grip,c=this._hand;if(t&&e.session.visibilityState!=="visible-blurred"){if(c&&t.hand){a=!0;for(const v of t.hand.values()){const m=e.getJointPose(v,n),u=this._getHandJoint(c,v);m!==null&&(u.matrix.fromArray(m.transform.matrix),u.matrix.decompose(u.position,u.rotation,u.scale),u.matrixWorldNeedsUpdate=!0,u.jointRadius=m.radius),u.visible=m!==null}const h=c.joints["index-finger-tip"],d=c.joints["thumb-tip"],f=h.position.distanceTo(d.position),p=.02,g=.005;c.inputState.pinching&&f>p+g?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!c.inputState.pinching&&f<=p-g&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else l!==null&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),r!==null&&(l.matrix.fromArray(r.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,r.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(r.linearVelocity)):l.hasLinearVelocity=!1,r.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(r.angularVelocity)):l.hasAngularVelocity=!1));o!==null&&(s=e.getPose(t.targetRaySpace,n),s===null&&r!==null&&(s=r),s!==null&&(o.matrix.fromArray(s.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,s.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(s.linearVelocity)):o.hasLinearVelocity=!1,s.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(s.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(km)))}return o!==null&&(o.visible=s!==null),l!==null&&(l.visible=r!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(t,e){if(t.joints[e.jointName]===void 0){const n=new Ci;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}const Vm=` +}`;function Om(i,t,e){let n=new eo;const s=new vt,r=new vt,a=new le,o=new su({depthPacking:ph}),l=new ru,c={},h=e.maxTextureSize,d={[zn]:ke,[ke]:zn,[hn]:hn},p=new Fe({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new vt},radius:{value:4}},vertexShader:Nm,fragmentShader:Fm}),f=p.clone();f.defines.HORIZONTAL_PASS=1;const g=new pe;g.setAttribute("position",new he(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new Se(g,p),m=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=Ol;let u=this.type;this.render=function(R,A,U){if(m.enabled===!1||m.autoUpdate===!1&&m.needsUpdate===!1||R.length===0)return;const S=i.getRenderTarget(),M=i.getActiveCubeFace(),D=i.getActiveMipmapLevel(),W=i.state;W.setBlending(bn),W.buffers.color.setClear(1,1,1,1),W.buffers.depth.setTest(!0),W.setScissorTest(!1);const z=u!==yn&&this.type===yn,V=u===yn&&this.type!==yn;for(let $=0,G=R.length;$h||s.y>h)&&(s.x>h&&(r.x=Math.floor(h/it.x),s.x=r.x*it.x,k.mapSize.x=r.x),s.y>h&&(r.y=Math.floor(h/it.y),s.y=r.y*it.y,k.mapSize.y=r.y)),k.map===null||z===!0||V===!0){const yt=this.type!==yn?{minFilter:qe,magFilter:qe}:{};k.map!==null&&k.map.dispose(),k.map=new on(s.x,s.y,yt),k.map.texture.name=J.name+".shadowMap",k.camera.updateProjectionMatrix()}i.setRenderTarget(k.map),i.clear();const ut=k.getViewportCount();for(let yt=0;yt0||A.map&&A.alphaTest>0){const W=M.uuid,z=A.uuid;let V=c[W];V===void 0&&(V={},c[W]=V);let $=V[z];$===void 0&&($=M.clone(),V[z]=$,A.addEventListener("dispose",L)),M=$}if(M.visible=A.visible,M.wireframe=A.wireframe,S===yn?M.side=A.shadowSide!==null?A.shadowSide:A.side:M.side=A.shadowSide!==null?A.shadowSide:d[A.side],M.alphaMap=A.alphaMap,M.alphaTest=A.alphaTest,M.map=A.map,M.clipShadows=A.clipShadows,M.clippingPlanes=A.clippingPlanes,M.clipIntersection=A.clipIntersection,M.displacementMap=A.displacementMap,M.displacementScale=A.displacementScale,M.displacementBias=A.displacementBias,M.wireframeLinewidth=A.wireframeLinewidth,M.linewidth=A.linewidth,U.isPointLight===!0&&M.isMeshDistanceMaterial===!0){const W=i.properties.get(M);W.light=U}return M}function y(R,A,U,S,M){if(R.visible===!1)return;if(R.layers.test(A.layers)&&(R.isMesh||R.isLine||R.isPoints)&&(R.castShadow||R.receiveShadow&&M===yn)&&(!R.frustumCulled||n.intersectsObject(R))){R.modelViewMatrix.multiplyMatrices(U.matrixWorldInverse,R.matrixWorld);const z=t.update(R),V=R.material;if(Array.isArray(V)){const $=z.groups;for(let G=0,J=$.length;G=1):k.indexOf("OpenGL ES")!==-1&&(J=parseFloat(/^OpenGL ES (\d)/.exec(k)[1]),G=J>=2);let it=null,ut={};const yt=i.getParameter(i.SCISSOR_BOX),Lt=i.getParameter(i.VIEWPORT),qt=new le().fromArray(yt),Y=new le().fromArray(Lt);function nt(C,et,H,q){const lt=new Uint8Array(4),ct=i.createTexture();i.bindTexture(C,ct),i.texParameteri(C,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(C,i.TEXTURE_MAG_FILTER,i.NEAREST);for(let Nt=0;Nt"u"?!1:/OculusBrowser/g.test(navigator.userAgent),c=new vt,h=new WeakMap;let d;const p=new WeakMap;let f=!1;try{f=typeof OffscreenCanvas<"u"&&new OffscreenCanvas(1,1).getContext("2d")!==null}catch{}function g(E,_){return f?new OffscreenCanvas(E,_):rr("canvas")}function v(E,_,F){let Z=1;const K=Et(E);if((K.width>F||K.height>F)&&(Z=F/Math.max(K.width,K.height)),Z<1)if(typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&E instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&E instanceof ImageBitmap||typeof VideoFrame<"u"&&E instanceof VideoFrame){const X=Math.floor(Z*K.width),St=Math.floor(Z*K.height);d===void 0&&(d=g(X,St));const ot=_?g(X,St):d;return ot.width=X,ot.height=St,ot.getContext("2d").drawImage(E,0,0,X,St),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+K.width+"x"+K.height+") to ("+X+"x"+St+")."),ot}else return"data"in E&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+K.width+"x"+K.height+")."),E;return E}function m(E){return E.generateMipmaps}function u(E){i.generateMipmap(E)}function T(E){return E.isWebGLCubeRenderTarget?i.TEXTURE_CUBE_MAP:E.isWebGL3DRenderTarget?i.TEXTURE_3D:E.isWebGLArrayRenderTarget||E.isCompressedArrayTexture?i.TEXTURE_2D_ARRAY:i.TEXTURE_2D}function b(E,_,F,Z,K=!1){if(E!==null){if(i[E]!==void 0)return i[E];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+E+"'")}let X=_;if(_===i.RED&&(F===i.FLOAT&&(X=i.R32F),F===i.HALF_FLOAT&&(X=i.R16F),F===i.UNSIGNED_BYTE&&(X=i.R8)),_===i.RED_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.R8UI),F===i.UNSIGNED_SHORT&&(X=i.R16UI),F===i.UNSIGNED_INT&&(X=i.R32UI),F===i.BYTE&&(X=i.R8I),F===i.SHORT&&(X=i.R16I),F===i.INT&&(X=i.R32I)),_===i.RG&&(F===i.FLOAT&&(X=i.RG32F),F===i.HALF_FLOAT&&(X=i.RG16F),F===i.UNSIGNED_BYTE&&(X=i.RG8)),_===i.RG_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RG8UI),F===i.UNSIGNED_SHORT&&(X=i.RG16UI),F===i.UNSIGNED_INT&&(X=i.RG32UI),F===i.BYTE&&(X=i.RG8I),F===i.SHORT&&(X=i.RG16I),F===i.INT&&(X=i.RG32I)),_===i.RGB_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RGB8UI),F===i.UNSIGNED_SHORT&&(X=i.RGB16UI),F===i.UNSIGNED_INT&&(X=i.RGB32UI),F===i.BYTE&&(X=i.RGB8I),F===i.SHORT&&(X=i.RGB16I),F===i.INT&&(X=i.RGB32I)),_===i.RGBA_INTEGER&&(F===i.UNSIGNED_BYTE&&(X=i.RGBA8UI),F===i.UNSIGNED_SHORT&&(X=i.RGBA16UI),F===i.UNSIGNED_INT&&(X=i.RGBA32UI),F===i.BYTE&&(X=i.RGBA8I),F===i.SHORT&&(X=i.RGBA16I),F===i.INT&&(X=i.RGBA32I)),_===i.RGB&&F===i.UNSIGNED_INT_5_9_9_9_REV&&(X=i.RGB9_E5),_===i.RGBA){const St=K?ir:$t.getTransfer(Z);F===i.FLOAT&&(X=i.RGBA32F),F===i.HALF_FLOAT&&(X=i.RGBA16F),F===i.UNSIGNED_BYTE&&(X=St===re?i.SRGB8_ALPHA8:i.RGBA8),F===i.UNSIGNED_SHORT_4_4_4_4&&(X=i.RGBA4),F===i.UNSIGNED_SHORT_5_5_5_1&&(X=i.RGB5_A1)}return(X===i.R16F||X===i.R32F||X===i.RG16F||X===i.RG32F||X===i.RGBA16F||X===i.RGBA32F)&&t.get("EXT_color_buffer_float"),X}function y(E,_){let F;return E?_===null||_===ni||_===Hi?F=i.DEPTH24_STENCIL8:_===fn?F=i.DEPTH32F_STENCIL8:_===ls&&(F=i.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):_===null||_===ni||_===Hi?F=i.DEPTH_COMPONENT24:_===fn?F=i.DEPTH_COMPONENT32F:_===ls&&(F=i.DEPTH_COMPONENT16),F}function L(E,_){return m(E)===!0||E.isFramebufferTexture&&E.minFilter!==qe&&E.minFilter!==dn?Math.log2(Math.max(_.width,_.height))+1:E.mipmaps!==void 0&&E.mipmaps.length>0?E.mipmaps.length:E.isCompressedTexture&&Array.isArray(E.image)?_.mipmaps.length:1}function R(E){const _=E.target;_.removeEventListener("dispose",R),U(_),_.isVideoTexture&&h.delete(_)}function A(E){const _=E.target;_.removeEventListener("dispose",A),M(_)}function U(E){const _=n.get(E);if(_.__webglInit===void 0)return;const F=E.source,Z=p.get(F);if(Z){const K=Z[_.__cacheKey];K.usedTimes--,K.usedTimes===0&&S(E),Object.keys(Z).length===0&&p.delete(F)}n.remove(E)}function S(E){const _=n.get(E);i.deleteTexture(_.__webglTexture);const F=E.source,Z=p.get(F);delete Z[_.__cacheKey],a.memory.textures--}function M(E){const _=n.get(E);if(E.depthTexture&&(E.depthTexture.dispose(),n.remove(E.depthTexture)),E.isWebGLCubeRenderTarget)for(let Z=0;Z<6;Z++){if(Array.isArray(_.__webglFramebuffer[Z]))for(let K=0;K<_.__webglFramebuffer[Z].length;K++)i.deleteFramebuffer(_.__webglFramebuffer[Z][K]);else i.deleteFramebuffer(_.__webglFramebuffer[Z]);_.__webglDepthbuffer&&i.deleteRenderbuffer(_.__webglDepthbuffer[Z])}else{if(Array.isArray(_.__webglFramebuffer))for(let Z=0;Z<_.__webglFramebuffer.length;Z++)i.deleteFramebuffer(_.__webglFramebuffer[Z]);else i.deleteFramebuffer(_.__webglFramebuffer);if(_.__webglDepthbuffer&&i.deleteRenderbuffer(_.__webglDepthbuffer),_.__webglMultisampledFramebuffer&&i.deleteFramebuffer(_.__webglMultisampledFramebuffer),_.__webglColorRenderbuffer)for(let Z=0;Z<_.__webglColorRenderbuffer.length;Z++)_.__webglColorRenderbuffer[Z]&&i.deleteRenderbuffer(_.__webglColorRenderbuffer[Z]);_.__webglDepthRenderbuffer&&i.deleteRenderbuffer(_.__webglDepthRenderbuffer)}const F=E.textures;for(let Z=0,K=F.length;Z=s.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+E+" texture units while this GPU supports only "+s.maxTextures),D+=1,E}function V(E){const _=[];return _.push(E.wrapS),_.push(E.wrapT),_.push(E.wrapR||0),_.push(E.magFilter),_.push(E.minFilter),_.push(E.anisotropy),_.push(E.internalFormat),_.push(E.format),_.push(E.type),_.push(E.generateMipmaps),_.push(E.premultiplyAlpha),_.push(E.flipY),_.push(E.unpackAlignment),_.push(E.colorSpace),_.join()}function $(E,_){const F=n.get(E);if(E.isVideoTexture&&Mt(E),E.isRenderTargetTexture===!1&&E.version>0&&F.__version!==E.version){const Z=E.image;if(Z===null)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else if(Z.complete===!1)console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");else{Y(F,E,_);return}}e.bindTexture(i.TEXTURE_2D,F.__webglTexture,i.TEXTURE0+_)}function G(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){Y(F,E,_);return}e.bindTexture(i.TEXTURE_2D_ARRAY,F.__webglTexture,i.TEXTURE0+_)}function J(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){Y(F,E,_);return}e.bindTexture(i.TEXTURE_3D,F.__webglTexture,i.TEXTURE0+_)}function k(E,_){const F=n.get(E);if(E.version>0&&F.__version!==E.version){nt(F,E,_);return}e.bindTexture(i.TEXTURE_CUBE_MAP,F.__webglTexture,i.TEXTURE0+_)}const it={[da]:i.REPEAT,[Jn]:i.CLAMP_TO_EDGE,[fa]:i.MIRRORED_REPEAT},ut={[qe]:i.NEAREST,[dh]:i.NEAREST_MIPMAP_NEAREST,[gs]:i.NEAREST_MIPMAP_LINEAR,[dn]:i.LINEAR,[xr]:i.LINEAR_MIPMAP_NEAREST,[Qn]:i.LINEAR_MIPMAP_LINEAR},yt={[gh]:i.NEVER,[yh]:i.ALWAYS,[_h]:i.LESS,[$l]:i.LEQUAL,[vh]:i.EQUAL,[Sh]:i.GEQUAL,[xh]:i.GREATER,[Mh]:i.NOTEQUAL};function Lt(E,_){if(_.type===fn&&t.has("OES_texture_float_linear")===!1&&(_.magFilter===dn||_.magFilter===xr||_.magFilter===gs||_.magFilter===Qn||_.minFilter===dn||_.minFilter===xr||_.minFilter===gs||_.minFilter===Qn)&&console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),i.texParameteri(E,i.TEXTURE_WRAP_S,it[_.wrapS]),i.texParameteri(E,i.TEXTURE_WRAP_T,it[_.wrapT]),(E===i.TEXTURE_3D||E===i.TEXTURE_2D_ARRAY)&&i.texParameteri(E,i.TEXTURE_WRAP_R,it[_.wrapR]),i.texParameteri(E,i.TEXTURE_MAG_FILTER,ut[_.magFilter]),i.texParameteri(E,i.TEXTURE_MIN_FILTER,ut[_.minFilter]),_.compareFunction&&(i.texParameteri(E,i.TEXTURE_COMPARE_MODE,i.COMPARE_REF_TO_TEXTURE),i.texParameteri(E,i.TEXTURE_COMPARE_FUNC,yt[_.compareFunction])),t.has("EXT_texture_filter_anisotropic")===!0){if(_.magFilter===qe||_.minFilter!==gs&&_.minFilter!==Qn||_.type===fn&&t.has("OES_texture_float_linear")===!1)return;if(_.anisotropy>1||n.get(_).__currentAnisotropy){const F=t.get("EXT_texture_filter_anisotropic");i.texParameterf(E,F.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(_.anisotropy,s.getMaxAnisotropy())),n.get(_).__currentAnisotropy=_.anisotropy}}}function qt(E,_){let F=!1;E.__webglInit===void 0&&(E.__webglInit=!0,_.addEventListener("dispose",R));const Z=_.source;let K=p.get(Z);K===void 0&&(K={},p.set(Z,K));const X=V(_);if(X!==E.__cacheKey){K[X]===void 0&&(K[X]={texture:i.createTexture(),usedTimes:0},a.memory.textures++,F=!0),K[X].usedTimes++;const St=K[E.__cacheKey];St!==void 0&&(K[E.__cacheKey].usedTimes--,St.usedTimes===0&&S(_)),E.__cacheKey=X,E.__webglTexture=K[X].texture}return F}function Y(E,_,F){let Z=i.TEXTURE_2D;(_.isDataArrayTexture||_.isCompressedArrayTexture)&&(Z=i.TEXTURE_2D_ARRAY),_.isData3DTexture&&(Z=i.TEXTURE_3D);const K=qt(E,_),X=_.source;e.bindTexture(Z,E.__webglTexture,i.TEXTURE0+F);const St=n.get(X);if(X.version!==St.__version||K===!0){e.activeTexture(i.TEXTURE0+F);const ot=$t.getPrimaries($t.workingColorSpace),dt=_.colorSpace===Fn?null:$t.getPrimaries(_.colorSpace),jt=_.colorSpace===Fn||ot===dt?i.NONE:i.BROWSER_DEFAULT_WEBGL;i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,_.flipY),i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL,_.premultiplyAlpha),i.pixelStorei(i.UNPACK_ALIGNMENT,_.unpackAlignment),i.pixelStorei(i.UNPACK_COLORSPACE_CONVERSION_WEBGL,jt);let tt=v(_.image,!1,s.maxTextureSize);tt=ne(_,tt);const mt=r.convert(_.format,_.colorSpace),bt=r.convert(_.type);let Pt=b(_.internalFormat,mt,bt,_.colorSpace,_.isVideoTexture);Lt(Z,_);let ft;const Xt=_.mipmaps,zt=_.isVideoTexture!==!0,se=St.__version===void 0||K===!0,C=X.dataReady,et=L(_,tt);if(_.isDepthTexture)Pt=y(_.format===ki,_.type),se&&(zt?e.texStorage2D(i.TEXTURE_2D,1,Pt,tt.width,tt.height):e.texImage2D(i.TEXTURE_2D,0,Pt,tt.width,tt.height,0,mt,bt,null));else if(_.isDataTexture)if(Xt.length>0){zt&&se&&e.texStorage2D(i.TEXTURE_2D,et,Pt,Xt[0].width,Xt[0].height);for(let H=0,q=Xt.length;H0){const lt=Jo(ft.width,ft.height,_.format,_.type);for(const ct of _.layerUpdates){const Nt=ft.data.subarray(ct*lt/ft.data.BYTES_PER_ELEMENT,(ct+1)*lt/ft.data.BYTES_PER_ELEMENT);e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,ct,ft.width,ft.height,1,mt,Nt)}_.clearLayerUpdates()}else e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,ft.width,ft.height,tt.depth,mt,ft.data)}else e.compressedTexImage3D(i.TEXTURE_2D_ARRAY,H,Pt,ft.width,ft.height,tt.depth,0,ft.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else zt?C&&e.texSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,ft.width,ft.height,tt.depth,mt,bt,ft.data):e.texImage3D(i.TEXTURE_2D_ARRAY,H,Pt,ft.width,ft.height,tt.depth,0,mt,bt,ft.data)}else{zt&&se&&e.texStorage2D(i.TEXTURE_2D,et,Pt,Xt[0].width,Xt[0].height);for(let H=0,q=Xt.length;H0){const H=Jo(tt.width,tt.height,_.format,_.type);for(const q of _.layerUpdates){const lt=tt.data.subarray(q*H/tt.data.BYTES_PER_ELEMENT,(q+1)*H/tt.data.BYTES_PER_ELEMENT);e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,q,tt.width,tt.height,1,mt,bt,lt)}_.clearLayerUpdates()}else e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,0,tt.width,tt.height,tt.depth,mt,bt,tt.data)}else e.texImage3D(i.TEXTURE_2D_ARRAY,0,Pt,tt.width,tt.height,tt.depth,0,mt,bt,tt.data);else if(_.isData3DTexture)zt?(se&&e.texStorage3D(i.TEXTURE_3D,et,Pt,tt.width,tt.height,tt.depth),C&&e.texSubImage3D(i.TEXTURE_3D,0,0,0,0,tt.width,tt.height,tt.depth,mt,bt,tt.data)):e.texImage3D(i.TEXTURE_3D,0,Pt,tt.width,tt.height,tt.depth,0,mt,bt,tt.data);else if(_.isFramebufferTexture){if(se)if(zt)e.texStorage2D(i.TEXTURE_2D,et,Pt,tt.width,tt.height);else{let H=tt.width,q=tt.height;for(let lt=0;lt>=1,q>>=1}}else if(Xt.length>0){if(zt&&se){const H=Et(Xt[0]);e.texStorage2D(i.TEXTURE_2D,et,Pt,H.width,H.height)}for(let H=0,q=Xt.length;H0&&et++;const q=Et(mt[0]);e.texStorage2D(i.TEXTURE_CUBE_MAP,et,Xt,q.width,q.height)}for(let q=0;q<6;q++)if(tt){zt?C&&e.texSubImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+q,0,0,0,mt[q].width,mt[q].height,Pt,ft,mt[q].data):e.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+q,0,Xt,mt[q].width,mt[q].height,0,Pt,ft,mt[q].data);for(let lt=0;lt>X),bt=Math.max(1,_.height>>X);K===i.TEXTURE_3D||K===i.TEXTURE_2D_ARRAY?e.texImage3D(K,X,dt,mt,bt,_.depth,0,St,ot,null):e.texImage2D(K,X,dt,mt,bt,0,St,ot,null)}e.bindFramebuffer(i.FRAMEBUFFER,E),kt(_)?o.framebufferTexture2DMultisampleEXT(i.FRAMEBUFFER,Z,K,tt.__webglTexture,0,Bt(_)):(K===i.TEXTURE_2D||K>=i.TEXTURE_CUBE_MAP_POSITIVE_X&&K<=i.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&i.framebufferTexture2D(i.FRAMEBUFFER,Z,K,tt.__webglTexture,X),e.bindFramebuffer(i.FRAMEBUFFER,null)}function at(E,_,F){if(i.bindRenderbuffer(i.RENDERBUFFER,E),_.depthBuffer){const Z=_.depthTexture,K=Z&&Z.isDepthTexture?Z.type:null,X=y(_.stencilBuffer,K),St=_.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,ot=Bt(_);kt(_)?o.renderbufferStorageMultisampleEXT(i.RENDERBUFFER,ot,X,_.width,_.height):F?i.renderbufferStorageMultisample(i.RENDERBUFFER,ot,X,_.width,_.height):i.renderbufferStorage(i.RENDERBUFFER,X,_.width,_.height),i.framebufferRenderbuffer(i.FRAMEBUFFER,St,i.RENDERBUFFER,E)}else{const Z=_.textures;for(let K=0;K{delete _.__boundDepthTexture,delete _.__depthDisposeCallback,Z.removeEventListener("dispose",K)};Z.addEventListener("dispose",K),_.__depthDisposeCallback=K}_.__boundDepthTexture=Z}if(E.depthTexture&&!_.__autoAllocateDepthBuffer){if(F)throw new Error("target.depthTexture not supported in Cube render targets");wt(_.__webglFramebuffer,E)}else if(F){_.__webglDepthbuffer=[];for(let Z=0;Z<6;Z++)if(e.bindFramebuffer(i.FRAMEBUFFER,_.__webglFramebuffer[Z]),_.__webglDepthbuffer[Z]===void 0)_.__webglDepthbuffer[Z]=i.createRenderbuffer(),at(_.__webglDepthbuffer[Z],E,!1);else{const K=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,X=_.__webglDepthbuffer[Z];i.bindRenderbuffer(i.RENDERBUFFER,X),i.framebufferRenderbuffer(i.FRAMEBUFFER,K,i.RENDERBUFFER,X)}}else if(e.bindFramebuffer(i.FRAMEBUFFER,_.__webglFramebuffer),_.__webglDepthbuffer===void 0)_.__webglDepthbuffer=i.createRenderbuffer(),at(_.__webglDepthbuffer,E,!1);else{const Z=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,K=_.__webglDepthbuffer;i.bindRenderbuffer(i.RENDERBUFFER,K),i.framebufferRenderbuffer(i.FRAMEBUFFER,Z,i.RENDERBUFFER,K)}e.bindFramebuffer(i.FRAMEBUFFER,null)}function Gt(E,_,F){const Z=n.get(E);_!==void 0&&xt(Z.__webglFramebuffer,E,E.texture,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,0),F!==void 0&&Ut(E)}function ce(E){const _=E.texture,F=n.get(E),Z=n.get(_);E.addEventListener("dispose",A);const K=E.textures,X=E.isWebGLCubeRenderTarget===!0,St=K.length>1;if(St||(Z.__webglTexture===void 0&&(Z.__webglTexture=i.createTexture()),Z.__version=_.version,a.memory.textures++),X){F.__webglFramebuffer=[];for(let ot=0;ot<6;ot++)if(_.mipmaps&&_.mipmaps.length>0){F.__webglFramebuffer[ot]=[];for(let dt=0;dt<_.mipmaps.length;dt++)F.__webglFramebuffer[ot][dt]=i.createFramebuffer()}else F.__webglFramebuffer[ot]=i.createFramebuffer()}else{if(_.mipmaps&&_.mipmaps.length>0){F.__webglFramebuffer=[];for(let ot=0;ot<_.mipmaps.length;ot++)F.__webglFramebuffer[ot]=i.createFramebuffer()}else F.__webglFramebuffer=i.createFramebuffer();if(St)for(let ot=0,dt=K.length;ot0&&kt(E)===!1){F.__webglMultisampledFramebuffer=i.createFramebuffer(),F.__webglColorRenderbuffer=[],e.bindFramebuffer(i.FRAMEBUFFER,F.__webglMultisampledFramebuffer);for(let ot=0;ot0)for(let dt=0;dt<_.mipmaps.length;dt++)xt(F.__webglFramebuffer[ot][dt],E,_,i.COLOR_ATTACHMENT0,i.TEXTURE_CUBE_MAP_POSITIVE_X+ot,dt);else xt(F.__webglFramebuffer[ot],E,_,i.COLOR_ATTACHMENT0,i.TEXTURE_CUBE_MAP_POSITIVE_X+ot,0);m(_)&&u(i.TEXTURE_CUBE_MAP),e.unbindTexture()}else if(St){for(let ot=0,dt=K.length;ot0)for(let dt=0;dt<_.mipmaps.length;dt++)xt(F.__webglFramebuffer[dt],E,_,i.COLOR_ATTACHMENT0,ot,dt);else xt(F.__webglFramebuffer,E,_,i.COLOR_ATTACHMENT0,ot,0);m(_)&&u(ot),e.unbindTexture()}E.depthBuffer&&Ut(E)}function rt(E){const _=E.textures;for(let F=0,Z=_.length;F0){if(kt(E)===!1){const _=E.textures,F=E.width,Z=E.height;let K=i.COLOR_BUFFER_BIT;const X=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,St=n.get(E),ot=_.length>1;if(ot)for(let dt=0;dt<_.length;dt++)e.bindFramebuffer(i.FRAMEBUFFER,St.__webglMultisampledFramebuffer),i.framebufferRenderbuffer(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.RENDERBUFFER,null),e.bindFramebuffer(i.FRAMEBUFFER,St.__webglFramebuffer),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.TEXTURE_2D,null,0);e.bindFramebuffer(i.READ_FRAMEBUFFER,St.__webglMultisampledFramebuffer),e.bindFramebuffer(i.DRAW_FRAMEBUFFER,St.__webglFramebuffer);for(let dt=0;dt<_.length;dt++){if(E.resolveDepthBuffer&&(E.depthBuffer&&(K|=i.DEPTH_BUFFER_BIT),E.stencilBuffer&&E.resolveStencilBuffer&&(K|=i.STENCIL_BUFFER_BIT)),ot){i.framebufferRenderbuffer(i.READ_FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.RENDERBUFFER,St.__webglColorRenderbuffer[dt]);const jt=n.get(_[dt]).__webglTexture;i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,jt,0)}i.blitFramebuffer(0,0,F,Z,0,0,F,Z,K,i.NEAREST),l===!0&&(Ct.length=0,w.length=0,Ct.push(i.COLOR_ATTACHMENT0+dt),E.depthBuffer&&E.resolveDepthBuffer===!1&&(Ct.push(X),w.push(X),i.invalidateFramebuffer(i.DRAW_FRAMEBUFFER,w)),i.invalidateFramebuffer(i.READ_FRAMEBUFFER,Ct))}if(e.bindFramebuffer(i.READ_FRAMEBUFFER,null),e.bindFramebuffer(i.DRAW_FRAMEBUFFER,null),ot)for(let dt=0;dt<_.length;dt++){e.bindFramebuffer(i.FRAMEBUFFER,St.__webglMultisampledFramebuffer),i.framebufferRenderbuffer(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.RENDERBUFFER,St.__webglColorRenderbuffer[dt]);const jt=n.get(_[dt]).__webglTexture;e.bindFramebuffer(i.FRAMEBUFFER,St.__webglFramebuffer),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.TEXTURE_2D,jt,0)}e.bindFramebuffer(i.DRAW_FRAMEBUFFER,St.__webglMultisampledFramebuffer)}else if(E.depthBuffer&&E.resolveDepthBuffer===!1&&l){const _=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT;i.invalidateFramebuffer(i.DRAW_FRAMEBUFFER,[_])}}}function Bt(E){return Math.min(s.maxSamples,E.samples)}function kt(E){const _=n.get(E);return E.samples>0&&t.has("WEBGL_multisampled_render_to_texture")===!0&&_.__useRenderToTexture!==!1}function Mt(E){const _=a.render.frame;h.get(E)!==_&&(h.set(E,_),E.update())}function ne(E,_){const F=E.colorSpace,Z=E.format,K=E.type;return E.isCompressedTexture===!0||E.isVideoTexture===!0||F!==Vi&&F!==Fn&&($t.getTransfer(F)===re?(Z!==an||K!==An)&&console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",F)),_}function Et(E){return typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement?(c.width=E.naturalWidth||E.width,c.height=E.naturalHeight||E.height):typeof VideoFrame<"u"&&E instanceof VideoFrame?(c.width=E.displayWidth,c.height=E.displayHeight):(c.width=E.width,c.height=E.height),c}this.allocateTextureUnit=z,this.resetTextureUnits=W,this.setTexture2D=$,this.setTexture2DArray=G,this.setTexture3D=J,this.setTextureCube=k,this.rebindTextures=Gt,this.setupRenderTarget=ce,this.updateRenderTargetMipmap=rt,this.updateMultisampleRenderTarget=ve,this.setupDepthRenderbuffer=Ut,this.setupFrameBufferTexture=xt,this.useMultisampledRTT=kt}function km(i,t){function e(n,s=Fn){let r;const a=$t.getTransfer(s);if(n===An)return i.UNSIGNED_BYTE;if(n===ja)return i.UNSIGNED_SHORT_4_4_4_4;if(n===Za)return i.UNSIGNED_SHORT_5_5_5_1;if(n===Gl)return i.UNSIGNED_INT_5_9_9_9_REV;if(n===kl)return i.BYTE;if(n===Vl)return i.SHORT;if(n===ls)return i.UNSIGNED_SHORT;if(n===qa)return i.INT;if(n===ni)return i.UNSIGNED_INT;if(n===fn)return i.FLOAT;if(n===Tn)return i.HALF_FLOAT;if(n===Wl)return i.ALPHA;if(n===Xl)return i.RGB;if(n===an)return i.RGBA;if(n===Yl)return i.LUMINANCE;if(n===ql)return i.LUMINANCE_ALPHA;if(n===Ii)return i.DEPTH_COMPONENT;if(n===ki)return i.DEPTH_STENCIL;if(n===Ka)return i.RED;if(n===$a)return i.RED_INTEGER;if(n===jl)return i.RG;if(n===Ja)return i.RG_INTEGER;if(n===Qa)return i.RGBA_INTEGER;if(n===qs||n===js||n===Zs||n===Ks)if(a===re)if(r=t.get("WEBGL_compressed_texture_s3tc_srgb"),r!==null){if(n===qs)return r.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===js)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===Zs)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===Ks)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null;else if(r=t.get("WEBGL_compressed_texture_s3tc"),r!==null){if(n===qs)return r.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===js)return r.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===Zs)return r.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===Ks)return r.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null;if(n===pa||n===ma||n===ga||n===_a)if(r=t.get("WEBGL_compressed_texture_pvrtc"),r!==null){if(n===pa)return r.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===ma)return r.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===ga)return r.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===_a)return r.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null;if(n===va||n===xa||n===Ma)if(r=t.get("WEBGL_compressed_texture_etc"),r!==null){if(n===va||n===xa)return a===re?r.COMPRESSED_SRGB8_ETC2:r.COMPRESSED_RGB8_ETC2;if(n===Ma)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:r.COMPRESSED_RGBA8_ETC2_EAC}else return null;if(n===Sa||n===ya||n===Ea||n===ba||n===Ta||n===wa||n===Aa||n===Ra||n===Ca||n===Pa||n===Da||n===La||n===Ua||n===Ia)if(r=t.get("WEBGL_compressed_texture_astc"),r!==null){if(n===Sa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:r.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===ya)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:r.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===Ea)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:r.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===ba)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:r.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===Ta)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:r.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===wa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:r.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===Aa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:r.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===Ra)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:r.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===Ca)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:r.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===Pa)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:r.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===Da)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:r.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===La)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:r.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===Ua)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:r.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===Ia)return a===re?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:r.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null;if(n===$s||n===Na||n===Fa)if(r=t.get("EXT_texture_compression_bptc"),r!==null){if(n===$s)return a===re?r.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:r.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===Na)return r.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===Fa)return r.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null;if(n===Zl||n===Oa||n===Ba||n===za)if(r=t.get("EXT_texture_compression_rgtc"),r!==null){if(n===$s)return r.COMPRESSED_RED_RGTC1_EXT;if(n===Oa)return r.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===Ba)return r.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===za)return r.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null;return n===Hi?i.UNSIGNED_INT_24_8:i[n]!==void 0?i[n]:null}return{convert:e}}const Vm={type:"move"};class $r{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new Pi,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new Pi,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new P,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new P),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new Pi,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new P,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new P),this._grip}dispatchEvent(t){return this._targetRay!==null&&this._targetRay.dispatchEvent(t),this._grip!==null&&this._grip.dispatchEvent(t),this._hand!==null&&this._hand.dispatchEvent(t),this}connect(t){if(t&&t.hand){const e=this._hand;if(e)for(const n of t.hand.values())this._getHandJoint(e,n)}return this.dispatchEvent({type:"connected",data:t}),this}disconnect(t){return this.dispatchEvent({type:"disconnected",data:t}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(t,e,n){let s=null,r=null,a=null;const o=this._targetRay,l=this._grip,c=this._hand;if(t&&e.session.visibilityState!=="visible-blurred"){if(c&&t.hand){a=!0;for(const v of t.hand.values()){const m=e.getJointPose(v,n),u=this._getHandJoint(c,v);m!==null&&(u.matrix.fromArray(m.transform.matrix),u.matrix.decompose(u.position,u.rotation,u.scale),u.matrixWorldNeedsUpdate=!0,u.jointRadius=m.radius),u.visible=m!==null}const h=c.joints["index-finger-tip"],d=c.joints["thumb-tip"],p=h.position.distanceTo(d.position),f=.02,g=.005;c.inputState.pinching&&p>f+g?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!c.inputState.pinching&&p<=f-g&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else l!==null&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),r!==null&&(l.matrix.fromArray(r.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,r.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(r.linearVelocity)):l.hasLinearVelocity=!1,r.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(r.angularVelocity)):l.hasAngularVelocity=!1));o!==null&&(s=e.getPose(t.targetRaySpace,n),s===null&&r!==null&&(s=r),s!==null&&(o.matrix.fromArray(s.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,s.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(s.linearVelocity)):o.hasLinearVelocity=!1,s.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(s.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(Vm)))}return o!==null&&(o.visible=s!==null),l!==null&&(l.visible=r!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(t,e){if(t.joints[e.jointName]===void 0){const n=new Pi;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}const Gm=` void main() { gl_Position = vec4( position, 1.0 ); -}`,Gm=` +}`,Wm=` uniform sampler2DArray depthColor; uniform float depthWidth; uniform float depthHeight; @@ -3824,7 +3824,7 @@ void main() { } -}`;class Wm{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(t,e,n){if(this.texture===null){const s=new Ce,r=t.properties.get(s);r.__webglTexture=e.texture,(e.depthNear!==n.depthNear||e.depthFar!==n.depthFar)&&(this.depthNear=e.depthNear,this.depthFar=e.depthFar),this.texture=s}}getMesh(t){if(this.texture!==null&&this.mesh===null){const e=t.cameras[0].viewport,n=new Ne({vertexShader:Vm,fragmentShader:Gm,uniforms:{depthColor:{value:this.texture},depthWidth:{value:e.z},depthHeight:{value:e.w}}});this.mesh=new Se(new us(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class Xm extends ii{constructor(t,e){super();const n=this;let s=null,r=1,a=null,o="local-floor",l=1,c=null,h=null,d=null,f=null,p=null,g=null;const v=new Wm,m=e.getContextAttributes();let u=null,T=null;const b=[],y=[],L=new vt;let R=null;const A=new Ye;A.viewport=new le;const U=new Ye;U.viewport=new le;const S=[A,U],M=new lu;let D=null,W=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(Y){let nt=b[Y];return nt===void 0&&(nt=new Zr,b[Y]=nt),nt.getTargetRaySpace()},this.getControllerGrip=function(Y){let nt=b[Y];return nt===void 0&&(nt=new Zr,b[Y]=nt),nt.getGripSpace()},this.getHand=function(Y){let nt=b[Y];return nt===void 0&&(nt=new Zr,b[Y]=nt),nt.getHandSpace()};function z(Y){const nt=y.indexOf(Y.inputSource);if(nt===-1)return;const xt=b[nt];xt!==void 0&&(xt.update(Y.inputSource,Y.frame,c||a),xt.dispatchEvent({type:Y.type,data:Y.inputSource}))}function V(){s.removeEventListener("select",z),s.removeEventListener("selectstart",z),s.removeEventListener("selectend",z),s.removeEventListener("squeeze",z),s.removeEventListener("squeezestart",z),s.removeEventListener("squeezeend",z),s.removeEventListener("end",V),s.removeEventListener("inputsourceschange",$);for(let Y=0;Y=0&&(y[at]=null,b[at].disconnect(xt))}for(let nt=0;nt=y.length){y.push(xt),at=Ut;break}else if(y[Ut]===null){y[Ut]=xt,at=Ut;break}if(at===-1)break}const wt=b[at];wt&&wt.connect(xt)}}const G=new P,J=new P;function k(Y,nt,xt){G.setFromMatrixPosition(nt.matrixWorld),J.setFromMatrixPosition(xt.matrixWorld);const at=G.distanceTo(J),wt=nt.projectionMatrix.elements,Ut=xt.projectionMatrix.elements,Gt=wt[14]/(wt[10]-1),ce=wt[14]/(wt[10]+1),rt=(wt[9]+1)/wt[5],Ct=(wt[9]-1)/wt[5],w=(wt[8]-1)/wt[0],ve=(Ut[8]+1)/Ut[0],Bt=Gt*w,kt=Gt*ve,Mt=at/(-w+ve),ne=Mt*-w;if(nt.matrixWorld.decompose(Y.position,Y.quaternion,Y.scale),Y.translateX(ne),Y.translateZ(Mt),Y.matrixWorld.compose(Y.position,Y.quaternion,Y.scale),Y.matrixWorldInverse.copy(Y.matrixWorld).invert(),wt[10]===-1)Y.projectionMatrix.copy(nt.projectionMatrix),Y.projectionMatrixInverse.copy(nt.projectionMatrixInverse);else{const Et=Gt+Mt,E=ce+Mt,_=Bt-ne,F=kt+(at-ne),Z=rt*ce/E*Et,K=Ct*ce/E*Et;Y.projectionMatrix.makePerspective(_,F,Z,K,Et,E),Y.projectionMatrixInverse.copy(Y.projectionMatrix).invert()}}function it(Y,nt){nt===null?Y.matrixWorld.copy(Y.matrix):Y.matrixWorld.multiplyMatrices(nt.matrixWorld,Y.matrix),Y.matrixWorldInverse.copy(Y.matrixWorld).invert()}this.updateCamera=function(Y){if(s===null)return;let nt=Y.near,xt=Y.far;v.texture!==null&&(v.depthNear>0&&(nt=v.depthNear),v.depthFar>0&&(xt=v.depthFar)),M.near=U.near=A.near=nt,M.far=U.far=A.far=xt,(D!==M.near||W!==M.far)&&(s.updateRenderState({depthNear:M.near,depthFar:M.far}),D=M.near,W=M.far),A.layers.mask=Y.layers.mask|2,U.layers.mask=Y.layers.mask|4,M.layers.mask=A.layers.mask|U.layers.mask;const at=Y.parent,wt=M.cameras;it(M,at);for(let Ut=0;Ut0&&(m.alphaTest.value=u.alphaTest);const T=t.get(u),b=T.envMap,y=T.envMapRotation;b&&(m.envMap.value=b,jn.copy(y),jn.x*=-1,jn.y*=-1,jn.z*=-1,b.isCubeTexture&&b.isRenderTargetTexture===!1&&(jn.y*=-1,jn.z*=-1),m.envMapRotation.value.setFromMatrix4(Ym.makeRotationFromEuler(jn)),m.flipEnvMap.value=b.isCubeTexture&&b.isRenderTargetTexture===!1?-1:1,m.reflectivity.value=u.reflectivity,m.ior.value=u.ior,m.refractionRatio.value=u.refractionRatio),u.lightMap&&(m.lightMap.value=u.lightMap,m.lightMapIntensity.value=u.lightMapIntensity,e(u.lightMap,m.lightMapTransform)),u.aoMap&&(m.aoMap.value=u.aoMap,m.aoMapIntensity.value=u.aoMapIntensity,e(u.aoMap,m.aoMapTransform))}function a(m,u){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,u.map&&(m.map.value=u.map,e(u.map,m.mapTransform))}function o(m,u){m.dashSize.value=u.dashSize,m.totalSize.value=u.dashSize+u.gapSize,m.scale.value=u.scale}function l(m,u,T,b){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,m.size.value=u.size*T,m.scale.value=b*.5,u.map&&(m.map.value=u.map,e(u.map,m.uvTransform)),u.alphaMap&&(m.alphaMap.value=u.alphaMap,e(u.alphaMap,m.alphaMapTransform)),u.alphaTest>0&&(m.alphaTest.value=u.alphaTest)}function c(m,u){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,m.rotation.value=u.rotation,u.map&&(m.map.value=u.map,e(u.map,m.mapTransform)),u.alphaMap&&(m.alphaMap.value=u.alphaMap,e(u.alphaMap,m.alphaMapTransform)),u.alphaTest>0&&(m.alphaTest.value=u.alphaTest)}function h(m,u){m.specular.value.copy(u.specular),m.shininess.value=Math.max(u.shininess,1e-4)}function d(m,u){u.gradientMap&&(m.gradientMap.value=u.gradientMap)}function f(m,u){m.metalness.value=u.metalness,u.metalnessMap&&(m.metalnessMap.value=u.metalnessMap,e(u.metalnessMap,m.metalnessMapTransform)),m.roughness.value=u.roughness,u.roughnessMap&&(m.roughnessMap.value=u.roughnessMap,e(u.roughnessMap,m.roughnessMapTransform)),u.envMap&&(m.envMapIntensity.value=u.envMapIntensity)}function p(m,u,T){m.ior.value=u.ior,u.sheen>0&&(m.sheenColor.value.copy(u.sheenColor).multiplyScalar(u.sheen),m.sheenRoughness.value=u.sheenRoughness,u.sheenColorMap&&(m.sheenColorMap.value=u.sheenColorMap,e(u.sheenColorMap,m.sheenColorMapTransform)),u.sheenRoughnessMap&&(m.sheenRoughnessMap.value=u.sheenRoughnessMap,e(u.sheenRoughnessMap,m.sheenRoughnessMapTransform))),u.clearcoat>0&&(m.clearcoat.value=u.clearcoat,m.clearcoatRoughness.value=u.clearcoatRoughness,u.clearcoatMap&&(m.clearcoatMap.value=u.clearcoatMap,e(u.clearcoatMap,m.clearcoatMapTransform)),u.clearcoatRoughnessMap&&(m.clearcoatRoughnessMap.value=u.clearcoatRoughnessMap,e(u.clearcoatRoughnessMap,m.clearcoatRoughnessMapTransform)),u.clearcoatNormalMap&&(m.clearcoatNormalMap.value=u.clearcoatNormalMap,e(u.clearcoatNormalMap,m.clearcoatNormalMapTransform),m.clearcoatNormalScale.value.copy(u.clearcoatNormalScale),u.side===ke&&m.clearcoatNormalScale.value.negate())),u.dispersion>0&&(m.dispersion.value=u.dispersion),u.iridescence>0&&(m.iridescence.value=u.iridescence,m.iridescenceIOR.value=u.iridescenceIOR,m.iridescenceThicknessMinimum.value=u.iridescenceThicknessRange[0],m.iridescenceThicknessMaximum.value=u.iridescenceThicknessRange[1],u.iridescenceMap&&(m.iridescenceMap.value=u.iridescenceMap,e(u.iridescenceMap,m.iridescenceMapTransform)),u.iridescenceThicknessMap&&(m.iridescenceThicknessMap.value=u.iridescenceThicknessMap,e(u.iridescenceThicknessMap,m.iridescenceThicknessMapTransform))),u.transmission>0&&(m.transmission.value=u.transmission,m.transmissionSamplerMap.value=T.texture,m.transmissionSamplerSize.value.set(T.width,T.height),u.transmissionMap&&(m.transmissionMap.value=u.transmissionMap,e(u.transmissionMap,m.transmissionMapTransform)),m.thickness.value=u.thickness,u.thicknessMap&&(m.thicknessMap.value=u.thicknessMap,e(u.thicknessMap,m.thicknessMapTransform)),m.attenuationDistance.value=u.attenuationDistance,m.attenuationColor.value.copy(u.attenuationColor)),u.anisotropy>0&&(m.anisotropyVector.value.set(u.anisotropy*Math.cos(u.anisotropyRotation),u.anisotropy*Math.sin(u.anisotropyRotation)),u.anisotropyMap&&(m.anisotropyMap.value=u.anisotropyMap,e(u.anisotropyMap,m.anisotropyMapTransform))),m.specularIntensity.value=u.specularIntensity,m.specularColor.value.copy(u.specularColor),u.specularColorMap&&(m.specularColorMap.value=u.specularColorMap,e(u.specularColorMap,m.specularColorMapTransform)),u.specularIntensityMap&&(m.specularIntensityMap.value=u.specularIntensityMap,e(u.specularIntensityMap,m.specularIntensityMapTransform))}function g(m,u){u.matcap&&(m.matcap.value=u.matcap)}function v(m,u){const T=t.get(u).light;m.referencePosition.value.setFromMatrixPosition(T.matrixWorld),m.nearDistance.value=T.shadow.camera.near,m.farDistance.value=T.shadow.camera.far}return{refreshFogUniforms:n,refreshMaterialUniforms:s}}function jm(i,t,e,n){let s={},r={},a=[];const o=i.getParameter(i.MAX_UNIFORM_BUFFER_BINDINGS);function l(T,b){const y=b.program;n.uniformBlockBinding(T,y)}function c(T,b){let y=s[T.id];y===void 0&&(g(T),y=h(T),s[T.id]=y,T.addEventListener("dispose",m));const L=b.program;n.updateUBOMapping(T,L);const R=t.render.frame;r[T.id]!==R&&(f(T),r[T.id]=R)}function h(T){const b=d();T.__bindingPointIndex=b;const y=i.createBuffer(),L=T.__size,R=T.usage;return i.bindBuffer(i.UNIFORM_BUFFER,y),i.bufferData(i.UNIFORM_BUFFER,L,R),i.bindBuffer(i.UNIFORM_BUFFER,null),i.bindBufferBase(i.UNIFORM_BUFFER,b,y),y}function d(){for(let T=0;T0&&(y+=L-R),T.__size=y,T.__cache={},this}function v(T){const b={boundary:0,storage:0};return typeof T=="number"||typeof T=="boolean"?(b.boundary=4,b.storage=4):T.isVector2?(b.boundary=8,b.storage=8):T.isVector3||T.isColor?(b.boundary=16,b.storage=12):T.isVector4?(b.boundary=16,b.storage=16):T.isMatrix3?(b.boundary=48,b.storage=48):T.isMatrix4?(b.boundary=64,b.storage=64):T.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",T),b}function m(T){const b=T.target;b.removeEventListener("dispose",m);const y=a.indexOf(b.__bindingPointIndex);a.splice(y,1),i.deleteBuffer(s[b.id]),delete s[b.id],delete r[b.id]}function u(){for(const T in s)i.deleteBuffer(s[T]);a=[],s={},r={}}return{bind:l,update:c,dispose:u}}class Zm{constructor(t={}){const{canvas:e=Eh(),context:n=null,depth:s=!0,stencil:r=!1,alpha:a=!1,antialias:o=!1,premultipliedAlpha:l=!0,preserveDrawingBuffer:c=!1,powerPreference:h="default",failIfMajorPerformanceCaveat:d=!1,reverseDepthBuffer:f=!1}=t;this.isWebGLRenderer=!0;let p;if(n!==null){if(typeof WebGLRenderingContext<"u"&&n instanceof WebGLRenderingContext)throw new Error("THREE.WebGLRenderer: WebGL 1 is not supported since r163.");p=n.getContextAttributes().alpha}else p=a;const g=new Uint32Array(4),v=new Int32Array(4);let m=null,u=null;const T=[],b=[];this.domElement=e,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this._outputColorSpace=Qe,this.toneMapping=On,this.toneMappingExposure=1;const y=this;let L=!1,R=0,A=0,U=null,S=-1,M=null;const D=new le,W=new le;let z=null;const V=new pt(0);let $=0,G=e.width,J=e.height,k=1,it=null,ut=null;const yt=new le(0,0,G,J),Lt=new le(0,0,G,J);let qt=!1;const Y=new to;let nt=!1,xt=!1;this.transmissionResolutionScale=1;const at=new ee,wt=new ee,Ut=new P,Gt=new le,ce={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};let rt=!1;function Ct(){return U===null?k:1}let w=n;function ve(x,I){return e.getContext(x,I)}try{const x={alpha:!0,depth:s,stencil:r,antialias:o,premultipliedAlpha:l,preserveDrawingBuffer:c,powerPreference:h,failIfMajorPerformanceCaveat:d};if("setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Xa}`),e.addEventListener("webglcontextlost",q,!1),e.addEventListener("webglcontextrestored",lt,!1),e.addEventListener("webglcontextcreationerror",ct,!1),w===null){const I="webgl2";if(w=ve(I,x),w===null)throw ve(I)?new Error("Error creating WebGL context with your selected attributes."):new Error("Error creating WebGL context.")}}catch(x){throw console.error("THREE.WebGLRenderer: "+x.message),x}let Bt,kt,Mt,ne,Et,E,_,F,Z,K,X,St,ot,dt,jt,tt,mt,bt,Pt,ft,Xt,zt,ie,C;function et(){Bt=new sp(w),Bt.init(),zt=new Hm(w,Bt),kt=new Jf(w,Bt,t,zt),Mt=new Bm(w,Bt),kt.reverseDepthBuffer&&f&&Mt.buffers.depth.setReversed(!0),ne=new op(w),Et=new Tm,E=new zm(w,Bt,Mt,Et,kt,zt,ne),_=new tp(y),F=new ip(y),Z=new fu(w),ie=new Kf(w,Z),K=new rp(w,Z,ne,ie),X=new cp(w,K,Z,ne),Pt=new lp(w,kt,E),tt=new Qf(Et),St=new bm(y,_,F,Bt,kt,ie,tt),ot=new qm(y,Et),dt=new Am,jt=new Um(Bt),bt=new Zf(y,_,F,Mt,X,p,l),mt=new Fm(y,X,kt),C=new jm(w,ne,kt,Mt),ft=new $f(w,Bt,ne),Xt=new ap(w,Bt,ne),ne.programs=St.programs,y.capabilities=kt,y.extensions=Bt,y.properties=Et,y.renderLists=dt,y.shadowMap=mt,y.state=Mt,y.info=ne}et();const H=new Xm(y,w);this.xr=H,this.getContext=function(){return w},this.getContextAttributes=function(){return w.getContextAttributes()},this.forceContextLoss=function(){const x=Bt.get("WEBGL_lose_context");x&&x.loseContext()},this.forceContextRestore=function(){const x=Bt.get("WEBGL_lose_context");x&&x.restoreContext()},this.getPixelRatio=function(){return k},this.setPixelRatio=function(x){x!==void 0&&(k=x,this.setSize(G,J,!1))},this.getSize=function(x){return x.set(G,J)},this.setSize=function(x,I,O=!0){if(H.isPresenting){console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting.");return}G=x,J=I,e.width=Math.floor(x*k),e.height=Math.floor(I*k),O===!0&&(e.style.width=x+"px",e.style.height=I+"px"),this.setViewport(0,0,x,I)},this.getDrawingBufferSize=function(x){return x.set(G*k,J*k).floor()},this.setDrawingBufferSize=function(x,I,O){G=x,J=I,k=O,e.width=Math.floor(x*O),e.height=Math.floor(I*O),this.setViewport(0,0,x,I)},this.getCurrentViewport=function(x){return x.copy(D)},this.getViewport=function(x){return x.copy(yt)},this.setViewport=function(x,I,O,B){x.isVector4?yt.set(x.x,x.y,x.z,x.w):yt.set(x,I,O,B),Mt.viewport(D.copy(yt).multiplyScalar(k).round())},this.getScissor=function(x){return x.copy(Lt)},this.setScissor=function(x,I,O,B){x.isVector4?Lt.set(x.x,x.y,x.z,x.w):Lt.set(x,I,O,B),Mt.scissor(W.copy(Lt).multiplyScalar(k).round())},this.getScissorTest=function(){return qt},this.setScissorTest=function(x){Mt.setScissorTest(qt=x)},this.setOpaqueSort=function(x){it=x},this.setTransparentSort=function(x){ut=x},this.getClearColor=function(x){return x.copy(bt.getClearColor())},this.setClearColor=function(){bt.setClearColor.apply(bt,arguments)},this.getClearAlpha=function(){return bt.getClearAlpha()},this.setClearAlpha=function(){bt.setClearAlpha.apply(bt,arguments)},this.clear=function(x=!0,I=!0,O=!0){let B=0;if(x){let N=!1;if(U!==null){const Q=U.texture.format;N=Q===Ja||Q===$a||Q===Ka}if(N){const Q=U.texture.type,ht=Q===An||Q===ei||Q===os||Q===zi||Q===qa||Q===ja,gt=bt.getClearColor(),_t=bt.getClearAlpha(),It=gt.r,Ft=gt.g,Tt=gt.b;ht?(g[0]=It,g[1]=Ft,g[2]=Tt,g[3]=_t,w.clearBufferuiv(w.COLOR,0,g)):(v[0]=It,v[1]=Ft,v[2]=Tt,v[3]=_t,w.clearBufferiv(w.COLOR,0,v))}else B|=w.COLOR_BUFFER_BIT}I&&(B|=w.DEPTH_BUFFER_BIT),O&&(B|=w.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),w.clear(B)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){e.removeEventListener("webglcontextlost",q,!1),e.removeEventListener("webglcontextrestored",lt,!1),e.removeEventListener("webglcontextcreationerror",ct,!1),bt.dispose(),dt.dispose(),jt.dispose(),Et.dispose(),_.dispose(),F.dispose(),X.dispose(),ie.dispose(),C.dispose(),St.dispose(),H.dispose(),H.removeEventListener("sessionstart",so),H.removeEventListener("sessionend",ro),kn.stop()};function q(x){x.preventDefault(),console.log("THREE.WebGLRenderer: Context Lost."),L=!0}function lt(){console.log("THREE.WebGLRenderer: Context Restored."),L=!1;const x=ne.autoReset,I=mt.enabled,O=mt.autoUpdate,B=mt.needsUpdate,N=mt.type;et(),ne.autoReset=x,mt.enabled=I,mt.autoUpdate=O,mt.needsUpdate=B,mt.type=N}function ct(x){console.error("THREE.WebGLRenderer: A WebGL context could not be created. Reason: ",x.statusMessage)}function Nt(x){const I=x.target;I.removeEventListener("dispose",Nt),he(I)}function he(x){xe(x),Et.remove(x)}function xe(x){const I=Et.get(x).programs;I!==void 0&&(I.forEach(function(O){St.releaseProgram(O)}),x.isShaderMaterial&&St.releaseShaderCache(x))}this.renderBufferDirect=function(x,I,O,B,N,Q){I===null&&(I=ce);const ht=N.isMesh&&N.matrixWorld.determinant()<0,gt=vc(x,I,O,B,N);Mt.setMaterial(B,ht);let _t=O.index,It=1;if(B.wireframe===!0){if(_t=K.getWireframeAttribute(O),_t===void 0)return;It=2}const Ft=O.drawRange,Tt=O.attributes.position;let Zt=Ft.start*It,Qt=(Ft.start+Ft.count)*It;Q!==null&&(Zt=Math.max(Zt,Q.start*It),Qt=Math.min(Qt,(Q.start+Q.count)*It)),_t!==null?(Zt=Math.max(Zt,0),Qt=Math.min(Qt,_t.count)):Tt!=null&&(Zt=Math.max(Zt,0),Qt=Math.min(Qt,Tt.count));const me=Qt-Zt;if(me<0||me===1/0)return;ie.setup(N,B,gt,O,_t);let fe,Kt=ft;if(_t!==null&&(fe=Z.get(_t),Kt=Xt,Kt.setIndex(fe)),N.isMesh)B.wireframe===!0?(Mt.setLineWidth(B.wireframeLinewidth*Ct()),Kt.setMode(w.LINES)):Kt.setMode(w.TRIANGLES);else if(N.isLine){let At=B.linewidth;At===void 0&&(At=1),Mt.setLineWidth(At*Ct()),N.isLineSegments?Kt.setMode(w.LINES):N.isLineLoop?Kt.setMode(w.LINE_LOOP):Kt.setMode(w.LINE_STRIP)}else N.isPoints?Kt.setMode(w.POINTS):N.isSprite&&Kt.setMode(w.TRIANGLES);if(N.isBatchedMesh)if(N._multiDrawInstances!==null)Kt.renderMultiDrawInstances(N._multiDrawStarts,N._multiDrawCounts,N._multiDrawCount,N._multiDrawInstances);else if(Bt.get("WEBGL_multi_draw"))Kt.renderMultiDraw(N._multiDrawStarts,N._multiDrawCounts,N._multiDrawCount);else{const At=N._multiDrawStarts,Te=N._multiDrawCounts,te=N._multiDrawCount,en=_t?Z.get(_t).bytesPerElement:1,ai=Et.get(B).currentProgram.getUniforms();for(let Ge=0;Ge{function Q(){if(B.forEach(function(ht){Et.get(ht).currentProgram.isReady()&&B.delete(ht)}),B.size===0){N(x);return}setTimeout(Q,10)}Bt.get("KHR_parallel_shader_compile")!==null?Q():setTimeout(Q,10)})};let Ve=null;function mn(x){Ve&&Ve(x)}function so(){kn.stop()}function ro(){kn.start()}const kn=new hc;kn.setAnimationLoop(mn),typeof self<"u"&&kn.setContext(self),this.setAnimationLoop=function(x){Ve=x,H.setAnimationLoop(x),x===null?kn.stop():kn.start()},H.addEventListener("sessionstart",so),H.addEventListener("sessionend",ro),this.render=function(x,I){if(I!==void 0&&I.isCamera!==!0){console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");return}if(L===!0)return;if(x.matrixWorldAutoUpdate===!0&&x.updateMatrixWorld(),I.parent===null&&I.matrixWorldAutoUpdate===!0&&I.updateMatrixWorld(),H.enabled===!0&&H.isPresenting===!0&&(H.cameraAutoUpdate===!0&&H.updateCamera(I),I=H.getCamera()),x.isScene===!0&&x.onBeforeRender(y,x,I,U),u=jt.get(x,b.length),u.init(I),b.push(u),wt.multiplyMatrices(I.projectionMatrix,I.matrixWorldInverse),Y.setFromProjectionMatrix(wt),xt=this.localClippingEnabled,nt=tt.init(this.clippingPlanes,xt),m=dt.get(x,T.length),m.init(),T.push(m),H.enabled===!0&&H.isPresenting===!0){const Q=y.xr.getDepthSensingMesh();Q!==null&&pr(Q,I,-1/0,y.sortObjects)}pr(x,I,0,y.sortObjects),m.finish(),y.sortObjects===!0&&m.sort(it,ut),rt=H.enabled===!1||H.isPresenting===!1||H.hasDepthSensing()===!1,rt&&bt.addToRenderList(m,x),this.info.render.frame++,nt===!0&&tt.beginShadows();const O=u.state.shadowsArray;mt.render(O,x,I),nt===!0&&tt.endShadows(),this.info.autoReset===!0&&this.info.reset();const B=m.opaque,N=m.transmissive;if(u.setupLights(),I.isArrayCamera){const Q=I.cameras;if(N.length>0)for(let ht=0,gt=Q.length;ht0&&oo(B,N,x,I),rt&&bt.render(x),ao(m,x,I);U!==null&&A===0&&(E.updateMultisampleRenderTarget(U),E.updateRenderTargetMipmap(U)),x.isScene===!0&&x.onAfterRender(y,x,I),ie.resetDefaultState(),S=-1,M=null,b.pop(),b.length>0?(u=b[b.length-1],nt===!0&&tt.setGlobalState(y.clippingPlanes,u.state.camera)):u=null,T.pop(),T.length>0?m=T[T.length-1]:m=null};function pr(x,I,O,B){if(x.visible===!1)return;if(x.layers.test(I.layers)){if(x.isGroup)O=x.renderOrder;else if(x.isLOD)x.autoUpdate===!0&&x.update(I);else if(x.isLight)u.pushLight(x),x.castShadow&&u.pushShadow(x);else if(x.isSprite){if(!x.frustumCulled||Y.intersectsSprite(x)){B&&Gt.setFromMatrixPosition(x.matrixWorld).applyMatrix4(wt);const ht=X.update(x),gt=x.material;gt.visible&&m.push(x,ht,gt,O,Gt.z,null)}}else if((x.isMesh||x.isLine||x.isPoints)&&(!x.frustumCulled||Y.intersectsObject(x))){const ht=X.update(x),gt=x.material;if(B&&(x.boundingSphere!==void 0?(x.boundingSphere===null&&x.computeBoundingSphere(),Gt.copy(x.boundingSphere.center)):(ht.boundingSphere===null&&ht.computeBoundingSphere(),Gt.copy(ht.boundingSphere.center)),Gt.applyMatrix4(x.matrixWorld).applyMatrix4(wt)),Array.isArray(gt)){const _t=ht.groups;for(let It=0,Ft=_t.length;It0&&fs(N,I,O),Q.length>0&&fs(Q,I,O),ht.length>0&&fs(ht,I,O),Mt.buffers.depth.setTest(!0),Mt.buffers.depth.setMask(!0),Mt.buffers.color.setMask(!0),Mt.setPolygonOffset(!1)}function oo(x,I,O,B){if((O.isScene===!0?O.overrideMaterial:null)!==null)return;u.state.transmissionRenderTarget[B.id]===void 0&&(u.state.transmissionRenderTarget[B.id]=new on(1,1,{generateMipmaps:!0,type:Bt.has("EXT_color_buffer_half_float")||Bt.has("EXT_color_buffer_float")?Tn:An,minFilter:Qn,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:$t.workingColorSpace}));const Q=u.state.transmissionRenderTarget[B.id],ht=B.viewport||D;Q.setSize(ht.z*y.transmissionResolutionScale,ht.w*y.transmissionResolutionScale);const gt=y.getRenderTarget();y.setRenderTarget(Q),y.getClearColor(V),$=y.getClearAlpha(),$<1&&y.setClearColor(16777215,.5),y.clear(),rt&&bt.render(O);const _t=y.toneMapping;y.toneMapping=On;const It=B.viewport;if(B.viewport!==void 0&&(B.viewport=void 0),u.setupLightsView(B),nt===!0&&tt.setGlobalState(y.clippingPlanes,B),fs(x,O,B),E.updateMultisampleRenderTarget(Q),E.updateRenderTargetMipmap(Q),Bt.has("WEBGL_multisampled_render_to_texture")===!1){let Ft=!1;for(let Tt=0,Zt=I.length;Tt0),Tt=!!O.morphAttributes.position,Zt=!!O.morphAttributes.normal,Qt=!!O.morphAttributes.color;let me=On;B.toneMapped&&(U===null||U.isXRRenderTarget===!0)&&(me=y.toneMapping);const fe=O.morphAttributes.position||O.morphAttributes.normal||O.morphAttributes.color,Kt=fe!==void 0?fe.length:0,At=Et.get(B),Te=u.state.lights;if(nt===!0&&(xt===!0||x!==M)){const De=x===M&&B.id===S;tt.setState(B,x,De)}let te=!1;B.version===At.__version?(At.needsLights&&At.lightsStateVersion!==Te.state.version||At.outputColorSpace!==gt||N.isBatchedMesh&&At.batching===!1||!N.isBatchedMesh&&At.batching===!0||N.isBatchedMesh&&At.batchingColor===!0&&N.colorTexture===null||N.isBatchedMesh&&At.batchingColor===!1&&N.colorTexture!==null||N.isInstancedMesh&&At.instancing===!1||!N.isInstancedMesh&&At.instancing===!0||N.isSkinnedMesh&&At.skinning===!1||!N.isSkinnedMesh&&At.skinning===!0||N.isInstancedMesh&&At.instancingColor===!0&&N.instanceColor===null||N.isInstancedMesh&&At.instancingColor===!1&&N.instanceColor!==null||N.isInstancedMesh&&At.instancingMorph===!0&&N.morphTexture===null||N.isInstancedMesh&&At.instancingMorph===!1&&N.morphTexture!==null||At.envMap!==_t||B.fog===!0&&At.fog!==Q||At.numClippingPlanes!==void 0&&(At.numClippingPlanes!==tt.numPlanes||At.numIntersection!==tt.numIntersection)||At.vertexAlphas!==It||At.vertexTangents!==Ft||At.morphTargets!==Tt||At.morphNormals!==Zt||At.morphColors!==Qt||At.toneMapping!==me||At.morphTargetsCount!==Kt)&&(te=!0):(te=!0,At.__version=B.version);let en=At.currentProgram;te===!0&&(en=ps(B,I,N));let ai=!1,Ge=!1,Xi=!1;const ue=en.getUniforms(),Ze=At.uniforms;if(Mt.useProgram(en.program)&&(ai=!0,Ge=!0,Xi=!0),B.id!==S&&(S=B.id,Ge=!0),ai||M!==x){Mt.buffers.depth.getReversed()?(at.copy(x.projectionMatrix),Th(at),wh(at),ue.setValue(w,"projectionMatrix",at)):ue.setValue(w,"projectionMatrix",x.projectionMatrix),ue.setValue(w,"viewMatrix",x.matrixWorldInverse);const Fe=ue.map.cameraPosition;Fe!==void 0&&Fe.setValue(w,Ut.setFromMatrixPosition(x.matrixWorld)),kt.logarithmicDepthBuffer&&ue.setValue(w,"logDepthBufFC",2/(Math.log(x.far+1)/Math.LN2)),(B.isMeshPhongMaterial||B.isMeshToonMaterial||B.isMeshLambertMaterial||B.isMeshBasicMaterial||B.isMeshStandardMaterial||B.isShaderMaterial)&&ue.setValue(w,"isOrthographic",x.isOrthographicCamera===!0),M!==x&&(M=x,Ge=!0,Xi=!0)}if(N.isSkinnedMesh){ue.setOptional(w,N,"bindMatrix"),ue.setOptional(w,N,"bindMatrixInverse");const De=N.skeleton;De&&(De.boneTexture===null&&De.computeBoneTexture(),ue.setValue(w,"boneTexture",De.boneTexture,E))}N.isBatchedMesh&&(ue.setOptional(w,N,"batchingTexture"),ue.setValue(w,"batchingTexture",N._matricesTexture,E),ue.setOptional(w,N,"batchingIdTexture"),ue.setValue(w,"batchingIdTexture",N._indirectTexture,E),ue.setOptional(w,N,"batchingColorTexture"),N._colorsTexture!==null&&ue.setValue(w,"batchingColorTexture",N._colorsTexture,E));const Ke=O.morphAttributes;if((Ke.position!==void 0||Ke.normal!==void 0||Ke.color!==void 0)&&Pt.update(N,O,en),(Ge||At.receiveShadow!==N.receiveShadow)&&(At.receiveShadow=N.receiveShadow,ue.setValue(w,"receiveShadow",N.receiveShadow)),B.isMeshGouraudMaterial&&B.envMap!==null&&(Ze.envMap.value=_t,Ze.flipEnvMap.value=_t.isCubeTexture&&_t.isRenderTargetTexture===!1?-1:1),B.isMeshStandardMaterial&&B.envMap===null&&I.environment!==null&&(Ze.envMapIntensity.value=I.environmentIntensity),Ge&&(ue.setValue(w,"toneMappingExposure",y.toneMappingExposure),At.needsLights&&xc(Ze,Xi),Q&&B.fog===!0&&ot.refreshFogUniforms(Ze,Q),ot.refreshMaterialUniforms(Ze,B,k,J,u.state.transmissionRenderTarget[x.id]),$s.upload(w,co(At),Ze,E)),B.isShaderMaterial&&B.uniformsNeedUpdate===!0&&($s.upload(w,co(At),Ze,E),B.uniformsNeedUpdate=!1),B.isSpriteMaterial&&ue.setValue(w,"center",N.center),ue.setValue(w,"modelViewMatrix",N.modelViewMatrix),ue.setValue(w,"normalMatrix",N.normalMatrix),ue.setValue(w,"modelMatrix",N.matrixWorld),B.isShaderMaterial||B.isRawShaderMaterial){const De=B.uniformsGroups;for(let Fe=0,mr=De.length;Fe0&&E.useMultisampledRTT(x)===!1?N=Et.get(x).__webglMultisampledFramebuffer:Array.isArray(Ft)?N=Ft[O]:N=Ft,D.copy(x.viewport),W.copy(x.scissor),z=x.scissorTest}else D.copy(yt).multiplyScalar(k).floor(),W.copy(Lt).multiplyScalar(k).floor(),z=qt;if(O!==0&&(N=Sc),Mt.bindFramebuffer(w.FRAMEBUFFER,N)&&B&&Mt.drawBuffers(x,N),Mt.viewport(D),Mt.scissor(W),Mt.setScissorTest(z),Q){const _t=Et.get(x.texture);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_CUBE_MAP_POSITIVE_X+I,_t.__webglTexture,O)}else if(ht){const _t=Et.get(x.texture),It=I;w.framebufferTextureLayer(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,_t.__webglTexture,O,It)}else if(x!==null&&O!==0){const _t=Et.get(x.texture);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,_t.__webglTexture,O)}S=-1},this.readRenderTargetPixels=function(x,I,O,B,N,Q,ht){if(!(x&&x.isWebGLRenderTarget)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");return}let gt=Et.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&ht!==void 0&&(gt=gt[ht]),gt){Mt.bindFramebuffer(w.FRAMEBUFFER,gt);try{const _t=x.texture,It=_t.format,Ft=_t.type;if(!kt.textureFormatReadable(It)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");return}if(!kt.textureTypeReadable(Ft)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");return}I>=0&&I<=x.width-B&&O>=0&&O<=x.height-N&&w.readPixels(I,O,B,N,zt.convert(It),zt.convert(Ft),Q)}finally{const _t=U!==null?Et.get(U).__webglFramebuffer:null;Mt.bindFramebuffer(w.FRAMEBUFFER,_t)}}},this.readRenderTargetPixelsAsync=async function(x,I,O,B,N,Q,ht){if(!(x&&x.isWebGLRenderTarget))throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let gt=Et.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&ht!==void 0&&(gt=gt[ht]),gt){const _t=x.texture,It=_t.format,Ft=_t.type;if(!kt.textureFormatReadable(It))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!kt.textureTypeReadable(Ft))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(I>=0&&I<=x.width-B&&O>=0&&O<=x.height-N){Mt.bindFramebuffer(w.FRAMEBUFFER,gt);const Tt=w.createBuffer();w.bindBuffer(w.PIXEL_PACK_BUFFER,Tt),w.bufferData(w.PIXEL_PACK_BUFFER,Q.byteLength,w.STREAM_READ),w.readPixels(I,O,B,N,zt.convert(It),zt.convert(Ft),0);const Zt=U!==null?Et.get(U).__webglFramebuffer:null;Mt.bindFramebuffer(w.FRAMEBUFFER,Zt);const Qt=w.fenceSync(w.SYNC_GPU_COMMANDS_COMPLETE,0);return w.flush(),await bh(w,Qt,4),w.bindBuffer(w.PIXEL_PACK_BUFFER,Tt),w.getBufferSubData(w.PIXEL_PACK_BUFFER,0,Q),w.deleteBuffer(Tt),w.deleteSync(Qt),Q}else throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(x,I=null,O=0){x.isTexture!==!0&&(Ai("WebGLRenderer: copyFramebufferToTexture function signature has changed."),I=arguments[0]||null,x=arguments[1]);const B=Math.pow(2,-O),N=Math.floor(x.image.width*B),Q=Math.floor(x.image.height*B),ht=I!==null?I.x:0,gt=I!==null?I.y:0;E.setTexture2D(x,0),w.copyTexSubImage2D(w.TEXTURE_2D,O,0,0,ht,gt,N,Q),Mt.unbindTexture()};const yc=w.createFramebuffer(),Ec=w.createFramebuffer();this.copyTextureToTexture=function(x,I,O=null,B=null,N=0,Q=null){x.isTexture!==!0&&(Ai("WebGLRenderer: copyTextureToTexture function signature has changed."),B=arguments[0]||null,x=arguments[1],I=arguments[2],Q=arguments[3]||0,O=null),Q===null&&(N!==0?(Ai("WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels."),Q=N,N=0):Q=0);let ht,gt,_t,It,Ft,Tt,Zt,Qt,me;const fe=x.isCompressedTexture?x.mipmaps[Q]:x.image;if(O!==null)ht=O.max.x-O.min.x,gt=O.max.y-O.min.y,_t=O.isBox3?O.max.z-O.min.z:1,It=O.min.x,Ft=O.min.y,Tt=O.isBox3?O.min.z:0;else{const Ke=Math.pow(2,-N);ht=Math.floor(fe.width*Ke),gt=Math.floor(fe.height*Ke),x.isDataArrayTexture?_t=fe.depth:x.isData3DTexture?_t=Math.floor(fe.depth*Ke):_t=1,It=0,Ft=0,Tt=0}B!==null?(Zt=B.x,Qt=B.y,me=B.z):(Zt=0,Qt=0,me=0);const Kt=zt.convert(I.format),At=zt.convert(I.type);let Te;I.isData3DTexture?(E.setTexture3D(I,0),Te=w.TEXTURE_3D):I.isDataArrayTexture||I.isCompressedArrayTexture?(E.setTexture2DArray(I,0),Te=w.TEXTURE_2D_ARRAY):(E.setTexture2D(I,0),Te=w.TEXTURE_2D),w.pixelStorei(w.UNPACK_FLIP_Y_WEBGL,I.flipY),w.pixelStorei(w.UNPACK_PREMULTIPLY_ALPHA_WEBGL,I.premultiplyAlpha),w.pixelStorei(w.UNPACK_ALIGNMENT,I.unpackAlignment);const te=w.getParameter(w.UNPACK_ROW_LENGTH),en=w.getParameter(w.UNPACK_IMAGE_HEIGHT),ai=w.getParameter(w.UNPACK_SKIP_PIXELS),Ge=w.getParameter(w.UNPACK_SKIP_ROWS),Xi=w.getParameter(w.UNPACK_SKIP_IMAGES);w.pixelStorei(w.UNPACK_ROW_LENGTH,fe.width),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,fe.height),w.pixelStorei(w.UNPACK_SKIP_PIXELS,It),w.pixelStorei(w.UNPACK_SKIP_ROWS,Ft),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Tt);const ue=x.isDataArrayTexture||x.isData3DTexture,Ze=I.isDataArrayTexture||I.isData3DTexture;if(x.isDepthTexture){const Ke=Et.get(x),De=Et.get(I),Fe=Et.get(Ke.__renderTarget),mr=Et.get(De.__renderTarget);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,Fe.__webglFramebuffer),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,mr.__webglFramebuffer);for(let Vn=0;Vn<_t;Vn++)ue&&(w.framebufferTextureLayer(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Et.get(x).__webglTexture,N,Tt+Vn),w.framebufferTextureLayer(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Et.get(I).__webglTexture,Q,me+Vn)),w.blitFramebuffer(It,Ft,ht,gt,Zt,Qt,ht,gt,w.DEPTH_BUFFER_BIT,w.NEAREST);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,null),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,null)}else if(N!==0||x.isRenderTargetTexture||Et.has(x)){const Ke=Et.get(x),De=Et.get(I);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,yc),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,Ec);for(let Fe=0;Fe<_t;Fe++)ue?w.framebufferTextureLayer(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Ke.__webglTexture,N,Tt+Fe):w.framebufferTexture2D(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,Ke.__webglTexture,N),Ze?w.framebufferTextureLayer(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,De.__webglTexture,Q,me+Fe):w.framebufferTexture2D(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,De.__webglTexture,Q),N!==0?w.blitFramebuffer(It,Ft,ht,gt,Zt,Qt,ht,gt,w.COLOR_BUFFER_BIT,w.NEAREST):Ze?w.copyTexSubImage3D(Te,Q,Zt,Qt,me+Fe,It,Ft,ht,gt):w.copyTexSubImage2D(Te,Q,Zt,Qt,It,Ft,ht,gt);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,null),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,null)}else Ze?x.isDataTexture||x.isData3DTexture?w.texSubImage3D(Te,Q,Zt,Qt,me,ht,gt,_t,Kt,At,fe.data):I.isCompressedArrayTexture?w.compressedTexSubImage3D(Te,Q,Zt,Qt,me,ht,gt,_t,Kt,fe.data):w.texSubImage3D(Te,Q,Zt,Qt,me,ht,gt,_t,Kt,At,fe):x.isDataTexture?w.texSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,ht,gt,Kt,At,fe.data):x.isCompressedTexture?w.compressedTexSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,fe.width,fe.height,Kt,fe.data):w.texSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,ht,gt,Kt,At,fe);w.pixelStorei(w.UNPACK_ROW_LENGTH,te),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,en),w.pixelStorei(w.UNPACK_SKIP_PIXELS,ai),w.pixelStorei(w.UNPACK_SKIP_ROWS,Ge),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Xi),Q===0&&I.generateMipmaps&&w.generateMipmap(Te),Mt.unbindTexture()},this.copyTextureToTexture3D=function(x,I,O=null,B=null,N=0){return x.isTexture!==!0&&(Ai("WebGLRenderer: copyTextureToTexture3D function signature has changed."),O=arguments[0]||null,B=arguments[1]||null,x=arguments[2],I=arguments[3],N=arguments[4]||0),Ai('WebGLRenderer: copyTextureToTexture3D function has been deprecated. Use "copyTextureToTexture" instead.'),this.copyTextureToTexture(x,I,O,B,N)},this.initRenderTarget=function(x){Et.get(x).__webglFramebuffer===void 0&&E.setupRenderTarget(x)},this.initTexture=function(x){x.isCubeTexture?E.setTextureCube(x,0):x.isData3DTexture?E.setTexture3D(x,0):x.isDataArrayTexture||x.isCompressedArrayTexture?E.setTexture2DArray(x,0):E.setTexture2D(x,0),Mt.unbindTexture()},this.resetState=function(){R=0,A=0,U=null,Mt.reset(),ie.reset()},typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return En}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(t){this._outputColorSpace=t;const e=this.getContext();e.drawingBufferColorspace=$t._getDrawingBufferColorSpace(t),e.unpackColorSpace=$t._getUnpackColorSpace()}}const yl={type:"change"},io={type:"start"},mc={type:"end"},Ws=new cs,El=new Nn,Km=Math.cos(70*yh.DEG2RAD),Me=new P,Oe=2*Math.PI,oe={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},Kr=1e-6;class $m extends uu{constructor(t,e=null){super(t,e),this.state=oe.NONE,this.enabled=!0,this.target=new P,this.cursor=new P,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minTargetRadius=0,this.maxTargetRadius=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.keyRotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:Di.ROTATE,MIDDLE:Di.DOLLY,RIGHT:Di.PAN},this.touches={ONE:Ri.ROTATE,TWO:Ri.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this._lastPosition=new P,this._lastQuaternion=new ni,this._lastTargetPosition=new P,this._quat=new ni().setFromUnitVectors(t.up,new P(0,1,0)),this._quatInverse=this._quat.clone().invert(),this._spherical=new Ko,this._sphericalDelta=new Ko,this._scale=1,this._panOffset=new P,this._rotateStart=new vt,this._rotateEnd=new vt,this._rotateDelta=new vt,this._panStart=new vt,this._panEnd=new vt,this._panDelta=new vt,this._dollyStart=new vt,this._dollyEnd=new vt,this._dollyDelta=new vt,this._dollyDirection=new P,this._mouse=new vt,this._performCursorZoom=!1,this._pointers=[],this._pointerPositions={},this._controlActive=!1,this._onPointerMove=Qm.bind(this),this._onPointerDown=Jm.bind(this),this._onPointerUp=tg.bind(this),this._onContextMenu=og.bind(this),this._onMouseWheel=ig.bind(this),this._onKeyDown=sg.bind(this),this._onTouchStart=rg.bind(this),this._onTouchMove=ag.bind(this),this._onMouseDown=eg.bind(this),this._onMouseMove=ng.bind(this),this._interceptControlDown=lg.bind(this),this._interceptControlUp=cg.bind(this),this.domElement!==null&&this.connect(),this.update()}connect(){this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointercancel",this._onPointerUp),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("wheel",this._onMouseWheel,{passive:!1}),this.domElement.getRootNode().addEventListener("keydown",this._interceptControlDown,{passive:!0,capture:!0}),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointercancel",this._onPointerUp),this.domElement.removeEventListener("wheel",this._onMouseWheel),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.stopListenToKeyEvents(),this.domElement.getRootNode().removeEventListener("keydown",this._interceptControlDown,{capture:!0}),this.domElement.style.touchAction="auto"}dispose(){this.disconnect()}getPolarAngle(){return this._spherical.phi}getAzimuthalAngle(){return this._spherical.theta}getDistance(){return this.object.position.distanceTo(this.target)}listenToKeyEvents(t){t.addEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=t}stopListenToKeyEvents(){this._domElementKeyEvents!==null&&(this._domElementKeyEvents.removeEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=null)}saveState(){this.target0.copy(this.target),this.position0.copy(this.object.position),this.zoom0=this.object.zoom}reset(){this.target.copy(this.target0),this.object.position.copy(this.position0),this.object.zoom=this.zoom0,this.object.updateProjectionMatrix(),this.dispatchEvent(yl),this.update(),this.state=oe.NONE}update(t=null){const e=this.object.position;Me.copy(e).sub(this.target),Me.applyQuaternion(this._quat),this._spherical.setFromVector3(Me),this.autoRotate&&this.state===oe.NONE&&this._rotateLeft(this._getAutoRotationAngle(t)),this.enableDamping?(this._spherical.theta+=this._sphericalDelta.theta*this.dampingFactor,this._spherical.phi+=this._sphericalDelta.phi*this.dampingFactor):(this._spherical.theta+=this._sphericalDelta.theta,this._spherical.phi+=this._sphericalDelta.phi);let n=this.minAzimuthAngle,s=this.maxAzimuthAngle;isFinite(n)&&isFinite(s)&&(n<-Math.PI?n+=Oe:n>Math.PI&&(n-=Oe),s<-Math.PI?s+=Oe:s>Math.PI&&(s-=Oe),n<=s?this._spherical.theta=Math.max(n,Math.min(s,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(n+s)/2?Math.max(n,this._spherical.theta):Math.min(s,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let r=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const a=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),r=a!=this._spherical.radius}if(Me.setFromSpherical(this._spherical),Me.applyQuaternion(this._quatInverse),e.copy(this.target).add(Me),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let a=null;if(this.object.isPerspectiveCamera){const o=Me.length();a=this._clampDistance(o*this._scale);const l=o-a;this.object.position.addScaledVector(this._dollyDirection,l),this.object.updateMatrixWorld(),r=!!l}else if(this.object.isOrthographicCamera){const o=new P(this._mouse.x,this._mouse.y,0);o.unproject(this.object);const l=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),r=l!==this.object.zoom;const c=new P(this._mouse.x,this._mouse.y,0);c.unproject(this.object),this.object.position.sub(c).add(o),this.object.updateMatrixWorld(),a=Me.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;a!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(a).add(this.object.position):(Ws.origin.copy(this.object.position),Ws.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(Ws.direction))Kr||8*(1-this._lastQuaternion.dot(this.object.quaternion))>Kr||this._lastTargetPosition.distanceToSquared(this.target)>Kr?(this.dispatchEvent(yl),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(t){return t!==null?Oe/60*this.autoRotateSpeed*t:Oe/60/60*this.autoRotateSpeed}_getZoomScale(t){const e=Math.abs(t*.01);return Math.pow(.95,this.zoomSpeed*e)}_rotateLeft(t){this._sphericalDelta.theta-=t}_rotateUp(t){this._sphericalDelta.phi-=t}_panLeft(t,e){Me.setFromMatrixColumn(e,0),Me.multiplyScalar(-t),this._panOffset.add(Me)}_panUp(t,e){this.screenSpacePanning===!0?Me.setFromMatrixColumn(e,1):(Me.setFromMatrixColumn(e,0),Me.crossVectors(this.object.up,Me)),Me.multiplyScalar(t),this._panOffset.add(Me)}_pan(t,e){const n=this.domElement;if(this.object.isPerspectiveCamera){const s=this.object.position;Me.copy(s).sub(this.target);let r=Me.length();r*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*t*r/n.clientHeight,this.object.matrix),this._panUp(2*e*r/n.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(t*(this.object.right-this.object.left)/this.object.zoom/n.clientWidth,this.object.matrix),this._panUp(e*(this.object.top-this.object.bottom)/this.object.zoom/n.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(t,e){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const n=this.domElement.getBoundingClientRect(),s=t-n.left,r=e-n.top,a=n.width,o=n.height;this._mouse.x=s/a*2-1,this._mouse.y=-(r/o)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(t){return Math.max(this.minDistance,Math.min(this.maxDistance,t))}_handleMouseDownRotate(t){this._rotateStart.set(t.clientX,t.clientY)}_handleMouseDownDolly(t){this._updateZoomParameters(t.clientX,t.clientX),this._dollyStart.set(t.clientX,t.clientY)}_handleMouseDownPan(t){this._panStart.set(t.clientX,t.clientY)}_handleMouseMoveRotate(t){this._rotateEnd.set(t.clientX,t.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Oe*this._rotateDelta.x/e.clientHeight),this._rotateUp(Oe*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(t){this._dollyEnd.set(t.clientX,t.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(t){this._panEnd.set(t.clientX,t.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(t){this._updateZoomParameters(t.clientX,t.clientY),t.deltaY<0?this._dollyIn(this._getZoomScale(t.deltaY)):t.deltaY>0&&this._dollyOut(this._getZoomScale(t.deltaY)),this.update()}_handleKeyDown(t){let e=!1;switch(t.code){case this.keys.UP:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),e=!0;break;case this.keys.BOTTOM:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(-Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),e=!0;break;case this.keys.LEFT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),e=!0;break;case this.keys.RIGHT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(-Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),e=!0;break}e&&(t.preventDefault(),this.update())}_handleTouchStartRotate(t){if(this._pointers.length===1)this._rotateStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._rotateStart.set(n,s)}}_handleTouchStartPan(t){if(this._pointers.length===1)this._panStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panStart.set(n,s)}}_handleTouchStartDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyStart.set(0,r)}_handleTouchStartDollyPan(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enablePan&&this._handleTouchStartPan(t)}_handleTouchStartDollyRotate(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enableRotate&&this._handleTouchStartRotate(t)}_handleTouchMoveRotate(t){if(this._pointers.length==1)this._rotateEnd.set(t.pageX,t.pageY);else{const n=this._getSecondPointerPosition(t),s=.5*(t.pageX+n.x),r=.5*(t.pageY+n.y);this._rotateEnd.set(s,r)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Oe*this._rotateDelta.x/e.clientHeight),this._rotateUp(Oe*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(t){if(this._pointers.length===1)this._panEnd.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panEnd.set(n,s)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyEnd.set(0,r),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const a=(t.pageX+e.x)*.5,o=(t.pageY+e.y)*.5;this._updateZoomParameters(a,o)}_handleTouchMoveDollyPan(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enablePan&&this._handleTouchMovePan(t)}_handleTouchMoveDollyRotate(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enableRotate&&this._handleTouchMoveRotate(t)}_addPointer(t){this._pointers.push(t.pointerId)}_removePointer(t){delete this._pointerPositions[t.pointerId];for(let e=0;e=0&&(y[at]=null,b[at].disconnect(xt))}for(let nt=0;nt=y.length){y.push(xt),at=Ut;break}else if(y[Ut]===null){y[Ut]=xt,at=Ut;break}if(at===-1)break}const wt=b[at];wt&&wt.connect(xt)}}const G=new P,J=new P;function k(Y,nt,xt){G.setFromMatrixPosition(nt.matrixWorld),J.setFromMatrixPosition(xt.matrixWorld);const at=G.distanceTo(J),wt=nt.projectionMatrix.elements,Ut=xt.projectionMatrix.elements,Gt=wt[14]/(wt[10]-1),ce=wt[14]/(wt[10]+1),rt=(wt[9]+1)/wt[5],Ct=(wt[9]-1)/wt[5],w=(wt[8]-1)/wt[0],ve=(Ut[8]+1)/Ut[0],Bt=Gt*w,kt=Gt*ve,Mt=at/(-w+ve),ne=Mt*-w;if(nt.matrixWorld.decompose(Y.position,Y.quaternion,Y.scale),Y.translateX(ne),Y.translateZ(Mt),Y.matrixWorld.compose(Y.position,Y.quaternion,Y.scale),Y.matrixWorldInverse.copy(Y.matrixWorld).invert(),wt[10]===-1)Y.projectionMatrix.copy(nt.projectionMatrix),Y.projectionMatrixInverse.copy(nt.projectionMatrixInverse);else{const Et=Gt+Mt,E=ce+Mt,_=Bt-ne,F=kt+(at-ne),Z=rt*ce/E*Et,K=Ct*ce/E*Et;Y.projectionMatrix.makePerspective(_,F,Z,K,Et,E),Y.projectionMatrixInverse.copy(Y.projectionMatrix).invert()}}function it(Y,nt){nt===null?Y.matrixWorld.copy(Y.matrix):Y.matrixWorld.multiplyMatrices(nt.matrixWorld,Y.matrix),Y.matrixWorldInverse.copy(Y.matrixWorld).invert()}this.updateCamera=function(Y){if(s===null)return;let nt=Y.near,xt=Y.far;v.texture!==null&&(v.depthNear>0&&(nt=v.depthNear),v.depthFar>0&&(xt=v.depthFar)),M.near=U.near=A.near=nt,M.far=U.far=A.far=xt,(D!==M.near||W!==M.far)&&(s.updateRenderState({depthNear:M.near,depthFar:M.far}),D=M.near,W=M.far),A.layers.mask=Y.layers.mask|2,U.layers.mask=Y.layers.mask|4,M.layers.mask=A.layers.mask|U.layers.mask;const at=Y.parent,wt=M.cameras;it(M,at);for(let Ut=0;Ut0&&(m.alphaTest.value=u.alphaTest);const T=t.get(u),b=T.envMap,y=T.envMapRotation;b&&(m.envMap.value=b,jn.copy(y),jn.x*=-1,jn.y*=-1,jn.z*=-1,b.isCubeTexture&&b.isRenderTargetTexture===!1&&(jn.y*=-1,jn.z*=-1),m.envMapRotation.value.setFromMatrix4(qm.makeRotationFromEuler(jn)),m.flipEnvMap.value=b.isCubeTexture&&b.isRenderTargetTexture===!1?-1:1,m.reflectivity.value=u.reflectivity,m.ior.value=u.ior,m.refractionRatio.value=u.refractionRatio),u.lightMap&&(m.lightMap.value=u.lightMap,m.lightMapIntensity.value=u.lightMapIntensity,e(u.lightMap,m.lightMapTransform)),u.aoMap&&(m.aoMap.value=u.aoMap,m.aoMapIntensity.value=u.aoMapIntensity,e(u.aoMap,m.aoMapTransform))}function a(m,u){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,u.map&&(m.map.value=u.map,e(u.map,m.mapTransform))}function o(m,u){m.dashSize.value=u.dashSize,m.totalSize.value=u.dashSize+u.gapSize,m.scale.value=u.scale}function l(m,u,T,b){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,m.size.value=u.size*T,m.scale.value=b*.5,u.map&&(m.map.value=u.map,e(u.map,m.uvTransform)),u.alphaMap&&(m.alphaMap.value=u.alphaMap,e(u.alphaMap,m.alphaMapTransform)),u.alphaTest>0&&(m.alphaTest.value=u.alphaTest)}function c(m,u){m.diffuse.value.copy(u.color),m.opacity.value=u.opacity,m.rotation.value=u.rotation,u.map&&(m.map.value=u.map,e(u.map,m.mapTransform)),u.alphaMap&&(m.alphaMap.value=u.alphaMap,e(u.alphaMap,m.alphaMapTransform)),u.alphaTest>0&&(m.alphaTest.value=u.alphaTest)}function h(m,u){m.specular.value.copy(u.specular),m.shininess.value=Math.max(u.shininess,1e-4)}function d(m,u){u.gradientMap&&(m.gradientMap.value=u.gradientMap)}function p(m,u){m.metalness.value=u.metalness,u.metalnessMap&&(m.metalnessMap.value=u.metalnessMap,e(u.metalnessMap,m.metalnessMapTransform)),m.roughness.value=u.roughness,u.roughnessMap&&(m.roughnessMap.value=u.roughnessMap,e(u.roughnessMap,m.roughnessMapTransform)),u.envMap&&(m.envMapIntensity.value=u.envMapIntensity)}function f(m,u,T){m.ior.value=u.ior,u.sheen>0&&(m.sheenColor.value.copy(u.sheenColor).multiplyScalar(u.sheen),m.sheenRoughness.value=u.sheenRoughness,u.sheenColorMap&&(m.sheenColorMap.value=u.sheenColorMap,e(u.sheenColorMap,m.sheenColorMapTransform)),u.sheenRoughnessMap&&(m.sheenRoughnessMap.value=u.sheenRoughnessMap,e(u.sheenRoughnessMap,m.sheenRoughnessMapTransform))),u.clearcoat>0&&(m.clearcoat.value=u.clearcoat,m.clearcoatRoughness.value=u.clearcoatRoughness,u.clearcoatMap&&(m.clearcoatMap.value=u.clearcoatMap,e(u.clearcoatMap,m.clearcoatMapTransform)),u.clearcoatRoughnessMap&&(m.clearcoatRoughnessMap.value=u.clearcoatRoughnessMap,e(u.clearcoatRoughnessMap,m.clearcoatRoughnessMapTransform)),u.clearcoatNormalMap&&(m.clearcoatNormalMap.value=u.clearcoatNormalMap,e(u.clearcoatNormalMap,m.clearcoatNormalMapTransform),m.clearcoatNormalScale.value.copy(u.clearcoatNormalScale),u.side===ke&&m.clearcoatNormalScale.value.negate())),u.dispersion>0&&(m.dispersion.value=u.dispersion),u.iridescence>0&&(m.iridescence.value=u.iridescence,m.iridescenceIOR.value=u.iridescenceIOR,m.iridescenceThicknessMinimum.value=u.iridescenceThicknessRange[0],m.iridescenceThicknessMaximum.value=u.iridescenceThicknessRange[1],u.iridescenceMap&&(m.iridescenceMap.value=u.iridescenceMap,e(u.iridescenceMap,m.iridescenceMapTransform)),u.iridescenceThicknessMap&&(m.iridescenceThicknessMap.value=u.iridescenceThicknessMap,e(u.iridescenceThicknessMap,m.iridescenceThicknessMapTransform))),u.transmission>0&&(m.transmission.value=u.transmission,m.transmissionSamplerMap.value=T.texture,m.transmissionSamplerSize.value.set(T.width,T.height),u.transmissionMap&&(m.transmissionMap.value=u.transmissionMap,e(u.transmissionMap,m.transmissionMapTransform)),m.thickness.value=u.thickness,u.thicknessMap&&(m.thicknessMap.value=u.thicknessMap,e(u.thicknessMap,m.thicknessMapTransform)),m.attenuationDistance.value=u.attenuationDistance,m.attenuationColor.value.copy(u.attenuationColor)),u.anisotropy>0&&(m.anisotropyVector.value.set(u.anisotropy*Math.cos(u.anisotropyRotation),u.anisotropy*Math.sin(u.anisotropyRotation)),u.anisotropyMap&&(m.anisotropyMap.value=u.anisotropyMap,e(u.anisotropyMap,m.anisotropyMapTransform))),m.specularIntensity.value=u.specularIntensity,m.specularColor.value.copy(u.specularColor),u.specularColorMap&&(m.specularColorMap.value=u.specularColorMap,e(u.specularColorMap,m.specularColorMapTransform)),u.specularIntensityMap&&(m.specularIntensityMap.value=u.specularIntensityMap,e(u.specularIntensityMap,m.specularIntensityMapTransform))}function g(m,u){u.matcap&&(m.matcap.value=u.matcap)}function v(m,u){const T=t.get(u).light;m.referencePosition.value.setFromMatrixPosition(T.matrixWorld),m.nearDistance.value=T.shadow.camera.near,m.farDistance.value=T.shadow.camera.far}return{refreshFogUniforms:n,refreshMaterialUniforms:s}}function Zm(i,t,e,n){let s={},r={},a=[];const o=i.getParameter(i.MAX_UNIFORM_BUFFER_BINDINGS);function l(T,b){const y=b.program;n.uniformBlockBinding(T,y)}function c(T,b){let y=s[T.id];y===void 0&&(g(T),y=h(T),s[T.id]=y,T.addEventListener("dispose",m));const L=b.program;n.updateUBOMapping(T,L);const R=t.render.frame;r[T.id]!==R&&(p(T),r[T.id]=R)}function h(T){const b=d();T.__bindingPointIndex=b;const y=i.createBuffer(),L=T.__size,R=T.usage;return i.bindBuffer(i.UNIFORM_BUFFER,y),i.bufferData(i.UNIFORM_BUFFER,L,R),i.bindBuffer(i.UNIFORM_BUFFER,null),i.bindBufferBase(i.UNIFORM_BUFFER,b,y),y}function d(){for(let T=0;T0&&(y+=L-R),T.__size=y,T.__cache={},this}function v(T){const b={boundary:0,storage:0};return typeof T=="number"||typeof T=="boolean"?(b.boundary=4,b.storage=4):T.isVector2?(b.boundary=8,b.storage=8):T.isVector3||T.isColor?(b.boundary=16,b.storage=12):T.isVector4?(b.boundary=16,b.storage=16):T.isMatrix3?(b.boundary=48,b.storage=48):T.isMatrix4?(b.boundary=64,b.storage=64):T.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",T),b}function m(T){const b=T.target;b.removeEventListener("dispose",m);const y=a.indexOf(b.__bindingPointIndex);a.splice(y,1),i.deleteBuffer(s[b.id]),delete s[b.id],delete r[b.id]}function u(){for(const T in s)i.deleteBuffer(s[T]);a=[],s={},r={}}return{bind:l,update:c,dispose:u}}class Km{constructor(t={}){const{canvas:e=Th(),context:n=null,depth:s=!0,stencil:r=!1,alpha:a=!1,antialias:o=!1,premultipliedAlpha:l=!0,preserveDrawingBuffer:c=!1,powerPreference:h="default",failIfMajorPerformanceCaveat:d=!1,reverseDepthBuffer:p=!1}=t;this.isWebGLRenderer=!0;let f;if(n!==null){if(typeof WebGLRenderingContext<"u"&&n instanceof WebGLRenderingContext)throw new Error("THREE.WebGLRenderer: WebGL 1 is not supported since r163.");f=n.getContextAttributes().alpha}else f=a;const g=new Uint32Array(4),v=new Int32Array(4);let m=null,u=null;const T=[],b=[];this.domElement=e,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this._outputColorSpace=Qe,this.toneMapping=On,this.toneMappingExposure=1;const y=this;let L=!1,R=0,A=0,U=null,S=-1,M=null;const D=new le,W=new le;let z=null;const V=new pt(0);let $=0,G=e.width,J=e.height,k=1,it=null,ut=null;const yt=new le(0,0,G,J),Lt=new le(0,0,G,J);let qt=!1;const Y=new eo;let nt=!1,xt=!1;this.transmissionResolutionScale=1;const at=new ee,wt=new ee,Ut=new P,Gt=new le,ce={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};let rt=!1;function Ct(){return U===null?k:1}let w=n;function ve(x,I){return e.getContext(x,I)}try{const x={alpha:!0,depth:s,stencil:r,antialias:o,premultipliedAlpha:l,preserveDrawingBuffer:c,powerPreference:h,failIfMajorPerformanceCaveat:d};if("setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Ya}`),e.addEventListener("webglcontextlost",q,!1),e.addEventListener("webglcontextrestored",lt,!1),e.addEventListener("webglcontextcreationerror",ct,!1),w===null){const I="webgl2";if(w=ve(I,x),w===null)throw ve(I)?new Error("Error creating WebGL context with your selected attributes."):new Error("Error creating WebGL context.")}}catch(x){throw console.error("THREE.WebGLRenderer: "+x.message),x}let Bt,kt,Mt,ne,Et,E,_,F,Z,K,X,St,ot,dt,jt,tt,mt,bt,Pt,ft,Xt,zt,se,C;function et(){Bt=new rp(w),Bt.init(),zt=new km(w,Bt),kt=new Qf(w,Bt,t,zt),Mt=new zm(w,Bt),kt.reverseDepthBuffer&&p&&Mt.buffers.depth.setReversed(!0),ne=new lp(w),Et=new wm,E=new Hm(w,Bt,Mt,Et,kt,zt,ne),_=new ep(y),F=new sp(y),Z=new pu(w),se=new $f(w,Z),K=new ap(w,Z,ne,se),X=new hp(w,K,Z,ne),Pt=new cp(w,kt,E),tt=new tp(Et),St=new Tm(y,_,F,Bt,kt,se,tt),ot=new jm(y,Et),dt=new Rm,jt=new Im(Bt),bt=new Kf(y,_,F,Mt,X,f,l),mt=new Om(y,X,kt),C=new Zm(w,ne,kt,Mt),ft=new Jf(w,Bt,ne),Xt=new op(w,Bt,ne),ne.programs=St.programs,y.capabilities=kt,y.extensions=Bt,y.properties=Et,y.renderLists=dt,y.shadowMap=mt,y.state=Mt,y.info=ne}et();const H=new Ym(y,w);this.xr=H,this.getContext=function(){return w},this.getContextAttributes=function(){return w.getContextAttributes()},this.forceContextLoss=function(){const x=Bt.get("WEBGL_lose_context");x&&x.loseContext()},this.forceContextRestore=function(){const x=Bt.get("WEBGL_lose_context");x&&x.restoreContext()},this.getPixelRatio=function(){return k},this.setPixelRatio=function(x){x!==void 0&&(k=x,this.setSize(G,J,!1))},this.getSize=function(x){return x.set(G,J)},this.setSize=function(x,I,O=!0){if(H.isPresenting){console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting.");return}G=x,J=I,e.width=Math.floor(x*k),e.height=Math.floor(I*k),O===!0&&(e.style.width=x+"px",e.style.height=I+"px"),this.setViewport(0,0,x,I)},this.getDrawingBufferSize=function(x){return x.set(G*k,J*k).floor()},this.setDrawingBufferSize=function(x,I,O){G=x,J=I,k=O,e.width=Math.floor(x*O),e.height=Math.floor(I*O),this.setViewport(0,0,x,I)},this.getCurrentViewport=function(x){return x.copy(D)},this.getViewport=function(x){return x.copy(yt)},this.setViewport=function(x,I,O,B){x.isVector4?yt.set(x.x,x.y,x.z,x.w):yt.set(x,I,O,B),Mt.viewport(D.copy(yt).multiplyScalar(k).round())},this.getScissor=function(x){return x.copy(Lt)},this.setScissor=function(x,I,O,B){x.isVector4?Lt.set(x.x,x.y,x.z,x.w):Lt.set(x,I,O,B),Mt.scissor(W.copy(Lt).multiplyScalar(k).round())},this.getScissorTest=function(){return qt},this.setScissorTest=function(x){Mt.setScissorTest(qt=x)},this.setOpaqueSort=function(x){it=x},this.setTransparentSort=function(x){ut=x},this.getClearColor=function(x){return x.copy(bt.getClearColor())},this.setClearColor=function(){bt.setClearColor.apply(bt,arguments)},this.getClearAlpha=function(){return bt.getClearAlpha()},this.setClearAlpha=function(){bt.setClearAlpha.apply(bt,arguments)},this.clear=function(x=!0,I=!0,O=!0){let B=0;if(x){let N=!1;if(U!==null){const Q=U.texture.format;N=Q===Qa||Q===Ja||Q===$a}if(N){const Q=U.texture.type,ht=Q===An||Q===ni||Q===ls||Q===Hi||Q===ja||Q===Za,gt=bt.getClearColor(),_t=bt.getClearAlpha(),It=gt.r,Ft=gt.g,Tt=gt.b;ht?(g[0]=It,g[1]=Ft,g[2]=Tt,g[3]=_t,w.clearBufferuiv(w.COLOR,0,g)):(v[0]=It,v[1]=Ft,v[2]=Tt,v[3]=_t,w.clearBufferiv(w.COLOR,0,v))}else B|=w.COLOR_BUFFER_BIT}I&&(B|=w.DEPTH_BUFFER_BIT),O&&(B|=w.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),w.clear(B)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){e.removeEventListener("webglcontextlost",q,!1),e.removeEventListener("webglcontextrestored",lt,!1),e.removeEventListener("webglcontextcreationerror",ct,!1),bt.dispose(),dt.dispose(),jt.dispose(),Et.dispose(),_.dispose(),F.dispose(),X.dispose(),se.dispose(),C.dispose(),St.dispose(),H.dispose(),H.removeEventListener("sessionstart",ro),H.removeEventListener("sessionend",ao),kn.stop()};function q(x){x.preventDefault(),console.log("THREE.WebGLRenderer: Context Lost."),L=!0}function lt(){console.log("THREE.WebGLRenderer: Context Restored."),L=!1;const x=ne.autoReset,I=mt.enabled,O=mt.autoUpdate,B=mt.needsUpdate,N=mt.type;et(),ne.autoReset=x,mt.enabled=I,mt.autoUpdate=O,mt.needsUpdate=B,mt.type=N}function ct(x){console.error("THREE.WebGLRenderer: A WebGL context could not be created. Reason: ",x.statusMessage)}function Nt(x){const I=x.target;I.removeEventListener("dispose",Nt),ue(I)}function ue(x){xe(x),Et.remove(x)}function xe(x){const I=Et.get(x).programs;I!==void 0&&(I.forEach(function(O){St.releaseProgram(O)}),x.isShaderMaterial&&St.releaseShaderCache(x))}this.renderBufferDirect=function(x,I,O,B,N,Q){I===null&&(I=ce);const ht=N.isMesh&&N.matrixWorld.determinant()<0,gt=Mc(x,I,O,B,N);Mt.setMaterial(B,ht);let _t=O.index,It=1;if(B.wireframe===!0){if(_t=K.getWireframeAttribute(O),_t===void 0)return;It=2}const Ft=O.drawRange,Tt=O.attributes.position;let Zt=Ft.start*It,Qt=(Ft.start+Ft.count)*It;Q!==null&&(Zt=Math.max(Zt,Q.start*It),Qt=Math.min(Qt,(Q.start+Q.count)*It)),_t!==null?(Zt=Math.max(Zt,0),Qt=Math.min(Qt,_t.count)):Tt!=null&&(Zt=Math.max(Zt,0),Qt=Math.min(Qt,Tt.count));const me=Qt-Zt;if(me<0||me===1/0)return;se.setup(N,B,gt,O,_t);let fe,Kt=ft;if(_t!==null&&(fe=Z.get(_t),Kt=Xt,Kt.setIndex(fe)),N.isMesh)B.wireframe===!0?(Mt.setLineWidth(B.wireframeLinewidth*Ct()),Kt.setMode(w.LINES)):Kt.setMode(w.TRIANGLES);else if(N.isLine){let At=B.linewidth;At===void 0&&(At=1),Mt.setLineWidth(At*Ct()),N.isLineSegments?Kt.setMode(w.LINES):N.isLineLoop?Kt.setMode(w.LINE_LOOP):Kt.setMode(w.LINE_STRIP)}else N.isPoints?Kt.setMode(w.POINTS):N.isSprite&&Kt.setMode(w.TRIANGLES);if(N.isBatchedMesh)if(N._multiDrawInstances!==null)Kt.renderMultiDrawInstances(N._multiDrawStarts,N._multiDrawCounts,N._multiDrawCount,N._multiDrawInstances);else if(Bt.get("WEBGL_multi_draw"))Kt.renderMultiDraw(N._multiDrawStarts,N._multiDrawCounts,N._multiDrawCount);else{const At=N._multiDrawStarts,we=N._multiDrawCounts,te=N._multiDrawCount,en=_t?Z.get(_t).bytesPerElement:1,oi=Et.get(B).currentProgram.getUniforms();for(let Ge=0;Ge{function Q(){if(B.forEach(function(ht){Et.get(ht).currentProgram.isReady()&&B.delete(ht)}),B.size===0){N(x);return}setTimeout(Q,10)}Bt.get("KHR_parallel_shader_compile")!==null?Q():setTimeout(Q,10)})};let Ve=null;function mn(x){Ve&&Ve(x)}function ro(){kn.stop()}function ao(){kn.start()}const kn=new dc;kn.setAnimationLoop(mn),typeof self<"u"&&kn.setContext(self),this.setAnimationLoop=function(x){Ve=x,H.setAnimationLoop(x),x===null?kn.stop():kn.start()},H.addEventListener("sessionstart",ro),H.addEventListener("sessionend",ao),this.render=function(x,I){if(I!==void 0&&I.isCamera!==!0){console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");return}if(L===!0)return;if(x.matrixWorldAutoUpdate===!0&&x.updateMatrixWorld(),I.parent===null&&I.matrixWorldAutoUpdate===!0&&I.updateMatrixWorld(),H.enabled===!0&&H.isPresenting===!0&&(H.cameraAutoUpdate===!0&&H.updateCamera(I),I=H.getCamera()),x.isScene===!0&&x.onBeforeRender(y,x,I,U),u=jt.get(x,b.length),u.init(I),b.push(u),wt.multiplyMatrices(I.projectionMatrix,I.matrixWorldInverse),Y.setFromProjectionMatrix(wt),xt=this.localClippingEnabled,nt=tt.init(this.clippingPlanes,xt),m=dt.get(x,T.length),m.init(),T.push(m),H.enabled===!0&&H.isPresenting===!0){const Q=y.xr.getDepthSensingMesh();Q!==null&&_r(Q,I,-1/0,y.sortObjects)}_r(x,I,0,y.sortObjects),m.finish(),y.sortObjects===!0&&m.sort(it,ut),rt=H.enabled===!1||H.isPresenting===!1||H.hasDepthSensing()===!1,rt&&bt.addToRenderList(m,x),this.info.render.frame++,nt===!0&&tt.beginShadows();const O=u.state.shadowsArray;mt.render(O,x,I),nt===!0&&tt.endShadows(),this.info.autoReset===!0&&this.info.reset();const B=m.opaque,N=m.transmissive;if(u.setupLights(),I.isArrayCamera){const Q=I.cameras;if(N.length>0)for(let ht=0,gt=Q.length;ht0&&lo(B,N,x,I),rt&&bt.render(x),oo(m,x,I);U!==null&&A===0&&(E.updateMultisampleRenderTarget(U),E.updateRenderTargetMipmap(U)),x.isScene===!0&&x.onAfterRender(y,x,I),se.resetDefaultState(),S=-1,M=null,b.pop(),b.length>0?(u=b[b.length-1],nt===!0&&tt.setGlobalState(y.clippingPlanes,u.state.camera)):u=null,T.pop(),T.length>0?m=T[T.length-1]:m=null};function _r(x,I,O,B){if(x.visible===!1)return;if(x.layers.test(I.layers)){if(x.isGroup)O=x.renderOrder;else if(x.isLOD)x.autoUpdate===!0&&x.update(I);else if(x.isLight)u.pushLight(x),x.castShadow&&u.pushShadow(x);else if(x.isSprite){if(!x.frustumCulled||Y.intersectsSprite(x)){B&&Gt.setFromMatrixPosition(x.matrixWorld).applyMatrix4(wt);const ht=X.update(x),gt=x.material;gt.visible&&m.push(x,ht,gt,O,Gt.z,null)}}else if((x.isMesh||x.isLine||x.isPoints)&&(!x.frustumCulled||Y.intersectsObject(x))){const ht=X.update(x),gt=x.material;if(B&&(x.boundingSphere!==void 0?(x.boundingSphere===null&&x.computeBoundingSphere(),Gt.copy(x.boundingSphere.center)):(ht.boundingSphere===null&&ht.computeBoundingSphere(),Gt.copy(ht.boundingSphere.center)),Gt.applyMatrix4(x.matrixWorld).applyMatrix4(wt)),Array.isArray(gt)){const _t=ht.groups;for(let It=0,Ft=_t.length;It0&&ps(N,I,O),Q.length>0&&ps(Q,I,O),ht.length>0&&ps(ht,I,O),Mt.buffers.depth.setTest(!0),Mt.buffers.depth.setMask(!0),Mt.buffers.color.setMask(!0),Mt.setPolygonOffset(!1)}function lo(x,I,O,B){if((O.isScene===!0?O.overrideMaterial:null)!==null)return;u.state.transmissionRenderTarget[B.id]===void 0&&(u.state.transmissionRenderTarget[B.id]=new on(1,1,{generateMipmaps:!0,type:Bt.has("EXT_color_buffer_half_float")||Bt.has("EXT_color_buffer_float")?Tn:An,minFilter:Qn,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:$t.workingColorSpace}));const Q=u.state.transmissionRenderTarget[B.id],ht=B.viewport||D;Q.setSize(ht.z*y.transmissionResolutionScale,ht.w*y.transmissionResolutionScale);const gt=y.getRenderTarget();y.setRenderTarget(Q),y.getClearColor(V),$=y.getClearAlpha(),$<1&&y.setClearColor(16777215,.5),y.clear(),rt&&bt.render(O);const _t=y.toneMapping;y.toneMapping=On;const It=B.viewport;if(B.viewport!==void 0&&(B.viewport=void 0),u.setupLightsView(B),nt===!0&&tt.setGlobalState(y.clippingPlanes,B),ps(x,O,B),E.updateMultisampleRenderTarget(Q),E.updateRenderTargetMipmap(Q),Bt.has("WEBGL_multisampled_render_to_texture")===!1){let Ft=!1;for(let Tt=0,Zt=I.length;Tt0),Tt=!!O.morphAttributes.position,Zt=!!O.morphAttributes.normal,Qt=!!O.morphAttributes.color;let me=On;B.toneMapped&&(U===null||U.isXRRenderTarget===!0)&&(me=y.toneMapping);const fe=O.morphAttributes.position||O.morphAttributes.normal||O.morphAttributes.color,Kt=fe!==void 0?fe.length:0,At=Et.get(B),we=u.state.lights;if(nt===!0&&(xt===!0||x!==M)){const De=x===M&&B.id===S;tt.setState(B,x,De)}let te=!1;B.version===At.__version?(At.needsLights&&At.lightsStateVersion!==we.state.version||At.outputColorSpace!==gt||N.isBatchedMesh&&At.batching===!1||!N.isBatchedMesh&&At.batching===!0||N.isBatchedMesh&&At.batchingColor===!0&&N.colorTexture===null||N.isBatchedMesh&&At.batchingColor===!1&&N.colorTexture!==null||N.isInstancedMesh&&At.instancing===!1||!N.isInstancedMesh&&At.instancing===!0||N.isSkinnedMesh&&At.skinning===!1||!N.isSkinnedMesh&&At.skinning===!0||N.isInstancedMesh&&At.instancingColor===!0&&N.instanceColor===null||N.isInstancedMesh&&At.instancingColor===!1&&N.instanceColor!==null||N.isInstancedMesh&&At.instancingMorph===!0&&N.morphTexture===null||N.isInstancedMesh&&At.instancingMorph===!1&&N.morphTexture!==null||At.envMap!==_t||B.fog===!0&&At.fog!==Q||At.numClippingPlanes!==void 0&&(At.numClippingPlanes!==tt.numPlanes||At.numIntersection!==tt.numIntersection)||At.vertexAlphas!==It||At.vertexTangents!==Ft||At.morphTargets!==Tt||At.morphNormals!==Zt||At.morphColors!==Qt||At.toneMapping!==me||At.morphTargetsCount!==Kt)&&(te=!0):(te=!0,At.__version=B.version);let en=At.currentProgram;te===!0&&(en=ms(B,I,N));let oi=!1,Ge=!1,Yi=!1;const de=en.getUniforms(),Ze=At.uniforms;if(Mt.useProgram(en.program)&&(oi=!0,Ge=!0,Yi=!0),B.id!==S&&(S=B.id,Ge=!0),oi||M!==x){Mt.buffers.depth.getReversed()?(at.copy(x.projectionMatrix),Ah(at),Rh(at),de.setValue(w,"projectionMatrix",at)):de.setValue(w,"projectionMatrix",x.projectionMatrix),de.setValue(w,"viewMatrix",x.matrixWorldInverse);const Oe=de.map.cameraPosition;Oe!==void 0&&Oe.setValue(w,Ut.setFromMatrixPosition(x.matrixWorld)),kt.logarithmicDepthBuffer&&de.setValue(w,"logDepthBufFC",2/(Math.log(x.far+1)/Math.LN2)),(B.isMeshPhongMaterial||B.isMeshToonMaterial||B.isMeshLambertMaterial||B.isMeshBasicMaterial||B.isMeshStandardMaterial||B.isShaderMaterial)&&de.setValue(w,"isOrthographic",x.isOrthographicCamera===!0),M!==x&&(M=x,Ge=!0,Yi=!0)}if(N.isSkinnedMesh){de.setOptional(w,N,"bindMatrix"),de.setOptional(w,N,"bindMatrixInverse");const De=N.skeleton;De&&(De.boneTexture===null&&De.computeBoneTexture(),de.setValue(w,"boneTexture",De.boneTexture,E))}N.isBatchedMesh&&(de.setOptional(w,N,"batchingTexture"),de.setValue(w,"batchingTexture",N._matricesTexture,E),de.setOptional(w,N,"batchingIdTexture"),de.setValue(w,"batchingIdTexture",N._indirectTexture,E),de.setOptional(w,N,"batchingColorTexture"),N._colorsTexture!==null&&de.setValue(w,"batchingColorTexture",N._colorsTexture,E));const Ke=O.morphAttributes;if((Ke.position!==void 0||Ke.normal!==void 0||Ke.color!==void 0)&&Pt.update(N,O,en),(Ge||At.receiveShadow!==N.receiveShadow)&&(At.receiveShadow=N.receiveShadow,de.setValue(w,"receiveShadow",N.receiveShadow)),B.isMeshGouraudMaterial&&B.envMap!==null&&(Ze.envMap.value=_t,Ze.flipEnvMap.value=_t.isCubeTexture&&_t.isRenderTargetTexture===!1?-1:1),B.isMeshStandardMaterial&&B.envMap===null&&I.environment!==null&&(Ze.envMapIntensity.value=I.environmentIntensity),Ge&&(de.setValue(w,"toneMappingExposure",y.toneMappingExposure),At.needsLights&&Sc(Ze,Yi),Q&&B.fog===!0&&ot.refreshFogUniforms(Ze,Q),ot.refreshMaterialUniforms(Ze,B,k,J,u.state.transmissionRenderTarget[x.id]),tr.upload(w,ho(At),Ze,E)),B.isShaderMaterial&&B.uniformsNeedUpdate===!0&&(tr.upload(w,ho(At),Ze,E),B.uniformsNeedUpdate=!1),B.isSpriteMaterial&&de.setValue(w,"center",N.center),de.setValue(w,"modelViewMatrix",N.modelViewMatrix),de.setValue(w,"normalMatrix",N.normalMatrix),de.setValue(w,"modelMatrix",N.matrixWorld),B.isShaderMaterial||B.isRawShaderMaterial){const De=B.uniformsGroups;for(let Oe=0,vr=De.length;Oe0&&E.useMultisampledRTT(x)===!1?N=Et.get(x).__webglMultisampledFramebuffer:Array.isArray(Ft)?N=Ft[O]:N=Ft,D.copy(x.viewport),W.copy(x.scissor),z=x.scissorTest}else D.copy(yt).multiplyScalar(k).floor(),W.copy(Lt).multiplyScalar(k).floor(),z=qt;if(O!==0&&(N=Ec),Mt.bindFramebuffer(w.FRAMEBUFFER,N)&&B&&Mt.drawBuffers(x,N),Mt.viewport(D),Mt.scissor(W),Mt.setScissorTest(z),Q){const _t=Et.get(x.texture);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_CUBE_MAP_POSITIVE_X+I,_t.__webglTexture,O)}else if(ht){const _t=Et.get(x.texture),It=I;w.framebufferTextureLayer(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,_t.__webglTexture,O,It)}else if(x!==null&&O!==0){const _t=Et.get(x.texture);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,_t.__webglTexture,O)}S=-1},this.readRenderTargetPixels=function(x,I,O,B,N,Q,ht){if(!(x&&x.isWebGLRenderTarget)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");return}let gt=Et.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&ht!==void 0&&(gt=gt[ht]),gt){Mt.bindFramebuffer(w.FRAMEBUFFER,gt);try{const _t=x.texture,It=_t.format,Ft=_t.type;if(!kt.textureFormatReadable(It)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");return}if(!kt.textureTypeReadable(Ft)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");return}I>=0&&I<=x.width-B&&O>=0&&O<=x.height-N&&w.readPixels(I,O,B,N,zt.convert(It),zt.convert(Ft),Q)}finally{const _t=U!==null?Et.get(U).__webglFramebuffer:null;Mt.bindFramebuffer(w.FRAMEBUFFER,_t)}}},this.readRenderTargetPixelsAsync=async function(x,I,O,B,N,Q,ht){if(!(x&&x.isWebGLRenderTarget))throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let gt=Et.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&ht!==void 0&&(gt=gt[ht]),gt){const _t=x.texture,It=_t.format,Ft=_t.type;if(!kt.textureFormatReadable(It))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!kt.textureTypeReadable(Ft))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(I>=0&&I<=x.width-B&&O>=0&&O<=x.height-N){Mt.bindFramebuffer(w.FRAMEBUFFER,gt);const Tt=w.createBuffer();w.bindBuffer(w.PIXEL_PACK_BUFFER,Tt),w.bufferData(w.PIXEL_PACK_BUFFER,Q.byteLength,w.STREAM_READ),w.readPixels(I,O,B,N,zt.convert(It),zt.convert(Ft),0);const Zt=U!==null?Et.get(U).__webglFramebuffer:null;Mt.bindFramebuffer(w.FRAMEBUFFER,Zt);const Qt=w.fenceSync(w.SYNC_GPU_COMMANDS_COMPLETE,0);return w.flush(),await wh(w,Qt,4),w.bindBuffer(w.PIXEL_PACK_BUFFER,Tt),w.getBufferSubData(w.PIXEL_PACK_BUFFER,0,Q),w.deleteBuffer(Tt),w.deleteSync(Qt),Q}else throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(x,I=null,O=0){x.isTexture!==!0&&(Ri("WebGLRenderer: copyFramebufferToTexture function signature has changed."),I=arguments[0]||null,x=arguments[1]);const B=Math.pow(2,-O),N=Math.floor(x.image.width*B),Q=Math.floor(x.image.height*B),ht=I!==null?I.x:0,gt=I!==null?I.y:0;E.setTexture2D(x,0),w.copyTexSubImage2D(w.TEXTURE_2D,O,0,0,ht,gt,N,Q),Mt.unbindTexture()};const bc=w.createFramebuffer(),Tc=w.createFramebuffer();this.copyTextureToTexture=function(x,I,O=null,B=null,N=0,Q=null){x.isTexture!==!0&&(Ri("WebGLRenderer: copyTextureToTexture function signature has changed."),B=arguments[0]||null,x=arguments[1],I=arguments[2],Q=arguments[3]||0,O=null),Q===null&&(N!==0?(Ri("WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels."),Q=N,N=0):Q=0);let ht,gt,_t,It,Ft,Tt,Zt,Qt,me;const fe=x.isCompressedTexture?x.mipmaps[Q]:x.image;if(O!==null)ht=O.max.x-O.min.x,gt=O.max.y-O.min.y,_t=O.isBox3?O.max.z-O.min.z:1,It=O.min.x,Ft=O.min.y,Tt=O.isBox3?O.min.z:0;else{const Ke=Math.pow(2,-N);ht=Math.floor(fe.width*Ke),gt=Math.floor(fe.height*Ke),x.isDataArrayTexture?_t=fe.depth:x.isData3DTexture?_t=Math.floor(fe.depth*Ke):_t=1,It=0,Ft=0,Tt=0}B!==null?(Zt=B.x,Qt=B.y,me=B.z):(Zt=0,Qt=0,me=0);const Kt=zt.convert(I.format),At=zt.convert(I.type);let we;I.isData3DTexture?(E.setTexture3D(I,0),we=w.TEXTURE_3D):I.isDataArrayTexture||I.isCompressedArrayTexture?(E.setTexture2DArray(I,0),we=w.TEXTURE_2D_ARRAY):(E.setTexture2D(I,0),we=w.TEXTURE_2D),w.pixelStorei(w.UNPACK_FLIP_Y_WEBGL,I.flipY),w.pixelStorei(w.UNPACK_PREMULTIPLY_ALPHA_WEBGL,I.premultiplyAlpha),w.pixelStorei(w.UNPACK_ALIGNMENT,I.unpackAlignment);const te=w.getParameter(w.UNPACK_ROW_LENGTH),en=w.getParameter(w.UNPACK_IMAGE_HEIGHT),oi=w.getParameter(w.UNPACK_SKIP_PIXELS),Ge=w.getParameter(w.UNPACK_SKIP_ROWS),Yi=w.getParameter(w.UNPACK_SKIP_IMAGES);w.pixelStorei(w.UNPACK_ROW_LENGTH,fe.width),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,fe.height),w.pixelStorei(w.UNPACK_SKIP_PIXELS,It),w.pixelStorei(w.UNPACK_SKIP_ROWS,Ft),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Tt);const de=x.isDataArrayTexture||x.isData3DTexture,Ze=I.isDataArrayTexture||I.isData3DTexture;if(x.isDepthTexture){const Ke=Et.get(x),De=Et.get(I),Oe=Et.get(Ke.__renderTarget),vr=Et.get(De.__renderTarget);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,Oe.__webglFramebuffer),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,vr.__webglFramebuffer);for(let Vn=0;Vn<_t;Vn++)de&&(w.framebufferTextureLayer(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Et.get(x).__webglTexture,N,Tt+Vn),w.framebufferTextureLayer(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Et.get(I).__webglTexture,Q,me+Vn)),w.blitFramebuffer(It,Ft,ht,gt,Zt,Qt,ht,gt,w.DEPTH_BUFFER_BIT,w.NEAREST);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,null),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,null)}else if(N!==0||x.isRenderTargetTexture||Et.has(x)){const Ke=Et.get(x),De=Et.get(I);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,bc),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,Tc);for(let Oe=0;Oe<_t;Oe++)de?w.framebufferTextureLayer(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,Ke.__webglTexture,N,Tt+Oe):w.framebufferTexture2D(w.READ_FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,Ke.__webglTexture,N),Ze?w.framebufferTextureLayer(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,De.__webglTexture,Q,me+Oe):w.framebufferTexture2D(w.DRAW_FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,De.__webglTexture,Q),N!==0?w.blitFramebuffer(It,Ft,ht,gt,Zt,Qt,ht,gt,w.COLOR_BUFFER_BIT,w.NEAREST):Ze?w.copyTexSubImage3D(we,Q,Zt,Qt,me+Oe,It,Ft,ht,gt):w.copyTexSubImage2D(we,Q,Zt,Qt,It,Ft,ht,gt);Mt.bindFramebuffer(w.READ_FRAMEBUFFER,null),Mt.bindFramebuffer(w.DRAW_FRAMEBUFFER,null)}else Ze?x.isDataTexture||x.isData3DTexture?w.texSubImage3D(we,Q,Zt,Qt,me,ht,gt,_t,Kt,At,fe.data):I.isCompressedArrayTexture?w.compressedTexSubImage3D(we,Q,Zt,Qt,me,ht,gt,_t,Kt,fe.data):w.texSubImage3D(we,Q,Zt,Qt,me,ht,gt,_t,Kt,At,fe):x.isDataTexture?w.texSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,ht,gt,Kt,At,fe.data):x.isCompressedTexture?w.compressedTexSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,fe.width,fe.height,Kt,fe.data):w.texSubImage2D(w.TEXTURE_2D,Q,Zt,Qt,ht,gt,Kt,At,fe);w.pixelStorei(w.UNPACK_ROW_LENGTH,te),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,en),w.pixelStorei(w.UNPACK_SKIP_PIXELS,oi),w.pixelStorei(w.UNPACK_SKIP_ROWS,Ge),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Yi),Q===0&&I.generateMipmaps&&w.generateMipmap(we),Mt.unbindTexture()},this.copyTextureToTexture3D=function(x,I,O=null,B=null,N=0){return x.isTexture!==!0&&(Ri("WebGLRenderer: copyTextureToTexture3D function signature has changed."),O=arguments[0]||null,B=arguments[1]||null,x=arguments[2],I=arguments[3],N=arguments[4]||0),Ri('WebGLRenderer: copyTextureToTexture3D function has been deprecated. Use "copyTextureToTexture" instead.'),this.copyTextureToTexture(x,I,O,B,N)},this.initRenderTarget=function(x){Et.get(x).__webglFramebuffer===void 0&&E.setupRenderTarget(x)},this.initTexture=function(x){x.isCubeTexture?E.setTextureCube(x,0):x.isData3DTexture?E.setTexture3D(x,0):x.isDataArrayTexture||x.isCompressedArrayTexture?E.setTexture2DArray(x,0):E.setTexture2D(x,0),Mt.unbindTexture()},this.resetState=function(){R=0,A=0,U=null,Mt.reset(),se.reset()},typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return En}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(t){this._outputColorSpace=t;const e=this.getContext();e.drawingBufferColorspace=$t._getDrawingBufferColorSpace(t),e.unpackColorSpace=$t._getUnpackColorSpace()}}const El={type:"change"},so={type:"start"},_c={type:"end"},Ys=new hs,bl=new Nn,$m=Math.cos(70*bh.DEG2RAD),Me=new P,Be=2*Math.PI,oe={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},Jr=1e-6;class Jm extends du{constructor(t,e=null){super(t,e),this.state=oe.NONE,this.enabled=!0,this.target=new P,this.cursor=new P,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minTargetRadius=0,this.maxTargetRadius=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.keyRotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:Li.ROTATE,MIDDLE:Li.DOLLY,RIGHT:Li.PAN},this.touches={ONE:Ci.ROTATE,TWO:Ci.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this._lastPosition=new P,this._lastQuaternion=new ii,this._lastTargetPosition=new P,this._quat=new ii().setFromUnitVectors(t.up,new P(0,1,0)),this._quatInverse=this._quat.clone().invert(),this._spherical=new $o,this._sphericalDelta=new $o,this._scale=1,this._panOffset=new P,this._rotateStart=new vt,this._rotateEnd=new vt,this._rotateDelta=new vt,this._panStart=new vt,this._panEnd=new vt,this._panDelta=new vt,this._dollyStart=new vt,this._dollyEnd=new vt,this._dollyDelta=new vt,this._dollyDirection=new P,this._mouse=new vt,this._performCursorZoom=!1,this._pointers=[],this._pointerPositions={},this._controlActive=!1,this._onPointerMove=tg.bind(this),this._onPointerDown=Qm.bind(this),this._onPointerUp=eg.bind(this),this._onContextMenu=lg.bind(this),this._onMouseWheel=sg.bind(this),this._onKeyDown=rg.bind(this),this._onTouchStart=ag.bind(this),this._onTouchMove=og.bind(this),this._onMouseDown=ng.bind(this),this._onMouseMove=ig.bind(this),this._interceptControlDown=cg.bind(this),this._interceptControlUp=hg.bind(this),this.domElement!==null&&this.connect(),this.update()}connect(){this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointercancel",this._onPointerUp),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("wheel",this._onMouseWheel,{passive:!1}),this.domElement.getRootNode().addEventListener("keydown",this._interceptControlDown,{passive:!0,capture:!0}),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointercancel",this._onPointerUp),this.domElement.removeEventListener("wheel",this._onMouseWheel),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.stopListenToKeyEvents(),this.domElement.getRootNode().removeEventListener("keydown",this._interceptControlDown,{capture:!0}),this.domElement.style.touchAction="auto"}dispose(){this.disconnect()}getPolarAngle(){return this._spherical.phi}getAzimuthalAngle(){return this._spherical.theta}getDistance(){return this.object.position.distanceTo(this.target)}listenToKeyEvents(t){t.addEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=t}stopListenToKeyEvents(){this._domElementKeyEvents!==null&&(this._domElementKeyEvents.removeEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=null)}saveState(){this.target0.copy(this.target),this.position0.copy(this.object.position),this.zoom0=this.object.zoom}reset(){this.target.copy(this.target0),this.object.position.copy(this.position0),this.object.zoom=this.zoom0,this.object.updateProjectionMatrix(),this.dispatchEvent(El),this.update(),this.state=oe.NONE}update(t=null){const e=this.object.position;Me.copy(e).sub(this.target),Me.applyQuaternion(this._quat),this._spherical.setFromVector3(Me),this.autoRotate&&this.state===oe.NONE&&this._rotateLeft(this._getAutoRotationAngle(t)),this.enableDamping?(this._spherical.theta+=this._sphericalDelta.theta*this.dampingFactor,this._spherical.phi+=this._sphericalDelta.phi*this.dampingFactor):(this._spherical.theta+=this._sphericalDelta.theta,this._spherical.phi+=this._sphericalDelta.phi);let n=this.minAzimuthAngle,s=this.maxAzimuthAngle;isFinite(n)&&isFinite(s)&&(n<-Math.PI?n+=Be:n>Math.PI&&(n-=Be),s<-Math.PI?s+=Be:s>Math.PI&&(s-=Be),n<=s?this._spherical.theta=Math.max(n,Math.min(s,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(n+s)/2?Math.max(n,this._spherical.theta):Math.min(s,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let r=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const a=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),r=a!=this._spherical.radius}if(Me.setFromSpherical(this._spherical),Me.applyQuaternion(this._quatInverse),e.copy(this.target).add(Me),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let a=null;if(this.object.isPerspectiveCamera){const o=Me.length();a=this._clampDistance(o*this._scale);const l=o-a;this.object.position.addScaledVector(this._dollyDirection,l),this.object.updateMatrixWorld(),r=!!l}else if(this.object.isOrthographicCamera){const o=new P(this._mouse.x,this._mouse.y,0);o.unproject(this.object);const l=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),r=l!==this.object.zoom;const c=new P(this._mouse.x,this._mouse.y,0);c.unproject(this.object),this.object.position.sub(c).add(o),this.object.updateMatrixWorld(),a=Me.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;a!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(a).add(this.object.position):(Ys.origin.copy(this.object.position),Ys.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(Ys.direction))<$m?this.object.lookAt(this.target):(bl.setFromNormalAndCoplanarPoint(this.object.up,this.target),Ys.intersectPlane(bl,this.target))))}else if(this.object.isOrthographicCamera){const a=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),a!==this.object.zoom&&(this.object.updateProjectionMatrix(),r=!0)}return this._scale=1,this._performCursorZoom=!1,r||this._lastPosition.distanceToSquared(this.object.position)>Jr||8*(1-this._lastQuaternion.dot(this.object.quaternion))>Jr||this._lastTargetPosition.distanceToSquared(this.target)>Jr?(this.dispatchEvent(El),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(t){return t!==null?Be/60*this.autoRotateSpeed*t:Be/60/60*this.autoRotateSpeed}_getZoomScale(t){const e=Math.abs(t*.01);return Math.pow(.95,this.zoomSpeed*e)}_rotateLeft(t){this._sphericalDelta.theta-=t}_rotateUp(t){this._sphericalDelta.phi-=t}_panLeft(t,e){Me.setFromMatrixColumn(e,0),Me.multiplyScalar(-t),this._panOffset.add(Me)}_panUp(t,e){this.screenSpacePanning===!0?Me.setFromMatrixColumn(e,1):(Me.setFromMatrixColumn(e,0),Me.crossVectors(this.object.up,Me)),Me.multiplyScalar(t),this._panOffset.add(Me)}_pan(t,e){const n=this.domElement;if(this.object.isPerspectiveCamera){const s=this.object.position;Me.copy(s).sub(this.target);let r=Me.length();r*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*t*r/n.clientHeight,this.object.matrix),this._panUp(2*e*r/n.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(t*(this.object.right-this.object.left)/this.object.zoom/n.clientWidth,this.object.matrix),this._panUp(e*(this.object.top-this.object.bottom)/this.object.zoom/n.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(t,e){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const n=this.domElement.getBoundingClientRect(),s=t-n.left,r=e-n.top,a=n.width,o=n.height;this._mouse.x=s/a*2-1,this._mouse.y=-(r/o)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(t){return Math.max(this.minDistance,Math.min(this.maxDistance,t))}_handleMouseDownRotate(t){this._rotateStart.set(t.clientX,t.clientY)}_handleMouseDownDolly(t){this._updateZoomParameters(t.clientX,t.clientX),this._dollyStart.set(t.clientX,t.clientY)}_handleMouseDownPan(t){this._panStart.set(t.clientX,t.clientY)}_handleMouseMoveRotate(t){this._rotateEnd.set(t.clientX,t.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Be*this._rotateDelta.x/e.clientHeight),this._rotateUp(Be*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(t){this._dollyEnd.set(t.clientX,t.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(t){this._panEnd.set(t.clientX,t.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(t){this._updateZoomParameters(t.clientX,t.clientY),t.deltaY<0?this._dollyIn(this._getZoomScale(t.deltaY)):t.deltaY>0&&this._dollyOut(this._getZoomScale(t.deltaY)),this.update()}_handleKeyDown(t){let e=!1;switch(t.code){case this.keys.UP:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(Be*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),e=!0;break;case this.keys.BOTTOM:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(-Be*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),e=!0;break;case this.keys.LEFT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(Be*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),e=!0;break;case this.keys.RIGHT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(-Be*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),e=!0;break}e&&(t.preventDefault(),this.update())}_handleTouchStartRotate(t){if(this._pointers.length===1)this._rotateStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._rotateStart.set(n,s)}}_handleTouchStartPan(t){if(this._pointers.length===1)this._panStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panStart.set(n,s)}}_handleTouchStartDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyStart.set(0,r)}_handleTouchStartDollyPan(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enablePan&&this._handleTouchStartPan(t)}_handleTouchStartDollyRotate(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enableRotate&&this._handleTouchStartRotate(t)}_handleTouchMoveRotate(t){if(this._pointers.length==1)this._rotateEnd.set(t.pageX,t.pageY);else{const n=this._getSecondPointerPosition(t),s=.5*(t.pageX+n.x),r=.5*(t.pageY+n.y);this._rotateEnd.set(s,r)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Be*this._rotateDelta.x/e.clientHeight),this._rotateUp(Be*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(t){if(this._pointers.length===1)this._panEnd.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panEnd.set(n,s)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyEnd.set(0,r),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const a=(t.pageX+e.x)*.5,o=(t.pageY+e.y)*.5;this._updateZoomParameters(a,o)}_handleTouchMoveDollyPan(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enablePan&&this._handleTouchMovePan(t)}_handleTouchMoveDollyRotate(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enableRotate&&this._handleTouchMoveRotate(t)}_addPointer(t){this._pointers.push(t.pointerId)}_removePointer(t){delete this._pointerPositions[t.pointerId];for(let e=0;e{var e;(t instanceof Se||t instanceof Jh)&&((e=t.geometry)==null||e.dispose(),Array.isArray(t.material)?t.material.forEach(n=>n.dispose()):t.material&&t.material.dispose())}),i.renderer.dispose(),i.composer.dispose()}class Mg{constructor(t){Wt(this,"positions");Wt(this,"velocities");Wt(this,"running",!0);Wt(this,"step",0);Wt(this,"repulsionStrength",500);Wt(this,"attractionStrength",.01);Wt(this,"dampening",.9);Wt(this,"baseMaxSteps",300);Wt(this,"maxSteps",300);Wt(this,"cooldownExtension",0);this.positions=t,this.velocities=new Map;for(const e of t.keys())this.velocities.set(e,new P)}addNode(t,e){this.positions.set(t,e.clone()),this.velocities.set(t,new P),this.cooldownExtension=100,this.maxSteps=Math.max(this.maxSteps,this.step+this.cooldownExtension),this.running=!0}removeNode(t){this.positions.delete(t),this.velocities.delete(t)}tick(t){if(!this.running)return;if(this.step>this.maxSteps){this.cooldownExtension>0&&(this.cooldownExtension=0,this.maxSteps=this.baseMaxSteps);return}this.step++;const e=Math.max(.001,1-this.step/this.maxSteps),n=Array.from(this.positions.keys());for(let s=0;s0?.15+t.retention*.2:0,blending:He}),h=new Br(c);h.scale.set(s*4*n,s*4*n,1),h.position.copy(e),h.userData={isGlow:!0,nodeId:t.id},this.glowMap.set(t.id,h),this.group.add(h);const d=t.label||t.type,f=this.createTextSprite(d,"#e2e8f0");return f.position.copy(e),f.position.y+=s*2+1.5,f.userData={isLabel:!0,nodeId:t.id,offset:s*2+1.5},this.group.add(f),this.labelSprites.set(t.id,f),{mesh:l,glow:h,label:f,size:s}}addNode(t,e){const n=(e==null?void 0:e.clone())??new P((Math.random()-.5)*40,(Math.random()-.5)*40,(Math.random()-.5)*40);this.positions.set(t.id,n);const{mesh:s,glow:r,label:a}=this.createNodeMeshes(t,n,0);return s.scale.setScalar(.001),r.scale.set(.001,.001,1),r.material.opacity=0,a.material.opacity=0,this.materializingNodes.push({id:t.id,frame:0,totalFrames:30,mesh:s,glow:r,label:a,targetScale:.5+t.retention*2}),n}removeNode(t){const e=this.meshMap.get(t),n=this.glowMap.get(t),s=this.labelSprites.get(t);!e||!n||!s||(this.materializingNodes=this.materializingNodes.filter(r=>r.id!==t),this.dissolvingNodes.push({id:t,frame:0,totalFrames:60,mesh:e,glow:n,label:s,originalScale:e.scale.x}))}growNode(t,e){const n=this.meshMap.get(t);if(!n)return;const s=n.scale.x,r=.5+e*2;n.userData.retention=e,this.growingNodes.push({id:t,frame:0,totalFrames:30,startScale:s,targetScale:r})}createTextSprite(t,e){const n=document.createElement("canvas"),s=n.getContext("2d");n.width=512,n.height=64;const r=t.length>40?t.slice(0,37)+"...":t;s.clearRect(0,0,n.width,n.height),s.font="bold 28px -apple-system, BlinkMacSystemFont, sans-serif",s.textAlign="center",s.textBaseline="middle",s.shadowColor="rgba(0, 0, 0, 0.8)",s.shadowBlur=6,s.shadowOffsetX=0,s.shadowOffsetY=2,s.fillStyle=e,s.fillText(r,n.width/2,n.height/2);const a=new eu(n);a.needsUpdate=!0;const o=new Ha({map:a,transparent:!0,opacity:0,depthTest:!1,sizeAttenuation:!0}),l=new Br(o);return l.scale.set(12,1.5,1),l}updatePositions(){this.group.children.forEach(t=>{if(t.userData.nodeId){const e=this.positions.get(t.userData.nodeId);if(!e)return;t.userData.isGlow?t.position.copy(e):t.userData.isLabel?(t.position.copy(e),t.position.y+=t.userData.offset):t instanceof Se&&t.position.copy(e)}})}animate(t,e,n){var r,a;for(let o=this.materializingNodes.length-1;o>=0;o--){const l=this.materializingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=Tl(c);if(l.mesh.scale.setScalar(Math.max(.001,h)),l.frame>=5){const d=Math.min((l.frame-5)/5,1),f=l.glow.material;f.opacity=d*.25;const p=l.targetScale*4*h;l.glow.scale.set(p,p,1)}if(l.frame>=40){const d=Math.min((l.frame-40)/20,1);l.label.material.opacity=d*.9}l.frame>=60&&this.materializingNodes.splice(o,1)}for(let o=this.dissolvingNodes.length-1;o>=0;o--){const l=this.dissolvingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=1-Sg(c),d=Math.max(.001,l.originalScale*h);l.mesh.scale.setScalar(d);const f=d*4;l.glow.scale.set(f,f,1);const p=l.mesh.material;p.opacity*=.97,l.glow.material.opacity*=.95,l.label.material.opacity*=.93,l.frame>=l.totalFrames&&(this.group.remove(l.mesh),this.group.remove(l.glow),this.group.remove(l.label),l.mesh.geometry.dispose(),l.mesh.material.dispose(),(r=l.glow.material.map)==null||r.dispose(),l.glow.material.dispose(),(a=l.label.material.map)==null||a.dispose(),l.label.material.dispose(),this.meshMap.delete(l.id),this.glowMap.delete(l.id),this.labelSprites.delete(l.id),this.positions.delete(l.id),this.dissolvingNodes.splice(o,1))}for(let o=this.growingNodes.length-1;o>=0;o--){const l=this.growingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=l.startScale+(l.targetScale-l.startScale)*Tl(c),d=this.meshMap.get(l.id);d&&d.scale.setScalar(h);const f=this.glowMap.get(l.id);if(f){const p=h*4;f.scale.set(p,p,1)}l.frame>=l.totalFrames&&this.growingNodes.splice(o,1)}const s=new Set([...this.materializingNodes.map(o=>o.id),...this.dissolvingNodes.map(o=>o.id),...this.growingNodes.map(o=>o.id)]);this.meshMap.forEach((o,l)=>{if(s.has(l))return;const c=e.find(f=>f.id===l);if(!c)return;const h=1+Math.sin(t*1.5+e.indexOf(c)*.5)*.15*c.retention;o.scale.setScalar(h);const d=o.material;if(l===this.hoveredNode)d.emissiveIntensity=1;else if(l===this.selectedNode)d.emissiveIntensity=.8;else{const p=.3+c.retention*.5+Math.sin(t*(.8+c.retention*.7))*.1*c.retention;d.emissiveIntensity=p}}),this.labelSprites.forEach((o,l)=>{if(s.has(l))return;const c=this.positions.get(l);if(!c)return;const h=n.position.distanceTo(c),d=o.material,f=l===this.hoveredNode||l===this.selectedNode?1:h<40?.9:h<80?.9*(1-(h-40)/40):0;d.opacity+=(f-d.opacity)*.1})}getMeshes(){return Array.from(this.meshMap.values())}dispose(){this.group.traverse(t=>{var e,n,s,r,a;t instanceof Se?((e=t.geometry)==null||e.dispose(),(n=t.material)==null||n.dispose()):t instanceof Br&&((r=(s=t.material)==null?void 0:s.map)==null||r.dispose(),(a=t.material)==null||a.dispose())}),this.materializingNodes=[],this.dissolvingNodes=[],this.growingNodes=[]}}function Eg(i){return 1-Math.pow(1-i,3)}class bg{constructor(){Wt(this,"group");Wt(this,"growingEdges",[]);Wt(this,"dissolvingEdges",[]);this.group=new Ci}createEdges(t,e){for(const n of t){const s=e.get(n.source),r=e.get(n.target);if(!s||!r)continue;const a=[s,r],o=new pe().setFromPoints(a),l=new rr({color:4868730,transparent:!0,opacity:Math.min(.1+n.weight*.5,.6),blending:He}),c=new ka(o,l);c.userData={source:n.source,target:n.target},this.group.add(c)}}addEdge(t,e){const n=e.get(t.source),s=e.get(t.target);if(!n||!s)return;const r=[n.clone(),n.clone()],a=new pe().setFromPoints(r),o=new rr({color:4868730,transparent:!0,opacity:0,blending:He}),l=new ka(a,o);l.userData={source:t.source,target:t.target},this.group.add(l),this.growingEdges.push({line:l,source:t.source,target:t.target,frame:0,totalFrames:45})}removeEdgesForNode(t){const e=[];this.group.children.forEach(n=>{const s=n;(s.userData.source===t||s.userData.target===t)&&e.push(s)});for(const n of e)this.growingEdges=this.growingEdges.filter(s=>s.line!==n),this.dissolvingEdges.push({line:n,frame:0,totalFrames:40})}animateEdges(t){for(let e=this.growingEdges.length-1;e>=0;e--){const n=this.growingEdges[e];n.frame++;const s=Eg(Math.min(n.frame/n.totalFrames,1)),r=t.get(n.source),a=t.get(n.target);if(!r||!a)continue;const o=r.clone().lerp(a,s),l=n.line.geometry.attributes.position;l.setXYZ(0,r.x,r.y,r.z),l.setXYZ(1,o.x,o.y,o.z),l.needsUpdate=!0;const c=n.line.material;c.opacity=s*.5,n.frame>=n.totalFrames&&(c.opacity=.5,this.growingEdges.splice(e,1))}for(let e=this.dissolvingEdges.length-1;e>=0;e--){const n=this.dissolvingEdges[e];n.frame++;const s=n.frame/n.totalFrames,r=n.line.material;r.opacity=Math.max(0,.5*(1-s)),n.frame>=n.totalFrames&&(this.group.remove(n.line),n.line.geometry.dispose(),n.line.material.dispose(),this.dissolvingEdges.splice(e,1))}}updatePositions(t){this.group.children.forEach(e=>{const n=e;if(this.growingEdges.some(a=>a.line===n)||this.dissolvingEdges.some(a=>a.line===n))return;const s=t.get(n.userData.source),r=t.get(n.userData.target);if(s&&r){const a=n.geometry.attributes.position;a.setXYZ(0,s.x,s.y,s.z),a.setXYZ(1,r.x,r.y,r.z),a.needsUpdate=!0}})}dispose(){this.group.children.forEach(t=>{var n,s;const e=t;(n=e.geometry)==null||n.dispose(),(s=e.material)==null||s.dispose()}),this.growingEdges=[],this.dissolvingEdges=[]}}class Tg{constructor(t){Wt(this,"starField");Wt(this,"neuralParticles");this.starField=this.createStarField(),this.neuralParticles=this.createNeuralParticles(),t.add(this.starField),t.add(this.neuralParticles)}createStarField(){const e=new pe,n=new Float32Array(3e3*3),s=new Float32Array(3e3);for(let a=0;a<3e3;a++)n[a*3]=(Math.random()-.5)*1e3,n[a*3+1]=(Math.random()-.5)*1e3,n[a*3+2]=(Math.random()-.5)*1e3,s[a]=Math.random()*1.5;e.setAttribute("position",new de(n,3)),e.setAttribute("size",new de(s,1));const r=new Ni({color:6514417,size:.5,transparent:!0,opacity:.4,sizeAttenuation:!0,blending:He});return new rs(e,r)}createNeuralParticles(){const e=new pe,n=new Float32Array(500*3),s=new Float32Array(500*3);for(let a=0;a<500;a++)n[a*3]=(Math.random()-.5)*100,n[a*3+1]=(Math.random()-.5)*100,n[a*3+2]=(Math.random()-.5)*100,s[a*3]=.4+Math.random()*.3,s[a*3+1]=.3+Math.random()*.2,s[a*3+2]=.8+Math.random()*.2;e.setAttribute("position",new de(n,3)),e.setAttribute("color",new de(s,3));const r=new Ni({size:.3,vertexColors:!0,transparent:!0,opacity:.4,blending:He,sizeAttenuation:!0});return new rs(e,r)}animate(t){this.starField.rotation.y+=1e-4,this.starField.rotation.x+=5e-5;const e=this.neuralParticles.geometry.attributes.position;for(let n=0;n=0;s--){const r=this.pulseEffects[s];if(r.intensity-=r.decay,r.intensity<=0){this.pulseEffects.splice(s,1);continue}const a=t.get(r.nodeId);if(a){const o=a.material;o.emissive.lerp(r.color,r.intensity*.3),o.emissiveIntensity=Math.max(o.emissiveIntensity,r.intensity)}}for(let s=this.spawnBursts.length-1;s>=0;s--){const r=this.spawnBursts[s];if(r.age++,r.age>120){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),this.spawnBursts.splice(s,1);continue}const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity;for(let c=0;c=0;s--){const r=this.rainbowBursts[s];if(r.age++,r.age>r.maxAge){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),this.rainbowBursts.splice(s,1);continue}const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity;for(let f=0;f=0;s--){const r=this.rippleWaves[s];if(r.age++,r.radius+=r.speed,r.age>r.maxAge){this.rippleWaves.splice(s,1);continue}const a=r.radius,o=3;n.forEach((l,c)=>{if(r.pulsedNodes.has(c))return;const h=l.distanceTo(r.origin);if(h>=a-o&&h<=a+o){r.pulsedNodes.add(c),this.addPulse(c,.8,new pt(65489),.03);const d=t.get(c);d&&d.scale.multiplyScalar(1.3)}})}for(let s=this.implosions.length-1;s>=0;s--){const r=this.implosions[s];if(r.age++,r.age>r.maxAge+20){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),r.flash&&(this.scene.remove(r.flash),r.flash.geometry.dispose(),r.flash.material.dispose()),this.implosions.splice(s,1);continue}if(r.age<=r.maxAge){const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity,l=1+r.age*.02;for(let h=0;hr.maxAge){const a=(r.age-r.maxAge)/20;r.flash.material.opacity=Math.max(0,1-a),r.flash.scale.setScalar(1+a*3)}}for(let s=this.shockwaves.length-1;s>=0;s--){const r=this.shockwaves[s];if(r.age++,r.age>r.maxAge){this.scene.remove(r.mesh),r.mesh.geometry.dispose(),r.mesh.material.dispose(),this.shockwaves.splice(s,1);continue}const a=r.age/r.maxAge;r.mesh.scale.setScalar(1+a*20),r.mesh.material.opacity=.8*(1-a),r.mesh.lookAt(e.position)}for(let s=this.connectionFlashes.length-1;s>=0;s--){const r=this.connectionFlashes[s];if(r.intensity-=.015,r.intensity<=0){this.scene.remove(r.line),r.line.geometry.dispose(),r.line.material.dispose(),this.connectionFlashes.splice(s,1);continue}r.line.material.opacity=r.intensity}}dispose(){for(const t of this.spawnBursts)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose();for(const t of this.rainbowBursts)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose();for(const t of this.implosions)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose(),t.flash&&(this.scene.remove(t.flash),t.flash.geometry.dispose(),t.flash.material.dispose());for(const t of this.shockwaves)this.scene.remove(t.mesh),t.mesh.geometry.dispose(),t.mesh.material.dispose();for(const t of this.connectionFlashes)this.scene.remove(t.line),t.line.geometry.dispose(),t.line.material.dispose();this.pulseEffects=[],this.spawnBursts=[],this.rainbowBursts=[],this.rippleWaves=[],this.implosions=[],this.shockwaves=[],this.connectionFlashes=[]}}const Sn={bloomStrength:.8,rotateSpeed:.3,fogColor:328976,fogDensity:.008,nebulaIntensity:0,chromaticIntensity:.002,vignetteRadius:.9,breatheAmplitude:1},In={bloomStrength:1.8,rotateSpeed:.08,fogColor:656672,fogDensity:.006,nebulaIntensity:1,chromaticIntensity:.005,vignetteRadius:.7,breatheAmplitude:2};class Ag{constructor(){Wt(this,"active",!1);Wt(this,"transition",0);Wt(this,"transitionSpeed",.008);Wt(this,"current");Wt(this,"auroraHue",0);this.current={...Sn}}setActive(t){this.active=t}update(t,e,n,s,r){const a=this.active?1:0;this.transition+=(a-this.transition)*this.transitionSpeed*60*(1/60),this.transition=Math.max(0,Math.min(1,this.transition));const o=this.transition;this.current.bloomStrength=this.lerp(Sn.bloomStrength,In.bloomStrength,o),this.current.rotateSpeed=this.lerp(Sn.rotateSpeed,In.rotateSpeed,o),this.current.fogDensity=this.lerp(Sn.fogDensity,In.fogDensity,o),this.current.nebulaIntensity=this.lerp(Sn.nebulaIntensity,In.nebulaIntensity,o),this.current.chromaticIntensity=this.lerp(Sn.chromaticIntensity,In.chromaticIntensity,o),this.current.vignetteRadius=this.lerp(Sn.vignetteRadius,In.vignetteRadius,o),this.current.breatheAmplitude=this.lerp(Sn.breatheAmplitude,In.breatheAmplitude,o),e.strength=this.current.bloomStrength,n.autoRotateSpeed=this.current.rotateSpeed;const l=new pt(Sn.fogColor),c=new pt(In.fogColor),h=l.clone().lerp(c,o);if(t.fog=new ur(h,this.current.fogDensity),o>.01){this.auroraHue=r*.1%1;const d=new pt().setHSL(.75+this.auroraHue*.15,.8,.5),f=new pt().setHSL(.55+this.auroraHue*.2,.7,.4);s.point1.color.lerp(d,o*.3),s.point2.color.lerp(f,o*.3)}else s.point1.color.set(6514417),s.point2.color.set(11032055)}lerp(t,e,n){return t+(e-t)*n}}const Rg=50,as=[];function Cg(i,t,e){const n=i.tags??[],s=i.type??"";let r=null,a=0;for(const o of t){let l=0;o.type===s&&(l+=2);for(const c of o.tags)n.includes(c)&&(l+=1);l>a&&(a=l,r=o.id)}if(r&&a>0){const o=e.get(r);if(o)return new P(o.x+(Math.random()-.5)*10,o.y+(Math.random()-.5)*10,o.z+(Math.random()-.5)*10)}return new P((Math.random()-.5)*40,(Math.random()-.5)*40,(Math.random()-.5)*40)}function Pg(i,t){if(as.length<=Rg)return;const e=as.shift();i.edgeManager.removeEdgesForNode(e),i.nodeManager.removeNode(e),i.forceSim.removeNode(e),i.onMutation({type:"edgesRemoved",nodeId:e}),i.onMutation({type:"nodeRemoved",nodeId:e});const n=t.findIndex(s=>s.id===e);n!==-1&&t.splice(n,1)}function Dg(i,t,e){var d,f;const{effects:n,nodeManager:s,edgeManager:r,forceSim:a,camera:o,onMutation:l}=t,c=s.positions,h=s.meshMap;switch(i.type){case"MemoryCreated":{const p=i.data;if(!p.id)break;const g={id:p.id,label:(p.content??"").slice(0,60),type:p.node_type??"fact",retention:p.retention??.9,tags:p.tags??[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),isCenter:!1},v=Cg(g,e,c),m=s.addNode(g,v);a.addNode(p.id,m),as.push(p.id),Pg(t,e);const u=new pt(Nl[g.type]||"#00ffd1");n.createRainbowBurst(v,u),n.createShockwave(v,u,o);const T=u.clone();T.offsetHSL(.15,0,0),setTimeout(()=>{n.createShockwave(v,T,o)},166),n.createRippleWave(v),l({type:"nodeAdded",node:g});break}case"ConnectionDiscovered":{const p=i.data;if(!p.source_id||!p.target_id)break;const g=c.get(p.source_id),v=c.get(p.target_id),m={source:p.source_id,target:p.target_id,weight:p.weight??.5,type:p.connection_type??"semantic"};r.addEdge(m,c),g&&v&&n.createConnectionFlash(g,v,new pt(54527)),p.source_id&&h.has(p.source_id)&&n.addPulse(p.source_id,1,new pt(54527),.02),p.target_id&&h.has(p.target_id)&&n.addPulse(p.target_id,1,new pt(54527),.02),l({type:"edgeAdded",edge:m});break}case"MemoryDeleted":{const p=i.data;if(!p.id)break;const g=c.get(p.id);if(g){const m=new pt(16729943);n.createImplosion(g,m)}r.removeEdgesForNode(p.id),s.removeNode(p.id),a.removeNode(p.id);const v=as.indexOf(p.id);v!==-1&&as.splice(v,1),l({type:"edgesRemoved",nodeId:p.id}),l({type:"nodeRemoved",nodeId:p.id});break}case"MemoryPromoted":{const p=i.data,g=p==null?void 0:p.id;if(!g)break;const v=p.new_retention??.95;if(h.has(g)){s.growNode(g,v),n.addPulse(g,1.2,new pt(65416),.01);const m=c.get(g);m&&(n.createShockwave(m,new pt(65416),o),n.createSpawnBurst(m,new pt(65416))),l({type:"nodeUpdated",nodeId:g,retention:v})}break}case"MemoryDemoted":{const p=i.data,g=p==null?void 0:p.id;if(!g)break;const v=p.new_retention??.3;h.has(g)&&(s.growNode(g,v),n.addPulse(g,.8,new pt(16729943),.03),l({type:"nodeUpdated",nodeId:g,retention:v}));break}case"MemoryUpdated":{const p=i.data,g=p==null?void 0:p.id;if(!g||!h.has(g))break;n.addPulse(g,.6,new pt(8490232),.02),p.retention!==void 0&&(s.growNode(g,p.retention),l({type:"nodeUpdated",nodeId:g,retention:p.retention}));break}case"SearchPerformed":{h.forEach((p,g)=>{n.addPulse(g,.6+Math.random()*.4,new pt(8490232),.02)});break}case"DreamStarted":{h.forEach((p,g)=>{n.addPulse(g,1,new pt(11032055),.005)});break}case"DreamProgress":{const p=(d=i.data)==null?void 0:d.memory_id;p&&h.has(p)&&n.addPulse(p,1.5,new pt(12616956),.01);break}case"DreamCompleted":{n.createSpawnBurst(new P(0,0,0),new pt(11032055)),n.createShockwave(new P(0,0,0),new pt(11032055),o);break}case"RetentionDecayed":{const p=(f=i.data)==null?void 0:f.id;p&&h.has(p)&&n.addPulse(p,.8,new pt(16729943),.03);break}case"ConsolidationCompleted":{h.forEach((p,g)=>{n.addPulse(g,.4+Math.random()*.3,new pt(16758784),.015)});break}case"ActivationSpread":{const p=i.data;if(p.source_id&&p.target_ids){const g=c.get(p.source_id);if(g)for(const v of p.target_ids){const m=c.get(v);m&&n.createConnectionFlash(g,m,new pt(1370310))}}break}}}const Lg=` + }`})}}Wi.BlurDirectionX=new vt(1,0);Wi.BlurDirectionY=new vt(0,1);function vg(){const t=new Float32Array(6e3),e=new Float32Array(2e3*3);for(let r=0;r<2e3;r++){const a=Math.random()*Math.PI*2,o=Math.acos(2*Math.random()-1),l=600+Math.random()*400;t[r*3]=l*Math.sin(o)*Math.cos(a),t[r*3+1]=l*Math.sin(o)*Math.sin(a),t[r*3+2]=l*Math.cos(o);const c=Math.random();e[r*3]=.55+c*.25,e[r*3+1]=.55+c*.15,e[r*3+2]=.75+c*.25}const n=new pe;n.setAttribute("position",new he(t,3)),n.setAttribute("color",new he(e,3));const s=new ei({size:1.6,sizeAttenuation:!0,vertexColors:!0,transparent:!0,opacity:.6,depthWrite:!1,blending:Ne});return new Fi(n,s)}function xg(i){const t=new Kh;t.background=new pt(328975),t.fog=new pr(657946,.0035);const e=new Ye(60,i.clientWidth/i.clientHeight,.1,2e3);e.position.set(0,30,80);const n=new Km({antialias:!0,alpha:!0,powerPreference:"high-performance"});n.setSize(i.clientWidth,i.clientHeight),n.setPixelRatio(Math.min(window.devicePixelRatio,2)),n.toneMapping=zl,n.toneMappingExposure=1.25,i.appendChild(n.domElement);const s=new Jm(e,n.domElement);s.enableDamping=!0,s.dampingFactor=.05,s.rotateSpeed=.5,s.zoomSpeed=.8,s.minDistance=10,s.maxDistance=500,s.autoRotate=!0,s.autoRotateSpeed=.3;const r=new mg(n);r.addPass(new gg(t,e));const a=new Wi(new vt(i.clientWidth,i.clientHeight),.55,.6,.2);r.addPass(a);const o=new lu(2763354,.7);t.add(o);const l=new qo(6514417,1.8,240);l.position.set(50,50,50),t.add(l);const c=new qo(11032055,1.2,240);c.position.set(-50,-30,-50),t.add(c);const h=vg();t.add(h);const d=new uu;d.params.Points={threshold:2};const p=new vt;return{scene:t,camera:e,renderer:n,controls:s,composer:r,bloomPass:a,raycaster:d,mouse:p,lights:{ambient:o,point1:l,point2:c},starfield:h}}function Mg(i,t){const e=t.clientWidth,n=t.clientHeight;i.camera.aspect=e/n,i.camera.updateProjectionMatrix(),i.renderer.setSize(e,n),i.composer.setSize(e,n)}function Sg(i){i.scene.traverse(t=>{var e;(t instanceof Se||t instanceof tu)&&((e=t.geometry)==null||e.dispose(),Array.isArray(t.material)?t.material.forEach(n=>n.dispose()):t.material&&t.material.dispose())}),i.renderer.dispose(),i.composer.dispose()}class yg{constructor(t){Wt(this,"positions");Wt(this,"velocities");Wt(this,"running",!0);Wt(this,"step",0);Wt(this,"repulsionStrength",500);Wt(this,"attractionStrength",.01);Wt(this,"dampening",.9);Wt(this,"baseMaxSteps",300);Wt(this,"maxSteps",300);Wt(this,"cooldownExtension",0);this.positions=t,this.velocities=new Map;for(const e of t.keys())this.velocities.set(e,new P)}addNode(t,e){this.positions.set(t,e.clone()),this.velocities.set(t,new P),this.cooldownExtension=100,this.maxSteps=Math.max(this.maxSteps,this.step+this.cooldownExtension),this.running=!0}removeNode(t){this.positions.delete(t),this.velocities.delete(t)}tick(t){if(!this.running)return;if(this.step>this.maxSteps){this.cooldownExtension>0&&(this.cooldownExtension=0,this.maxSteps=this.baseMaxSteps);return}this.step++;const e=Math.max(.001,1-this.step/this.maxSteps),n=Array.from(this.positions.keys());for(let s=0;s0,o=new mr(s,16,16),l=new iu({color:new pt(r),emissive:new pt(r),emissiveIntensity:a?0:.3+t.retention*.5,roughness:.3,metalness:.1,transparent:!0,opacity:a?.2:.3+t.retention*.7}),c=new Se(o,l);c.position.copy(e),c.scale.setScalar(n),c.userData={nodeId:t.id,type:t.type,retention:t.retention},this.meshMap.set(t.id,c),this.group.add(c);const h=new Qs({map:Eg(),color:new pt(r),transparent:!0,opacity:n>0?a?.1:.3+t.retention*.35:0,blending:Ne,depthWrite:!1}),d=new Ns(h);d.scale.set(s*6*n,s*6*n,1),d.position.copy(e),d.userData={isGlow:!0,nodeId:t.id},this.glowMap.set(t.id,d),this.group.add(d);const p=t.label||t.type,f=this.createTextSprite(p,"#e2e8f0");return f.position.copy(e),f.position.y+=s*2+1.5,f.userData={isLabel:!0,nodeId:t.id,offset:s*2+1.5},this.group.add(f),this.labelSprites.set(t.id,f),{mesh:c,glow:d,label:f,size:s}}addNode(t,e){const n=(e==null?void 0:e.clone())??new P((Math.random()-.5)*40,(Math.random()-.5)*40,(Math.random()-.5)*40);this.positions.set(t.id,n);const{mesh:s,glow:r,label:a}=this.createNodeMeshes(t,n,0);return s.scale.setScalar(.001),r.scale.set(.001,.001,1),r.material.opacity=0,a.material.opacity=0,this.materializingNodes.push({id:t.id,frame:0,totalFrames:30,mesh:s,glow:r,label:a,targetScale:.5+t.retention*2}),n}removeNode(t){const e=this.meshMap.get(t),n=this.glowMap.get(t),s=this.labelSprites.get(t);!e||!n||!s||(this.materializingNodes=this.materializingNodes.filter(r=>r.id!==t),this.dissolvingNodes.push({id:t,frame:0,totalFrames:60,mesh:e,glow:n,label:s,originalScale:e.scale.x}))}growNode(t,e){const n=this.meshMap.get(t);if(!n)return;const s=n.scale.x,r=.5+e*2;n.userData.retention=e,this.growingNodes.push({id:t,frame:0,totalFrames:30,startScale:s,targetScale:r})}createTextSprite(t,e){const n=document.createElement("canvas"),s=n.getContext("2d");if(!s){const c=new Te;return new Ns(new Qs({map:c,transparent:!0,opacity:0}))}n.width=512,n.height=64;const r=t.length>40?t.slice(0,37)+"...":t;s.clearRect(0,0,n.width,n.height),s.font="bold 28px -apple-system, BlinkMacSystemFont, sans-serif",s.textAlign="center",s.textBaseline="middle",s.shadowColor="rgba(0, 0, 0, 0.8)",s.shadowBlur=6,s.shadowOffsetX=0,s.shadowOffsetY=2,s.fillStyle=e,s.fillText(r,n.width/2,n.height/2);const a=new lc(n);a.needsUpdate=!0;const o=new Qs({map:a,transparent:!0,opacity:0,depthTest:!1,sizeAttenuation:!0}),l=new Ns(o);return l.scale.set(12,1.5,1),l}updatePositions(){this.group.children.forEach(t=>{if(t.userData.nodeId){const e=this.positions.get(t.userData.nodeId);if(!e)return;t.userData.isGlow?t.position.copy(e):t.userData.isLabel?(t.position.copy(e),t.position.y+=t.userData.offset):t instanceof Se&&t.position.copy(e)}})}animate(t,e,n){var r,a;for(let o=this.materializingNodes.length-1;o>=0;o--){const l=this.materializingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=wl(c);if(l.mesh.scale.setScalar(Math.max(.001,h)),l.frame>=5){const d=Math.min((l.frame-5)/5,1),p=l.glow.material;p.opacity=d*.4;const f=l.targetScale*6*h;l.glow.scale.set(f,f,1)}if(l.frame>=40){const d=Math.min((l.frame-40)/20,1);l.label.material.opacity=d*.9}l.frame>=60&&this.materializingNodes.splice(o,1)}for(let o=this.dissolvingNodes.length-1;o>=0;o--){const l=this.dissolvingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=1-bg(c),d=Math.max(.001,l.originalScale*h);l.mesh.scale.setScalar(d);const p=d*6;l.glow.scale.set(p,p,1);const f=l.mesh.material;f.opacity*=.97,l.glow.material.opacity*=.95,l.label.material.opacity*=.93,l.frame>=l.totalFrames&&(this.group.remove(l.mesh),this.group.remove(l.glow),this.group.remove(l.label),l.mesh.geometry.dispose(),l.mesh.material.dispose(),(r=l.glow.material.map)==null||r.dispose(),l.glow.material.dispose(),(a=l.label.material.map)==null||a.dispose(),l.label.material.dispose(),this.meshMap.delete(l.id),this.glowMap.delete(l.id),this.labelSprites.delete(l.id),this.positions.delete(l.id),this.dissolvingNodes.splice(o,1))}for(let o=this.growingNodes.length-1;o>=0;o--){const l=this.growingNodes[o];l.frame++;const c=Math.min(l.frame/l.totalFrames,1),h=l.startScale+(l.targetScale-l.startScale)*wl(c),d=this.meshMap.get(l.id);d&&d.scale.setScalar(h);const p=this.glowMap.get(l.id);if(p){const f=h*6;p.scale.set(f,f,1)}l.frame>=l.totalFrames&&this.growingNodes.splice(o,1)}const s=new Set([...this.materializingNodes.map(o=>o.id),...this.dissolvingNodes.map(o=>o.id),...this.growingNodes.map(o=>o.id)]);this.meshMap.forEach((o,l)=>{if(s.has(l))return;const c=e.find(p=>p.id===l);if(!c)return;const h=1+Math.sin(t*1.5+e.indexOf(c)*.5)*.15*c.retention;o.scale.setScalar(h);const d=o.material;if(l===this.hoveredNode)d.emissiveIntensity=1;else if(l===this.selectedNode)d.emissiveIntensity=.8;else{const f=.3+c.retention*.5+Math.sin(t*(.8+c.retention*.7))*.1*c.retention;d.emissiveIntensity=f}}),this.labelSprites.forEach((o,l)=>{if(s.has(l))return;const c=this.positions.get(l);if(!c)return;const h=n.position.distanceTo(c),d=o.material,p=l===this.hoveredNode||l===this.selectedNode?1:h<40?.9:h<80?.9*(1-(h-40)/40):0;d.opacity+=(p-d.opacity)*.1})}getMeshes(){return Array.from(this.meshMap.values())}dispose(){this.group.traverse(t=>{var e,n,s,r,a;t instanceof Se?((e=t.geometry)==null||e.dispose(),(n=t.material)==null||n.dispose()):t instanceof Ns&&((r=(s=t.material)==null?void 0:s.map)==null||r.dispose(),(a=t.material)==null||a.dispose())}),this.materializingNodes=[],this.dissolvingNodes=[],this.growingNodes=[]}}function wg(i){return 1-Math.pow(1-i,3)}class Ag{constructor(){Wt(this,"group");Wt(this,"growingEdges",[]);Wt(this,"dissolvingEdges",[]);this.group=new Pi}createEdges(t,e){for(const n of t){const s=e.get(n.source),r=e.get(n.target);if(!s||!r)continue;const a=[s,r],o=new pe().setFromPoints(a),l=new lr({color:9133302,transparent:!0,opacity:Math.min(.25+n.weight*.5,.8),blending:Ne,depthWrite:!1}),c=new Va(o,l);c.userData={source:n.source,target:n.target},this.group.add(c)}}addEdge(t,e){const n=e.get(t.source),s=e.get(t.target);if(!n||!s)return;const r=[n.clone(),n.clone()],a=new pe().setFromPoints(r),o=new lr({color:9133302,transparent:!0,opacity:0,blending:Ne,depthWrite:!1}),l=new Va(a,o);l.userData={source:t.source,target:t.target},this.group.add(l),this.growingEdges.push({line:l,source:t.source,target:t.target,frame:0,totalFrames:45})}removeEdgesForNode(t){const e=[];this.group.children.forEach(n=>{const s=n;(s.userData.source===t||s.userData.target===t)&&e.push(s)});for(const n of e)this.growingEdges=this.growingEdges.filter(s=>s.line!==n),this.dissolvingEdges.push({line:n,frame:0,totalFrames:40})}animateEdges(t){for(let e=this.growingEdges.length-1;e>=0;e--){const n=this.growingEdges[e];n.frame++;const s=wg(Math.min(n.frame/n.totalFrames,1)),r=t.get(n.source),a=t.get(n.target);if(!r||!a)continue;const o=r.clone().lerp(a,s),l=n.line.geometry.attributes.position;l.setXYZ(0,r.x,r.y,r.z),l.setXYZ(1,o.x,o.y,o.z),l.needsUpdate=!0;const c=n.line.material;c.opacity=s*.65,n.frame>=n.totalFrames&&(c.opacity=.65,this.growingEdges.splice(e,1))}for(let e=this.dissolvingEdges.length-1;e>=0;e--){const n=this.dissolvingEdges[e];n.frame++;const s=n.frame/n.totalFrames,r=n.line.material;r.opacity=Math.max(0,.65*(1-s)),n.frame>=n.totalFrames&&(this.group.remove(n.line),n.line.geometry.dispose(),n.line.material.dispose(),this.dissolvingEdges.splice(e,1))}}updatePositions(t){this.group.children.forEach(e=>{const n=e;if(this.growingEdges.some(a=>a.line===n)||this.dissolvingEdges.some(a=>a.line===n))return;const s=t.get(n.userData.source),r=t.get(n.userData.target);if(s&&r){const a=n.geometry.attributes.position;a.setXYZ(0,s.x,s.y,s.z),a.setXYZ(1,r.x,r.y,r.z),a.needsUpdate=!0}})}dispose(){this.group.children.forEach(t=>{var n,s;const e=t;(n=e.geometry)==null||n.dispose(),(s=e.material)==null||s.dispose()}),this.growingEdges=[],this.dissolvingEdges=[]}}class Rg{constructor(t){Wt(this,"starField");Wt(this,"neuralParticles");this.starField=this.createStarField(),this.neuralParticles=this.createNeuralParticles(),t.add(this.starField),t.add(this.neuralParticles)}createStarField(){const e=new pe,n=new Float32Array(3e3*3),s=new Float32Array(3e3);for(let a=0;a<3e3;a++)n[a*3]=(Math.random()-.5)*1e3,n[a*3+1]=(Math.random()-.5)*1e3,n[a*3+2]=(Math.random()-.5)*1e3,s[a]=Math.random()*1.5;e.setAttribute("position",new he(n,3)),e.setAttribute("size",new he(s,1));const r=new ei({color:6514417,size:.5,transparent:!0,opacity:.4,sizeAttenuation:!0,blending:Ne});return new Fi(e,r)}createNeuralParticles(){const e=new pe,n=new Float32Array(500*3),s=new Float32Array(500*3);for(let a=0;a<500;a++)n[a*3]=(Math.random()-.5)*100,n[a*3+1]=(Math.random()-.5)*100,n[a*3+2]=(Math.random()-.5)*100,s[a*3]=.4+Math.random()*.3,s[a*3+1]=.3+Math.random()*.2,s[a*3+2]=.8+Math.random()*.2;e.setAttribute("position",new he(n,3)),e.setAttribute("color",new he(s,3));const r=new ei({size:.3,vertexColors:!0,transparent:!0,opacity:.4,blending:Ne,sizeAttenuation:!0});return new Fi(e,r)}animate(t){this.starField.rotation.y+=1e-4,this.starField.rotation.x+=5e-5;const e=this.neuralParticles.geometry.attributes.position;for(let n=0;n=0;s--){const r=this.pulseEffects[s];if(r.intensity-=r.decay,r.intensity<=0){this.pulseEffects.splice(s,1);continue}const a=t.get(r.nodeId);if(a){const o=a.material;o.emissive.lerp(r.color,r.intensity*.3),o.emissiveIntensity=Math.max(o.emissiveIntensity,r.intensity)}}for(let s=this.spawnBursts.length-1;s>=0;s--){const r=this.spawnBursts[s];if(r.age++,r.age>120){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),this.spawnBursts.splice(s,1);continue}const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity;for(let c=0;c=0;s--){const r=this.rainbowBursts[s];if(r.age++,r.age>r.maxAge){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),this.rainbowBursts.splice(s,1);continue}const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity;for(let p=0;p=0;s--){const r=this.rippleWaves[s];if(r.age++,r.radius+=r.speed,r.age>r.maxAge){this.rippleWaves.splice(s,1);continue}const a=r.radius,o=3;n.forEach((l,c)=>{if(r.pulsedNodes.has(c))return;const h=l.distanceTo(r.origin);h>=a-o&&h<=a+o&&(r.pulsedNodes.add(c),this.addPulse(c,.8,new pt(65489),.03))})}for(let s=this.implosions.length-1;s>=0;s--){const r=this.implosions[s];if(r.age++,r.age>r.maxAge+20){this.scene.remove(r.particles),r.particles.geometry.dispose(),r.particles.material.dispose(),r.flash&&(this.scene.remove(r.flash),r.flash.geometry.dispose(),r.flash.material.dispose()),this.implosions.splice(s,1);continue}if(r.age<=r.maxAge){const a=r.particles.geometry.attributes.position,o=r.particles.geometry.attributes.velocity,l=1+r.age*.02;for(let h=0;hr.maxAge){const a=(r.age-r.maxAge)/20;r.flash.material.opacity=Math.max(0,1-a),r.flash.scale.setScalar(1+a*3)}}for(let s=this.shockwaves.length-1;s>=0;s--){const r=this.shockwaves[s];if(r.age++,r.age>r.maxAge){this.scene.remove(r.mesh),r.mesh.geometry.dispose(),r.mesh.material.dispose(),this.shockwaves.splice(s,1);continue}const a=r.age/r.maxAge;r.mesh.scale.setScalar(1+a*20),r.mesh.material.opacity=.8*(1-a),r.mesh.lookAt(e.position)}for(let s=this.connectionFlashes.length-1;s>=0;s--){const r=this.connectionFlashes[s];if(r.intensity-=.015,r.intensity<=0){this.scene.remove(r.line),r.line.geometry.dispose(),r.line.material.dispose(),this.connectionFlashes.splice(s,1);continue}r.line.material.opacity=r.intensity}}dispose(){for(const t of this.spawnBursts)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose();for(const t of this.rainbowBursts)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose();for(const t of this.implosions)this.scene.remove(t.particles),t.particles.geometry.dispose(),t.particles.material.dispose(),t.flash&&(this.scene.remove(t.flash),t.flash.geometry.dispose(),t.flash.material.dispose());for(const t of this.shockwaves)this.scene.remove(t.mesh),t.mesh.geometry.dispose(),t.mesh.material.dispose();for(const t of this.connectionFlashes)this.scene.remove(t.line),t.line.geometry.dispose(),t.line.material.dispose();this.pulseEffects=[],this.spawnBursts=[],this.rainbowBursts=[],this.rippleWaves=[],this.implosions=[],this.shockwaves=[],this.connectionFlashes=[]}}const Sn={bloomStrength:.8,rotateSpeed:.3,fogColor:328976,fogDensity:.008,nebulaIntensity:0,chromaticIntensity:.002,vignetteRadius:.9,breatheAmplitude:1},In={bloomStrength:1.8,rotateSpeed:.08,fogColor:656672,fogDensity:.006,nebulaIntensity:1,chromaticIntensity:.005,vignetteRadius:.7,breatheAmplitude:2};class Pg{constructor(){Wt(this,"active",!1);Wt(this,"transition",0);Wt(this,"transitionSpeed",.008);Wt(this,"current");Wt(this,"auroraHue",0);this.current={...Sn}}setActive(t){this.active=t}update(t,e,n,s,r){const a=this.active?1:0;this.transition+=(a-this.transition)*this.transitionSpeed*60*(1/60),this.transition=Math.max(0,Math.min(1,this.transition));const o=this.transition;this.current.bloomStrength=this.lerp(Sn.bloomStrength,In.bloomStrength,o),this.current.rotateSpeed=this.lerp(Sn.rotateSpeed,In.rotateSpeed,o),this.current.fogDensity=this.lerp(Sn.fogDensity,In.fogDensity,o),this.current.nebulaIntensity=this.lerp(Sn.nebulaIntensity,In.nebulaIntensity,o),this.current.chromaticIntensity=this.lerp(Sn.chromaticIntensity,In.chromaticIntensity,o),this.current.vignetteRadius=this.lerp(Sn.vignetteRadius,In.vignetteRadius,o),this.current.breatheAmplitude=this.lerp(Sn.breatheAmplitude,In.breatheAmplitude,o),e.strength=this.current.bloomStrength,n.autoRotateSpeed=this.current.rotateSpeed;const l=new pt(Sn.fogColor),c=new pt(In.fogColor),h=l.clone().lerp(c,o);if(t.fog=new pr(h,this.current.fogDensity),o>.01){this.auroraHue=r*.1%1;const d=new pt().setHSL(.75+this.auroraHue*.15,.8,.5),p=new pt().setHSL(.55+this.auroraHue*.2,.7,.4);s.point1.color.lerp(d,o*.3),s.point2.color.lerp(p,o*.3)}else s.point1.color.set(6514417),s.point2.color.set(11032055)}lerp(t,e,n){return t+(e-t)*n}}const Dg=50,os=[];function Lg(i,t,e){const n=i.tags??[],s=i.type??"";let r=null,a=0;for(const o of t){let l=0;o.type===s&&(l+=2);for(const c of o.tags)n.includes(c)&&(l+=1);l>a&&(a=l,r=o.id)}if(r&&a>0){const o=e.get(r);if(o)return new P(o.x+(Math.random()-.5)*10,o.y+(Math.random()-.5)*10,o.z+(Math.random()-.5)*10)}return new P((Math.random()-.5)*40,(Math.random()-.5)*40,(Math.random()-.5)*40)}function Ug(i,t){if(os.length<=Dg)return;const e=os.shift();i.edgeManager.removeEdgesForNode(e),i.nodeManager.removeNode(e),i.forceSim.removeNode(e),i.onMutation({type:"edgesRemoved",nodeId:e}),i.onMutation({type:"nodeRemoved",nodeId:e});const n=t.findIndex(s=>s.id===e);n!==-1&&t.splice(n,1)}function Ig(i,t,e){var d,p;const{effects:n,nodeManager:s,edgeManager:r,forceSim:a,camera:o,onMutation:l}=t,c=s.positions,h=s.meshMap;switch(i.type){case"MemoryCreated":{const f=i.data;if(!f.id)break;const g={id:f.id,label:(f.content??"").slice(0,60),type:f.node_type??"fact",retention:Math.max(0,Math.min(1,f.retention??.9)),tags:f.tags??[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),isCenter:!1},v=Lg(g,e,c),m=s.addNode(g,v);a.addNode(f.id,m),os.push(f.id),Ug(t,e);const u=new pt(Fl[g.type]||"#00ffd1");n.createRainbowBurst(v,u),n.createShockwave(v,u,o);const T=u.clone();T.offsetHSL(.15,0,0),setTimeout(()=>{n.createShockwave(v,T,o)},166),n.createRippleWave(v),l({type:"nodeAdded",node:g});break}case"ConnectionDiscovered":{const f=i.data;if(!f.source_id||!f.target_id)break;const g=c.get(f.source_id),v=c.get(f.target_id),m={source:f.source_id,target:f.target_id,weight:f.weight??.5,type:f.connection_type??"semantic"};r.addEdge(m,c),g&&v&&n.createConnectionFlash(g,v,new pt(54527)),f.source_id&&h.has(f.source_id)&&n.addPulse(f.source_id,1,new pt(54527),.02),f.target_id&&h.has(f.target_id)&&n.addPulse(f.target_id,1,new pt(54527),.02),l({type:"edgeAdded",edge:m});break}case"MemoryDeleted":{const f=i.data;if(!f.id)break;const g=c.get(f.id);if(g){const m=new pt(16729943);n.createImplosion(g,m)}r.removeEdgesForNode(f.id),s.removeNode(f.id),a.removeNode(f.id);const v=os.indexOf(f.id);v!==-1&&os.splice(v,1),l({type:"edgesRemoved",nodeId:f.id}),l({type:"nodeRemoved",nodeId:f.id});break}case"MemoryPromoted":{const f=i.data,g=f==null?void 0:f.id;if(!g)break;const v=f.new_retention??.95;if(h.has(g)){s.growNode(g,v),n.addPulse(g,1.2,new pt(65416),.01);const m=c.get(g);m&&(n.createShockwave(m,new pt(65416),o),n.createSpawnBurst(m,new pt(65416))),l({type:"nodeUpdated",nodeId:g,retention:v})}break}case"MemoryDemoted":{const f=i.data,g=f==null?void 0:f.id;if(!g)break;const v=f.new_retention??.3;h.has(g)&&(s.growNode(g,v),n.addPulse(g,.8,new pt(16729943),.03),l({type:"nodeUpdated",nodeId:g,retention:v}));break}case"MemoryUpdated":{const f=i.data,g=f==null?void 0:f.id;if(!g||!h.has(g))break;n.addPulse(g,.6,new pt(8490232),.02),f.retention!==void 0&&(s.growNode(g,f.retention),l({type:"nodeUpdated",nodeId:g,retention:f.retention}));break}case"SearchPerformed":{h.forEach((f,g)=>{n.addPulse(g,.6+Math.random()*.4,new pt(8490232),.02)});break}case"DreamStarted":{h.forEach((f,g)=>{n.addPulse(g,1,new pt(11032055),.005)});break}case"DreamProgress":{const f=(d=i.data)==null?void 0:d.memory_id;f&&h.has(f)&&n.addPulse(f,1.5,new pt(12616956),.01);break}case"DreamCompleted":{n.createSpawnBurst(new P(0,0,0),new pt(11032055)),n.createShockwave(new P(0,0,0),new pt(11032055),o);break}case"RetentionDecayed":{const f=(p=i.data)==null?void 0:p.id;f&&h.has(f)&&n.addPulse(f,.8,new pt(16729943),.03);break}case"ConsolidationCompleted":{h.forEach((f,g)=>{n.addPulse(g,.4+Math.random()*.3,new pt(16758784),.015)});break}case"ActivationSpread":{const f=i.data;if(f.source_id&&f.target_ids){const g=c.get(f.source_id);if(g)for(const v of f.target_ids){const m=c.get(v);m&&n.createConnectionFlash(g,m,new pt(1370310))}}break}}}const Ng=` varying vec2 vUv; void main() { vUv = uv; gl_Position = vec4(position, 1.0); } -`,Ug=` +`,Fg=` precision highp float; uniform float uTime; @@ -4031,7 +4031,7 @@ void main() { gl_FragColor = vec4(color, 1.0); } -`;function Ig(i){const t=new us(2,2),e=new Ne({vertexShader:Lg,fragmentShader:Ug,uniforms:{uTime:{value:0},uResolution:{value:new vt(window.innerWidth,window.innerHeight)},uDreamIntensity:{value:0}},depthWrite:!1,depthTest:!1,transparent:!1}),n=new Se(t,e);return n.frustumCulled=!1,n.renderOrder=-1e3,i.add(n),{mesh:n,material:e}}function Ng(i,t,e,n,s){i.uniforms.uTime.value=t,i.uniforms.uDreamIntensity.value=e,i.uniforms.uResolution.value.set(n,s)}const Fg={uniforms:{tDiffuse:{value:null},uIntensity:{value:.002}},vertexShader:` +`;function Og(i){const t=new ds(2,2),e=new Fe({vertexShader:Ng,fragmentShader:Fg,uniforms:{uTime:{value:0},uResolution:{value:new vt(window.innerWidth,window.innerHeight)},uDreamIntensity:{value:0}},depthWrite:!1,depthTest:!1,transparent:!1}),n=new Se(t,e);return n.frustumCulled=!1,n.renderOrder=-1e3,i.add(n),{mesh:n,material:e}}function Bg(i,t,e,n,s){i.uniforms.uTime.value=t,i.uniforms.uDreamIntensity.value=e,i.uniforms.uResolution.value.set(n,s)}const zg={uniforms:{tDiffuse:{value:null},uIntensity:{value:.002}},vertexShader:` varying vec2 vUv; void main() { vUv = uv; @@ -4061,7 +4061,7 @@ void main() { gl_FragColor = vec4(r, g, b, 1.0); } - `},Og={uniforms:{tDiffuse:{value:null},uTime:{value:0},uIntensity:{value:.04}},vertexShader:` + `},Hg={uniforms:{tDiffuse:{value:null},uTime:{value:0},uIntensity:{value:.04}},vertexShader:` varying vec2 vUv; void main() { vUv = uv; @@ -4083,7 +4083,7 @@ void main() { color.rgb += grain * uIntensity; gl_FragColor = color; } - `},Bg={uniforms:{tDiffuse:{value:null},uRadius:{value:.9},uSoftness:{value:.5}},vertexShader:` + `},kg={uniforms:{tDiffuse:{value:null},uRadius:{value:.9},uSoftness:{value:.5}},vertexShader:` varying vec2 vUv; void main() { vUv = uv; @@ -4103,11 +4103,11 @@ void main() { color.rgb *= vignette; gl_FragColor = color; } - `};function zg(i){const t=new Js(Fg),e=new Js(Og),n=new Js(Bg);return i.addPass(t),i.addPass(e),i.addPass(n),{chromatic:t,grain:e,vignette:n}}function Hg(i,t,e){i.chromatic.uniforms.uIntensity.value=.002+(.005-.002)*e,i.grain.uniforms.uTime.value=t,i.grain.uniforms.uIntensity.value=.04+e*.02;const r=.9,a=.7;i.vignette.uniforms.uRadius.value=r+(a-r)*e}var kg=je('
');function Vg(i,t){lr(t,!0);let e=Qs(t,"events",19,()=>[]),n=Qs(t,"isDreaming",3,!1),s,r,a,o,l,c,h,d,f,p,g,v=0,m=[];Al(()=>{r=_g(s),p=Ig(r.scene).material,g=zg(r.composer),c=new Tg(r.scene),o=new yg,l=new bg,h=new wg(r.scene),f=new Ag;const U=o.createNodes(t.nodes);l.createEdges(t.edges,U),d=new Mg(U),m=[...t.nodes],r.scene.add(l.group),r.scene.add(o.group),u(),window.addEventListener("resize",b),s.addEventListener("pointermove",y),s.addEventListener("click",L)}),Rl(()=>{cancelAnimationFrame(a),window.removeEventListener("resize",b),s==null||s.removeEventListener("pointermove",y),s==null||s.removeEventListener("click",L),h==null||h.dispose(),c==null||c.dispose(),o==null||o.dispose(),l==null||l.dispose(),r&&xg(r)});function u(){a=requestAnimationFrame(u);const A=performance.now()*.001;d.tick(t.edges),o.updatePositions(),l.updatePositions(o.positions),l.animateEdges(o.positions),c.animate(A),o.animate(A,m,r.camera),f.setActive(n()),f.update(r.scene,r.bloomPass,r.controls,r.lights,A),Ng(p,A,f.current.nebulaIntensity,s.clientWidth,s.clientHeight),Hg(g,A,f.current.nebulaIntensity),T(),h.update(o.meshMap,r.camera,o.positions),r.controls.update(),r.composer.render()}function T(){if(!e()||e().length<=v)return;const A=e().slice(v);v=e().length;const U={effects:h,nodeManager:o,edgeManager:l,forceSim:d,camera:r.camera,onMutation:S=>{var M;S.type==="nodeAdded"?m=[...m,S.node]:S.type==="nodeRemoved"&&(m=m.filter(D=>D.id!==S.nodeId)),(M=t.onGraphMutation)==null||M.call(t,S)}};for(const S of A)Dg(S,U,m)}function b(){!s||!r||vg(r,s)}function y(A){const U=s.getBoundingClientRect();r.mouse.x=(A.clientX-U.left)/U.width*2-1,r.mouse.y=-((A.clientY-U.top)/U.height)*2+1,r.raycaster.setFromCamera(r.mouse,r.camera);const S=r.raycaster.intersectObjects(o.getMeshes());S.length>0?(o.hoveredNode=S[0].object.userData.nodeId,s.style.cursor="pointer"):(o.hoveredNode=null,s.style.cursor="grab")}function L(){var A;if(o.hoveredNode){o.selectedNode=o.hoveredNode,(A=t.onSelect)==null||A.call(t,o.hoveredNode);const U=o.positions.get(o.hoveredNode);U&&r.controls.target.lerp(U.clone(),.5)}}var R=kg();Uc(R,A=>s=A,()=>s),ze(i,R),cr()}var Gg=je('
'),Wg=je('
');function Xg(i,t){lr(t,!0);let e=Qs(t,"width",3,240),n=Qs(t,"height",3,80);function s(m){return t.stability<=0?0:Math.exp(-m/t.stability)}let r=ti(()=>{const m=[],u=Math.max(t.stability*3,30),T=4,b=e()-T*2,y=n()-T*2;for(let L=0;L<=50;L++){const R=L/50*u,A=s(R),U=T+L/50*b,S=T+(1-A)*y;m.push(`${L===0?"M":"L"}${U.toFixed(1)},${S.toFixed(1)}`)}return m.join(" ")}),a=ti(()=>[{label:"Now",days:0,value:t.retention},{label:"1d",days:1,value:s(1)},{label:"7d",days:7,value:s(7)},{label:"30d",days:30,value:s(30)}]);function o(m){return m>.7?"#10b981":m>.4?"#f59e0b":"#ef4444"}var l=Wg(),c=Dt(l),h=Dt(c),d=Ot(h),f=Ot(d),p=Ot(f),g=Ot(p);wc(),Rt(c);var v=Ot(c,2);$r(v,21,()=>j(a),Jr,(m,u)=>{var T=Gg(),b=Dt(T),y=Dt(b);Rt(b);var L=Ot(b,2),R=Dt(L);Rt(L),Rt(T),ln((A,U)=>{_e(y,`${j(u).label??""}:`),Ll(L,`color: ${A??""}`),_e(R,`${U??""}%`)},[()=>o(j(u).value),()=>(j(u).value*100).toFixed(0)]),ze(m,T)}),Rt(v),Rt(l),ln(m=>{Be(c,"width",e()),Be(c,"height",n()),Be(c,"viewBox",`0 0 ${e()??""} ${n()??""}`),Be(h,"y1",4+(n()-8)*.5),Be(h,"x2",e()-4),Be(h,"y2",4+(n()-8)*.5),Be(d,"y1",4+(n()-8)*.8),Be(d,"x2",e()-4),Be(d,"y2",4+(n()-8)*.8),Be(f,"d",j(r)),Be(p,"d",`${j(r)??""} L${e()-4},${n()-4} L4,${n()-4} Z`),Be(g,"cy",4+(1-t.retention)*(n()-8)),Be(g,"fill",m)},[()=>o(t.retention)]),ze(i,l),cr()}function wl(i,t,e){const n=e.getTime(),s=new Set,r=new Map,a=i.filter(l=>{const c=new Date(l.createdAt).getTime();if(c<=n){s.add(l.id);const h=n-c,d=1440*60*1e3,f=hs.has(l.source)&&s.has(l.target));return{visibleNodes:a,visibleEdges:o,nodeOpacities:r}}function Yg(i){if(i.length===0){const n=new Date;return{oldest:n,newest:n}}let t=1/0,e=-1/0;for(const n of i){const s=new Date(n.createdAt).getTime();se&&(e=s)}return{oldest:new Date(t),newest:new Date(e)}}var qg=je(`
');function Xg(i,t){ur(t,!0);let e=nr(t,"events",19,()=>[]),n=nr(t,"isDreaming",3,!1),s,r,a,o,l,c,h,d,p,f,g,v=0,m=[];Rl(()=>{r=xg(s),f=Og(r.scene).material,g=Vg(r.composer),c=new Rg(r.scene),o=new Tg,l=new Ag,h=new Cg(r.scene),p=new Pg;const U=o.createNodes(t.nodes);l.createEdges(t.edges,U),d=new yg(U),m=[...t.nodes],r.scene.add(l.group),r.scene.add(o.group),u(),window.addEventListener("resize",b),s.addEventListener("pointermove",y),s.addEventListener("click",L)}),Cl(()=>{cancelAnimationFrame(a),window.removeEventListener("resize",b),s==null||s.removeEventListener("pointermove",y),s==null||s.removeEventListener("click",L),h==null||h.dispose(),c==null||c.dispose(),o==null||o.dispose(),l==null||l.dispose(),r&&Sg(r)});function u(){a=requestAnimationFrame(u);const A=performance.now()*.001;d.tick(t.edges),o.updatePositions(),l.updatePositions(o.positions),l.animateEdges(o.positions),c.animate(A),o.animate(A,m,r.camera),p.setActive(n()),p.update(r.scene,r.bloomPass,r.controls,r.lights,A),Bg(f,A,p.current.nebulaIntensity,s.clientWidth,s.clientHeight),Gg(g,A,p.current.nebulaIntensity),T(),h.update(o.meshMap,r.camera,o.positions),r.controls.update(),r.composer.render()}function T(){if(!e()||e().length<=v)return;const A=e().slice(v);v=e().length;const U={effects:h,nodeManager:o,edgeManager:l,forceSim:d,camera:r.camera,onMutation:S=>{var M;S.type==="nodeAdded"?m=[...m,S.node]:S.type==="nodeRemoved"&&(m=m.filter(D=>D.id!==S.nodeId)),(M=t.onGraphMutation)==null||M.call(t,S)}};for(const S of A)Ig(S,U,m)}function b(){!s||!r||Mg(r,s)}function y(A){const U=s.getBoundingClientRect();r.mouse.x=(A.clientX-U.left)/U.width*2-1,r.mouse.y=-((A.clientY-U.top)/U.height)*2+1,r.raycaster.setFromCamera(r.mouse,r.camera);const S=r.raycaster.intersectObjects(o.getMeshes());S.length>0?(o.hoveredNode=S[0].object.userData.nodeId,s.style.cursor="pointer"):(o.hoveredNode=null,s.style.cursor="grab")}function L(){var A;if(o.hoveredNode){o.selectedNode=o.hoveredNode,(A=t.onSelect)==null||A.call(t,o.hoveredNode);const U=o.positions.get(o.hoveredNode);U&&r.controls.target.lerp(U.clone(),.5)}}var R=Wg();Nc(R,A=>s=A,()=>s),He(i,R),dr()}var Yg=je('
'),qg=je('
');function jg(i,t){ur(t,!0);let e=nr(t,"width",3,240),n=nr(t,"height",3,80);function s(m){return t.stability<=0?0:Math.exp(-m/t.stability)}let r=ti(()=>{const m=[],u=Math.max(t.stability*3,30),T=4,b=e()-T*2,y=n()-T*2;for(let L=0;L<=50;L++){const R=L/50*u,A=s(R),U=T+L/50*b,S=T+(1-A)*y;m.push(`${L===0?"M":"L"}${U.toFixed(1)},${S.toFixed(1)}`)}return m.join(" ")}),a=ti(()=>[{label:"Now",days:0,value:t.retention},{label:"1d",days:1,value:s(1)},{label:"7d",days:7,value:s(7)},{label:"30d",days:30,value:s(30)}]);function o(m){return m>.7?"#10b981":m>.4?"#f59e0b":"#ef4444"}var l=qg(),c=Dt(l),h=Dt(c),d=Ot(h),p=Ot(d),f=Ot(p),g=Ot(f);Rc(),Rt(c);var v=Ot(c,2);Qr(v,21,()=>j(a),ta,(m,u)=>{var T=Yg(),b=Dt(T),y=Dt(b);Rt(b);var L=Ot(b,2),R=Dt(L);Rt(L),Rt(T),ln((A,U)=>{_e(y,`${j(u).label??""}:`),Ul(L,`color: ${A??""}`),_e(R,`${U??""}%`)},[()=>o(j(u).value),()=>(j(u).value*100).toFixed(0)]),He(m,T)}),Rt(v),Rt(l),ln(m=>{ze(c,"width",e()),ze(c,"height",n()),ze(c,"viewBox",`0 0 ${e()??""} ${n()??""}`),ze(h,"y1",4+(n()-8)*.5),ze(h,"x2",e()-4),ze(h,"y2",4+(n()-8)*.5),ze(d,"y1",4+(n()-8)*.8),ze(d,"x2",e()-4),ze(d,"y2",4+(n()-8)*.8),ze(p,"d",j(r)),ze(f,"d",`${j(r)??""} L${e()-4},${n()-4} L4,${n()-4} Z`),ze(g,"cy",4+(1-t.retention)*(n()-8)),ze(g,"fill",m)},[()=>o(t.retention)]),He(i,l),dr()}function Al(i,t,e){const n=e.getTime(),s=new Set,r=new Map,a=i.filter(l=>{const c=new Date(l.createdAt).getTime();if(c<=n){s.add(l.id);const h=n-c,d=1440*60*1e3,p=hs.has(l.source)&&s.has(l.target));return{visibleNodes:a,visibleEdges:o,nodeOpacities:r}}function Zg(i){if(i.length===0){const n=new Date;return{oldest:n,newest:n}}let t=1/0,e=-1/0;for(const n of i){const s=new Date(n.createdAt).getTime();se&&(e=s)}return{oldest:new Date(t),newest:new Date(e)}}var Kg=je(`
`),jg=je('');function Zg(i,t){lr(t,!0);let e=Ie(!1),n=Ie(!1),s=Ie(1),r=Ie(100),a,o=0,l=ti(()=>Yg(t.nodes)),c=ti(()=>{const b=j(l).oldest.getTime(),L=j(l).newest.getTime()-b||1;return new Date(b+j(r)/100*L)});function h(b){return b.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function d(){se(e,!j(e)),t.onToggle(j(e)),j(e)&&(se(r,100),t.onDateChange(j(c)))}function f(){se(n,!j(n)),j(n)?(se(r,0),o=performance.now(),p()):cancelAnimationFrame(a)}function p(){a=requestAnimationFrame(b=>{const y=(b-o)/1e3;o=b;const L=j(l).oldest.getTime(),A=(j(l).newest.getTime()-L)/(1440*60*1e3)||1,U=j(s)/A*100;if(se(r,Math.min(100,j(r)+U*y),!0),t.onDateChange(j(c)),j(r)>=100){se(n,!1);return}p()})}function g(){t.onDateChange(j(c))}Rl(()=>{cancelAnimationFrame(a)});var v=Rc(),m=Cl(v);{var u=b=>{var y=qg(),L=Dt(y),R=Dt(L),A=Dt(R),U=Dt(A),S=Dt(U,!0);Rt(U);var M=Ot(U,2),D=Dt(M);D.value=D.__value=1;var W=Ot(D);W.value=W.__value=7;var z=Ot(W);z.value=z.__value=30,Rt(M),Rt(A);var V=Ot(A,2),$=Dt(V,!0);Rt(V);var G=Ot(V,2);Rt(R);var J=Ot(R,2);Dl(J);var k=Ot(J,2),it=Dt(k),ut=Dt(it,!0);Rt(it);var yt=Ot(it,2),Lt=Dt(yt,!0);Rt(yt),Rt(k),Rt(L),Rt(y),ln((qt,Y,nt)=>{_e(S,j(n)?"⏸":"▶"),_e($,qt),_e(ut,Y),_e(Lt,nt)},[()=>h(j(c)),()=>h(j(l).oldest),()=>h(j(l).newest)]),Je("click",U,f),Il(M,()=>j(s),qt=>se(s,qt)),Je("click",G,d),Je("input",J,g),Ul(J,()=>j(r),qt=>se(r,qt)),ze(b,y)},T=b=>{var y=jg();Je("click",y,d),ze(b,y)};wi(m,b=>{j(e)?b(u):b(T,!1)})}ze(i,v),cr()}Pl(["click","input"]);var Kg=je('

Loading memory graph...

'),$g=je('

Your Mind Awaits

'),Jg=je(' · · ',1),Qg=je(' '),t_=je('
'),e_=je("
"),n_=je(`

Memory Detail

Retention Forecast
◬ Explore Connections
`),i_=je(`
`);function b_(i,t){lr(t,!0);const e=()=>Dc(Ic,"$eventFeed",n),[n,s]=Pc();let r=Ie(null),a=Ie(null),o=Ie(!0),l=Ie(""),c=Ie(!1),h=Ie(""),d=Ie(150),f=Ie(!1),p=Ie(Ac(new Date)),g=Ie(0),v=Ie(0),m=ti(()=>j(r)?j(f)?wl(j(r).nodes,j(r).edges,j(p)).visibleNodes:j(r).nodes:[]),u=ti(()=>j(r)?j(f)?wl(j(r).nodes,j(r).edges,j(p)).visibleEdges:j(r).edges:[]);function T(rt){if(j(r))switch(rt.type){case"nodeAdded":j(r).nodes=[...j(r).nodes,rt.node],j(r).nodeCount=j(r).nodes.length,se(g,j(r).nodeCount,!0);break;case"nodeRemoved":j(r).nodes=j(r).nodes.filter(Ct=>Ct.id!==rt.nodeId),j(r).nodeCount=j(r).nodes.length,se(g,j(r).nodeCount,!0);break;case"edgeAdded":j(r).edges=[...j(r).edges,rt.edge],j(r).edgeCount=j(r).edges.length,se(v,j(r).edgeCount,!0);break;case"edgesRemoved":j(r).edges=j(r).edges.filter(Ct=>Ct.source!==rt.nodeId&&Ct.target!==rt.nodeId),j(r).edgeCount=j(r).edges.length,se(v,j(r).edgeCount,!0);break;case"nodeUpdated":{const Ct=j(r).nodes.find(w=>w.id===rt.nodeId);Ct&&(Ct.retention=rt.retention);break}}}Al(()=>b());async function b(rt,Ct){se(o,!0),se(l,"");try{se(r,await Yi.graph({max_nodes:j(d),depth:3,query:rt||void 0,center_id:Ct||void 0}),!0),j(r)&&(se(g,j(r).nodeCount,!0),se(v,j(r).edgeCount,!0))}catch{se(l,"No memories yet. Start using Vestige to populate your graph.")}finally{se(o,!1)}}async function y(){se(c,!0);try{await Yi.dream(),await b()}catch{}finally{se(c,!1)}}async function L(rt){try{se(a,await Yi.memories.get(rt),!0)}catch{se(a,null)}}function R(){j(h).trim()&&b(j(h))}var A=i_(),U=Dt(A);{var S=rt=>{var Ct=Kg();ze(rt,Ct)},M=rt=>{var Ct=$g(),w=Dt(Ct),ve=Ot(Dt(w),4),Bt=Dt(ve,!0);Rt(ve),Rt(w),Rt(Ct),ln(()=>_e(Bt,j(l))),ze(rt,Ct)},D=rt=>{Vg(rt,{get nodes(){return j(m)},get edges(){return j(u)},get centerId(){return j(r).center_id},get events(){return e()},get isDreaming(){return j(c)},onSelect:L,onGraphMutation:T})};wi(U,rt=>{j(o)?rt(S):j(l)?rt(M,1):j(r)&&rt(D,2)})}var W=Ot(U,2),z=Dt(W),V=Dt(z);Dl(V);var $=Ot(V,2);Rt(z);var G=Ot(z,2),J=Dt(G),k=Dt(J);k.value=k.__value=50;var it=Ot(k);it.value=it.__value=100;var ut=Ot(it);ut.value=ut.__value=150;var yt=Ot(ut);yt.value=yt.__value=200,Rt(J);var Lt=Ot(J,2),qt=Dt(Lt,!0);Rt(Lt);var Y=Ot(Lt,2);Rt(G),Rt(W);var nt=Ot(W,2),xt=Dt(nt);{var at=rt=>{var Ct=Jg(),w=Cl(Ct),ve=Dt(w);Rt(w);var Bt=Ot(w,4),kt=Dt(Bt);Rt(Bt);var Mt=Ot(Bt,4),ne=Dt(Mt);Rt(Mt),ln(()=>{_e(ve,`${j(g)??""} nodes`),_e(kt,`${j(v)??""} edges`),_e(ne,`depth ${j(r).depth??""}`)}),ze(rt,Ct)};wi(xt,rt=>{j(r)&&rt(at)})}Rt(nt);var wt=Ot(nt,2);{var Ut=rt=>{Zg(rt,{get nodes(){return j(r).nodes},onDateChange:Ct=>{se(p,Ct,!0)},onToggle:Ct=>{se(f,Ct,!0)}})};wi(wt,rt=>{j(r)&&rt(Ut)})}var Gt=Ot(wt,2);{var ce=rt=>{var Ct=n_(),w=Dt(Ct),ve=Ot(Dt(w),2);Rt(w);var Bt=Ot(w,2),kt=Dt(Bt),Mt=Dt(kt),ne=Dt(Mt,!0);Rt(Mt);var Et=Ot(Mt,2);$r(Et,17,()=>j(a).tags,Jr,(C,et)=>{var H=Qg(),q=Dt(H,!0);Rt(H),ln(()=>_e(q,j(et))),ze(C,H)}),Rt(kt);var E=Ot(kt,2),_=Dt(E,!0);Rt(E);var F=Ot(E,2);$r(F,21,()=>[{label:"Retention",value:j(a).retentionStrength},{label:"Storage",value:j(a).storageStrength},{label:"Retrieval",value:j(a).retrievalStrength}],Jr,(C,et)=>{var H=t_(),q=Dt(H),lt=Dt(q),ct=Dt(lt,!0);Rt(lt);var Nt=Ot(lt,2),he=Dt(Nt);Rt(Nt),Rt(q);var xe=Ot(q,2),Jt=Dt(xe);Rt(xe),Rt(H),ln(Ve=>{_e(ct,j(et).label),_e(he,`${Ve??""}%`),Ll(Jt,`width: ${j(et).value*100}%; background: ${j(et).value>.7?"#10b981":j(et).value>.4?"#f59e0b":"#ef4444"}`)},[()=>(j(et).value*100).toFixed(1)]),ze(C,H)}),Rt(F);var Z=Ot(F,2),K=Ot(Dt(Z),2);{let C=ti(()=>j(a).storageStrength*30);Xg(K,{get retention(){return j(a).retentionStrength},get stability(){return j(C)}})}Rt(Z);var X=Ot(Z,2),St=Dt(X),ot=Dt(St);Rt(St);var dt=Ot(St,2),jt=Dt(dt);Rt(dt);var tt=Ot(dt,2);{var mt=C=>{var et=e_(),H=Dt(et);Rt(et),ln(q=>_e(H,`Accessed: ${q??""}`),[()=>new Date(j(a).lastAccessedAt).toLocaleString()]),ze(C,et)};wi(tt,C=>{j(a).lastAccessedAt&&C(mt)})}var bt=Ot(tt,2),Pt=Dt(bt);Rt(bt),Rt(X);var ft=Ot(X,2),Xt=Dt(ft),zt=Ot(Xt,2);Rt(ft);var ie=Ot(ft,2);Rt(Bt),Rt(Ct),ln((C,et)=>{_e(ne,j(a).nodeType),_e(_,j(a).content),_e(ot,`Created: ${C??""}`),_e(jt,`Updated: ${et??""}`),_e(Pt,`Reviews: ${j(a).reviewCount??0??""}`),Be(ie,"href",`${Lc??""}/explore`)},[()=>new Date(j(a).createdAt).toLocaleString(),()=>new Date(j(a).updatedAt).toLocaleString()]),Je("click",ve,()=>se(a,null)),Je("click",Xt,()=>{j(a)&&Yi.memories.promote(j(a).id)}),Je("click",zt,()=>{j(a)&&Yi.memories.demote(j(a).id)}),ze(rt,Ct)};wi(Gt,rt=>{j(a)&&rt(ce)})}Rt(A),ln(()=>{Lt.disabled=j(c),Cc(Lt,1,`px-4 py-2 rounded-xl bg-dream/20 border border-dream/40 text-dream-glow text-sm + [&::-webkit-slider-thumb]:shadow-[0_0_8px_rgba(129,140,248,0.4)]"/>
`),$g=je('');function Jg(i,t){ur(t,!0);let e=Ie(!1),n=Ie(!1),s=Ie(1),r=Ie(100),a,o=0,l=ti(()=>Zg(t.nodes)),c=ti(()=>{const b=j(l).oldest.getTime(),L=j(l).newest.getTime()-b||1;return new Date(b+j(r)/100*L)});function h(b){return b.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function d(){ie(e,!j(e)),t.onToggle(j(e)),j(e)&&(ie(r,100),t.onDateChange(j(c)))}function p(){ie(n,!j(n)),j(n)?(ie(r,0),o=performance.now(),f()):cancelAnimationFrame(a)}function f(){j(n)&&(a=requestAnimationFrame(b=>{const y=(b-o)/1e3;o=b;const L=j(l).oldest.getTime(),A=(j(l).newest.getTime()-L)/(1440*60*1e3)||1,U=j(s)/A*100;if(ie(r,Math.min(100,j(r)+U*y),!0),t.onDateChange(j(c)),j(r)>=100){ie(n,!1);return}f()}))}function g(){t.onDateChange(j(c))}Cl(()=>{ie(n,!1),cancelAnimationFrame(a)});var v=Pc(),m=Pl(v);{var u=b=>{var y=Kg(),L=Dt(y),R=Dt(L),A=Dt(R),U=Dt(A),S=Dt(U,!0);Rt(U);var M=Ot(U,2),D=Dt(M);D.value=D.__value=1;var W=Ot(D);W.value=W.__value=7;var z=Ot(W);z.value=z.__value=30,Rt(M),Rt(A);var V=Ot(A,2),$=Dt(V,!0);Rt(V);var G=Ot(V,2);Rt(R);var J=Ot(R,2);Ll(J);var k=Ot(J,2),it=Dt(k),ut=Dt(it,!0);Rt(it);var yt=Ot(it,2),Lt=Dt(yt,!0);Rt(yt),Rt(k),Rt(L),Rt(y),ln((qt,Y,nt)=>{_e(S,j(n)?"⏸":"▶"),_e($,qt),_e(ut,Y),_e(Lt,nt)},[()=>h(j(c)),()=>h(j(l).oldest),()=>h(j(l).newest)]),Je("click",U,p),Nl(M,()=>j(s),qt=>ie(s,qt)),Je("click",G,d),Je("input",J,g),Il(J,()=>j(r),qt=>ie(r,qt)),He(b,y)},T=b=>{var y=$g();Je("click",y,d),He(b,y)};Ai(m,b=>{j(e)?b(u):b(T,!1)})}He(i,v),dr()}Dl(["click","input"]);var Qg=je('

Loading memory graph...

'),t_=je('

Your Mind Awaits

'),e_=je(' · · ',1),n_=je(' '),i_=je('
'),s_=je("
"),r_=je(`

Memory Detail

Retention Forecast
◬ Explore Connections
`),a_=je(`
`);function A_(i,t){ur(t,!0);const e=()=>Uc(Fc,"$eventFeed",n),[n,s]=Lc();let r=Ie(null),a=Ie(null),o=Ie(!0),l=Ie(""),c=Ie(!1),h=Ie(""),d=Ie(150),p=Ie(!1),f=Ie(Cc(new Date)),g=Ie(0),v=Ie(0),m=ti(()=>j(r)?j(p)?Al(j(r).nodes,j(r).edges,j(f)).visibleNodes:j(r).nodes:[]),u=ti(()=>j(r)?j(p)?Al(j(r).nodes,j(r).edges,j(f)).visibleEdges:j(r).edges:[]);function T(rt){if(j(r))switch(rt.type){case"nodeAdded":j(r).nodes=[...j(r).nodes,rt.node],j(r).nodeCount=j(r).nodes.length,ie(g,j(r).nodeCount,!0);break;case"nodeRemoved":j(r).nodes=j(r).nodes.filter(Ct=>Ct.id!==rt.nodeId),j(r).nodeCount=j(r).nodes.length,ie(g,j(r).nodeCount,!0);break;case"edgeAdded":j(r).edges=[...j(r).edges,rt.edge],j(r).edgeCount=j(r).edges.length,ie(v,j(r).edgeCount,!0);break;case"edgesRemoved":j(r).edges=j(r).edges.filter(Ct=>Ct.source!==rt.nodeId&&Ct.target!==rt.nodeId),j(r).edgeCount=j(r).edges.length,ie(v,j(r).edgeCount,!0);break;case"nodeUpdated":{const Ct=j(r).nodes.find(w=>w.id===rt.nodeId);Ct&&(Ct.retention=rt.retention);break}}}Rl(()=>b());async function b(rt,Ct){ie(o,!0),ie(l,"");try{ie(r,await qi.graph({max_nodes:j(d),depth:3,query:rt||void 0,center_id:Ct||void 0}),!0),j(r)&&(ie(g,j(r).nodeCount,!0),ie(v,j(r).edgeCount,!0))}catch{ie(l,"No memories yet. Start using Vestige to populate your graph.")}finally{ie(o,!1)}}async function y(){ie(c,!0);try{await qi.dream(),await b()}catch{}finally{ie(c,!1)}}async function L(rt){try{ie(a,await qi.memories.get(rt),!0)}catch{ie(a,null)}}function R(){j(h).trim()&&b(j(h))}var A=a_(),U=Dt(A);{var S=rt=>{var Ct=Qg();He(rt,Ct)},M=rt=>{var Ct=t_(),w=Dt(Ct),ve=Ot(Dt(w),4),Bt=Dt(ve,!0);Rt(ve),Rt(w),Rt(Ct),ln(()=>_e(Bt,j(l))),He(rt,Ct)},D=rt=>{Xg(rt,{get nodes(){return j(m)},get edges(){return j(u)},get centerId(){return j(r).center_id},get events(){return e()},get isDreaming(){return j(c)},onSelect:L,onGraphMutation:T})};Ai(U,rt=>{j(o)?rt(S):j(l)?rt(M,1):j(r)&&rt(D,2)})}var W=Ot(U,2),z=Dt(W),V=Dt(z);Ll(V);var $=Ot(V,2);Rt(z);var G=Ot(z,2),J=Dt(G),k=Dt(J);k.value=k.__value=50;var it=Ot(k);it.value=it.__value=100;var ut=Ot(it);ut.value=ut.__value=150;var yt=Ot(ut);yt.value=yt.__value=200,Rt(J);var Lt=Ot(J,2),qt=Dt(Lt,!0);Rt(Lt);var Y=Ot(Lt,2);Rt(G),Rt(W);var nt=Ot(W,2),xt=Dt(nt);{var at=rt=>{var Ct=e_(),w=Pl(Ct),ve=Dt(w);Rt(w);var Bt=Ot(w,4),kt=Dt(Bt);Rt(Bt);var Mt=Ot(Bt,4),ne=Dt(Mt);Rt(Mt),ln(()=>{_e(ve,`${j(g)??""} nodes`),_e(kt,`${j(v)??""} edges`),_e(ne,`depth ${j(r).depth??""}`)}),He(rt,Ct)};Ai(xt,rt=>{j(r)&&rt(at)})}Rt(nt);var wt=Ot(nt,2);{var Ut=rt=>{Jg(rt,{get nodes(){return j(r).nodes},onDateChange:Ct=>{ie(f,Ct,!0)},onToggle:Ct=>{ie(p,Ct,!0)}})};Ai(wt,rt=>{j(r)&&rt(Ut)})}var Gt=Ot(wt,2);{var ce=rt=>{var Ct=r_(),w=Dt(Ct),ve=Ot(Dt(w),2);Rt(w);var Bt=Ot(w,2),kt=Dt(Bt),Mt=Dt(kt),ne=Dt(Mt,!0);Rt(Mt);var Et=Ot(Mt,2);Qr(Et,17,()=>j(a).tags,ta,(C,et)=>{var H=n_(),q=Dt(H,!0);Rt(H),ln(()=>_e(q,j(et))),He(C,H)}),Rt(kt);var E=Ot(kt,2),_=Dt(E,!0);Rt(E);var F=Ot(E,2);Qr(F,21,()=>[{label:"Retention",value:j(a).retentionStrength},{label:"Storage",value:j(a).storageStrength},{label:"Retrieval",value:j(a).retrievalStrength}],ta,(C,et)=>{var H=i_(),q=Dt(H),lt=Dt(q),ct=Dt(lt,!0);Rt(lt);var Nt=Ot(lt,2),ue=Dt(Nt);Rt(Nt),Rt(q);var xe=Ot(q,2),Jt=Dt(xe);Rt(xe),Rt(H),ln(Ve=>{_e(ct,j(et).label),_e(ue,`${Ve??""}%`),Ul(Jt,`width: ${j(et).value*100}%; background: ${j(et).value>.7?"#10b981":j(et).value>.4?"#f59e0b":"#ef4444"}`)},[()=>(j(et).value*100).toFixed(1)]),He(C,H)}),Rt(F);var Z=Ot(F,2),K=Ot(Dt(Z),2);{let C=ti(()=>j(a).storageStrength*30);jg(K,{get retention(){return j(a).retentionStrength},get stability(){return j(C)}})}Rt(Z);var X=Ot(Z,2),St=Dt(X),ot=Dt(St);Rt(St);var dt=Ot(St,2),jt=Dt(dt);Rt(dt);var tt=Ot(dt,2);{var mt=C=>{var et=s_(),H=Dt(et);Rt(et),ln(q=>_e(H,`Accessed: ${q??""}`),[()=>new Date(j(a).lastAccessedAt).toLocaleString()]),He(C,et)};Ai(tt,C=>{j(a).lastAccessedAt&&C(mt)})}var bt=Ot(tt,2),Pt=Dt(bt);Rt(bt),Rt(X);var ft=Ot(X,2),Xt=Dt(ft),zt=Ot(Xt,2);Rt(ft);var se=Ot(ft,2);Rt(Bt),Rt(Ct),ln((C,et)=>{_e(ne,j(a).nodeType),_e(_,j(a).content),_e(ot,`Created: ${C??""}`),_e(jt,`Updated: ${et??""}`),_e(Pt,`Reviews: ${j(a).reviewCount??0??""}`),ze(se,"href",`${Ic??""}/explore`)},[()=>new Date(j(a).createdAt).toLocaleString(),()=>new Date(j(a).updatedAt).toLocaleString()]),Je("click",ve,()=>ie(a,null)),Je("click",Xt,()=>{j(a)&&qi.memories.promote(j(a).id)}),Je("click",zt,()=>{j(a)&&qi.memories.demote(j(a).id)}),He(rt,Ct)};Ai(Gt,rt=>{j(a)&&rt(ce)})}Rt(A),ln(()=>{Lt.disabled=j(c),Dc(Lt,1,`px-4 py-2 rounded-xl bg-dream/20 border border-dream/40 text-dream-glow text-sm hover:bg-dream/30 transition-all backdrop-blur-sm disabled:opacity-50 - ${j(c)?"glow-dream animate-pulse-glow":""}`),_e(qt,j(c)?"◈ Dreaming...":"◈ Dream")}),Je("keydown",V,rt=>rt.key==="Enter"&&R()),Ul(V,()=>j(h),rt=>se(h,rt)),Je("click",$,R),Je("change",J,()=>b()),Il(J,()=>j(d),rt=>se(d,rt)),Je("click",Lt,y),Je("click",Y,()=>b()),ze(i,A),cr(),s()}Pl(["keydown","click","change"]);export{b_ as component}; + ${j(c)?"glow-dream animate-pulse-glow":""}`),_e(qt,j(c)?"◈ Dreaming...":"◈ Dream")}),Je("keydown",V,rt=>rt.key==="Enter"&&R()),Il(V,()=>j(h),rt=>ie(h,rt)),Je("click",$,R),Je("change",J,()=>b()),Nl(J,()=>j(d),rt=>ie(d,rt)),Je("click",Lt,y),Je("click",Y,()=>b()),He(i,A),dr(),s()}Dl(["keydown","click","change"]);export{A_ as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.br b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.br new file mode 100644 index 0000000..1c077a5 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.gz b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.gz new file mode 100644 index 0000000..ea54cb0 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/6.BEn_WCBk.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.br b/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.br deleted file mode 100644 index c0af552..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.gz b/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.gz deleted file mode 100644 index fbb9870..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/6.CBsTT29y.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js similarity index 75% rename from apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js rename to apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js index 774aa7c..58d9b03 100644 --- a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js +++ b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js @@ -1 +1 @@ -import"../chunks/Bzak7iHL.js";import{o as ut}from"../chunks/DUC-ssvh.js";import{p as gt,s as T,c as Q,t as u,a as ft,d,e as s,h as $,g as t,r as e,G as ht}from"../chunks/BBD-8XME.js";import{d as bt,s as l,a as yt}from"../chunks/DNn3Nckx.js";import{i as R}from"../chunks/RaRNNC-y.js";import{e as U,i as D}from"../chunks/C5a--lgk.js";import{a as o,f as n}from"../chunks/CKcqngaU.js";import{s as q}from"../chunks/CBWLjDtu.js";import{a as Z}from"../chunks/BcuCGYSa.js";var wt=n(""),Rt=n('
'),Nt=n('
'),St=n('

Use "Remind me..." in conversation to create intentions.

'),kt=n(' '),Ot=n(' '),$t=n('

'),zt=n('
'),Ct=n('

No predictions yet. Use Vestige more to train the predictive model.

'),It=n(" "),Pt=n(' '),Tt=n('

'),Ut=n('
'),Dt=n('

Intentions & Predictions

Prospective Memory

"Remember to do X when Y happens"

Predicted Needs

What you might need next
');function Wt(tt,et){gt(et,!0);let z=T(Q([])),j=T(Q([])),A=T(!0),N=T("active");const at={active:"text-synapse-glow bg-synapse/10 border-synapse/30",fulfilled:"text-recall bg-recall/10 border-recall/30",cancelled:"text-dim bg-white/[0.03] border-subtle/20",snoozed:"text-dream-glow bg-dream/10 border-dream/30"},st={critical:"text-decay",high:"text-amber-400",normal:"text-dim",low:"text-muted"},rt={time:"⏰",context:"◎",event:"⚡"};ut(async()=>{await B()});async function B(){$(A,!0);try{const[r,i]=await Promise.all([Z.intentions(t(N)),Z.predict()]);$(z,r.intentions||[],!0),$(j,i.predictions||[],!0)}catch{}finally{$(A,!1)}}async function it(r){$(N,r,!0),await B()}function F(r){if(!r)return"";try{return new Date(r).toLocaleDateString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return r}}var G=Dt(),L=s(G),H=d(s(L),2),dt=s(H);e(H),e(L);var M=d(L,2),Y=d(s(M),2);U(Y,20,()=>["active","fulfilled","snoozed","cancelled","all"],D,(r,i)=>{var v=wt(),a=s(v,!0);e(v),u(x=>{q(v,1,`px-3 py-1.5 rounded-xl text-xs transition ${t(N)===i?"bg-synapse/20 text-synapse-glow border border-synapse/40":"glass-subtle text-dim hover:bg-white/[0.03]"}`),l(a,x)},[()=>i.charAt(0).toUpperCase()+i.slice(1)]),yt("click",v,()=>it(i)),o(r,v)}),e(Y);var lt=d(Y,2);{var vt=r=>{var i=Nt();U(i,20,()=>Array(4),D,(v,a)=>{var x=Rt();o(v,x)}),e(i),o(r,i)},ot=r=>{var i=St(),v=d(s(i),2),a=s(v);e(v),ht(2),e(i),u(()=>l(a,`No ${t(N)==="all"?"":t(N)+" "}intentions.`)),o(r,i)},nt=r=>{var i=zt();U(i,21,()=>t(z),D,(v,a)=>{var x=$t(),f=s(x),h=s(f),C=s(h,!0);e(h);var g=d(h,2),S=s(g),I=s(S,!0);e(S);var b=d(S,2),y=s(b),P=s(y,!0);e(y);var w=d(y,2),E=s(w);e(w);var k=d(w,2),c=s(k);e(k);var p=d(k,2);{var O=m=>{var _=kt(),W=s(_);e(_),u(X=>l(W,`deadline: ${X??""}`),[()=>F(t(a).deadline)]),o(m,_)};R(p,m=>{t(a).deadline&&m(O)})}var V=d(p,2);{var mt=m=>{var _=Ot(),W=s(_);e(_),u(X=>l(W,`snoozed until ${X??""}`),[()=>F(t(a).snoozed_until)]),o(m,_)};R(V,m=>{t(a).snoozed_until&&m(mt)})}e(b),e(g);var K=d(g,2),_t=s(K,!0);e(K),e(f),e(x),u((m,_)=>{l(C,rt[t(a).trigger_type]||"◇"),l(I,t(a).content),q(y,1,`px-2 py-0.5 text-[10px] rounded-lg border ${(at[t(a).status]||"text-dim bg-white/[0.03] border-subtle/20")??""}`),l(P,t(a).status),q(w,1,`text-[10px] ${(st[t(a).priority]||"text-muted")??""}`),l(E,`${t(a).priority??""} priority`),l(c,`${t(a).trigger_type??""}: ${m??""}`),l(_t,_)},[()=>t(a).trigger_value.length>40?t(a).trigger_value.slice(0,37)+"...":t(a).trigger_value,()=>F(t(a).created_at)]),o(v,x)}),e(i),o(r,i)};R(lt,r=>{t(A)?r(vt):t(z).length===0?r(ot,1):r(nt,!1)})}e(M);var J=d(M,2),pt=d(s(J),2);{var xt=r=>{var i=Ct();o(r,i)},ct=r=>{var i=Ut();U(i,21,()=>t(j),D,(v,a,x)=>{var f=Tt(),h=s(f);h.textContent=x+1;var C=d(h,2),g=s(C),S=s(g,!0);e(g);var I=d(g,2),b=s(I),y=s(b,!0);e(b);var P=d(b,2);{var w=c=>{var p=It(),O=s(p);e(p),u(V=>l(O,`${V??""}% retention`),[()=>(Number(t(a).retention)*100).toFixed(0)]),o(c,p)};R(P,c=>{t(a).retention&&c(w)})}var E=d(P,2);{var k=c=>{var p=Pt(),O=s(p);e(p),u(()=>l(O,`${t(a).predictedNeed??""} need`)),o(c,p)};R(E,c=>{t(a).predictedNeed&&c(k)})}e(I),e(C),e(f),u(()=>{l(S,t(a).content),l(y,t(a).nodeType)}),o(v,f)}),e(i),o(r,i)};R(pt,r=>{t(j).length===0?r(xt):r(ct,!1)})}e(J),e(G),u(()=>l(dt,`${t(z).length??""} intentions`)),o(tt,G),ft()}bt(["click"]);export{Wt as component}; +import"../chunks/Bzak7iHL.js";import{o as ut}from"../chunks/DeTA_5mp.js";import{p as gt,s as T,c as Q,t as u,a as ft,d,e as s,h as $,g as t,r as e,O as ht}from"../chunks/nyjtQ1Ok.js";import{d as bt,s as l,a as yt}from"../chunks/C4L78yoI.js";import{i as R}from"../chunks/B17metm1.js";import{e as U,i as D}from"../chunks/BilMa3tw.js";import{a as o,f as n}from"../chunks/B0IenmM-.js";import{s as q}from"../chunks/BgOFZ9jq.js";import{a as Z}from"../chunks/BcuCGYSa.js";var wt=n(""),Rt=n('
'),Nt=n('
'),Ot=n('

Use "Remind me..." in conversation to create intentions.

'),St=n(' '),kt=n(' '),$t=n('

'),zt=n('
'),Ct=n('

No predictions yet. Use Vestige more to train the predictive model.

'),It=n(" "),Pt=n(' '),Tt=n('

'),Ut=n('
'),Dt=n('

Intentions & Predictions

Prospective Memory

"Remember to do X when Y happens"

Predicted Needs

What you might need next
');function Wt(tt,et){gt(et,!0);let z=T(Q([])),j=T(Q([])),A=T(!0),N=T("active");const at={active:"text-synapse-glow bg-synapse/10 border-synapse/30",fulfilled:"text-recall bg-recall/10 border-recall/30",cancelled:"text-dim bg-white/[0.03] border-subtle/20",snoozed:"text-dream-glow bg-dream/10 border-dream/30"},st={critical:"text-decay",high:"text-amber-400",normal:"text-dim",low:"text-muted"},rt={time:"⏰",context:"◎",event:"⚡"};ut(async()=>{await B()});async function B(){$(A,!0);try{const[r,i]=await Promise.all([Z.intentions(t(N)),Z.predict()]);$(z,r.intentions||[],!0),$(j,i.predictions||[],!0)}catch{}finally{$(A,!1)}}async function it(r){$(N,r,!0),await B()}function F(r){if(!r)return"";try{return new Date(r).toLocaleDateString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return r}}var L=Dt(),G=s(L),H=d(s(G),2),dt=s(H);e(H),e(G);var M=d(G,2),Y=d(s(M),2);U(Y,20,()=>["active","fulfilled","snoozed","cancelled","all"],D,(r,i)=>{var v=wt(),a=s(v,!0);e(v),u(x=>{q(v,1,`px-3 py-1.5 rounded-xl text-xs transition ${t(N)===i?"bg-synapse/20 text-synapse-glow border border-synapse/40":"glass-subtle text-dim hover:bg-white/[0.03]"}`),l(a,x)},[()=>i.charAt(0).toUpperCase()+i.slice(1)]),yt("click",v,()=>it(i)),o(r,v)}),e(Y);var lt=d(Y,2);{var vt=r=>{var i=Nt();U(i,20,()=>Array(4),D,(v,a)=>{var x=Rt();o(v,x)}),e(i),o(r,i)},ot=r=>{var i=Ot(),v=d(s(i),2),a=s(v);e(v),ht(2),e(i),u(()=>l(a,`No ${t(N)==="all"?"":t(N)+" "}intentions.`)),o(r,i)},nt=r=>{var i=zt();U(i,21,()=>t(z),D,(v,a)=>{var x=$t(),f=s(x),h=s(f),C=s(h,!0);e(h);var g=d(h,2),O=s(g),I=s(O,!0);e(O);var b=d(O,2),y=s(b),P=s(y,!0);e(y);var w=d(y,2),E=s(w);e(w);var S=d(w,2),c=s(S);e(S);var p=d(S,2);{var k=m=>{var _=St(),W=s(_);e(_),u(X=>l(W,`deadline: ${X??""}`),[()=>F(t(a).deadline)]),o(m,_)};R(p,m=>{t(a).deadline&&m(k)})}var V=d(p,2);{var mt=m=>{var _=kt(),W=s(_);e(_),u(X=>l(W,`snoozed until ${X??""}`),[()=>F(t(a).snoozed_until)]),o(m,_)};R(V,m=>{t(a).snoozed_until&&m(mt)})}e(b),e(g);var K=d(g,2),_t=s(K,!0);e(K),e(f),e(x),u((m,_)=>{l(C,rt[t(a).trigger_type]||"◇"),l(I,t(a).content),q(y,1,`px-2 py-0.5 text-[10px] rounded-lg border ${(at[t(a).status]||"text-dim bg-white/[0.03] border-subtle/20")??""}`),l(P,t(a).status),q(w,1,`text-[10px] ${(st[t(a).priority]||"text-muted")??""}`),l(E,`${t(a).priority??""} priority`),l(c,`${t(a).trigger_type??""}: ${m??""}`),l(_t,_)},[()=>t(a).trigger_value.length>40?t(a).trigger_value.slice(0,37)+"...":t(a).trigger_value,()=>F(t(a).created_at)]),o(v,x)}),e(i),o(r,i)};R(lt,r=>{t(A)?r(vt):t(z).length===0?r(ot,1):r(nt,!1)})}e(M);var J=d(M,2),pt=d(s(J),2);{var xt=r=>{var i=Ct();o(r,i)},ct=r=>{var i=Ut();U(i,21,()=>t(j),D,(v,a,x)=>{var f=Tt(),h=s(f);h.textContent=x+1;var C=d(h,2),g=s(C),O=s(g,!0);e(g);var I=d(g,2),b=s(I),y=s(b,!0);e(b);var P=d(b,2);{var w=c=>{var p=It(),k=s(p);e(p),u(V=>l(k,`${V??""}% retention`),[()=>(Number(t(a).retention)*100).toFixed(0)]),o(c,p)};R(P,c=>{t(a).retention&&c(w)})}var E=d(P,2);{var S=c=>{var p=Pt(),k=s(p);e(p),u(()=>l(k,`${t(a).predictedNeed??""} need`)),o(c,p)};R(E,c=>{t(a).predictedNeed&&c(S)})}e(I),e(C),e(f),u(()=>{l(O,t(a).content),l(y,t(a).nodeType)}),o(v,f)}),e(i),o(r,i)};R(pt,r=>{t(j).length===0?r(xt):r(ct,!1)})}e(J),e(L),u(()=>l(dt,`${t(z).length??""} intentions`)),o(tt,L),ft()}bt(["click"]);export{Wt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.br b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.br new file mode 100644 index 0000000..584d937 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.gz b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.gz new file mode 100644 index 0000000..7959a81 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/7.404BTmXF.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.br b/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.br deleted file mode 100644 index bc143fd..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.gz b/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.gz deleted file mode 100644 index 985dd20..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/7.UPq6Ja2I.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.br b/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.br deleted file mode 100644 index 9b46fd8..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.gz b/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.gz deleted file mode 100644 index b6b6ac8..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js similarity index 89% rename from apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js rename to apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js index 47f865c..2521bcd 100644 --- a/apps/dashboard/build/_app/immutable/nodes/8.B2QXJFjO.js +++ b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js @@ -1,4 +1,4 @@ -import"../chunks/Bzak7iHL.js";import{o as qe}from"../chunks/DUC-ssvh.js";import{p as Be,s as b,c as Qe,t as E,g as e,a as Ye,d as t,e as s,h as u,r as a}from"../chunks/BBD-8XME.js";import{d as ze,a as p,s as v}from"../chunks/DNn3Nckx.js";import{i as ce}from"../chunks/RaRNNC-y.js";import{e as Z,i as ue}from"../chunks/C5a--lgk.js";import{a as _,f as g}from"../chunks/CKcqngaU.js";import{r as xe}from"../chunks/BVZqxpRe.js";import{s as Ge}from"../chunks/CBWLjDtu.js";import{s as _e}from"../chunks/DBfx-YTU.js";import{b as fe}from"../chunks/BxfT1SOA.js";import{b as He}from"../chunks/C-QujEl6.js";import{a as f}from"../chunks/BcuCGYSa.js";import{N as Ie}from"../chunks/CZ45jJaw.js";var Je=g('
'),Ke=g('
'),Ue=g(' '),Ve=g('

Promote Demote Delete
'),We=g(''),Xe=g('
'),Ze=g(`

Memories

'),Ke=g('
'),Ue=g(' '),Ve=g('

Promote Demote Delete
'),We=g(''),Xe=g('
'),Ze=g(`

Memories

Min retention:
`);function xt(ge,me){Be(me,!0);let k=b(Qe([])),P=b(""),S=b(""),be="",h=b(0),F=b(!0),T=b(null),ee;qe(()=>m());async function m(){u(F,!0);try{const i={};e(P)&&(i.q=e(P)),e(S)&&(i.node_type=e(S)),e(h)>0&&(i.min_retention=String(e(h)));const c=await f.memories.list(i);u(k,c.memories,!0)}catch{u(k,[],!0)}finally{u(F,!1)}}function he(){clearTimeout(ee),ee=setTimeout(m,300)}function ye(i){return i>.7?"#10b981":i>.4?"#f59e0b":"#ef4444"}var M=Ze(),A=s(M),te=t(s(A),2),we=s(te);a(te),a(A);var C=t(A,2),$=s(C);xe($);var y=t($,2),N=s(y);N.value=N.__value="";var O=t(N);O.value=O.__value="fact";var R=t(O);R.value=R.__value="concept";var j=t(R);j.value=j.__value="event";var L=t(j);L.value=L.__value="person";var q=t(L);q.value=q.__value="place";var B=t(q);B.value=B.__value="note";var Q=t(B);Q.value=Q.__value="pattern";var ae=t(Q);ae.value=ae.__value="decision",a(y);var se=t(y,2),D=t(s(se),2);xe(D);var ie=t(D,2),ke=s(ie);a(ie),a(se),a(C);var Pe=t(C,2);{var Se=i=>{var c=Ke();Z(c,20,()=>Array(8),ue,(w,o)=>{var x=Je();_(w,x)}),a(c),_(i,c)},Te=i=>{var c=Xe();Z(c,21,()=>e(k),w=>w.id,(w,o)=>{var x=We(),Y=s(x),z=s(Y),G=s(z),oe=s(G),H=t(oe,2),$e=s(H,!0);a(H);var De=t(H,2);Z(De,17,()=>e(o).tags.slice(0,3),ue,(n,l)=>{var d=Ue(),J=s(d,!0);a(d),E(()=>v(J,e(l))),_(n,d)}),a(G);var re=t(G,2),Ee=s(re,!0);a(re),a(z);var ne=t(z,2),I=s(ne),Fe=s(I);a(I);var le=t(I,2),Me=s(le);a(le),a(ne),a(Y);var Ae=t(Y,2);{var Ce=n=>{var l=Ve(),d=s(l),J=s(d,!0);a(d);var K=t(d,2),U=s(K),Ne=s(U);a(U);var V=t(U,2),Oe=s(V);a(V);var de=t(V,2),Re=s(de);a(de),a(K);var pe=t(K,2),W=s(pe),X=t(W,2),ve=t(X,2);a(pe),a(l),E((r,je,Le)=>{v(J,e(o).content),v(Ne,`Storage: ${r??""}%`),v(Oe,`Retrieval: ${je??""}%`),v(Re,`Created: ${Le??""}`)},[()=>(e(o).storageStrength*100).toFixed(1),()=>(e(o).retrievalStrength*100).toFixed(1),()=>new Date(e(o).createdAt).toLocaleDateString()]),p("click",W,r=>{r.stopPropagation(),f.memories.promote(e(o).id)}),p("keydown",W,r=>{r.key==="Enter"&&(r.stopPropagation(),f.memories.promote(e(o).id))}),p("click",X,r=>{r.stopPropagation(),f.memories.demote(e(o).id)}),p("keydown",X,r=>{r.key==="Enter"&&(r.stopPropagation(),f.memories.demote(e(o).id))}),p("click",ve,async r=>{r.stopPropagation(),await f.memories.delete(e(o).id),m()}),p("keydown",ve,async r=>{r.key==="Enter"&&(r.stopPropagation(),await f.memories.delete(e(o).id),m())}),_(n,l)};ce(Ae,n=>{var l;((l=e(T))==null?void 0:l.id)===e(o).id&&n(Ce)})}a(x),E((n,l)=>{var d;Ge(x,1,`text-left p-4 glass-subtle rounded-xl hover:bg-white/[0.04] transition-all duration-200 group ${((d=e(T))==null?void 0:d.id)===e(o).id?"!border-synapse/40 glow-synapse":""}`),_e(oe,`background: ${(Ie[e(o).nodeType]||"#8B95A5")??""}`),v($e,e(o).nodeType),v(Ee,e(o).content),_e(Fe,`width: ${e(o).retentionStrength*100}%; background: ${n??""}`),v(Me,`${l??""}%`)},[()=>ye(e(o).retentionStrength),()=>(e(o).retentionStrength*100).toFixed(0)]),p("click",x,()=>{var n;return u(T,((n=e(T))==null?void 0:n.id)===e(o).id?null:e(o),!0)}),_(w,x)}),a(c),_(i,c)};ce(Pe,i=>{e(F)?i(Se):i(Te,!1)})}a(M),E(i=>{v(we,`${e(k).length??""} results`),v(ke,`${i??""}%`)},[()=>(e(h)*100).toFixed(0)]),p("input",$,he),fe($,()=>e(P),i=>u(P,i)),p("change",y,m),He(y,()=>e(S),i=>u(S,i)),p("change",D,m),fe(D,()=>e(h),i=>u(h,i)),_(ge,M),Ye()}ze(["input","change","click","keydown"]);export{xt as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.br b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.br new file mode 100644 index 0000000..7973b77 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.gz b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.gz new file mode 100644 index 0000000..0c88612 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/8.CJVG2CGC.js.gz differ diff --git a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.br b/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.br deleted file mode 100644 index 84fc5aa..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.br and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.gz b/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.gz deleted file mode 100644 index 856a655..0000000 Binary files a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js.gz and /dev/null differ diff --git a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js similarity index 83% rename from apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js rename to apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js index 700377e..10726b8 100644 --- a/apps/dashboard/build/_app/immutable/nodes/9.B4Pp7ME7.js +++ b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js @@ -1,2 +1,2 @@ -import"../chunks/Bzak7iHL.js";import{o as ze}from"../chunks/DUC-ssvh.js";import{p as Je,t as w,a as We,d as r,e as t,g as s,s as S,h as m,r as e,G as b,f as Be,u as j}from"../chunks/BBD-8XME.js";import{d as He,a as X,s as p}from"../chunks/DNn3Nckx.js";import{i as u}from"../chunks/RaRNNC-y.js";import{e as Z,i as ee}from"../chunks/C5a--lgk.js";import{a as v,f as l,t as ue}from"../chunks/CKcqngaU.js";import{s as ge}from"../chunks/CBWLjDtu.js";import{s as fe}from"../chunks/DBfx-YTU.js";import{s as Le,a as te}from"../chunks/BexJutgU.js";import{a as T}from"../chunks/BcuCGYSa.js";import{m as Ue,a as Ye,i as qe}from"../chunks/CruZBLYW.js";var Qe=l(' Running...',1),Xe=l('
Processed
'),Ze=l('
Decayed
'),et=l('
Embedded
'),tt=l('
'),st=l(' Dreaming...',1),at=l('
'),it=l('
Insights Discovered:
',1),dt=l('
Connections found:
'),rt=l('
Memories replayed:
'),ot=l('
'),nt=l('
'),vt=l('
'),lt=l('

Retention Distribution

'),ct=l('
'),xt=l(`

Settings & System

Memories
Avg Retention
WebSocket
v2.1
Vestige

Cognitive Operations

FSRS-6 Consolidation
Apply spaced-repetition decay, regenerate embeddings, run maintenance
Memory Dream Cycle
Replay memories, discover hidden connections, synthesize insights

Keyboard Shortcuts

About

V
Vestige v2.1 "Nuclear Dashboard"
Your AI's long-term memory system
29 cognitive modules
FSRS-6 spaced repetition
Nomic Embed v1.5 (256d)
Jina Reranker v1 Turbo
USearch HNSW (20x FAISS)
Local-first, zero cloud
Built with Rust + Axum + SvelteKit 2 + Svelte 5 + Three.js + Tailwind CSS 4
`);function Ct(_e,be){Je(be,!0);const ye=()=>te(Ue,"$memoryCount",I),P=()=>te(Ye,"$avgRetention",I),se=()=>te(qe,"$isConnected",I),[I,he]=Le();let E=S(!1),A=S(!1),y=S(null),g=S(null),we=S(null),$=S(null),ae=S(!0),Se=S(null);ze(()=>{N()});async function N(){m(ae,!0);try{const[a,o,c]=await Promise.all([T.stats().catch(()=>null),T.health().catch(()=>null),T.retentionDistribution().catch(()=>null)]);m(we,a,!0),m(Se,o,!0),m($,c,!0)}finally{m(ae,!1)}}async function ke(){m(E,!0),m(y,null);try{m(y,await T.consolidate(),!0),await N()}catch{}finally{m(E,!1)}}async function Ce(){m(A,!0),m(g,null);try{m(g,await T.dream(),!0),await N()}catch{}finally{m(A,!1)}}var K=xt(),V=t(K),Re=r(t(V),2);e(V);var z=r(V,2),J=t(z),ie=t(J),$e=t(ie,!0);e(ie),b(2),e(J);var W=r(J,2),B=t(W),Ae=t(B);e(B),b(2),e(W);var de=r(W,2),re=t(de),oe=t(re),ne=r(oe,2),De=t(ne,!0);e(ne),e(re),b(2),e(de),b(2),e(z);var H=r(z,2),L=r(t(H),2),U=t(L),O=r(t(U),2),Ge=t(O);{var Me=a=>{var o=Qe();b(),v(a,o)},Fe=a=>{var o=ue("Consolidate");v(a,o)};u(Ge,a=>{s(E)?a(Me):a(Fe,!1)})}e(O),e(U);var je=r(U,2);{var Te=a=>{var o=tt(),c=t(o),f=t(c);{var k=d=>{var i=Xe(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).nodesProcessed)),v(d,i)};u(f,d=>{s(y).nodesProcessed!==void 0&&d(k)})}var _=r(f,2);{var h=d=>{var i=Ze(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).decayApplied)),v(d,i)};u(_,d=>{s(y).decayApplied!==void 0&&d(h)})}var C=r(_,2);{var G=d=>{var i=et(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).embeddingsGenerated)),v(d,i)};u(C,d=>{s(y).embeddingsGenerated!==void 0&&d(G)})}e(c),e(o),v(a,o)};u(je,a=>{s(y)&&a(Te)})}e(L);var ve=r(L,2),Y=t(ve),D=r(t(Y),2),Ee=t(D);{var Ne=a=>{var o=st();b(),v(a,o)},Oe=a=>{var o=ue("Dream");v(a,o)};u(Ee,a=>{s(A)?a(Ne):a(Oe,!1)})}e(D),e(Y);var Pe=r(Y,2);{var Ie=a=>{var o=ot(),c=t(o);{var f=d=>{var i=it(),n=r(Be(i),2);Z(n,17,()=>s(g).insights,ee,(x,M)=>{var R=at(),F=t(R,!0);e(R),w(q=>p(F,q),[()=>typeof s(M)=="string"?s(M):JSON.stringify(s(M))]),v(x,R)}),v(d,i)},k=j(()=>s(g).insights&&Array.isArray(s(g).insights));u(c,d=>{s(k)&&d(f)})}var _=r(c,2);{var h=d=>{var i=dt(),n=r(t(i)),x=t(n,!0);e(n),e(i),w(()=>p(x,s(g).connections_found)),v(d,i)};u(_,d=>{s(g).connections_found!==void 0&&d(h)})}var C=r(_,2);{var G=d=>{var i=rt(),n=r(t(i)),x=t(n,!0);e(n),e(i),w(()=>p(x,s(g).memories_replayed)),v(d,i)};u(C,d=>{s(g).memories_replayed!==void 0&&d(G)})}e(o),v(a,o)};u(Pe,a=>{s(g)&&a(Ie)})}e(ve),e(H);var le=r(H,2);{var Ke=a=>{var o=lt(),c=r(t(o),2),f=t(c);{var k=h=>{var C=vt();Z(C,21,()=>s($).distribution,ee,(G,d,i)=>{const n=j(()=>Math.max(...s($).distribution.map(Q=>Q.count),1)),x=j(()=>s(d).count/s(n)*100),M=j(()=>i<2?"#ef4444":i<4?"#f59e0b":i<7?"#6366f1":"#10b981");var R=nt(),F=t(R),q=t(F,!0);e(F);var pe=r(F,2),Ve=r(pe,2);Ve.textContent=`${i*10}%`,e(R),w(Q=>{p(q,s(d).count),fe(pe,`height: ${Q??""}%; background: ${s(M)??""}; opacity: 0.7`)},[()=>Math.max(s(x),2)]),v(G,R)}),e(C),v(h,C)},_=j(()=>s($).distribution&&Array.isArray(s($).distribution));u(f,h=>{s(_)&&h(k)})}e(c),e(o),v(a,o)};u(le,a=>{s($)&&a(Ke)})}var ce=r(le,2),xe=r(t(ce),2),me=t(xe);Z(me,20,()=>[{key:"⌘ K",desc:"Command palette"},{key:"/",desc:"Focus search"},{key:"G",desc:"Go to Graph"},{key:"M",desc:"Go to Memories"},{key:"T",desc:"Go to Timeline"},{key:"F",desc:"Go to Feed"},{key:"E",desc:"Go to Explore"},{key:"S",desc:"Go to Stats"}],ee,(a,o)=>{var c=ct(),f=t(c),k=t(f,!0);e(f);var _=r(f,2),h=t(_,!0);e(_),e(c),w(()=>{p(k,o.key),p(h,o.desc)}),v(a,c)}),e(me),e(xe),e(ce),b(2),e(K),w(a=>{p($e,ye()),fe(B,`color: ${P()>.7?"#10b981":P()>.4?"#f59e0b":"#ef4444"}`),p(Ae,`${a??""}%`),ge(oe,1,`w-2.5 h-2.5 rounded-full ${se()?"bg-recall animate-pulse-glow":"bg-decay"}`),p(De,se()?"Online":"Offline"),O.disabled=s(E),D.disabled=s(A),ge(D,1,`px-4 py-2 bg-dream/20 border border-dream/40 text-dream-glow text-sm rounded-xl hover:bg-dream/30 transition disabled:opacity-50 flex items-center gap-2 - ${s(A)?"glow-dream animate-pulse-glow":""}`)},[()=>(P()*100).toFixed(1)]),X("click",Re,N),X("click",O,ke),X("click",D,Ce),v(_e,K),We(),he()}He(["click"]);export{Ct as component}; +import"../chunks/Bzak7iHL.js";import{o as ze}from"../chunks/DeTA_5mp.js";import{p as Je,t as w,a as We,d as r,e as t,g as s,s as S,h as m,r as e,O as b,f as Be,u as j}from"../chunks/nyjtQ1Ok.js";import{d as He,a as X,s as p}from"../chunks/C4L78yoI.js";import{i as u}from"../chunks/B17metm1.js";import{e as Z,i as ee}from"../chunks/BilMa3tw.js";import{a as v,f as l,t as ue}from"../chunks/B0IenmM-.js";import{s as ge}from"../chunks/BgOFZ9jq.js";import{s as fe}from"../chunks/D2QmVWrb.js";import{s as Le,a as te}from"../chunks/C3ZC25l2.js";import{a as O}from"../chunks/BcuCGYSa.js";import{m as Ue,a as Ye,i as qe}from"../chunks/B6fk3AxI.js";var Qe=l(' Running...',1),Xe=l('
Processed
'),Ze=l('
Decayed
'),et=l('
Embedded
'),tt=l('
'),st=l(' Dreaming...',1),at=l('
'),it=l('
Insights Discovered:
',1),dt=l('
Connections found:
'),rt=l('
Memories replayed:
'),ot=l('
'),nt=l('
'),vt=l('
'),lt=l('

Retention Distribution

'),ct=l('
'),xt=l(`

Settings & System

Memories
Avg Retention
WebSocket
v2.1
Vestige

Cognitive Operations

FSRS-6 Consolidation
Apply spaced-repetition decay, regenerate embeddings, run maintenance
Memory Dream Cycle
Replay memories, discover hidden connections, synthesize insights

Keyboard Shortcuts

About

V
Vestige v2.1 "Nuclear Dashboard"
Your AI's long-term memory system
29 cognitive modules
FSRS-6 spaced repetition
Nomic Embed v1.5 (256d)
Jina Reranker v1 Turbo
USearch HNSW (20x FAISS)
Local-first, zero cloud
Built with Rust + Axum + SvelteKit 2 + Svelte 5 + Three.js + Tailwind CSS 4
`);function Ct(_e,be){Je(be,!0);const ye=()=>te(Ue,"$memoryCount",I),P=()=>te(Ye,"$avgRetention",I),se=()=>te(qe,"$isConnected",I),[I,he]=Le();let T=S(!1),A=S(!1),y=S(null),g=S(null),we=S(null),$=S(null),ae=S(!0),Se=S(null);ze(()=>{E()});async function E(){m(ae,!0);try{const[a,o,c]=await Promise.all([O.stats().catch(()=>null),O.health().catch(()=>null),O.retentionDistribution().catch(()=>null)]);m(we,a,!0),m(Se,o,!0),m($,c,!0)}finally{m(ae,!1)}}async function ke(){m(T,!0),m(y,null);try{m(y,await O.consolidate(),!0),await E()}catch{}finally{m(T,!1)}}async function Ce(){m(A,!0),m(g,null);try{m(g,await O.dream(),!0),await E()}catch{}finally{m(A,!1)}}var K=xt(),V=t(K),Re=r(t(V),2);e(V);var z=r(V,2),J=t(z),ie=t(J),$e=t(ie,!0);e(ie),b(2),e(J);var W=r(J,2),B=t(W),Ae=t(B);e(B),b(2),e(W);var de=r(W,2),re=t(de),oe=t(re),ne=r(oe,2),De=t(ne,!0);e(ne),e(re),b(2),e(de),b(2),e(z);var H=r(z,2),L=r(t(H),2),U=t(L),N=r(t(U),2),Ge=t(N);{var Me=a=>{var o=Qe();b(),v(a,o)},Fe=a=>{var o=ue("Consolidate");v(a,o)};u(Ge,a=>{s(T)?a(Me):a(Fe,!1)})}e(N),e(U);var je=r(U,2);{var Oe=a=>{var o=tt(),c=t(o),f=t(c);{var k=d=>{var i=Xe(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).nodesProcessed)),v(d,i)};u(f,d=>{s(y).nodesProcessed!==void 0&&d(k)})}var _=r(f,2);{var h=d=>{var i=Ze(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).decayApplied)),v(d,i)};u(_,d=>{s(y).decayApplied!==void 0&&d(h)})}var C=r(_,2);{var G=d=>{var i=et(),n=t(i),x=t(n,!0);e(n),b(2),e(i),w(()=>p(x,s(y).embeddingsGenerated)),v(d,i)};u(C,d=>{s(y).embeddingsGenerated!==void 0&&d(G)})}e(c),e(o),v(a,o)};u(je,a=>{s(y)&&a(Oe)})}e(L);var ve=r(L,2),Y=t(ve),D=r(t(Y),2),Te=t(D);{var Ee=a=>{var o=st();b(),v(a,o)},Ne=a=>{var o=ue("Dream");v(a,o)};u(Te,a=>{s(A)?a(Ee):a(Ne,!1)})}e(D),e(Y);var Pe=r(Y,2);{var Ie=a=>{var o=ot(),c=t(o);{var f=d=>{var i=it(),n=r(Be(i),2);Z(n,17,()=>s(g).insights,ee,(x,M)=>{var R=at(),F=t(R,!0);e(R),w(q=>p(F,q),[()=>typeof s(M)=="string"?s(M):JSON.stringify(s(M))]),v(x,R)}),v(d,i)},k=j(()=>s(g).insights&&Array.isArray(s(g).insights));u(c,d=>{s(k)&&d(f)})}var _=r(c,2);{var h=d=>{var i=dt(),n=r(t(i)),x=t(n,!0);e(n),e(i),w(()=>p(x,s(g).connections_found)),v(d,i)};u(_,d=>{s(g).connections_found!==void 0&&d(h)})}var C=r(_,2);{var G=d=>{var i=rt(),n=r(t(i)),x=t(n,!0);e(n),e(i),w(()=>p(x,s(g).memories_replayed)),v(d,i)};u(C,d=>{s(g).memories_replayed!==void 0&&d(G)})}e(o),v(a,o)};u(Pe,a=>{s(g)&&a(Ie)})}e(ve),e(H);var le=r(H,2);{var Ke=a=>{var o=lt(),c=r(t(o),2),f=t(c);{var k=h=>{var C=vt();Z(C,21,()=>s($).distribution,ee,(G,d,i)=>{const n=j(()=>Math.max(...s($).distribution.map(Q=>Q.count),1)),x=j(()=>s(d).count/s(n)*100),M=j(()=>i<2?"#ef4444":i<4?"#f59e0b":i<7?"#6366f1":"#10b981");var R=nt(),F=t(R),q=t(F,!0);e(F);var pe=r(F,2),Ve=r(pe,2);Ve.textContent=`${i*10}%`,e(R),w(Q=>{p(q,s(d).count),fe(pe,`height: ${Q??""}%; background: ${s(M)??""}; opacity: 0.7`)},[()=>Math.max(s(x),2)]),v(G,R)}),e(C),v(h,C)},_=j(()=>s($).distribution&&Array.isArray(s($).distribution));u(f,h=>{s(_)&&h(k)})}e(c),e(o),v(a,o)};u(le,a=>{s($)&&a(Ke)})}var ce=r(le,2),xe=r(t(ce),2),me=t(xe);Z(me,20,()=>[{key:"⌘ K",desc:"Command palette"},{key:"/",desc:"Focus search"},{key:"G",desc:"Go to Graph"},{key:"M",desc:"Go to Memories"},{key:"T",desc:"Go to Timeline"},{key:"F",desc:"Go to Feed"},{key:"E",desc:"Go to Explore"},{key:"S",desc:"Go to Stats"}],ee,(a,o)=>{var c=ct(),f=t(c),k=t(f,!0);e(f);var _=r(f,2),h=t(_,!0);e(_),e(c),w(()=>{p(k,o.key),p(h,o.desc)}),v(a,c)}),e(me),e(xe),e(ce),b(2),e(K),w(a=>{p($e,ye()),fe(B,`color: ${P()>.7?"#10b981":P()>.4?"#f59e0b":"#ef4444"}`),p(Ae,`${a??""}%`),ge(oe,1,`w-2.5 h-2.5 rounded-full ${se()?"bg-recall animate-pulse-glow":"bg-decay"}`),p(De,se()?"Online":"Offline"),N.disabled=s(T),D.disabled=s(A),ge(D,1,`px-4 py-2 bg-dream/20 border border-dream/40 text-dream-glow text-sm rounded-xl hover:bg-dream/30 transition disabled:opacity-50 flex items-center gap-2 + ${s(A)?"glow-dream animate-pulse-glow":""}`)},[()=>(P()*100).toFixed(1)]),X("click",Re,E),X("click",N,ke),X("click",D,Ce),v(_e,K),We(),he()}He(["click"]);export{Ct as component}; diff --git a/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.br b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.br new file mode 100644 index 0000000..3aba712 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.br differ diff --git a/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.gz b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.gz new file mode 100644 index 0000000..d6c38b8 Binary files /dev/null and b/apps/dashboard/build/_app/immutable/nodes/9.BHweFYNs.js.gz differ diff --git a/apps/dashboard/build/_app/version.json b/apps/dashboard/build/_app/version.json index 20252d2..d4514a1 100644 --- a/apps/dashboard/build/_app/version.json +++ b/apps/dashboard/build/_app/version.json @@ -1 +1 @@ -{"version":"1773441353786"} \ No newline at end of file +{"version":"1776204719942"} \ No newline at end of file diff --git a/apps/dashboard/build/_app/version.json.br b/apps/dashboard/build/_app/version.json.br index 7ac6ca9..565d48d 100644 Binary files a/apps/dashboard/build/_app/version.json.br and b/apps/dashboard/build/_app/version.json.br differ diff --git a/apps/dashboard/build/_app/version.json.gz b/apps/dashboard/build/_app/version.json.gz index c0d2794..19c9eb7 100644 Binary files a/apps/dashboard/build/_app/version.json.gz and b/apps/dashboard/build/_app/version.json.gz differ diff --git a/apps/dashboard/build/favicon.svg.gz b/apps/dashboard/build/favicon.svg.gz index 88ee5b2..61b0904 100644 Binary files a/apps/dashboard/build/favicon.svg.gz and b/apps/dashboard/build/favicon.svg.gz differ diff --git a/apps/dashboard/build/index.html b/apps/dashboard/build/index.html index 08a4155..7ad805c 100644 --- a/apps/dashboard/build/index.html +++ b/apps/dashboard/build/index.html @@ -11,21 +11,21 @@ - - - - - - - - - + + + + + + + + + - - - - - + + + + + Vestige @@ -33,7 +33,7 @@
+ +{#if $suppressedCount > 0} +
+
+ + +
+ + Actively forgetting {$suppressedCount} {$suppressedCount === 1 ? 'memory' : 'memories'} + +
+{/if} diff --git a/apps/dashboard/src/lib/graph/__tests__/edges.test.ts b/apps/dashboard/src/lib/graph/__tests__/edges.test.ts index eca71ec..8aa9ec4 100644 --- a/apps/dashboard/src/lib/graph/__tests__/edges.test.ts +++ b/apps/dashboard/src/lib/graph/__tests__/edges.test.ts @@ -48,12 +48,14 @@ describe('EdgeManager', () => { expect(line.userData.target).toBe('b'); }); - it('caps opacity at 0.6', () => { + it('caps opacity at 0.8 (raised from 0.6 in v2.0.6 issue #31 fix)', () => { const edges = [makeEdge('a', 'b', { weight: 10.0 })]; manager.createEdges(edges, positions); const line = manager.group.children[0] as any; - expect(line.material.opacity).toBeLessThanOrEqual(0.6); + expect(line.material.opacity).toBeLessThanOrEqual(0.8); + // Baseline floor too — with weight 10 we should be at the cap, not below old 0.6 + expect(line.material.opacity).toBeGreaterThanOrEqual(0.6); }); }); @@ -122,7 +124,8 @@ describe('EdgeManager', () => { } const line = manager.group.children[0] as any; - expect(line.material.opacity).toBe(0.5); + // v2.0.6 issue #31 fix raised final edge opacity 0.5 → 0.65 + expect(line.material.opacity).toBe(0.65); }); it('uses easeOutCubic for smooth deceleration', () => { @@ -266,7 +269,8 @@ describe('EdgeManager', () => { // Both should be fully grown expect(manager.group.children.length).toBe(2); manager.group.children.forEach((child) => { - expect((child as any).material.opacity).toBe(0.5); + // v2.0.6 issue #31 fix raised final edge opacity 0.5 → 0.65 + expect((child as any).material.opacity).toBe(0.65); }); }); diff --git a/apps/dashboard/src/lib/graph/__tests__/setup.ts b/apps/dashboard/src/lib/graph/__tests__/setup.ts index 64b79b0..cc9117f 100644 --- a/apps/dashboard/src/lib/graph/__tests__/setup.ts +++ b/apps/dashboard/src/lib/graph/__tests__/setup.ts @@ -3,15 +3,29 @@ */ import { vi } from 'vitest'; +// Minimal canvas gradient mock — collects colour stops so tests can inspect +// them if they want to, but is mostly a no-op for runtime. +function createMockGradient() { + return { + colorStops: [] as Array<{ offset: number; color: string }>, + addColorStop(offset: number, color: string) { + this.colorStops.push({ offset, color }); + }, + }; +} + // Minimal canvas 2D context mock const mockContext2D = { clearRect: vi.fn(), + fillRect: vi.fn(), fillText: vi.fn(), measureText: vi.fn(() => ({ width: 100 })), + createRadialGradient: vi.fn(() => createMockGradient()), + createLinearGradient: vi.fn(() => createMockGradient()), font: '', textAlign: '', textBaseline: '', - fillStyle: '', + fillStyle: '' as string | object, shadowColor: '', shadowBlur: 0, shadowOffsetX: 0, diff --git a/apps/dashboard/src/lib/graph/__tests__/three-mock.ts b/apps/dashboard/src/lib/graph/__tests__/three-mock.ts index 3ff349c..b665ed7 100644 --- a/apps/dashboard/src/lib/graph/__tests__/three-mock.ts +++ b/apps/dashboard/src/lib/graph/__tests__/three-mock.ts @@ -282,10 +282,16 @@ export class MeshBasicMaterial extends BaseMaterial { } export class LineBasicMaterial extends BaseMaterial { + depthWrite = true; constructor(params?: Record) { super(); if (params) { if (typeof params.opacity === 'number') this.opacity = params.opacity; + if (typeof params.transparent === 'boolean') this.transparent = params.transparent; + if (params.color instanceof Color) this.color = params.color; + else if (typeof params.color === 'number') this.color = new Color(params.color); + if (typeof params.blending === 'number') this.blending = params.blending; + if (typeof params.depthWrite === 'boolean') this.depthWrite = params.depthWrite; } } } @@ -303,10 +309,19 @@ export class PointsMaterial extends BaseMaterial { } export class SpriteMaterial extends BaseMaterial { + depthWrite = true; constructor(params?: Record) { super(); if (params) { if (typeof params.opacity === 'number') this.opacity = params.opacity; + if (typeof params.transparent === 'boolean') this.transparent = params.transparent; + if (params.color instanceof Color) this.color = params.color; + else if (typeof params.color === 'number') this.color = new Color(params.color); + if (typeof params.blending === 'number') this.blending = params.blending; + if (typeof params.depthWrite === 'boolean') this.depthWrite = params.depthWrite; + if (params.map && typeof params.map === 'object') { + this.map = params.map as { dispose: () => void }; + } } } } diff --git a/apps/dashboard/src/lib/graph/__tests__/ui-fixes.test.ts b/apps/dashboard/src/lib/graph/__tests__/ui-fixes.test.ts new file mode 100644 index 0000000..05023d7 --- /dev/null +++ b/apps/dashboard/src/lib/graph/__tests__/ui-fixes.test.ts @@ -0,0 +1,236 @@ +/** + * Regression tests for vestige issue #31 (v2.0.6 Phase 1 dashboard UI fix). + * + * Before v2.0.6 the graph view rendered "glowing cubes" instead of round halos, + * with navy edges swallowed by heavy fog. Root cause: the node glow SpriteMaterial + * had no `map` set, so THREE.Sprite rendered as a solid-coloured plane whose + * square edges were then amplified by UnrealBloomPass into hard bright squares. + * + * These tests lock in every property that was broken so any regression surfaces + * as a red test instead of shipping another ugly screenshot into the issue tracker. + * + * The scene.ts assertions are intentionally source-level (fs regex) because the + * real scene.ts pulls in three/addons (OrbitControls, EffectComposer, UnrealBloomPass, + * WebGLRenderer) which are painful to mock in isolation. Reading the .ts file and + * regex-checking the magic numbers catches accidental revert/tweaks without needing + * a full WebGL harness. + */ +import { describe, it, expect, vi, beforeEach, beforeAll } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +vi.mock('three', async () => { + const mock = await import('./three-mock'); + return { ...mock }; +}); + +import { NodeManager } from '../nodes'; +import { EdgeManager } from '../edges'; +import { Vector3, AdditiveBlending } from './three-mock'; +import { makeNode, makeEdge, resetNodeCounter } from './helpers'; + +// --------------------------------------------------------------------------- +// 1. Node glow sprite — THE fix for the "glowing cubes" artifact +// --------------------------------------------------------------------------- +describe('issue #31 — node glow sprites render as round halos, not squares', () => { + let manager: NodeManager; + + beforeEach(() => { + resetNodeCounter(); + manager = new NodeManager(); + }); + + it('glow SpriteMaterial has a map set (the root cause of the square artifact)', () => { + manager.createNodes([makeNode({ id: 'a', retention: 0.8 })]); + const glow = manager.glowMap.get('a')!; + const mat = glow.material as any; + + // Without a map, THREE.Sprite renders as a solid coloured plane — + // additive blend + bloom then turns it into a glowing square. + // The fix generates a shared radial-gradient CanvasTexture and assigns + // it here, so bloom has a soft circular shape to diffuse. + expect(mat.map).not.toBeNull(); + expect(mat.map).toBeDefined(); + }); + + it('glow sprites on multiple nodes SHARE the same texture instance (singleton cache)', () => { + // The shared texture is a module-level cache — if a future refactor + // accidentally creates one per-node we'll leak memory on large graphs. + manager.createNodes([ + makeNode({ id: 'a' }), + makeNode({ id: 'b' }), + makeNode({ id: 'c' }), + ]); + const a = (manager.glowMap.get('a')!.material as any).map; + const b = (manager.glowMap.get('b')!.material as any).map; + const c = (manager.glowMap.get('c')!.material as any).map; + + expect(a).toBe(b); + expect(b).toBe(c); + }); + + it('glow sprite has depthWrite:false to prevent z-fighting with the sphere behind it', () => { + manager.createNodes([makeNode({ id: 'a' })]); + const mat = manager.glowMap.get('a')!.material as any; + expect(mat.depthWrite).toBe(false); + }); + + it('glow sprite uses additive blending (required for bloom to read as light)', () => { + manager.createNodes([makeNode({ id: 'a' })]); + const mat = manager.glowMap.get('a')!.material as any; + expect(mat.blending).toBe(AdditiveBlending); + }); + + it('glow sprite scale uses the new 6× multiplier (was 4× — gradient needed more footprint)', () => { + // size = 0.5 + retention*2 → 0.5 + 1.0*2 = 2.5 + // glow scale with new formula: 2.5 * 6 * 1.0 = 15 + manager.createNodes([makeNode({ id: 'full', retention: 1.0 })]); + const glow = manager.glowMap.get('full')!; + expect(glow.scale.x).toBeCloseTo(15, 5); + expect(glow.scale.y).toBeCloseTo(15, 5); + }); + + it('glow sprite base opacity is 0.3 + retention*0.35 (was 0.15 + retention*0.2)', () => { + manager.createNodes([makeNode({ id: 'full', retention: 1.0 })]); + const mat = manager.glowMap.get('full')!.material as any; + // 0.3 + 1.0 * 0.35 = 0.65 + expect(mat.opacity).toBeCloseTo(0.65, 5); + }); + + it('suppressed node glow opacity drops to 0.1 (v2.0.5 active forgetting)', () => { + manager.createNodes([makeNode({ id: 's', retention: 0.8, suppression_count: 2 })]); + const mat = manager.glowMap.get('s')!.material as any; + expect(mat.opacity).toBeCloseTo(0.1, 5); + }); +}); + +// --------------------------------------------------------------------------- +// 2. Edge materials — dark navy → brand violet, higher opacity +// --------------------------------------------------------------------------- +describe('issue #31 — edges are brand violet and actually visible', () => { + let manager: EdgeManager; + let positions: Map>; + + beforeEach(() => { + manager = new EdgeManager(); + positions = new Map([ + ['a', new Vector3(0, 0, 0)], + ['b', new Vector3(10, 0, 0)], + ]); + }); + + it('edge color is brand violet 0x8b5cf6, not the old dark navy 0x4a4a7a', () => { + manager.createEdges([makeEdge('a', 'b', { weight: 0.5 })], positions); + const line = manager.group.children[0] as any; + const c = line.material.color; + + // 0x8b5cf6 → r=139/255, g=92/255, b=246/255 + expect(c.r).toBeCloseTo(0x8b / 255, 3); + expect(c.g).toBeCloseTo(0x5c / 255, 3); + expect(c.b).toBeCloseTo(0xf6 / 255, 3); + + // And definitely NOT the old navy 0x4a4a7a (74/255, 74/255, 122/255) + expect(c.r).not.toBeCloseTo(0x4a / 255, 3); + }); + + it('edges have depthWrite:false so they additively blend through fog cleanly', () => { + manager.createEdges([makeEdge('a', 'b')], positions); + const line = manager.group.children[0] as any; + expect(line.material.depthWrite).toBe(false); + }); + + it('edge opacity base is 0.25 + weight*0.5 (was 0.1 + weight*0.5)', () => { + manager.createEdges([makeEdge('a', 'b', { weight: 0.5 })], positions); + const line = manager.group.children[0] as any; + // 0.25 + 0.5 * 0.5 = 0.5 + expect(line.material.opacity).toBeCloseTo(0.5, 5); + }); + + it('edge opacity with low weight still reads (new floor catches regressions)', () => { + manager.createEdges([makeEdge('a', 'b', { weight: 0.0 })], positions); + const line = manager.group.children[0] as any; + // Floor is 0.25 — used to be 0.1 which was invisible through fog + expect(line.material.opacity).toBeGreaterThanOrEqual(0.25); + }); + + it('edge opacity cap is 0.8 (was 0.6)', () => { + manager.createEdges([makeEdge('a', 'b', { weight: 100.0 })], positions); + const line = manager.group.children[0] as any; + expect(line.material.opacity).toBeCloseTo(0.8, 5); + }); +}); + +// --------------------------------------------------------------------------- +// 3. Scene config — source-level regex assertions (scene.ts needs three/addons) +// --------------------------------------------------------------------------- +describe('issue #31 — scene.ts bloom/fog/starfield config is locked in', () => { + const __dirname = dirname(fileURLToPath(import.meta.url)); + let src: string; + + beforeAll(() => { + src = readFileSync(resolve(__dirname, '../scene.ts'), 'utf-8'); + }); + + it('fog density is reduced from 0.008 → 0.0035', () => { + // Positive match: the new density appears inside a FogExp2 call + expect(src).toMatch(/FogExp2\(\s*0x[0-9a-f]+,\s*0\.0035/i); + // Negative match: the old aggressive density is gone + expect(src).not.toMatch(/FogExp2\(\s*0x[0-9a-f]+,\s*0\.008\b/i); + }); + + it('bloom strength is 0.55 (was 0.8 — was blown out)', () => { + // Match on the constructor signature: (size, strength, radius, threshold) + expect(src).toMatch( + /new UnrealBloomPass\([\s\S]*?,\s*0\.55,\s*0\.6,\s*0\.2\s*\)/ + ); + // Old values must be gone + expect(src).not.toMatch(/new UnrealBloomPass\([\s\S]*?,\s*0\.8,\s*0\.4,\s*0\.85\s*\)/); + }); + + it('scene.background is explicitly set (not left as default black void)', () => { + expect(src).toMatch(/scene\.background\s*=/); + }); + + it('a starfield is created and added to the scene', () => { + // createStarfield helper exists and is called at least once + expect(src).toMatch(/function\s+createStarfield\s*\(/); + expect(src).toMatch(/createStarfield\s*\(\s*\)/); + expect(src).toMatch(/scene\.add\(\s*starfield\s*\)/); + }); + + it('starfield is exposed on SceneContext (so dispose/update can touch it later)', () => { + expect(src).toMatch(/starfield:\s*THREE\.Points/); + }); + + it('ACESFilmicToneMapping still active (did not accidentally revert tone map)', () => { + expect(src).toMatch(/ACESFilmicToneMapping/); + }); +}); + +// --------------------------------------------------------------------------- +// 4. Source-level checks on nodes.ts — the shared glow texture helper +// --------------------------------------------------------------------------- +describe('issue #31 — nodes.ts glow texture helper exists and is a singleton', () => { + const __dirname = dirname(fileURLToPath(import.meta.url)); + let src: string; + + beforeAll(() => { + src = readFileSync(resolve(__dirname, '../nodes.ts'), 'utf-8'); + }); + + it('shared glow texture cache exists at module level', () => { + expect(src).toMatch(/let\s+sharedGlowTexture/); + expect(src).toMatch(/function\s+getGlowTexture\s*\(/); + }); + + it('radial gradient has a transparent outer stop (not hard edge)', () => { + // The key insight — colour stops must go to rgba(255,255,255,0) at the edge + expect(src).toMatch(/createRadialGradient/); + expect(src).toMatch(/rgba\(255,\s*255,\s*255,\s*0(?:\.0)?\)/); + }); + + it('SpriteMaterial is constructed with a map parameter', () => { + expect(src).toMatch(/new THREE\.SpriteMaterial\(\{[\s\S]*?map:\s*getGlowTexture\(\)/); + }); +}); diff --git a/apps/dashboard/src/lib/graph/edges.ts b/apps/dashboard/src/lib/graph/edges.ts index 9e8e37a..8022443 100644 --- a/apps/dashboard/src/lib/graph/edges.ts +++ b/apps/dashboard/src/lib/graph/edges.ts @@ -36,11 +36,15 @@ export class EdgeManager { const points = [sourcePos, targetPos]; const geometry = new THREE.BufferGeometry().setFromPoints(points); + // Brand violet (#8b5cf6) instead of the old dark navy 0x4a4a7a + // which was invisible against the fog. Higher opacity base so + // edges actually read as a graph. const material = new THREE.LineBasicMaterial({ - color: 0x4a4a7a, + color: 0x8b5cf6, transparent: true, - opacity: Math.min(0.1 + edge.weight * 0.5, 0.6), + opacity: Math.min(0.25 + edge.weight * 0.5, 0.8), blending: THREE.AdditiveBlending, + depthWrite: false, }); const line = new THREE.Line(geometry, material); @@ -58,10 +62,11 @@ export class EdgeManager { const points = [sourcePos.clone(), sourcePos.clone()]; const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.LineBasicMaterial({ - color: 0x4a4a7a, + color: 0x8b5cf6, transparent: true, opacity: 0, blending: THREE.AdditiveBlending, + depthWrite: false, }); const line = new THREE.Line(geometry, material); @@ -111,11 +116,11 @@ export class EdgeManager { attrs.needsUpdate = true; const mat = g.line.material as THREE.LineBasicMaterial; - mat.opacity = progress * 0.5; + mat.opacity = progress * 0.65; if (g.frame >= g.totalFrames) { - // Final opacity from weight - mat.opacity = 0.5; + // Final opacity matches new createEdges baseline + mat.opacity = 0.65; this.growingEdges.splice(i, 1); } } @@ -126,7 +131,7 @@ export class EdgeManager { d.frame++; const progress = d.frame / d.totalFrames; const mat = d.line.material as THREE.LineBasicMaterial; - mat.opacity = Math.max(0, 0.5 * (1 - progress)); + mat.opacity = Math.max(0, 0.65 * (1 - progress)); if (d.frame >= d.totalFrames) { this.group.remove(d.line); diff --git a/apps/dashboard/src/lib/graph/nodes.ts b/apps/dashboard/src/lib/graph/nodes.ts index 0bb6e39..b8af78e 100644 --- a/apps/dashboard/src/lib/graph/nodes.ts +++ b/apps/dashboard/src/lib/graph/nodes.ts @@ -2,6 +2,37 @@ import * as THREE from 'three'; import type { GraphNode } from '$types'; import { NODE_TYPE_COLORS } from '$types'; +// Shared radial-gradient texture used for every node's glow Sprite. +// Without a map, THREE.Sprite renders as a flat coloured plane — additive- +// blending + UnrealBloomPass then amplifies its square edges into the +// hard-edged "glowing cubes" artefact reported in issue #31. Using a +// soft radial gradient gives a real round halo and lets bloom do its job. +let sharedGlowTexture: THREE.Texture | null = null; +function getGlowTexture(): THREE.Texture { + if (sharedGlowTexture) return sharedGlowTexture; + const size = 128; + const canvas = document.createElement('canvas'); + canvas.width = size; + canvas.height = size; + const ctx = canvas.getContext('2d'); + if (!ctx) { + // Fallback: empty 1x1 texture; halos will be invisible but nothing crashes. + sharedGlowTexture = new THREE.Texture(); + return sharedGlowTexture; + } + const gradient = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2); + gradient.addColorStop(0.0, 'rgba(255, 255, 255, 1.0)'); + gradient.addColorStop(0.25, 'rgba(255, 255, 255, 0.7)'); + gradient.addColorStop(0.55, 'rgba(255, 255, 255, 0.2)'); + gradient.addColorStop(1.0, 'rgba(255, 255, 255, 0.0)'); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, size, size); + const tex = new THREE.CanvasTexture(canvas); + tex.needsUpdate = true; + sharedGlowTexture = tex; + return tex; +} + function easeOutElastic(t: number): number { if (t === 0 || t === 1) return t; const p = 0.3; @@ -90,16 +121,20 @@ export class NodeManager { const size = 0.5 + node.retention * 2; const color = NODE_TYPE_COLORS[node.type] || '#8B95A5'; + // v2.0.5 Active Forgetting: suppressed memories dim to 20% opacity + // and lose their emissive glow, mimicking inhibitory-control silencing. + const isSuppressed = (node.suppression_count ?? 0) > 0; + // Node mesh const geometry = new THREE.SphereGeometry(size, 16, 16); const material = new THREE.MeshStandardMaterial({ color: new THREE.Color(color), emissive: new THREE.Color(color), - emissiveIntensity: 0.3 + node.retention * 0.5, + emissiveIntensity: isSuppressed ? 0.0 : 0.3 + node.retention * 0.5, roughness: 0.3, metalness: 0.1, transparent: true, - opacity: 0.3 + node.retention * 0.7, + opacity: isSuppressed ? 0.2 : 0.3 + node.retention * 0.7, }); const mesh = new THREE.Mesh(geometry, material); @@ -109,15 +144,20 @@ export class NodeManager { this.meshMap.set(node.id, mesh); this.group.add(mesh); - // Glow sprite + // Glow sprite — radial-gradient texture kills the square-halo artefact + // from issue #31. depthWrite:false prevents z-fighting with the sphere. const spriteMat = new THREE.SpriteMaterial({ + map: getGlowTexture(), color: new THREE.Color(color), transparent: true, - opacity: initialScale > 0 ? 0.15 + node.retention * 0.2 : 0, + opacity: initialScale > 0 ? (isSuppressed ? 0.1 : 0.3 + node.retention * 0.35) : 0, blending: THREE.AdditiveBlending, + depthWrite: false, }); const sprite = new THREE.Sprite(spriteMat); - sprite.scale.set(size * 4 * initialScale, size * 4 * initialScale, 1); + // Slightly larger halo — the gradient falls off quickly so we need + // more screen real estate for a visible soft bloom footprint. + sprite.scale.set(size * 6 * initialScale, size * 6 * initialScale, 1); sprite.position.copy(pos); sprite.userData = { isGlow: true, nodeId: node.id }; this.glowMap.set(node.id, sprite); @@ -275,8 +315,8 @@ export class NodeManager { if (mn.frame >= 5) { const glowT = Math.min((mn.frame - 5) / 5, 1); const glowMat = mn.glow.material as THREE.SpriteMaterial; - glowMat.opacity = glowT * 0.25; - const glowSize = mn.targetScale * 4 * scale; + glowMat.opacity = glowT * 0.4; + const glowSize = mn.targetScale * 6 * scale; mn.glow.scale.set(glowSize, glowSize, 1); } @@ -300,7 +340,7 @@ export class NodeManager { const scale = Math.max(0.001, dn.originalScale * shrink); dn.mesh.scale.setScalar(scale); - const glowScale = scale * 4; + const glowScale = scale * 6; dn.glow.scale.set(glowScale, glowScale, 1); // Fade opacity @@ -342,7 +382,7 @@ export class NodeManager { const glow = this.glowMap.get(gn.id); if (glow) { - const glowSize = scale * 4; + const glowSize = scale * 6; glow.scale.set(glowSize, glowSize, 1); } diff --git a/apps/dashboard/src/lib/graph/scene.ts b/apps/dashboard/src/lib/graph/scene.ts index bbd39f0..6f05cca 100644 --- a/apps/dashboard/src/lib/graph/scene.ts +++ b/apps/dashboard/src/lib/graph/scene.ts @@ -18,11 +18,53 @@ export interface SceneContext { point1: THREE.PointLight; point2: THREE.PointLight; }; + starfield: THREE.Points; +} + +function createStarfield(): THREE.Points { + // 2000 dim points distributed on a spherical shell at radius 600-1000. + // Purely decorative depth cue — never intersects the graph area and + // sits below the bloom threshold so it doesn't bloom. + const starCount = 2000; + const positions = new Float32Array(starCount * 3); + const colors = new Float32Array(starCount * 3); + for (let i = 0; i < starCount; i++) { + const theta = Math.random() * Math.PI * 2; + const phi = Math.acos(2 * Math.random() - 1); + const r = 600 + Math.random() * 400; + positions[i * 3] = r * Math.sin(phi) * Math.cos(theta); + positions[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta); + positions[i * 3 + 2] = r * Math.cos(phi); + // Subtle colour variation — mostly cool white, some violet tint. + const tint = Math.random(); + colors[i * 3] = 0.55 + tint * 0.25; + colors[i * 3 + 1] = 0.55 + tint * 0.15; + colors[i * 3 + 2] = 0.75 + tint * 0.25; + } + const geo = new THREE.BufferGeometry(); + geo.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + geo.setAttribute('color', new THREE.BufferAttribute(colors, 3)); + const mat = new THREE.PointsMaterial({ + size: 1.6, + sizeAttenuation: true, + vertexColors: true, + transparent: true, + opacity: 0.6, + depthWrite: false, + blending: THREE.AdditiveBlending, + }); + return new THREE.Points(geo, mat); } export function createScene(container: HTMLDivElement): SceneContext { const scene = new THREE.Scene(); - scene.fog = new THREE.FogExp2(0x050510, 0.008); + // Darker-than-black background with a subtle colour cast. Combined with + // the starfield and reduced fog, the void has depth instead of reading + // as a broken shader canvas. + scene.background = new THREE.Color(0x05050f); + // Fog density reduced 0.008 → 0.0035 — the old value was killing every + // edge and node past 50 units. Lighter colour blends into the background. + scene.fog = new THREE.FogExp2(0x0a0a1a, 0.0035); const camera = new THREE.PerspectiveCamera( 60, @@ -40,7 +82,7 @@ export function createScene(container: HTMLDivElement): SceneContext { renderer.setSize(container.clientWidth, container.clientHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.toneMapping = THREE.ACESFilmicToneMapping; - renderer.toneMappingExposure = 1.2; + renderer.toneMappingExposure = 1.25; container.appendChild(renderer.domElement); const controls = new OrbitControls(camera, renderer.domElement); @@ -55,25 +97,32 @@ export function createScene(container: HTMLDivElement): SceneContext { const composer = new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); + // Bloom retuned for radial-gradient glow sprites (issue #31 fix): + // strength 0.8 → 0.55 — gentler, avoids the old blown-out look + // radius 0.4 → 0.6 — softer falloff, diffuses cleanly through glow + // threshold 0.85 → 0.2 — let mid-tones bloom instead of highlights only const bloomPass = new UnrealBloomPass( new THREE.Vector2(container.clientWidth, container.clientHeight), - 0.8, - 0.4, - 0.85 + 0.55, + 0.6, + 0.2 ); composer.addPass(bloomPass); - const ambient = new THREE.AmbientLight(0x1a1a3a, 0.5); + const ambient = new THREE.AmbientLight(0x2a2a5a, 0.7); scene.add(ambient); - const point1 = new THREE.PointLight(0x6366f1, 1.5, 200); + const point1 = new THREE.PointLight(0x6366f1, 1.8, 240); point1.position.set(50, 50, 50); scene.add(point1); - const point2 = new THREE.PointLight(0xa855f7, 1, 200); + const point2 = new THREE.PointLight(0xa855f7, 1.2, 240); point2.position.set(-50, -30, -50); scene.add(point2); + const starfield = createStarfield(); + scene.add(starfield); + const raycaster = new THREE.Raycaster(); raycaster.params.Points = { threshold: 2 }; const mouse = new THREE.Vector2(); @@ -88,6 +137,7 @@ export function createScene(container: HTMLDivElement): SceneContext { raycaster, mouse, lights: { ambient, point1, point2 }, + starfield, }; } diff --git a/apps/dashboard/src/lib/stores/websocket.ts b/apps/dashboard/src/lib/stores/websocket.ts index c9985f1..8ae8c65 100644 --- a/apps/dashboard/src/lib/stores/websocket.ts +++ b/apps/dashboard/src/lib/stores/websocket.ts @@ -101,3 +101,7 @@ export const memoryCount = derived(websocket, $ws => export const avgRetention = derived(websocket, $ws => ($ws.lastHeartbeat?.data?.avg_retention as number) ?? 0 ); +// v2.0.5: count of memories actively being forgotten (suppression_count > 0) +export const suppressedCount = derived(websocket, $ws => + ($ws.lastHeartbeat?.data?.suppressed_count as number) ?? 0 +); diff --git a/apps/dashboard/src/lib/types/index.ts b/apps/dashboard/src/lib/types/index.ts index effed1e..0e2a6de 100644 --- a/apps/dashboard/src/lib/types/index.ts +++ b/apps/dashboard/src/lib/types/index.ts @@ -74,6 +74,9 @@ export interface GraphNode { createdAt: string; updatedAt: string; isCenter: boolean; + // v2.0.5 Active Forgetting — top-down suppression state + suppression_count?: number; + suppressed_at?: string; } export interface GraphEdge { @@ -150,6 +153,9 @@ export type VestigeEventType = | 'MemoryDeleted' | 'MemoryPromoted' | 'MemoryDemoted' + | 'MemorySuppressed' + | 'MemoryUnsuppressed' + | 'Rac1CascadeSwept' | 'SearchPerformed' | 'DreamStarted' | 'DreamProgress' @@ -198,6 +204,9 @@ export const EVENT_TYPE_COLORS: Record = { MemoryDeleted: '#FF4757', MemoryPromoted: '#00FF88', MemoryDemoted: '#FF6B35', + MemorySuppressed: '#A33FFF', + MemoryUnsuppressed: '#14E8C6', + Rac1CascadeSwept: '#6E3FFF', SearchPerformed: '#818CF8', DreamStarted: '#9D00FF', DreamProgress: '#B44AFF', diff --git a/apps/dashboard/src/routes/+layout.svelte b/apps/dashboard/src/routes/+layout.svelte index 41280b9..5050f37 100644 --- a/apps/dashboard/src/routes/+layout.svelte +++ b/apps/dashboard/src/routes/+layout.svelte @@ -4,7 +4,8 @@ import { page } from '$app/stores'; import { goto } from '$app/navigation'; import { base } from '$app/paths'; - import { websocket, isConnected, memoryCount, avgRetention } from '$stores/websocket'; + import { websocket, isConnected, memoryCount, avgRetention, suppressedCount } from '$stores/websocket'; + import ForgettingIndicator from '$lib/components/ForgettingIndicator.svelte'; let { children } = $props(); let showCommandPalette = $state(false); @@ -144,6 +145,11 @@
{$memoryCount} memories
{($avgRetention * 100).toFixed(0)}% retention
+ {#if $suppressedCount > 0} + + {/if}
diff --git a/crates/vestige-core/Cargo.toml b/crates/vestige-core/Cargo.toml index 193ad84..212cde6 100644 --- a/crates/vestige-core/Cargo.toml +++ b/crates/vestige-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vestige-core" -version = "2.0.4" +version = "2.0.5" edition = "2024" rust-version = "1.91" authors = ["Vestige Team"] diff --git a/crates/vestige-core/benches/search_bench.rs b/crates/vestige-core/benches/search_bench.rs index b27f286..c10ef9d 100644 --- a/crates/vestige-core/benches/search_bench.rs +++ b/crates/vestige-core/benches/search_bench.rs @@ -3,10 +3,10 @@ //! Benchmarks for core search operations using Criterion. //! Run with: cargo bench -p vestige-core -use criterion::{criterion_group, criterion_main, Criterion, black_box}; -use vestige_core::search::hyde::{classify_intent, expand_query, centroid_embedding}; -use vestige_core::search::{reciprocal_rank_fusion, linear_combination, sanitize_fts5_query}; +use criterion::{Criterion, black_box, criterion_group, criterion_main}; use vestige_core::embeddings::cosine_similarity; +use vestige_core::search::hyde::{centroid_embedding, classify_intent, expand_query}; +use vestige_core::search::{linear_combination, reciprocal_rank_fusion, sanitize_fts5_query}; fn bench_classify_intent(c: &mut Criterion) { let queries = [ @@ -29,7 +29,9 @@ fn bench_classify_intent(c: &mut Criterion) { fn bench_expand_query(c: &mut Criterion) { c.bench_function("expand_query", |b| { b.iter(|| { - black_box(expand_query("What is spaced repetition and how does FSRS work?")); + black_box(expand_query( + "What is spaced repetition and how does FSRS work?", + )); }) }); } @@ -37,11 +39,7 @@ fn bench_expand_query(c: &mut Criterion) { fn bench_centroid_embedding(c: &mut Criterion) { // Simulate 4 embeddings of 256 dimensions let embeddings: Vec> = (0..4) - .map(|i| { - (0..256) - .map(|j| ((i * 256 + j) as f32).sin()) - .collect() - }) + .map(|i| (0..256).map(|j| ((i * 256 + j) as f32).sin()).collect()) .collect(); c.bench_function("centroid_256d_4vecs", |b| { @@ -61,7 +59,11 @@ fn bench_rrf_fusion(c: &mut Criterion) { c.bench_function("rrf_50x50", |b| { b.iter(|| { - black_box(reciprocal_rank_fusion(&keyword_results, &semantic_results, 60.0)); + black_box(reciprocal_rank_fusion( + &keyword_results, + &semantic_results, + 60.0, + )); }) }); } @@ -76,7 +78,12 @@ fn bench_linear_combination(c: &mut Criterion) { c.bench_function("linear_combo_50x50", |b| { b.iter(|| { - black_box(linear_combination(&keyword_results, &semantic_results, 0.3, 0.7)); + black_box(linear_combination( + &keyword_results, + &semantic_results, + 0.3, + 0.7, + )); }) }); } @@ -84,7 +91,9 @@ fn bench_linear_combination(c: &mut Criterion) { fn bench_sanitize_fts5(c: &mut Criterion) { c.bench_function("sanitize_fts5_query", |b| { b.iter(|| { - black_box(sanitize_fts5_query("hello world \"exact phrase\" OR special-chars!@#")); + black_box(sanitize_fts5_query( + "hello world \"exact phrase\" OR special-chars!@#", + )); }) }); } diff --git a/crates/vestige-core/src/advanced/adaptive_embedding.rs b/crates/vestige-core/src/advanced/adaptive_embedding.rs index d4b39d3..001c191 100644 --- a/crates/vestige-core/src/advanced/adaptive_embedding.rs +++ b/crates/vestige-core/src/advanced/adaptive_embedding.rs @@ -766,6 +766,6 @@ fn main() -> Result<(), std::io::Error> { embedder.embed_auto("Another text sample."); let stats = embedder.stats(); - assert!(stats.len() > 0); + assert!(!stats.is_empty()); } } diff --git a/crates/vestige-core/src/advanced/chains.rs b/crates/vestige-core/src/advanced/chains.rs index 9d6e59a..8df1fff 100644 --- a/crates/vestige-core/src/advanced/chains.rs +++ b/crates/vestige-core/src/advanced/chains.rs @@ -300,7 +300,11 @@ impl MemoryChainBuilder { } // Sort by score (descending) - all_paths.sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal)); + all_paths.sort_by(|a, b| { + b.score + .partial_cmp(&a.score) + .unwrap_or(std::cmp::Ordering::Equal) + }); // Return top paths all_paths.into_iter().take(10).collect() diff --git a/crates/vestige-core/src/advanced/compression.rs b/crates/vestige-core/src/advanced/compression.rs index 0a53664..d5358b4 100644 --- a/crates/vestige-core/src/advanced/compression.rs +++ b/crates/vestige-core/src/advanced/compression.rs @@ -445,7 +445,11 @@ impl MemoryCompressor { } // Sort by importance and deduplicate - facts.sort_by(|a, b| b.importance.partial_cmp(&a.importance).unwrap_or(std::cmp::Ordering::Equal)); + facts.sort_by(|a, b| { + b.importance + .partial_cmp(&a.importance) + .unwrap_or(std::cmp::Ordering::Equal) + }); self.deduplicate_facts(facts) } diff --git a/crates/vestige-core/src/advanced/cross_project.rs b/crates/vestige-core/src/advanced/cross_project.rs index 126463c..f48b964 100644 --- a/crates/vestige-core/src/advanced/cross_project.rs +++ b/crates/vestige-core/src/advanced/cross_project.rs @@ -432,10 +432,11 @@ impl CrossProjectLearner { // Check each trigger for trigger in &pattern.pattern.triggers { if let Some((matches, reason)) = self.check_trigger(trigger, context) - && matches { - match_scores.push(trigger.confidence); - match_reasons.push(reason); - } + && matches + { + match_scores.push(trigger.confidence); + match_reasons.push(reason); + } } if match_scores.is_empty() { @@ -547,10 +548,11 @@ impl CrossProjectLearner { let success_rate = success_count as f64 / total_count as f64; if let Ok(mut patterns) = self.patterns.write() - && let Some(pattern) = patterns.get_mut(pattern_id) { - pattern.success_rate = success_rate; - pattern.application_count = total_count as u32; - } + && let Some(pattern) = patterns.get_mut(pattern_id) + { + pattern.success_rate = success_rate; + pattern.application_count = total_count as u32; + } } fn extract_patterns_from_category( @@ -595,38 +597,39 @@ impl CrossProjectLearner { let pattern_id = format!("auto-{}-{}", category_to_string(&category), keyword); if let Ok(mut patterns) = self.patterns.write() - && !patterns.contains_key(&pattern_id) { - patterns.insert( - pattern_id.clone(), - UniversalPattern { - id: pattern_id, - pattern: CodePattern { - name: format!("{} pattern", keyword), - category: category.clone(), - description: format!( - "Pattern involving '{}' observed in {} projects", - keyword, - projects.len() - ), - example: None, - triggers: vec![PatternTrigger { - trigger_type: TriggerType::Topic, - value: keyword.clone(), - confidence: 0.5, - }], - benefits: vec![], - considerations: vec![], - }, - projects_seen_in: projects.iter().map(|s| s.to_string()).collect(), - success_rate: 0.5, // Default until validated - applicability: format!("When working with {}", keyword), - confidence: 0.5, - first_seen: Utc::now(), - last_seen: Utc::now(), - application_count: 0, + && !patterns.contains_key(&pattern_id) + { + patterns.insert( + pattern_id.clone(), + UniversalPattern { + id: pattern_id, + pattern: CodePattern { + name: format!("{} pattern", keyword), + category: category.clone(), + description: format!( + "Pattern involving '{}' observed in {} projects", + keyword, + projects.len() + ), + example: None, + triggers: vec![PatternTrigger { + trigger_type: TriggerType::Topic, + value: keyword.clone(), + confidence: 0.5, + }], + benefits: vec![], + considerations: vec![], }, - ); - } + projects_seen_in: projects.iter().map(|s| s.to_string()).collect(), + success_rate: 0.5, // Default until validated + applicability: format!("When working with {}", keyword), + confidence: 0.5, + first_seen: Utc::now(), + last_seen: Utc::now(), + application_count: 0, + }, + ); + } } } } diff --git a/crates/vestige-core/src/advanced/dreams.rs b/crates/vestige-core/src/advanced/dreams.rs index a4ddac5..d01d8e2 100644 --- a/crates/vestige-core/src/advanced/dreams.rs +++ b/crates/vestige-core/src/advanced/dreams.rs @@ -455,9 +455,10 @@ impl ConsolidationScheduler { // Strengthen connections between sequentially replayed memories for window in replay.sequence.windows(2) { if let [id_a, id_b] = window - && graph.strengthen_connection(id_a, id_b, 0.1) { - strengthened += 1; - } + && graph.strengthen_connection(id_a, id_b, 0.1) + { + strengthened += 1; + } } // Also strengthen based on discovered patterns @@ -704,11 +705,12 @@ impl ConnectionGraph { for (a, b) in [(from_id, to_id), (to_id, from_id)] { if let Some(connections) = self.connections.get_mut(a) - && let Some(conn) = connections.iter_mut().find(|c| c.target_id == b) { - conn.strength = (conn.strength + boost).min(2.0); - conn.last_strengthened = now; - strengthened = true; - } + && let Some(conn) = connections.iter_mut().find(|c| c.target_id == b) + { + conn.strength = (conn.strength + boost).min(2.0); + conn.last_strengthened = now; + strengthened = true; + } } strengthened @@ -1481,9 +1483,10 @@ impl MemoryDreamer { // Try to generate insight from this cluster if let Some(insight) = self.generate_insight_from_cluster(&cluster_memories) - && insight.novelty_score >= self.config.min_novelty { - insights.push(insight); - } + && insight.novelty_score >= self.config.min_novelty + { + insights.push(insight); + } if insights.len() >= self.config.max_insights { break; diff --git a/crates/vestige-core/src/advanced/importance.rs b/crates/vestige-core/src/advanced/importance.rs index 3579626..6c06376 100644 --- a/crates/vestige-core/src/advanced/importance.rs +++ b/crates/vestige-core/src/advanced/importance.rs @@ -232,9 +232,10 @@ impl ImportanceTracker { // Store context with event if let Ok(mut events) = self.recent_events.write() && let Some(event) = events.last_mut() - && event.memory_id == memory_id { - event.context = Some(context.to_string()); - } + && event.memory_id == memory_id + { + event.context = Some(context.to_string()); + } } /// Apply importance decay to all memories @@ -339,7 +340,11 @@ impl ImportanceTracker { /// Get memories sorted by importance pub fn get_top_by_importance(&self, limit: usize) -> Vec { let mut scores = self.get_all_scores(); - scores.sort_by(|a, b| b.final_score.partial_cmp(&a.final_score).unwrap_or(std::cmp::Ordering::Equal)); + scores.sort_by(|a, b| { + b.final_score + .partial_cmp(&a.final_score) + .unwrap_or(std::cmp::Ordering::Equal) + }); scores.truncate(limit); scores } @@ -355,7 +360,9 @@ impl ImportanceTracker { scores.sort_by(|a, b| { let a_neglect = a.base_importance - a.usage_importance; let b_neglect = b.base_importance - b.usage_importance; - b_neglect.partial_cmp(&a_neglect).unwrap_or(std::cmp::Ordering::Equal) + b_neglect + .partial_cmp(&a_neglect) + .unwrap_or(std::cmp::Ordering::Equal) }); scores.truncate(limit); @@ -446,7 +453,10 @@ mod tests { assert_eq!(score.retrieval_count, 3); assert_eq!(score.helpful_count, 3); // 0.1 * 1.15^3 = ~0.152, so should be > initial 0.1 - assert!(score.usage_importance > 0.1, "Should be boosted from baseline"); + assert!( + score.usage_importance > 0.1, + "Should be boosted from baseline" + ); } #[test] diff --git a/crates/vestige-core/src/advanced/intent.rs b/crates/vestige-core/src/advanced/intent.rs index 61cfacc..a59cb2e 100644 --- a/crates/vestige-core/src/advanced/intent.rs +++ b/crates/vestige-core/src/advanced/intent.rs @@ -562,9 +562,10 @@ impl IntentDetector { } ActionType::FileOpened | ActionType::FileEdited => { if let Some(file) = &action.file - && let Some(name) = file.file_name() { - suspected_area = name.to_string_lossy().to_string(); - } + && let Some(name) = file.file_name() + { + suspected_area = name.to_string_lossy().to_string(); + } } _ => {} } diff --git a/crates/vestige-core/src/advanced/mod.rs b/crates/vestige-core/src/advanced/mod.rs index d74d46f..fdbdfe4 100644 --- a/crates/vestige-core/src/advanced/mod.rs +++ b/crates/vestige-core/src/advanced/mod.rs @@ -29,7 +29,10 @@ pub mod speculative; // Re-exports for convenient access pub use adaptive_embedding::{AdaptiveEmbedder, ContentType, EmbeddingStrategy, Language}; -pub use chains::{ChainStep, Connection, ConnectionType, MemoryChainBuilder, MemoryNode, MemoryPath, ReasoningChain}; +pub use chains::{ + ChainStep, Connection, ConnectionType, MemoryChainBuilder, MemoryNode, MemoryPath, + ReasoningChain, +}; pub use compression::{CompressedMemory, CompressionConfig, CompressionStats, MemoryCompressor}; pub use cross_project::{ ApplicableKnowledge, CrossProjectLearner, ProjectContext, UniversalPattern, @@ -58,14 +61,14 @@ pub use dreams::{ }; pub use importance::{ImportanceDecayConfig, ImportanceScore, ImportanceTracker, UsageEvent}; pub use intent::{ActionType, DetectedIntent, IntentDetector, MaintenanceType, UserAction}; -pub use reconsolidation::{ - AccessContext, AccessTrigger, AppliedModification, ChangeSummary, LabileState, MemorySnapshot, - Modification, ReconsolidatedMemory, ReconsolidationManager, ReconsolidationStats, - RelationshipType, RetrievalRecord, -}; pub use prediction_error::{ CandidateMemory, CreateReason, EvaluationIntent, GateDecision, GateStats, MergeStrategy, PredictionErrorConfig, PredictionErrorGate, SimilarityResult, SupersedeReason, UpdateType, cosine_similarity, }; +pub use reconsolidation::{ + AccessContext, AccessTrigger, AppliedModification, ChangeSummary, LabileState, MemorySnapshot, + Modification, ReconsolidatedMemory, ReconsolidationManager, ReconsolidationStats, + RelationshipType, RetrievalRecord, +}; pub use speculative::{PredictedMemory, PredictionContext, SpeculativeRetriever, UsagePattern}; diff --git a/crates/vestige-core/src/advanced/prediction_error.rs b/crates/vestige-core/src/advanced/prediction_error.rs index d458fd1..3693d77 100644 --- a/crates/vestige-core/src/advanced/prediction_error.rs +++ b/crates/vestige-core/src/advanced/prediction_error.rs @@ -123,9 +123,15 @@ impl GateDecision { /// Get the prediction error score pub fn prediction_error(&self) -> f32 { match self { - Self::Create { prediction_error, .. } => *prediction_error, - Self::Update { prediction_error, .. } => *prediction_error, - Self::Supersede { prediction_error, .. } => *prediction_error, + Self::Create { + prediction_error, .. + } => *prediction_error, + Self::Update { + prediction_error, .. + } => *prediction_error, + Self::Supersede { + prediction_error, .. + } => *prediction_error, Self::Merge { avg_similarity, .. } => 1.0 - avg_similarity, } } @@ -368,7 +374,11 @@ impl PredictionErrorGate { .collect(); // Sort by similarity (highest first) - similarities.sort_by(|a, b| b.similarity.partial_cmp(&a.similarity).unwrap_or(std::cmp::Ordering::Equal)); + similarities.sort_by(|a, b| { + b.similarity + .partial_cmp(&a.similarity) + .unwrap_or(std::cmp::Ordering::Equal) + }); // Take top candidates let top_candidates: Vec<_> = similarities @@ -394,8 +404,9 @@ impl PredictionErrorGate { if let Some(c) = candidate { // If similar and the existing memory was demoted, supersede it if best.similarity >= self.config.similarity_threshold - && c.was_demoted - && self.config.auto_supersede_demoted { + && c.was_demoted + && self.config.auto_supersede_demoted + { self.stats.supersedes += 1; return GateDecision::Supersede { old_memory_id: c.id.clone(), @@ -406,8 +417,8 @@ impl PredictionErrorGate { } // Check for correction (similar but contradictory) - if best.similarity >= self.config.correction_threshold - && best.appears_contradictory { + if best.similarity >= self.config.correction_threshold && best.appears_contradictory + { self.stats.supersedes += 1; return GateDecision::Supersede { old_memory_id: c.id.clone(), @@ -418,7 +429,8 @@ impl PredictionErrorGate { } // Regular update for similar content - if best.similarity >= self.config.similarity_threshold && self.config.prefer_updates { + if best.similarity >= self.config.similarity_threshold && self.config.prefer_updates + { self.stats.updates += 1; return GateDecision::Update { target_id: best.memory_id.clone(), @@ -442,7 +454,10 @@ impl PredictionErrorGate { self.stats.merges += 1; return GateDecision::Merge { - memory_ids: merge_candidates.iter().map(|s| s.memory_id.clone()).collect(), + memory_ids: merge_candidates + .iter() + .map(|s| s.memory_id.clone()) + .collect(), avg_similarity, strategy: MergeStrategy::Combine, }; @@ -501,7 +516,10 @@ impl PredictionErrorGate { self.evaluate(new_content, new_embedding, candidates) } } - EvaluationIntent::Supersede { old_memory_id, reason } => { + EvaluationIntent::Supersede { + old_memory_id, + reason, + } => { if let Some(c) = candidates.iter().find(|c| c.id == old_memory_id) { let similarity = cosine_similarity(new_embedding, &c.embedding); self.stats.supersedes += 1; @@ -515,9 +533,7 @@ impl PredictionErrorGate { self.evaluate(new_content, new_embedding, candidates) } } - EvaluationIntent::Auto => { - self.evaluate(new_content, new_embedding, candidates) - } + EvaluationIntent::Auto => self.evaluate(new_content, new_embedding, candidates), } } @@ -596,7 +612,10 @@ pub enum EvaluationIntent { /// Force update of specific memory ForceUpdate { target_id: String }, /// Force supersede of specific memory - Supersede { old_memory_id: String, reason: SupersedeReason }, + Supersede { + old_memory_id: String, + reason: SupersedeReason, + }, } // ============================================================================ @@ -680,18 +699,22 @@ mod tests { // Create embeddings with controlled similarity based on seed // Seeds close to each other = similar vectors // Seeds far apart = different vectors - (0..384).map(|i| { - let base = (i as f32 / 384.0) * std::f32::consts::PI * 2.0; - (base * seed).sin() - }).collect() + (0..384) + .map(|i| { + let base = (i as f32 / 384.0) * std::f32::consts::PI * 2.0; + (base * seed).sin() + }) + .collect() } fn make_orthogonal_embedding() -> Vec { // Create an embedding that's orthogonal to seed=1.0 - (0..384).map(|i| { - let base = (i as f32 / 384.0) * std::f32::consts::PI * 2.0; - (base + std::f32::consts::PI / 2.0).sin() // 90 degree phase shift - }).collect() + (0..384) + .map(|i| { + let base = (i as f32 / 384.0) * std::f32::consts::PI * 2.0; + (base + std::f32::consts::PI / 2.0).sin() // 90 degree phase shift + }) + .collect() } fn make_candidate(id: &str, seed: f32) -> CandidateMemory { @@ -728,7 +751,13 @@ mod tests { let decision = gate.evaluate("New content", &embedding, &[]); - assert!(matches!(decision, GateDecision::Create { reason: CreateReason::FirstMemory, .. })); + assert!(matches!( + decision, + GateDecision::Create { + reason: CreateReason::FirstMemory, + .. + } + )); } #[test] @@ -762,7 +791,10 @@ mod tests { // Should supersede the demoted memory if similarity is above threshold // If not superseding, it should at least update - assert!(matches!(decision, GateDecision::Supersede { .. } | GateDecision::Update { .. })); + assert!(matches!( + decision, + GateDecision::Supersede { .. } | GateDecision::Update { .. } + )); } #[test] @@ -812,7 +844,13 @@ mod tests { EvaluationIntent::ForceCreate, ); - assert!(matches!(decision, GateDecision::Create { reason: CreateReason::ExplicitCreate, .. })); + assert!(matches!( + decision, + GateDecision::Create { + reason: CreateReason::ExplicitCreate, + .. + } + )); } #[test] @@ -825,7 +863,9 @@ mod tests { "Updated content", &embedding, &[candidate], - EvaluationIntent::ForceUpdate { target_id: "mem-1".to_string() }, + EvaluationIntent::ForceUpdate { + target_id: "mem-1".to_string(), + }, ); assert!(matches!(decision, GateDecision::Update { .. })); diff --git a/crates/vestige-core/src/advanced/reconsolidation.rs b/crates/vestige-core/src/advanced/reconsolidation.rs index 7b201e2..83bc39e 100644 --- a/crates/vestige-core/src/advanced/reconsolidation.rs +++ b/crates/vestige-core/src/advanced/reconsolidation.rs @@ -517,13 +517,14 @@ impl ReconsolidationManager { } if let Some(state) = self.labile_memories.get_mut(memory_id) - && state.is_within_window(self.labile_window) { - let success = state.add_modification(modification); - if success { - self.stats.total_modifications += 1; - } - return success; + && state.is_within_window(self.labile_window) + { + let success = state.add_modification(modification); + if success { + self.stats.total_modifications += 1; } + return success; + } false } @@ -690,13 +691,14 @@ impl ReconsolidationManager { if let Ok(history) = self.retrieval_history.read() { for record in history.iter() { if record.memory_id == memory_id - && let Some(context) = &record.context { - for co_id in &context.co_retrieved { - if co_id != memory_id { - *co_retrieved.entry(co_id.clone()).or_insert(0) += 1; - } + && let Some(context) = &record.context + { + for co_id in &context.co_retrieved { + if co_id != memory_id { + *co_retrieved.entry(co_id.clone()).or_insert(0) += 1; } } + } } } @@ -921,7 +923,7 @@ mod tests { #[test] fn test_relationship_types() { - let relationships = vec![ + let relationships = [ RelationshipType::Supports, RelationshipType::Contradicts, RelationshipType::Elaborates, diff --git a/crates/vestige-core/src/advanced/speculative.rs b/crates/vestige-core/src/advanced/speculative.rs index 7b9442e..eebe947 100644 --- a/crates/vestige-core/src/advanced/speculative.rs +++ b/crates/vestige-core/src/advanced/speculative.rs @@ -193,7 +193,11 @@ impl SpeculativeRetriever { // Deduplicate and sort by confidence predictions = self.deduplicate_predictions(predictions); - predictions.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap_or(std::cmp::Ordering::Equal)); + predictions.sort_by(|a, b| { + b.confidence + .partial_cmp(&a.confidence) + .unwrap_or(std::cmp::Ordering::Equal) + }); predictions.truncate(MAX_PREDICTIONS); // Filter by minimum confidence @@ -266,11 +270,12 @@ impl SpeculativeRetriever { // Update file-memory associations if let Some(file) = file_context - && let Ok(mut map) = self.file_memory_map.write() { - map.entry(file.to_string()) - .or_insert_with(Vec::new) - .push(memory_id.to_string()); - } + && let Ok(mut map) = self.file_memory_map.write() + { + map.entry(file.to_string()) + .or_insert_with(Vec::new) + .push(memory_id.to_string()); + } } /// Get cached predictions diff --git a/crates/vestige-core/src/codebase/context.rs b/crates/vestige-core/src/codebase/context.rs index a8ff103..170d556 100644 --- a/crates/vestige-core/src/codebase/context.rs +++ b/crates/vestige-core/src/codebase/context.rs @@ -587,9 +587,10 @@ impl ContextCapture { // Java Spring if let Ok(content) = fs::read_to_string(self.project_root.join("pom.xml")) - && content.contains("spring") { - frameworks.push(Framework::Spring); - } + && content.contains("spring") + { + frameworks.push(Framework::Spring); + } // Ruby Rails if self.file_exists("config/routes.rb") { @@ -613,36 +614,40 @@ impl ContextCapture { fn detect_project_name(&self) -> Result> { // Try Cargo.toml if let Ok(content) = fs::read_to_string(self.project_root.join("Cargo.toml")) - && let Some(name) = self.extract_toml_value(&content, "name") { - return Ok(Some(name)); - } + && let Some(name) = self.extract_toml_value(&content, "name") + { + return Ok(Some(name)); + } // Try package.json if let Ok(content) = fs::read_to_string(self.project_root.join("package.json")) - && let Some(name) = self.extract_json_value(&content, "name") { - return Ok(Some(name)); - } + && let Some(name) = self.extract_json_value(&content, "name") + { + return Ok(Some(name)); + } // Try pyproject.toml if let Ok(content) = fs::read_to_string(self.project_root.join("pyproject.toml")) - && let Some(name) = self.extract_toml_value(&content, "name") { - return Ok(Some(name)); - } + && let Some(name) = self.extract_toml_value(&content, "name") + { + return Ok(Some(name)); + } // Try go.mod if let Ok(content) = fs::read_to_string(self.project_root.join("go.mod")) && let Some(line) = content.lines().next() - && line.starts_with("module ") { - let name = line - .trim_start_matches("module ") - .split('/') - .next_back() - .unwrap_or("") - .to_string(); - if !name.is_empty() { - return Ok(Some(name)); - } - } + && line.starts_with("module ") + { + let name = line + .trim_start_matches("module ") + .split('/') + .next_back() + .unwrap_or("") + .to_string(); + if !name.is_empty() { + return Ok(Some(name)); + } + } // Fall back to directory name Ok(self @@ -729,17 +734,18 @@ impl ContextCapture { for test_dir in test_dirs { let test_path = self.project_root.join(test_dir); if test_path.exists() - && let Ok(entries) = fs::read_dir(&test_path) { - for entry in entries.filter_map(|e| e.ok()) { - let entry_path = entry.path(); - if let Some(entry_stem) = entry_path.file_stem() { - let entry_stem = entry_stem.to_string_lossy(); - if entry_stem.contains(&stem) { - related.push(entry_path); - } + && let Ok(entries) = fs::read_dir(&test_path) + { + for entry in entries.filter_map(|e| e.ok()) { + let entry_path = entry.path(); + if let Some(entry_stem) = entry_path.file_stem() { + let entry_stem = entry_stem.to_string_lossy(); + if entry_stem.contains(&stem) { + related.push(entry_path); } } } + } } // For Rust, look for mod.rs in same directory @@ -794,38 +800,40 @@ impl ContextCapture { // For Rust, use the parent directory name relative to src/ if path.extension().map(|e| e == "rs").unwrap_or(false) && let Ok(relative) = path.strip_prefix(&self.project_root) - && let Ok(src_relative) = relative.strip_prefix("src") { - // Get the module path - let components: Vec<_> = src_relative - .parent()? - .components() - .map(|c| c.as_os_str().to_string_lossy().to_string()) - .collect(); + && let Ok(src_relative) = relative.strip_prefix("src") + { + // Get the module path + let components: Vec<_> = src_relative + .parent()? + .components() + .map(|c| c.as_os_str().to_string_lossy().to_string()) + .collect(); - if !components.is_empty() { - return Some(components.join("::")); - } - } + if !components.is_empty() { + return Some(components.join("::")); + } + } // For TypeScript/JavaScript, use the parent directory if path .extension() .map(|e| e == "ts" || e == "tsx" || e == "js" || e == "jsx") .unwrap_or(false) - && let Ok(relative) = path.strip_prefix(&self.project_root) { - // Skip src/ or lib/ prefix - let relative = relative - .strip_prefix("src") - .or_else(|_| relative.strip_prefix("lib")) - .unwrap_or(relative); + && let Ok(relative) = path.strip_prefix(&self.project_root) + { + // Skip src/ or lib/ prefix + let relative = relative + .strip_prefix("src") + .or_else(|_| relative.strip_prefix("lib")) + .unwrap_or(relative); - if let Some(parent) = relative.parent() { - let module = parent.to_string_lossy().replace('/', "."); - if !module.is_empty() { - return Some(module); - } + if let Some(parent) = relative.parent() { + let module = parent.to_string_lossy().replace('/', "."); + if !module.is_empty() { + return Some(module); } } + } None } @@ -865,10 +873,11 @@ impl ContextCapture { let trimmed = line.trim(); if (trimmed.starts_with(&format!("{} ", key)) || trimmed.starts_with(&format!("{}=", key))) - && let Some(value) = trimmed.split('=').nth(1) { - let value = value.trim().trim_matches('"').trim_matches('\''); - return Some(value.to_string()); - } + && let Some(value) = trimmed.split('=').nth(1) + { + let value = value.trim().trim_matches('"').trim_matches('\''); + return Some(value.to_string()); + } } None } diff --git a/crates/vestige-core/src/codebase/git.rs b/crates/vestige-core/src/codebase/git.rs index 2b7e21d..ea4fdae 100644 --- a/crates/vestige-core/src/codebase/git.rs +++ b/crates/vestige-core/src/codebase/git.rs @@ -275,9 +275,10 @@ impl GitAnalyzer { files.push(path.to_path_buf()); } if let Some(path) = delta.old_file().path() - && !files.contains(&path.to_path_buf()) { - files.push(path.to_path_buf()); - } + && !files.contains(&path.to_path_buf()) + { + files.push(path.to_path_buf()); + } } } @@ -408,7 +409,11 @@ impl GitAnalyzer { } // Sort by strength - relationships.sort_by(|a, b| b.strength.partial_cmp(&a.strength).unwrap_or(std::cmp::Ordering::Equal)); + relationships.sort_by(|a, b| { + b.strength + .partial_cmp(&a.strength) + .unwrap_or(std::cmp::Ordering::Equal) + }); Ok(relationships) } @@ -492,9 +497,10 @@ impl GitAnalyzer { .unwrap_or_else(Utc::now); if let Some(since_time) = since - && commit_time < since_time { - continue; - } + && commit_time < since_time + { + continue; + } let message = commit.message().map(|m| m.to_string()).unwrap_or_default(); @@ -541,7 +547,12 @@ impl GitAnalyzer { let symptom = if let Some(colon_byte_pos) = first_line.find(':') { // Convert byte position to char position for safe slicing let colon_char_pos = first_line[..colon_byte_pos].chars().count(); - first_line.chars().skip(colon_char_pos + 1).collect::().trim().to_string() + first_line + .chars() + .skip(colon_char_pos + 1) + .collect::() + .trim() + .to_string() } else { first_line.to_string() }; diff --git a/crates/vestige-core/src/codebase/patterns.rs b/crates/vestige-core/src/codebase/patterns.rs index ae9e972..e6835b0 100644 --- a/crates/vestige-core/src/codebase/patterns.rs +++ b/crates/vestige-core/src/codebase/patterns.rs @@ -210,18 +210,23 @@ impl PatternDetector { for pattern in relevant_patterns { if let Some(confidence) = self.calculate_match_confidence(code, &code_lower, pattern) - && confidence >= 0.3 { - matches.push(PatternMatch { - pattern: pattern.clone(), - confidence, - location: None, // Would need line-level analysis - suggestions: self.generate_suggestions(pattern, code), - }); - } + && confidence >= 0.3 + { + matches.push(PatternMatch { + pattern: pattern.clone(), + confidence, + location: None, // Would need line-level analysis + suggestions: self.generate_suggestions(pattern, code), + }); + } } // Sort by confidence - matches.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap_or(std::cmp::Ordering::Equal)); + matches.sort_by(|a, b| { + b.confidence + .partial_cmp(&a.confidence) + .unwrap_or(std::cmp::Ordering::Equal) + }); Ok(matches) } @@ -325,7 +330,11 @@ impl PatternDetector { } // Sort by relevance - suggestions.sort_by(|a, b| b.relevance.partial_cmp(&a.relevance).unwrap_or(std::cmp::Ordering::Equal)); + suggestions.sort_by(|a, b| { + b.relevance + .partial_cmp(&a.relevance) + .unwrap_or(std::cmp::Ordering::Equal) + }); Ok(suggestions) } diff --git a/crates/vestige-core/src/codebase/relationships.rs b/crates/vestige-core/src/codebase/relationships.rs index 8430756..b2a8644 100644 --- a/crates/vestige-core/src/codebase/relationships.rs +++ b/crates/vestige-core/src/codebase/relationships.rs @@ -630,9 +630,7 @@ mod tests { let related = tracker.get_related_files(Path::new("src/main.rs")).unwrap(); assert!(!related.is_empty()); - assert!(related - .iter() - .any(|r| r.path == PathBuf::from("src/lib.rs"))); + assert!(related.iter().any(|r| r.path == Path::new("src/lib.rs"))); } #[test] diff --git a/crates/vestige-core/src/codebase/types.rs b/crates/vestige-core/src/codebase/types.rs index 802ad29..4abbff1 100644 --- a/crates/vestige-core/src/codebase/types.rs +++ b/crates/vestige-core/src/codebase/types.rs @@ -221,7 +221,6 @@ pub enum DecisionStatus { Deprecated, } - // ============================================================================ // BUG FIX // ============================================================================ @@ -273,7 +272,6 @@ pub enum BugSeverity { Trivial, } - // ============================================================================ // CODE PATTERN // ============================================================================ diff --git a/crates/vestige-core/src/codebase/watcher.rs b/crates/vestige-core/src/codebase/watcher.rs index 187bb72..c69ad81 100644 --- a/crates/vestige-core/src/codebase/watcher.rs +++ b/crates/vestige-core/src/codebase/watcher.rs @@ -10,13 +10,13 @@ use std::collections::HashSet; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use chrono::{DateTime, Utc}; use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; -use tokio::sync::{broadcast, mpsc, RwLock}; +use tokio::sync::{RwLock, broadcast, mpsc}; use super::patterns::PatternDetector; use super::relationships::RelationshipTracker; @@ -576,11 +576,12 @@ impl ManualEventHandler { // Detect patterns if self.config.detect_patterns - && let Ok(content) = std::fs::read_to_string(path) { - let language = CodebaseWatcher::detect_language(path); - let detector = self.detector.read().await; - let _ = detector.detect_patterns(&content, &language); - } + && let Ok(content) = std::fs::read_to_string(path) + { + let language = CodebaseWatcher::detect_language(path); + let detector = self.detector.read().await; + let _ = detector.detect_patterns(&content, &language); + } Ok(()) } diff --git a/crates/vestige-core/src/consolidation/mod.rs b/crates/vestige-core/src/consolidation/mod.rs index dbae9b2..8a7aa94 100644 --- a/crates/vestige-core/src/consolidation/mod.rs +++ b/crates/vestige-core/src/consolidation/mod.rs @@ -7,12 +7,11 @@ //! - Prune very weak memories (optional) //! - 4-Phase biologically-accurate dream cycle (v2.0) -mod sleep; pub mod phases; +mod sleep; -pub use sleep::SleepConsolidation; pub use phases::{ - DreamEngine, DreamPhase, FourPhaseDreamResult, PhaseResult, - TriagedMemory, TriageCategory, CreativeConnection, CreativeConnectionType, - DreamInsight, + CreativeConnection, CreativeConnectionType, DreamEngine, DreamInsight, DreamPhase, + FourPhaseDreamResult, PhaseResult, TriageCategory, TriagedMemory, }; +pub use sleep::SleepConsolidation; diff --git a/crates/vestige-core/src/consolidation/phases.rs b/crates/vestige-core/src/consolidation/phases.rs index bc50e56..abf6019 100644 --- a/crates/vestige-core/src/consolidation/phases.rs +++ b/crates/vestige-core/src/consolidation/phases.rs @@ -18,7 +18,7 @@ use std::time::Instant; use chrono::{DateTime, Utc}; use crate::memory::KnowledgeNode; -use crate::neuroscience::emotional_memory::{EmotionalMemory, EmotionCategory}; +use crate::neuroscience::emotional_memory::{EmotionCategory, EmotionalMemory}; use crate::neuroscience::importance_signals::ImportanceSignals; use crate::neuroscience::synaptic_tagging::SynapticTaggingSystem; @@ -197,13 +197,11 @@ impl DreamEngine { phases.push(phase2); // ==================== PHASE 3: REM (Creative) ==================== - let (connections, emotional_processed, phase3) = - self.phase_rem(&triaged, emotional_memory); + let (connections, emotional_processed, phase3) = self.phase_rem(&triaged, emotional_memory); phases.push(phase3); // ==================== PHASE 4: Integration ==================== - let (insights, phase4) = - self.phase_integration(&connections, &triaged); + let (insights, phase4) = self.phase_integration(&connections, &triaged); phases.push(phase4); FourPhaseDreamResult { @@ -262,26 +260,31 @@ impl DreamEngine { } // Sort by importance (highest first) - triaged.sort_by(|a, b| b.importance.partial_cmp(&a.importance).unwrap_or(std::cmp::Ordering::Equal)); + triaged.sort_by(|a, b| { + b.importance + .partial_cmp(&a.importance) + .unwrap_or(std::cmp::Ordering::Equal) + }); // Build replay queue: 70% high-value, 30% random noise floor let high_value_count = (triaged.len() as f64 * self.high_value_ratio).ceil() as usize; let random_count = triaged.len().saturating_sub(high_value_count); - let mut replay_queue: Vec = triaged.iter() + let mut replay_queue: Vec = triaged + .iter() .take(high_value_count) .map(|m| m.id.clone()) .collect(); // Add random noise floor from the remaining memories if random_count > 0 { - let remaining: Vec<&TriagedMemory> = triaged.iter() - .skip(high_value_count) - .collect(); + let remaining: Vec<&TriagedMemory> = triaged.iter().skip(high_value_count).collect(); // Simple deterministic shuffle using content hash let mut noise: Vec<&TriagedMemory> = remaining; noise.sort_by_key(|m| { - let hash: u64 = m.id.bytes().fold(0u64, |acc, b| acc.wrapping_mul(31).wrapping_add(b as u64)); + let hash: u64 = + m.id.bytes() + .fold(0u64, |acc, b| acc.wrapping_mul(31).wrapping_add(b as u64)); hash }); for m in noise.iter().take(random_count) { @@ -307,7 +310,9 @@ impl DreamEngine { actions.push(format!( "Replay queue: {} high-value + {} noise = {} total", high_value_count.min(triaged.len()), - replay_queue.len().saturating_sub(high_value_count.min(triaged.len())), + replay_queue + .len() + .saturating_sub(high_value_count.min(triaged.len())), replay_queue.len() )); @@ -333,16 +338,25 @@ impl DreamEngine { emotion: &EmotionCategory, ) -> TriageCategory { // High emotional content - if matches!(emotion, EmotionCategory::Frustration | EmotionCategory::Urgency | EmotionCategory::Joy | EmotionCategory::Surprise) - && node.sentiment_magnitude > 0.4 { - return TriageCategory::Emotional; - } + if matches!( + emotion, + EmotionCategory::Frustration + | EmotionCategory::Urgency + | EmotionCategory::Joy + | EmotionCategory::Surprise + ) && node.sentiment_magnitude > 0.4 + { + return TriageCategory::Emotional; + } // Future-relevant (intentions, TODOs) let content_lower = node.content.to_lowercase(); - if content_lower.contains("todo") || content_lower.contains("remind") - || content_lower.contains("intention") || content_lower.contains("next time") - || content_lower.contains("plan to") { + if content_lower.contains("todo") + || content_lower.contains("remind") + || content_lower.contains("intention") + || content_lower.contains("next time") + || content_lower.contains("plan to") + { return TriageCategory::FutureRelevant; } @@ -403,7 +417,8 @@ impl DreamEngine { actions.push(format!( "Processed {} waves of {} memories", - wave_count, replay_queue.len() + wave_count, + replay_queue.len() )); actions.push(format!( "Strengthened {} memories via synaptic tagging", @@ -459,7 +474,11 @@ impl DreamEngine { // Group memories by primary tag for cross-domain pairing let mut tag_groups: HashMap> = HashMap::new(); for tm in triaged { - let primary_tag = tm.tags.first().cloned().unwrap_or_else(|| "untagged".to_string()); + let primary_tag = tm + .tags + .first() + .cloned() + .unwrap_or_else(|| "untagged".to_string()); tag_groups.entry(primary_tag).or_default().push(tm); } @@ -487,7 +506,11 @@ impl DreamEngine { if similarity > self.min_insight_confidence { let conn_type = self.classify_connection(mem_a, mem_b, similarity); let insight = self.generate_connection_insight( - mem_a, mem_b, &tag_keys[i], &tag_keys[j], conn_type, + mem_a, + mem_b, + &tag_keys[i], + &tag_keys[j], + conn_type, ); connections.push(CreativeConnection { @@ -531,7 +554,10 @@ impl DreamEngine { // Pattern extraction: find repeated patterns across memories let pattern_count = self.extract_patterns(triaged, &mut connections); if pattern_count > 0 { - actions.push(format!("Pattern extraction: {} shared patterns found", pattern_count)); + actions.push(format!( + "Pattern extraction: {} shared patterns found", + pattern_count + )); } let phase = PhaseResult { @@ -545,11 +571,13 @@ impl DreamEngine { } fn content_similarity(&self, a: &str, b: &str) -> f64 { - let words_a: HashSet<&str> = a.split_whitespace() + let words_a: HashSet<&str> = a + .split_whitespace() .map(|w| w.trim_matches(|c: char| !c.is_alphanumeric())) .filter(|w| w.len() > 3) .collect(); - let words_b: HashSet<&str> = b.split_whitespace() + let words_b: HashSet<&str> = b + .split_whitespace() .map(|w| w.trim_matches(|c: char| !c.is_alphanumeric())) .filter(|w| w.len() > 3) .collect(); @@ -598,8 +626,16 @@ impl DreamEngine { tag_b: &str, conn_type: CreativeConnectionType, ) -> String { - let a_summary = if a.content.len() > 60 { &a.content[..60] } else { &a.content }; - let b_summary = if b.content.len() > 60 { &b.content[..60] } else { &b.content }; + let a_summary = if a.content.len() > 60 { + &a.content[..60] + } else { + &a.content + }; + let b_summary = if b.content.len() > 60 { + &b.content[..60] + } else { + &b.content + }; match conn_type { CreativeConnectionType::CrossDomain => { @@ -638,7 +674,9 @@ impl DreamEngine { let mut bigram_index: HashMap<(String, String), Vec> = HashMap::new(); for (idx, tm) in triaged.iter().enumerate() { - let words: Vec = tm.content.split_whitespace() + let words: Vec = tm + .content + .split_whitespace() .map(|w| w.to_lowercase()) .filter(|w| w.len() > 3) .collect(); @@ -656,18 +694,21 @@ impl DreamEngine { pattern_count += 1; // Create a connection between the first and last memory sharing this pattern if let (Some(&first), Some(&last)) = (indices.first(), indices.last()) - && first != last { - connections.push(CreativeConnection { - memory_a_id: triaged[first].id.clone(), - memory_b_id: triaged[last].id.clone(), - insight: format!( - "Shared pattern '{} {}' found across {} memories", - bigram.0, bigram.1, indices.len() - ), - confidence: (indices.len() as f64 / triaged.len() as f64).min(1.0), - connection_type: CreativeConnectionType::CrossDomain, - }); - } + && first != last + { + connections.push(CreativeConnection { + memory_a_id: triaged[first].id.clone(), + memory_b_id: triaged[last].id.clone(), + insight: format!( + "Shared pattern '{} {}' found across {} memories", + bigram.0, + bigram.1, + indices.len() + ), + confidence: (indices.len() as f64 / triaged.len() as f64).min(1.0), + connection_type: CreativeConnectionType::CrossDomain, + }); + } } } @@ -692,7 +733,8 @@ impl DreamEngine { let mut actions = Vec::new(); // Validate connections: keep only those above threshold - let valid_connections: Vec<&CreativeConnection> = connections.iter() + let valid_connections: Vec<&CreativeConnection> = connections + .iter() .filter(|c| c.confidence >= self.validation_threshold) .collect(); @@ -739,7 +781,9 @@ impl DreamEngine { insights.sort_by(|a, b| { let score_a = a.confidence * a.novelty; let score_b = b.confidence * b.novelty; - score_b.partial_cmp(&score_a).unwrap_or(std::cmp::Ordering::Equal) + score_b + .partial_cmp(&score_a) + .unwrap_or(std::cmp::Ordering::Equal) }); // Cap at 20 insights @@ -753,7 +797,10 @@ impl DreamEngine { } else { triaged.iter().map(|m| m.retention_strength).sum::() / triaged.len() as f64 }; - actions.push(format!("Average retention across dreamed memories: {:.2}", avg_retention)); + actions.push(format!( + "Average retention across dreamed memories: {:.2}", + avg_retention + )); let phase = PhaseResult { phase: DreamPhase::Integration, @@ -840,6 +887,8 @@ mod tests { temporal_level: None, has_embedding: None, embedding_model: None, + suppression_count: 0, + suppressed_at: None, } } @@ -863,13 +912,15 @@ mod tests { let importance = ImportanceSignals::new(); let mut synaptic = SynapticTaggingSystem::new(); - let memories: Vec = (0..10).map(|i| { - make_test_node( - &format!("mem-{}", i), - &format!("Test memory content for dream cycle number {}", i), - &["test"], - ) - }).collect(); + let memories: Vec = (0..10) + .map(|i| { + make_test_node( + &format!("mem-{}", i), + &format!("Test memory content for dream cycle number {}", i), + &["test"], + ) + }) + .collect(); let result = engine.run(&memories, &mut emotional, &importance, &mut synaptic); @@ -890,7 +941,11 @@ mod tests { let memories = vec![ make_emotional_node("emo-1", "Critical production crash error panic!", 0.9), - make_test_node("future-1", "TODO: remind me to add caching next time", &["planning"]), + make_test_node( + "future-1", + "TODO: remind me to add caching next time", + &["planning"], + ), make_test_node("standard-1", "The function returns a string", &["docs"]), ]; @@ -915,13 +970,15 @@ mod tests { let mut emotional = EmotionalMemory::new(); let importance = ImportanceSignals::new(); - let memories: Vec = (0..20).map(|i| { - make_test_node( - &format!("mem-{}", i), - &format!("Memory with varying importance content {}", i), - &["test"], - ) - }).collect(); + let memories: Vec = (0..20) + .map(|i| { + make_test_node( + &format!("mem-{}", i), + &format!("Memory with varying importance content {}", i), + &["test"], + ) + }) + .collect(); let (_triaged, queue, _phase) = engine.phase_nrem1(&memories, &mut emotional, &importance); @@ -934,8 +991,8 @@ mod tests { let engine = DreamEngine::new(); let mut synaptic = SynapticTaggingSystem::new(); - let triaged: Vec = (0..10).map(|i| { - TriagedMemory { + let triaged: Vec = (0..10) + .map(|i| TriagedMemory { id: format!("mem-{}", i), content: format!("Test memory {}", i), importance: 0.5, @@ -945,8 +1002,8 @@ mod tests { retention_strength: 0.7, emotional_valence: 0.0, is_flashbulb: false, - } - }).collect(); + }) + .collect(); let replay_queue: Vec = triaged.iter().map(|m| m.id.clone()).collect(); @@ -1031,7 +1088,10 @@ mod tests { assert_eq!(phase.phase, DreamPhase::Rem); // Should find connection via shared "error handling" and "pattern" words - assert!(!connections.is_empty(), "Should find cross-domain error handling pattern"); + assert!( + !connections.is_empty(), + "Should find cross-domain error handling pattern" + ); } #[test] @@ -1039,23 +1099,25 @@ mod tests { let engine = DreamEngine::new(); let mut emotional = EmotionalMemory::new(); - let triaged = vec![ - TriagedMemory { - id: "angry-1".to_string(), - content: "Critical production error crashed the entire system".to_string(), - importance: 0.8, - category: TriageCategory::Emotional, - tags: vec!["incident".to_string()], - created_at: Utc::now(), - retention_strength: 0.9, - emotional_valence: -0.8, - is_flashbulb: false, - }, - ]; + let triaged = vec![TriagedMemory { + id: "angry-1".to_string(), + content: "Critical production error crashed the entire system".to_string(), + importance: 0.8, + category: TriageCategory::Emotional, + tags: vec!["incident".to_string()], + created_at: Utc::now(), + retention_strength: 0.9, + emotional_valence: -0.8, + is_flashbulb: false, + }]; - let (_connections, emotional_processed, _phase) = engine.phase_rem(&triaged, &mut emotional); + let (_connections, emotional_processed, _phase) = + engine.phase_rem(&triaged, &mut emotional); - assert_eq!(emotional_processed, 1, "Negative emotional memory should be processed"); + assert_eq!( + emotional_processed, 1, + "Negative emotional memory should be processed" + ); } #[test] @@ -1120,7 +1182,11 @@ mod tests { "error handling with Result type pattern", "error handling with try-catch pattern", ); - assert!(sim > 0.2, "Similar content should have >0.2 Jaccard: {}", sim); + assert!( + sim > 0.2, + "Similar content should have >0.2 Jaccard: {}", + sim + ); let dissim = engine.content_similarity( "Rust memory management with ownership", @@ -1151,16 +1217,19 @@ mod tests { let importance = ImportanceSignals::new(); let mut synaptic = SynapticTaggingSystem::new(); - let memories: Vec = (0..5).map(|i| { - make_test_node(&format!("m{}", i), &format!("Content {}", i), &["test"]) - }).collect(); + let memories: Vec = (0..5) + .map(|i| make_test_node(&format!("m{}", i), &format!("Content {}", i), &["test"])) + .collect(); let result = engine.run(&memories, &mut emotional, &importance, &mut synaptic); for phase in &result.phases { // Duration should be non-negative (might be 0ms for fast operations) assert!(phase.duration_ms < 10000); - assert!(!phase.actions.is_empty(), "Each phase should report actions"); + assert!( + !phase.actions.is_empty(), + "Each phase should report actions" + ); } } @@ -1170,7 +1239,11 @@ mod tests { let mut emotional = EmotionalMemory::new(); let importance = ImportanceSignals::new(); - let mut node = make_test_node("flash-1", "CRITICAL: Production server crash! Emergency rollback needed immediately!", &["incident"]); + let mut node = make_test_node( + "flash-1", + "CRITICAL: Production server crash! Emergency rollback needed immediately!", + &["incident"], + ); node.sentiment_magnitude = 0.9; let (triaged, _queue, phase) = engine.phase_nrem1(&[node], &mut emotional, &importance); diff --git a/crates/vestige-core/src/embeddings/mod.rs b/crates/vestige-core/src/embeddings/mod.rs index 29eb300..5d89c10 100644 --- a/crates/vestige-core/src/embeddings/mod.rs +++ b/crates/vestige-core/src/embeddings/mod.rs @@ -15,8 +15,8 @@ mod local; pub(crate) use local::get_cache_dir; pub use local::{ - cosine_similarity, dot_product, euclidean_distance, matryoshka_truncate, Embedding, - EmbeddingError, EmbeddingService, BATCH_SIZE, EMBEDDING_DIMENSIONS, MAX_TEXT_LENGTH, + BATCH_SIZE, EMBEDDING_DIMENSIONS, Embedding, EmbeddingError, EmbeddingService, MAX_TEXT_LENGTH, + cosine_similarity, dot_product, euclidean_distance, matryoshka_truncate, }; pub use code::CodeEmbedding; diff --git a/crates/vestige-core/src/fsrs/algorithm.rs b/crates/vestige-core/src/fsrs/algorithm.rs index 5973e08..2e85832 100644 --- a/crates/vestige-core/src/fsrs/algorithm.rs +++ b/crates/vestige-core/src/fsrs/algorithm.rs @@ -348,7 +348,8 @@ mod tests { #[test] fn test_fsrs6_constants() { assert_eq!(FSRS6_WEIGHTS.len(), 21); - assert!(FSRS6_WEIGHTS[20] > 0.0 && FSRS6_WEIGHTS[20] < 1.0); + let w20 = FSRS6_WEIGHTS[20]; + assert!(w20 > 0.0 && w20 < 1.0); } #[test] diff --git a/crates/vestige-core/src/fsrs/mod.rs b/crates/vestige-core/src/fsrs/mod.rs index 36a0ddc..f882c66 100644 --- a/crates/vestige-core/src/fsrs/mod.rs +++ b/crates/vestige-core/src/fsrs/mod.rs @@ -19,6 +19,14 @@ mod optimizer; mod scheduler; pub use algorithm::{ + DEFAULT_DECAY, + DEFAULT_RETENTION, + // Constants + FSRS6_WEIGHTS, + MAX_DIFFICULTY, + MAX_STABILITY, + MIN_DIFFICULTY, + MIN_STABILITY, apply_sentiment_boost, fuzz_interval, initial_difficulty, @@ -38,14 +46,6 @@ pub use algorithm::{ retrievability_with_decay, same_day_stability, same_day_stability_with_weights, - DEFAULT_DECAY, - DEFAULT_RETENTION, - // Constants - FSRS6_WEIGHTS, - MAX_DIFFICULTY, - MAX_STABILITY, - MIN_DIFFICULTY, - MIN_STABILITY, }; pub use scheduler::{ diff --git a/crates/vestige-core/src/fsrs/optimizer.rs b/crates/vestige-core/src/fsrs/optimizer.rs index 90d5be0..59fcacf 100644 --- a/crates/vestige-core/src/fsrs/optimizer.rs +++ b/crates/vestige-core/src/fsrs/optimizer.rs @@ -3,7 +3,7 @@ //! Personalizes FSRS parameters based on user review history. //! Uses gradient-free optimization to minimize prediction error. -use super::algorithm::{retrievability_with_decay, FSRS6_WEIGHTS}; +use super::algorithm::{FSRS6_WEIGHTS, retrievability_with_decay}; use chrono::{DateTime, Utc}; // ============================================================================ diff --git a/crates/vestige-core/src/fsrs/scheduler.rs b/crates/vestige-core/src/fsrs/scheduler.rs index 1c7edc7..e5ab0d6 100644 --- a/crates/vestige-core/src/fsrs/scheduler.rs +++ b/crates/vestige-core/src/fsrs/scheduler.rs @@ -7,11 +7,10 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use super::algorithm::{ - apply_sentiment_boost, fuzz_interval, initial_difficulty_with_weights, - initial_stability_with_weights, next_difficulty_with_weights, + DEFAULT_RETENTION, FSRS6_WEIGHTS, MAX_STABILITY, apply_sentiment_boost, fuzz_interval, + initial_difficulty_with_weights, initial_stability_with_weights, next_difficulty_with_weights, next_forget_stability_with_weights, next_interval_with_decay, next_recall_stability_with_weights, retrievability_with_decay, same_day_stability_with_weights, - DEFAULT_RETENTION, FSRS6_WEIGHTS, MAX_STABILITY, }; // ============================================================================ @@ -243,13 +242,11 @@ impl FSRSScheduler { // Apply sentiment boost if self.enable_sentiment_boost && let Some(sentiment) = sentiment_boost - && sentiment > 0.0 { - new_state.stability = apply_sentiment_boost( - new_state.stability, - sentiment, - self.max_sentiment_boost, - ); - } + && sentiment > 0.0 + { + new_state.stability = + apply_sentiment_boost(new_state.stability, sentiment, self.max_sentiment_boost); + } let mut interval = next_interval_with_decay(new_state.stability, self.params.desired_retention, w20) @@ -436,9 +433,11 @@ mod tests { #[test] fn test_custom_parameters() { - let mut params = FSRSParameters::default(); - params.desired_retention = 0.85; - params.enable_fuzz = false; + let params = FSRSParameters { + desired_retention: 0.85, + enable_fuzz: false, + ..FSRSParameters::default() + }; let scheduler = FSRSScheduler::new(params); let card = scheduler.new_card(); diff --git a/crates/vestige-core/src/fts.rs b/crates/vestige-core/src/fts.rs index c3d0752..e4cadfb 100644 --- a/crates/vestige-core/src/fts.rs +++ b/crates/vestige-core/src/fts.rs @@ -84,10 +84,7 @@ mod tests { #[test] fn test_sanitize_fts5_query_special_chars() { assert_eq!(sanitize_fts5_query("hello* world"), "\"hello world\""); - assert_eq!( - sanitize_fts5_query("content:secret"), - "\"content secret\"" - ); + assert_eq!(sanitize_fts5_query("content:secret"), "\"content secret\""); assert_eq!(sanitize_fts5_query("^boost"), "\"boost\""); } diff --git a/crates/vestige-core/src/lib.rs b/crates/vestige-core/src/lib.rs index d0bcd0b..306b2d2 100644 --- a/crates/vestige-core/src/lib.rs +++ b/crates/vestige-core/src/lib.rs @@ -114,20 +114,27 @@ pub mod neuroscience; // Memory types pub use memory::{ - ConsolidationResult, EmbeddingResult, IngestInput, KnowledgeNode, MatchType, MemoryStats, - NodeType, RecallInput, SearchMode, SearchResult, SimilarityResult, TemporalRange, + ConsolidationResult, // GOD TIER 2026: New types - EdgeType, KnowledgeEdge, MemoryScope, MemorySystem, + EdgeType, + EmbeddingResult, + IngestInput, + KnowledgeEdge, + KnowledgeNode, + MatchType, + MemoryScope, + MemoryStats, + MemorySystem, + NodeType, + RecallInput, + SearchMode, + SearchResult, + SimilarityResult, + TemporalRange, }; // FSRS-6 algorithm pub use fsrs::{ - initial_difficulty, - initial_stability, - next_interval, - // Core functions for advanced usage - retrievability, - retrievability_with_decay, FSRSParameters, FSRSScheduler, FSRSState, @@ -135,6 +142,12 @@ pub use fsrs::{ PreviewResults, Rating, ReviewResult, + initial_difficulty, + initial_stability, + next_interval, + // Core functions for advanced usage + retrievability, + retrievability_with_decay, }; // Storage layer @@ -146,9 +159,8 @@ pub use storage::{ // Consolidation (sleep-inspired memory processing) pub use consolidation::SleepConsolidation; pub use consolidation::{ - DreamEngine, DreamPhase, FourPhaseDreamResult, PhaseResult, - TriagedMemory, TriageCategory, CreativeConnection, CreativeConnectionType, - DreamInsight, + CreativeConnection, CreativeConnectionType, DreamEngine, DreamInsight, DreamPhase, + FourPhaseDreamResult, PhaseResult, TriageCategory, TriagedMemory, }; // Advanced features (bleeding edge 2026) @@ -162,6 +174,8 @@ pub use advanced::{ AdaptiveEmbedder, ApplicableKnowledge, AppliedModification, + // Prediction Error Gating (solves bad vs good similar memory problem) + CandidateMemory, ChainStep, ChangeSummary, CompressedMemory, @@ -175,16 +189,20 @@ pub use advanced::{ // Sleep consolidation (automatic background consolidation) ConsolidationScheduler, ContentType, + CreateReason, // Cross-project learning CrossProjectLearner, DetectedIntent, + DiscoveredConnection, + DiscoveredConnectionType, DreamConfig, // DreamMemory - input type for dreaming DreamMemory, - DiscoveredConnection, - DiscoveredConnectionType, DreamResult, EmbeddingStrategy, + EvaluationIntent, + GateDecision, + GateStats, ImportanceDecayConfig, ImportanceScore, // Importance tracking @@ -204,11 +222,14 @@ pub use advanced::{ MemoryPath, MemoryReplay, MemorySnapshot, + MergeStrategy, Modification, Pattern, PatternType, PredictedMemory, PredictionContext, + PredictionErrorConfig, + PredictionErrorGate, ProjectContext, ReasoningChain, ReconsolidatedMemory, @@ -217,25 +238,16 @@ pub use advanced::{ ReconsolidationStats, RelationshipType, RetrievalRecord, + SimilarityResult as PredictionSimilarityResult, // Speculative retrieval SpeculativeRetriever, + SupersedeReason, SynthesizedInsight, UniversalPattern, + UpdateType, UsageEvent, UsagePattern, UserAction, - // Prediction Error Gating (solves bad vs good similar memory problem) - CandidateMemory, - CreateReason, - EvaluationIntent, - GateDecision, - GateStats, - MergeStrategy, - PredictionErrorConfig, - PredictionErrorGate, - SimilarityResult as PredictionSimilarityResult, - SupersedeReason, - UpdateType, }; // Codebase memory (Vestige's killer differentiator) @@ -315,14 +327,20 @@ pub use neuroscience::{ ContextReinstatement, ContextWeights, DecayFunction, + // Emotional Memory (Brown & Kulik 1977, Bower 1981, LaBar & Cabeza 2006) + EmotionCategory, EmotionalContext, + EmotionalEvaluation, EmotionalMarker, + EmotionalMemory, + EmotionalMemoryStats, EncodingContext, FullMemory, // Hippocampal Indexing (Teyler & Rudy, 2007) HippocampalIndex, HippocampalIndexConfig, HippocampalIndexError, + INDEX_EMBEDDING_DIM, ImportanceCluster, ImportanceConsolidationConfig, ImportanceEncodingConfig, @@ -374,40 +392,34 @@ pub use neuroscience::{ TemporalMarker, TimeOfDay, TopicalContext, - INDEX_EMBEDDING_DIM, - // Emotional Memory (Brown & Kulik 1977, Bower 1981, LaBar & Cabeza 2006) - EmotionCategory, - EmotionalEvaluation, - EmotionalMemory, - EmotionalMemoryStats, }; // Embeddings (when feature enabled) #[cfg(feature = "embeddings")] pub use embeddings::{ - cosine_similarity, euclidean_distance, Embedding, EmbeddingError, EmbeddingService, - EMBEDDING_DIMENSIONS, + EMBEDDING_DIMENSIONS, Embedding, EmbeddingError, EmbeddingService, cosine_similarity, + euclidean_distance, }; // Search (when feature enabled) #[cfg(feature = "vector-search")] pub use search::{ - linear_combination, - reciprocal_rank_fusion, HybridSearchConfig, // Hybrid search HybridSearcher, // Keyword search KeywordSearcher, - VectorIndex, - VectorIndexConfig, - VectorIndexStats, - VectorSearchError, + RerankedResult, // GOD TIER 2026: Reranking Reranker, RerankerConfig, RerankerError, - RerankedResult, + VectorIndex, + VectorIndexConfig, + VectorIndexStats, + VectorSearchError, + linear_combination, + reciprocal_rank_fusion, }; // ============================================================================ @@ -450,6 +462,8 @@ pub mod prelude { // Sleep consolidation ConsolidationScheduler, CrossProjectLearner, + EvaluationIntent, + GateDecision, ImportanceTracker, IntentDetector, LabileState, @@ -459,14 +473,12 @@ pub mod prelude { MemoryReplay, Modification, PredictedMemory, + // Prediction Error Gating + PredictionErrorGate, ReconsolidatedMemory, // Reconsolidation ReconsolidationManager, SpeculativeRetriever, - // Prediction Error Gating - PredictionErrorGate, - GateDecision, - EvaluationIntent, }; // Codebase memory diff --git a/crates/vestige-core/src/memory/mod.rs b/crates/vestige-core/src/memory/mod.rs index 0b5350e..e7c61d4 100644 --- a/crates/vestige-core/src/memory/mod.rs +++ b/crates/vestige-core/src/memory/mod.rs @@ -299,7 +299,6 @@ pub struct ConsolidationResult { pub w20_optimized: Option, } - // ============================================================================ // SEARCH RESULTS // ============================================================================ @@ -360,4 +359,3 @@ pub struct EmbeddingResult { /// Error messages for failures pub errors: Vec, } - diff --git a/crates/vestige-core/src/memory/node.rs b/crates/vestige-core/src/memory/node.rs index 90e672d..9785387 100644 --- a/crates/vestige-core/src/memory/node.rs +++ b/crates/vestige-core/src/memory/node.rs @@ -179,6 +179,15 @@ pub struct KnowledgeNode { /// Which model generated the embedding #[serde(skip_serializing_if = "Option::is_none")] pub embedding_model: Option, + + // ========== Active Forgetting (v2.0.5, Anderson 2025 + Davis Rac1) ========== + /// Top-down suppression count — compounds with each `suppress` call + /// (Suppression-Induced Forgetting, Anderson 2025). + #[serde(default)] + pub suppression_count: i32, + /// Timestamp of the most recent suppression (for 24h labile window). + #[serde(skip_serializing_if = "Option::is_none")] + pub suppressed_at: Option>, } impl Default for KnowledgeNode { @@ -213,6 +222,8 @@ impl Default for KnowledgeNode { temporal_level: None, has_embedding: None, embedding_model: None, + suppression_count: 0, + suppressed_at: None, } } } diff --git a/crates/vestige-core/src/neuroscience/active_forgetting.rs b/crates/vestige-core/src/neuroscience/active_forgetting.rs new file mode 100644 index 0000000..0a90769 --- /dev/null +++ b/crates/vestige-core/src/neuroscience/active_forgetting.rs @@ -0,0 +1,226 @@ +//! Active Forgetting — Top-Down Inhibitory Control of Memory (v2.0.5) +//! +//! Implements user-initiated memory suppression, distinct from passive FSRS +//! decay and from bottom-up retrieval-induced forgetting (Anderson 1994, +//! `memory_states.rs`). This module models the right-lateral-prefrontal-cortex +//! gated inhibitory pathway, where top-down cognitive control compounds with +//! each stopping attempt (Suppression-Induced Forgetting) and spreads via a +//! Rac1-GTPase-like cascade to co-activated synaptic neighbors. +//! +//! ## References +//! +//! - Anderson, M. C., Hanslmayr, S., & Quaegebeur, L. (2025). Brain mechanisms +//! underlying the inhibitory control of thought. *Nature Reviews Neuroscience*. +//! DOI: 10.1038/s41583-025-00929-y. Establishes rDLPFC as the domain-general +//! inhibitory controller; SIF scales with stopping attempts; incentive-resistant. +//! - Cervantes-Sandoval, I., Chakraborty, M., MacMullen, C., & Davis, R. L. +//! (2020). Rac1 Impairs Forgetting-Induced Cellular Plasticity in Mushroom +//! Body Output Neurons. *Front Cell Neurosci*. PMC7477079. Establishes Rac1 +//! GTPase as the active synaptic destabilization mechanism. +//! +//! ## Contrast with existing modules +//! +//! - `memory_states.rs` (Anderson 1994, RIF): BOTTOM-UP, passive consequence +//! of retrieval competition. When memory A wins a query, its competitors +//! automatically lose retrievability. +//! - `active_forgetting.rs` (Anderson 2025, SIF + Davis Rac1): TOP-DOWN, +//! user-initiated via the `suppress` MCP tool. Compounds with each call. +//! Spreads to neighbors. Reversible within a 24h labile window. + +use chrono::{DateTime, Duration, Utc}; +use serde::{Deserialize, Serialize}; + +/// Default SIF penalty coefficient per suppression increment. +pub const DEFAULT_SIF_K: f64 = 0.15; + +/// Maximum cumulative penalty from compounding suppression. +/// Matches Anderson's empirical SIF saturation. +pub const DEFAULT_MAX_PENALTY: f64 = 0.8; + +/// Cascade attenuation factor for Rac1 spreading to co-activated neighbors. +pub const DEFAULT_CASCADE_DECAY: f64 = 0.3; + +/// Labile window in hours during which a suppression may be reversed. +/// Parallels Nader's 5-minute reconsolidation window on a 24-hour axis. +pub const DEFAULT_LABILE_HOURS: i64 = 24; + +/// Maximum per-neighbor retrieval-strength decrement during cascade. +pub const DEFAULT_CASCADE_RETRIEVAL_DECREMENT_CAP: f64 = 0.15; + +/// Top-down inhibitory control over memory retrieval. +/// +/// Stateless — all persistent state lives on the `knowledge_nodes` table +/// (columns `suppression_count`, `suppressed_at`). This struct exposes pure +/// helper functions consumed by `Storage::suppress_memory`, +/// `Storage::reverse_suppression`, `Storage::apply_rac1_cascade`, and the +/// `search_unified` score adjustment stage. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ActiveForgettingSystem { + /// Penalty coefficient per suppression increment (SIF). + pub k: f64, + /// Maximum cumulative penalty cap. + pub max_penalty: f64, + /// Cascade attenuation factor for Rac1 spreading. + pub cascade_decay: f64, + /// Reversal window in hours. + pub labile_hours: i64, +} + +impl Default for ActiveForgettingSystem { + fn default() -> Self { + Self { + k: DEFAULT_SIF_K, + max_penalty: DEFAULT_MAX_PENALTY, + cascade_decay: DEFAULT_CASCADE_DECAY, + labile_hours: DEFAULT_LABILE_HOURS, + } + } +} + +impl ActiveForgettingSystem { + /// Create a new system with default parameters. + pub fn new() -> Self { + Self::default() + } + + /// Compute the retrieval-score penalty for a memory with the given + /// suppression count. Penalty grows linearly then saturates at + /// `max_penalty` (Anderson's empirical SIF ceiling). + /// + /// Applied in `search_unified` as `score *= (1.0 - penalty)`. + pub fn retrieval_penalty(&self, suppression_count: i32) -> f64 { + if suppression_count <= 0 { + return 0.0; + } + (self.k * suppression_count as f64).min(self.max_penalty) + } + + /// Return `true` if a suppression is within the labile window and + /// therefore reversible. Matches reconsolidation semantics on a 24h axis. + pub fn is_reversible(&self, suppressed_at: DateTime) -> bool { + Utc::now() - suppressed_at < Duration::hours(self.labile_hours) + } + + /// Stability multiplier to apply to a neighbor of a suppressed memory + /// during the Rac1 cascade. Stronger co-activation edges propagate more + /// decay. A 1.0 edge yields `(1 - cascade_decay)` = 0.7 by default + /// (30% stability loss per cascade hop), clamped never below 0.1. + pub fn cascade_stability_factor(&self, edge_strength: f64) -> f64 { + (1.0 - self.cascade_decay * edge_strength.clamp(0.0, 1.0)).max(0.1) + } + + /// Retrieval-strength decrement for a cascade neighbor, proportional to + /// co-activation edge strength and capped at + /// `DEFAULT_CASCADE_RETRIEVAL_DECREMENT_CAP`. + pub fn cascade_retrieval_decrement(&self, edge_strength: f64) -> f64 { + (0.05 * edge_strength.clamp(0.0, 1.0)).min(DEFAULT_CASCADE_RETRIEVAL_DECREMENT_CAP) + } + + /// Time remaining in the labile window, or `None` if expired. + pub fn remaining_labile_time(&self, suppressed_at: DateTime) -> Option { + let window = Duration::hours(self.labile_hours); + let elapsed = Utc::now() - suppressed_at; + if elapsed >= window { + None + } else { + Some(window - elapsed) + } + } + + /// Deadline timestamp after which reversal will fail. + pub fn reversible_until(&self, suppressed_at: DateTime) -> DateTime { + suppressed_at + Duration::hours(self.labile_hours) + } +} + +/// Aggregate statistics about active-forgetting state across all memories. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct SuppressionStats { + /// Total memories with suppression_count > 0. + pub total_suppressed: usize, + /// Memories suppressed within the last `labile_hours` (still reversible). + pub recently_reversible: usize, + /// Mean suppression_count across all suppressed memories. + pub avg_suppression_count: f64, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sif_penalty_compounds() { + let sys = ActiveForgettingSystem::new(); + assert_eq!(sys.retrieval_penalty(0), 0.0); + assert!((sys.retrieval_penalty(1) - 0.15).abs() < 1e-9); + assert!((sys.retrieval_penalty(2) - 0.30).abs() < 1e-9); + assert!((sys.retrieval_penalty(5) - 0.75).abs() < 1e-9); + // Saturates at max_penalty + assert!((sys.retrieval_penalty(6) - 0.80).abs() < 1e-9); + assert!((sys.retrieval_penalty(100) - 0.80).abs() < 1e-9); + } + + #[test] + fn test_labile_window_reversible() { + let sys = ActiveForgettingSystem::new(); + let recent = Utc::now() - Duration::hours(23); + assert!(sys.is_reversible(recent)); + let expired = Utc::now() - Duration::hours(25); + assert!(!sys.is_reversible(expired)); + assert!(sys.is_reversible(Utc::now())); + } + + #[test] + fn test_cascade_attenuation() { + let sys = ActiveForgettingSystem::new(); + let strong = sys.cascade_stability_factor(0.9); + let weak = sys.cascade_stability_factor(0.1); + assert!(strong < weak, "strong edges should propagate more decay"); + // Zero edge → no decay + assert!((sys.cascade_stability_factor(0.0) - 1.0).abs() < 1e-9); + // Factor never zeroes out + assert!(sys.cascade_stability_factor(1.0) >= 0.1); + } + + #[test] + fn test_default_params_reasonable() { + let sys = ActiveForgettingSystem::new(); + assert!(sys.k > 0.0 && sys.k <= 0.25, "k should be in (0, 0.25]"); + assert!( + sys.max_penalty >= 0.5 && sys.max_penalty <= 0.95, + "max_penalty should be in [0.5, 0.95]" + ); + assert!(sys.labile_hours >= 12 && sys.labile_hours <= 72); + assert!(sys.cascade_decay > 0.0 && sys.cascade_decay < 1.0); + } + + #[test] + fn test_reversible_until_deadline() { + let sys = ActiveForgettingSystem::new(); + let now = Utc::now(); + let deadline = sys.reversible_until(now); + let expected = now + Duration::hours(24); + assert!((deadline - expected).num_milliseconds().abs() < 100); + } + + #[test] + fn test_remaining_labile_time_expired_returns_none() { + let sys = ActiveForgettingSystem::new(); + let past = Utc::now() - Duration::hours(30); + assert!(sys.remaining_labile_time(past).is_none()); + let recent = Utc::now() - Duration::hours(10); + let remaining = sys.remaining_labile_time(recent); + assert!(remaining.is_some()); + // Should have ~14 hours left (24h window - 10h elapsed) + let hours_left = remaining.unwrap().num_hours(); + assert!((13..=14).contains(&hours_left)); + } + + #[test] + fn test_cascade_retrieval_decrement_capped() { + let sys = ActiveForgettingSystem::new(); + assert!((sys.cascade_retrieval_decrement(0.0) - 0.0).abs() < 1e-9); + assert!(sys.cascade_retrieval_decrement(0.5) <= DEFAULT_CASCADE_RETRIEVAL_DECREMENT_CAP); + assert!(sys.cascade_retrieval_decrement(1.0) <= DEFAULT_CASCADE_RETRIEVAL_DECREMENT_CAP); + } +} diff --git a/crates/vestige-core/src/neuroscience/context_memory.rs b/crates/vestige-core/src/neuroscience/context_memory.rs index e220f9a..d89594c 100644 --- a/crates/vestige-core/src/neuroscience/context_memory.rs +++ b/crates/vestige-core/src/neuroscience/context_memory.rs @@ -911,33 +911,38 @@ impl ContextMatcher { // Same session is a very strong match if let (Some(e_id), Some(r_id)) = (&encoding.session_id, &retrieval.session_id) - && e_id == r_id { - return 1.0; - } + && e_id == r_id + { + return 1.0; + } // Project match (0.4 weight) if let (Some(e_proj), Some(r_proj)) = (&encoding.project, &retrieval.project) - && e_proj == r_proj { - score += 0.4; - } + && e_proj == r_proj + { + score += 0.4; + } // Activity type match (0.3 weight) if let (Some(e_act), Some(r_act)) = (&encoding.activity_type, &retrieval.activity_type) - && e_act == r_act { - score += 0.3; - } + && e_act == r_act + { + score += 0.3; + } // Git branch match (0.2 weight) if let (Some(e_br), Some(r_br)) = (&encoding.git_branch, &retrieval.git_branch) - && e_br == r_br { - score += 0.2; - } + && e_br == r_br + { + score += 0.2; + } // Active file match (0.1 weight) if let (Some(e_file), Some(r_file)) = (&encoding.active_file, &retrieval.active_file) - && e_file == r_file { - score += 0.1; - } + && e_file == r_file + { + score += 0.1; + } score } @@ -985,7 +990,11 @@ impl ContextMatcher { .collect(); // Sort by combined score (descending) - scored.sort_by(|a, b| b.combined_score.partial_cmp(&a.combined_score).unwrap_or(std::cmp::Ordering::Equal)); + scored.sort_by(|a, b| { + b.combined_score + .partial_cmp(&a.combined_score) + .unwrap_or(std::cmp::Ordering::Equal) + }); scored } @@ -1103,9 +1112,11 @@ mod tests { topical.add_topic("security"); topical.extract_keywords_from("implementing OAuth2 authentication flow"); - assert!(topical - .active_topics - .contains(&"authentication".to_string())); + assert!( + topical + .active_topics + .contains(&"authentication".to_string()) + ); assert!(topical.keywords.contains(&"oauth2".to_string())); let terms = topical.all_terms(); @@ -1118,10 +1129,11 @@ mod tests { ctx.add_topic("api-design"); ctx.set_project("vestige"); - assert!(ctx - .topical - .active_topics - .contains(&"api-design".to_string())); + assert!( + ctx.topical + .active_topics + .contains(&"api-design".to_string()) + ); assert_eq!(ctx.session.project, Some("vestige".to_string())); } @@ -1137,7 +1149,11 @@ mod tests { let ctx2 = ctx1.clone(); let similarity = matcher.match_contexts(&ctx1, &ctx2); - assert!(similarity > 0.8, "Same context should have high similarity, got {}", similarity); + assert!( + similarity > 0.8, + "Same context should have high similarity, got {}", + similarity + ); } #[test] diff --git a/crates/vestige-core/src/neuroscience/emotional_memory.rs b/crates/vestige-core/src/neuroscience/emotional_memory.rs index 9fcb7de..bc5a527 100644 --- a/crates/vestige-core/src/neuroscience/emotional_memory.rs +++ b/crates/vestige-core/src/neuroscience/emotional_memory.rs @@ -216,15 +216,25 @@ impl EmotionalMemory { // Check negation context (simple window-based) let negation_words: Vec<&str> = vec![ - "not", "no", "never", "don't", "doesn't", "didn't", "won't", - "can't", "couldn't", "shouldn't", "without", "hardly", + "not", + "no", + "never", + "don't", + "doesn't", + "didn't", + "won't", + "can't", + "couldn't", + "shouldn't", + "without", + "hardly", ]; for (i, word) in words.iter().enumerate() { if let Some(&(valence, arousal)) = self.lexicon.get(word.as_str()) { // Check for negation in 3-word window before - let negated = (i.saturating_sub(3)..i) - .any(|j| negation_words.contains(&words[j].as_str())); + let negated = + (i.saturating_sub(3)..i).any(|j| negation_words.contains(&words[j].as_str())); let effective_valence = if negated { -valence * 0.7 } else { valence }; @@ -269,9 +279,14 @@ impl EmotionalMemory { }; // Flashbulb detection: high novelty proxy (urgency/surprise markers) + high arousal - let novelty_proxy = urgency_boost + if category == EmotionCategory::Surprise { 0.4 } else { 0.0 }; - let is_flashbulb = novelty_proxy >= FLASHBULB_NOVELTY_THRESHOLD - && arousal >= FLASHBULB_AROUSAL_THRESHOLD; + let novelty_proxy = urgency_boost + + if category == EmotionCategory::Surprise { + 0.4 + } else { + 0.0 + }; + let is_flashbulb = + novelty_proxy >= FLASHBULB_NOVELTY_THRESHOLD && arousal >= FLASHBULB_AROUSAL_THRESHOLD; if is_flashbulb { self.flashbulbs_detected += 1; @@ -447,66 +462,114 @@ impl EmotionalMemory { // Positive / Low arousal for (word, v, a) in [ - ("good", 0.6, 0.3), ("nice", 0.5, 0.2), ("clean", 0.4, 0.2), - ("simple", 0.3, 0.1), ("smooth", 0.4, 0.2), ("stable", 0.4, 0.1), - ("helpful", 0.5, 0.3), ("elegant", 0.6, 0.3), ("solid", 0.4, 0.2), + ("good", 0.6, 0.3), + ("nice", 0.5, 0.2), + ("clean", 0.4, 0.2), + ("simple", 0.3, 0.1), + ("smooth", 0.4, 0.2), + ("stable", 0.4, 0.1), + ("helpful", 0.5, 0.3), + ("elegant", 0.6, 0.3), + ("solid", 0.4, 0.2), ] { lex.insert(word.to_string(), (v, a)); } // Positive / High arousal for (word, v, a) in [ - ("amazing", 0.9, 0.8), ("excellent", 0.8, 0.6), ("perfect", 0.9, 0.7), - ("awesome", 0.8, 0.7), ("great", 0.7, 0.5), ("fantastic", 0.9, 0.8), - ("brilliant", 0.8, 0.7), ("incredible", 0.9, 0.8), ("love", 0.8, 0.7), - ("success", 0.7, 0.6), ("solved", 0.7, 0.6), ("fixed", 0.6, 0.5), - ("working", 0.5, 0.4), ("breakthrough", 0.9, 0.9), ("discovered", 0.7, 0.7), + ("amazing", 0.9, 0.8), + ("excellent", 0.8, 0.6), + ("perfect", 0.9, 0.7), + ("awesome", 0.8, 0.7), + ("great", 0.7, 0.5), + ("fantastic", 0.9, 0.8), + ("brilliant", 0.8, 0.7), + ("incredible", 0.9, 0.8), + ("love", 0.8, 0.7), + ("success", 0.7, 0.6), + ("solved", 0.7, 0.6), + ("fixed", 0.6, 0.5), + ("working", 0.5, 0.4), + ("breakthrough", 0.9, 0.9), + ("discovered", 0.7, 0.7), ] { lex.insert(word.to_string(), (v, a)); } // Negative / Low arousal for (word, v, a) in [ - ("bad", -0.5, 0.3), ("wrong", -0.4, 0.3), ("slow", -0.3, 0.2), - ("confusing", -0.4, 0.3), ("unclear", -0.3, 0.2), ("messy", -0.4, 0.3), - ("annoying", -0.5, 0.4), ("boring", -0.3, 0.1), ("ugly", -0.5, 0.3), - ("deprecated", -0.3, 0.2), ("stale", -0.3, 0.1), + ("bad", -0.5, 0.3), + ("wrong", -0.4, 0.3), + ("slow", -0.3, 0.2), + ("confusing", -0.4, 0.3), + ("unclear", -0.3, 0.2), + ("messy", -0.4, 0.3), + ("annoying", -0.5, 0.4), + ("boring", -0.3, 0.1), + ("ugly", -0.5, 0.3), + ("deprecated", -0.3, 0.2), + ("stale", -0.3, 0.1), ] { lex.insert(word.to_string(), (v, a)); } // Negative / High arousal (bugs, errors, failures) for (word, v, a) in [ - ("error", -0.6, 0.7), ("bug", -0.6, 0.6), ("crash", -0.8, 0.9), - ("fail", -0.7, 0.7), ("failed", -0.7, 0.7), ("failure", -0.7, 0.7), - ("broken", -0.7, 0.7), ("panic", -0.9, 0.9), ("fatal", -0.9, 0.9), - ("critical", -0.5, 0.9), ("severe", -0.6, 0.8), ("urgent", -0.3, 0.9), - ("emergency", -0.5, 0.9), ("vulnerability", -0.7, 0.8), - ("exploit", -0.7, 0.8), ("leaked", -0.8, 0.9), ("compromised", -0.8, 0.9), - ("timeout", -0.5, 0.6), ("deadlock", -0.7, 0.8), ("overflow", -0.6, 0.7), - ("corruption", -0.8, 0.8), ("regression", -0.6, 0.7), - ("blocker", -0.6, 0.8), ("outage", -0.8, 0.9), ("incident", -0.5, 0.7), + ("error", -0.6, 0.7), + ("bug", -0.6, 0.6), + ("crash", -0.8, 0.9), + ("fail", -0.7, 0.7), + ("failed", -0.7, 0.7), + ("failure", -0.7, 0.7), + ("broken", -0.7, 0.7), + ("panic", -0.9, 0.9), + ("fatal", -0.9, 0.9), + ("critical", -0.5, 0.9), + ("severe", -0.6, 0.8), + ("urgent", -0.3, 0.9), + ("emergency", -0.5, 0.9), + ("vulnerability", -0.7, 0.8), + ("exploit", -0.7, 0.8), + ("leaked", -0.8, 0.9), + ("compromised", -0.8, 0.9), + ("timeout", -0.5, 0.6), + ("deadlock", -0.7, 0.8), + ("overflow", -0.6, 0.7), + ("corruption", -0.8, 0.8), + ("regression", -0.6, 0.7), + ("blocker", -0.6, 0.8), + ("outage", -0.8, 0.9), + ("incident", -0.5, 0.7), ] { lex.insert(word.to_string(), (v, a)); } // Surprise / Discovery for (word, v, a) in [ - ("unexpected", 0.0, 0.7), ("surprising", 0.1, 0.7), - ("strange", -0.1, 0.6), ("weird", -0.2, 0.5), - ("interesting", 0.4, 0.6), ("curious", 0.3, 0.5), - ("insight", 0.6, 0.7), ("realized", 0.4, 0.6), - ("found", 0.3, 0.5), ("noticed", 0.2, 0.4), + ("unexpected", 0.0, 0.7), + ("surprising", 0.1, 0.7), + ("strange", -0.1, 0.6), + ("weird", -0.2, 0.5), + ("interesting", 0.4, 0.6), + ("curious", 0.3, 0.5), + ("insight", 0.6, 0.7), + ("realized", 0.4, 0.6), + ("found", 0.3, 0.5), + ("noticed", 0.2, 0.4), ] { lex.insert(word.to_string(), (v, a)); } // Technical intensity markers for (word, v, a) in [ - ("production", -0.1, 0.7), ("deploy", 0.1, 0.6), - ("migration", -0.1, 0.5), ("refactor", 0.1, 0.4), - ("security", -0.1, 0.6), ("performance", 0.1, 0.4), - ("important", 0.2, 0.6), ("remember", 0.1, 0.5), + ("production", -0.1, 0.7), + ("deploy", 0.1, 0.6), + ("migration", -0.1, 0.5), + ("refactor", 0.1, 0.4), + ("security", -0.1, 0.6), + ("performance", 0.1, 0.4), + ("important", 0.2, 0.6), + ("remember", 0.1, 0.5), ] { lex.insert(word.to_string(), (v, a)); } @@ -572,16 +635,33 @@ mod tests { fn test_positive_content() { let mut em = EmotionalMemory::new(); let eval = em.evaluate_content("Amazing breakthrough! The fix is working perfectly"); - assert!(eval.valence > 0.3, "Expected positive valence, got {}", eval.valence); - assert!(eval.arousal > 0.4, "Expected high arousal, got {}", eval.arousal); + assert!( + eval.valence > 0.3, + "Expected positive valence, got {}", + eval.valence + ); + assert!( + eval.arousal > 0.4, + "Expected high arousal, got {}", + eval.arousal + ); } #[test] fn test_negative_content() { let mut em = EmotionalMemory::new(); - let eval = em.evaluate_content("Critical bug: production server crash with data corruption"); - assert!(eval.valence < -0.3, "Expected negative valence, got {}", eval.valence); - assert!(eval.arousal > 0.5, "Expected high arousal, got {}", eval.arousal); + let eval = + em.evaluate_content("Critical bug: production server crash with data corruption"); + assert!( + eval.valence < -0.3, + "Expected negative valence, got {}", + eval.valence + ); + assert!( + eval.arousal > 0.5, + "Expected high arousal, got {}", + eval.arousal + ); } #[test] @@ -592,7 +672,10 @@ mod tests { 0.8, // High novelty 0.9, // High arousal ); - assert!(eval.is_flashbulb, "Should detect flashbulb with high novelty + arousal"); + assert!( + eval.is_flashbulb, + "Should detect flashbulb with high novelty + arousal" + ); } #[test] @@ -611,7 +694,10 @@ mod tests { let mut em = EmotionalMemory::new(); let positive = em.evaluate_content("This is amazing"); let negated = em.evaluate_content("This is not amazing"); - assert!(negated.valence < positive.valence, "Negation should reduce valence"); + assert!( + negated.valence < positive.valence, + "Negation should reduce valence" + ); } #[test] @@ -632,15 +718,24 @@ mod tests { em.evaluate_content("Great amazing perfect success"); } let (mood_v, _) = em.current_mood(); - assert!(mood_v > 0.3, "Mood should be positive after positive content"); + assert!( + mood_v > 0.3, + "Mood should be positive after positive content" + ); // Positive memory should get boost let boost = em.mood_congruence_boost(0.7); - assert!(boost > 0.0, "Positive memory should get mood-congruent boost"); + assert!( + boost > 0.0, + "Positive memory should get mood-congruent boost" + ); // Negative memory should get less/no boost let neg_boost = em.mood_congruence_boost(-0.7); - assert!(neg_boost < boost, "Negative memory should get less boost in positive mood"); + assert!( + neg_boost < boost, + "Negative memory should get less boost in positive mood" + ); } #[test] @@ -674,7 +769,10 @@ mod tests { } let (v1, a1) = em.current_mood(); assert!(v1 < 0.0, "Mood should be negative after negative content"); - assert!(a1 > 0.3, "Arousal should be elevated after negative content"); + assert!( + a1 > 0.3, + "Arousal should be elevated after negative content" + ); } #[test] diff --git a/crates/vestige-core/src/neuroscience/hippocampal_index.rs b/crates/vestige-core/src/neuroscience/hippocampal_index.rs index a8fa0f9..5e1a367 100644 --- a/crates/vestige-core/src/neuroscience/hippocampal_index.rs +++ b/crates/vestige-core/src/neuroscience/hippocampal_index.rs @@ -1076,9 +1076,10 @@ impl ContentStore { // Check cache first let cache_key = self.cache_key(pointer); if let Ok(cache) = self.cache.read() - && let Some(data) = cache.get(&cache_key) { - return Ok(data.clone()); - } + && let Some(data) = cache.get(&cache_key) + { + return Ok(data.clone()); + } // Retrieve from storage let data = match &pointer.storage_location { @@ -1131,22 +1132,23 @@ impl ContentStore { } if let Ok(mut cache) = self.cache.write() - && let Ok(mut size) = self.current_cache_size.write() { - // Evict if necessary - while *size + data_size > self.max_cache_size && !cache.is_empty() { - // Simple eviction: remove first entry - if let Some(key_to_remove) = cache.keys().next().cloned() { - if let Some(removed) = cache.remove(&key_to_remove) { - *size = size.saturating_sub(removed.len()); - } - } else { - break; + && let Ok(mut size) = self.current_cache_size.write() + { + // Evict if necessary + while *size + data_size > self.max_cache_size && !cache.is_empty() { + // Simple eviction: remove first entry + if let Some(key_to_remove) = cache.keys().next().cloned() { + if let Some(removed) = cache.remove(&key_to_remove) { + *size = size.saturating_sub(removed.len()); } + } else { + break; } - - cache.insert(key.to_string(), data.to_vec()); - *size += data_size; } + + cache.insert(key.to_string(), data.to_vec()); + *size += data_size; + } } /// Retrieve from SQLite (placeholder - to be integrated with Storage) @@ -1393,15 +1395,16 @@ impl HippocampalIndex { // Calculate semantic score if let Some(ref query_embedding) = query.semantic_embedding - && !index.semantic_summary.is_empty() { - let query_compressed = self.compress_embedding(query_embedding); - match_result.semantic_score = - self.cosine_similarity(&query_compressed, &index.semantic_summary); + && !index.semantic_summary.is_empty() + { + let query_compressed = self.compress_embedding(query_embedding); + match_result.semantic_score = + self.cosine_similarity(&query_compressed, &index.semantic_summary); - if match_result.semantic_score < query.min_similarity { - continue; - } + if match_result.semantic_score < query.min_similarity { + continue; } + } // Calculate text score if let Some(ref text_query) = query.text_query { @@ -1442,21 +1445,24 @@ impl HippocampalIndex { fn passes_filters(&self, index: &MemoryIndex, query: &IndexQuery) -> bool { // Time range filter if let Some((start, end)) = query.time_range - && (index.temporal_marker.created_at < start || index.temporal_marker.created_at > end) { - return false; - } + && (index.temporal_marker.created_at < start || index.temporal_marker.created_at > end) + { + return false; + } // Importance flags filter if let Some(ref required) = query.required_flags - && !index.matches_importance(required.to_bits()) { - return false; - } + && !index.matches_importance(required.to_bits()) + { + return false; + } // Node type filter if let Some(ref types) = query.node_types - && !types.contains(&index.node_type) { - return false; - } + && !types.contains(&index.node_type) + { + return false; + } true } @@ -1574,9 +1580,10 @@ impl HippocampalIndex { for m in matches { // Record access if let Ok(mut indices) = self.indices.write() - && let Some(index) = indices.get_mut(&m.index.memory_id) { - index.record_access(); - } + && let Some(index) = indices.get_mut(&m.index.memory_id) + { + index.record_access(); + } match self.retrieve_content(&m.index) { Ok(memory) => memories.push(memory), @@ -1881,37 +1888,39 @@ impl HippocampalIndex { ) -> Result { // Check if already indexed if let Ok(indices) = self.indices.read() - && indices.contains_key(node_id) { - return Err(HippocampalIndexError::MigrationError( - "Node already indexed".to_string(), - )); - } + && indices.contains_key(node_id) + { + return Err(HippocampalIndexError::MigrationError( + "Node already indexed".to_string(), + )); + } // Create the index let barcode = self.index_memory(node_id, content, node_type, created_at, embedding)?; // Update importance flags based on existing data if let Ok(mut indices) = self.indices.write() - && let Some(index) = indices.get_mut(node_id) { - // Set high retention flag if applicable - if retention_strength > 0.7 { - index.importance_flags.set_high_retention(true); - } - - // Set emotional flag if applicable - if sentiment_magnitude > 0.5 { - index.importance_flags.set_emotional(true); - } - - // Add SQLite content pointer - index.content_pointers.clear(); - index.add_content_pointer(ContentPointer::sqlite( - "knowledge_nodes", - barcode.id as i64, - ContentType::Text, - )); + && let Some(index) = indices.get_mut(node_id) + { + // Set high retention flag if applicable + if retention_strength > 0.7 { + index.importance_flags.set_high_retention(true); } + // Set emotional flag if applicable + if sentiment_magnitude > 0.5 { + index.importance_flags.set_emotional(true); + } + + // Add SQLite content pointer + index.content_pointers.clear(); + index.add_content_pointer(ContentPointer::sqlite( + "knowledge_nodes", + barcode.id as i64, + ContentType::Text, + )); + } + Ok(barcode) } diff --git a/crates/vestige-core/src/neuroscience/importance_signals.rs b/crates/vestige-core/src/neuroscience/importance_signals.rs index cf26e63..f44f3fb 100644 --- a/crates/vestige-core/src/neuroscience/importance_signals.rs +++ b/crates/vestige-core/src/neuroscience/importance_signals.rs @@ -359,17 +359,18 @@ impl PredictionModel { let ngrams = self.extract_ngrams(content); if let Ok(mut patterns) = self.patterns.write() - && let Ok(mut total) = self.total_count.write() { - for ngram in ngrams { - *patterns.entry(ngram).or_insert(0) += 1; - *total += 1; - } - - // Prune if too large - if patterns.len() > MAX_PREDICTION_PATTERNS { - self.apply_decay(&mut patterns); - } + && let Ok(mut total) = self.total_count.write() + { + for ngram in ngrams { + *patterns.entry(ngram).or_insert(0) += 1; + *total += 1; } + + // Prune if too large + if patterns.len() > MAX_PREDICTION_PATTERNS { + self.apply_decay(&mut patterns); + } + } } fn compute_prediction_error(&self, content: &str) -> f64 { @@ -1186,7 +1187,11 @@ impl RewardSignal { // Limit pattern count if patterns.len() > 1000 { - patterns.sort_by(|a, b| b.strength.partial_cmp(&a.strength).unwrap_or(std::cmp::Ordering::Equal)); + patterns.sort_by(|a, b| { + b.strength + .partial_cmp(&a.strength) + .unwrap_or(std::cmp::Ordering::Equal) + }); patterns.truncate(500); } } @@ -1226,7 +1231,9 @@ impl RewardSignal { entries.sort_by(|a, b| { // Sort by score, then by recency - b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal).then_with(|| b.2.cmp(&a.2)) + b.1.partial_cmp(&a.1) + .unwrap_or(std::cmp::Ordering::Equal) + .then_with(|| b.2.cmp(&a.2)) }); // Keep top entries diff --git a/crates/vestige-core/src/neuroscience/memory_states.rs b/crates/vestige-core/src/neuroscience/memory_states.rs index 8f1bf33..0aca454 100644 --- a/crates/vestige-core/src/neuroscience/memory_states.rs +++ b/crates/vestige-core/src/neuroscience/memory_states.rs @@ -1267,13 +1267,14 @@ impl MemoryStateInfo { } MemoryState::Unavailable => { if let Some(until) = lifecycle.suppression_until - && until > now { - recommendations.push(format!( - "This memory is temporarily suppressed. \ + && until > now + { + recommendations.push(format!( + "This memory is temporarily suppressed. \ It will become accessible again after {}.", - until.format("%Y-%m-%d %H:%M UTC") - )); - } + until.format("%Y-%m-%d %H:%M UTC") + )); + } } MemoryState::Dormant => { if duration_since_access.num_days() > 20 { diff --git a/crates/vestige-core/src/neuroscience/mod.rs b/crates/vestige-core/src/neuroscience/mod.rs index 65a933c..21aab14 100644 --- a/crates/vestige-core/src/neuroscience/mod.rs +++ b/crates/vestige-core/src/neuroscience/mod.rs @@ -57,6 +57,7 @@ //! - Collins, A. M., & Loftus, E. F. (1975). A spreading-activation theory of semantic //! processing. Psychological Review. +pub mod active_forgetting; pub mod context_memory; pub mod emotional_memory; pub mod hippocampal_index; @@ -67,6 +68,12 @@ pub mod prospective_memory; pub mod spreading_activation; pub mod synaptic_tagging; +// Active forgetting — top-down inhibitory control (Anderson 2025 + Davis Rac1) +pub use active_forgetting::{ + ActiveForgettingSystem, DEFAULT_CASCADE_DECAY, DEFAULT_LABILE_HOURS, DEFAULT_MAX_PENALTY, + DEFAULT_SIF_K, SuppressionStats, +}; + // Re-exports for convenient access pub use synaptic_tagging::{ // Results @@ -94,15 +101,23 @@ pub use context_memory::{ // Memory states (accessibility continuum) pub use memory_states::{ + // Constants + ACCESSIBILITY_ACTIVE, + ACCESSIBILITY_DORMANT, + ACCESSIBILITY_SILENT, + ACCESSIBILITY_UNAVAILABLE, // Accessibility scoring AccessibilityCalculator, BatchUpdateResult, + COMPETITION_SIMILARITY_THRESHOLD, CompetitionCandidate, CompetitionConfig, CompetitionEvent, // Competition system (Retrieval-Induced Forgetting) CompetitionManager, CompetitionResult, + DEFAULT_ACTIVE_DECAY_HOURS, + DEFAULT_DORMANT_DECAY_DAYS, LifecycleSummary, MemoryLifecycle, // Core types @@ -116,14 +131,6 @@ pub use memory_states::{ StateTransitionReason, // State management StateUpdateService, - // Constants - ACCESSIBILITY_ACTIVE, - ACCESSIBILITY_DORMANT, - ACCESSIBILITY_SILENT, - ACCESSIBILITY_UNAVAILABLE, - COMPETITION_SIMILARITY_THRESHOLD, - DEFAULT_ACTIVE_DECAY_HOURS, - DEFAULT_DORMANT_DECAY_DAYS, }; // Multi-channel importance signaling (Neuromodulator-inspired) @@ -174,6 +181,8 @@ pub use hippocampal_index::{ HippocampalIndex, HippocampalIndexConfig, HippocampalIndexError, + // Constants + INDEX_EMBEDDING_DIM, ImportanceFlags, IndexLink, IndexMatch, @@ -187,40 +196,39 @@ pub use hippocampal_index::{ MigrationResult, StorageLocation, TemporalMarker, - // Constants - INDEX_EMBEDDING_DIM, }; // Predictive memory retrieval (Free Energy Principle - Friston, 2010) pub use predictive_retrieval::{ // Backward-compatible aliases ContextualPredictor, - Prediction, - PredictionConfidence, - PredictiveConfig, - PredictiveRetriever, - SequencePredictor, - TemporalPredictor, // Enhanced types (Friston's Active Inference) PredictedMemory, + Prediction, + PredictionConfidence, PredictionOutcome, PredictionReason, + PredictiveConfig, PredictiveMemory, PredictiveMemoryConfig, PredictiveMemoryError, + PredictiveRetriever, ProjectContext as PredictiveProjectContext, QueryPattern, + SequencePredictor, SessionContext as PredictiveSessionContext, TemporalPatterns, + TemporalPredictor, UserModel, }; // Prospective memory (Einstein & McDaniel, 1990) pub use prospective_memory::{ - // Core engine - ProspectiveMemory, - ProspectiveMemoryConfig, - ProspectiveMemoryError, + // Context monitoring + Context as ProspectiveContext, + ContextMonitor, + // Triggers and patterns + ContextPattern, // Intentions Intention, IntentionParser, @@ -229,13 +237,12 @@ pub use prospective_memory::{ IntentionStatus, IntentionTrigger, Priority, - // Triggers and patterns - ContextPattern, + // Core engine + ProspectiveMemory, + ProspectiveMemoryConfig, + ProspectiveMemoryError, RecurrencePattern, TriggerPattern, - // Context monitoring - Context as ProspectiveContext, - ContextMonitor, }; // Spreading activation (Associative Memory Network - Collins & Loftus, 1975) diff --git a/crates/vestige-core/src/neuroscience/predictive_retrieval.rs b/crates/vestige-core/src/neuroscience/predictive_retrieval.rs index 4bace7c..9c79c3e 100644 --- a/crates/vestige-core/src/neuroscience/predictive_retrieval.rs +++ b/crates/vestige-core/src/neuroscience/predictive_retrieval.rs @@ -915,7 +915,11 @@ impl PredictiveMemory { predictions.retain(|p| p.confidence >= self.config.min_confidence); // Sort by confidence - predictions.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap_or(std::cmp::Ordering::Equal)); + predictions.sort_by(|a, b| { + b.confidence + .partial_cmp(&a.confidence) + .unwrap_or(std::cmp::Ordering::Equal) + }); // Truncate to max predictions.truncate(self.config.max_predictions); diff --git a/crates/vestige-core/src/neuroscience/prospective_memory.rs b/crates/vestige-core/src/neuroscience/prospective_memory.rs index 868e1e5..133f17d 100644 --- a/crates/vestige-core/src/neuroscience/prospective_memory.rs +++ b/crates/vestige-core/src/neuroscience/prospective_memory.rs @@ -130,8 +130,7 @@ pub type Result = std::result::Result; // ============================================================================ /// Priority levels for intentions -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -#[derive(Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)] pub enum Priority { /// Low priority - nice to remember Low = 1, @@ -144,7 +143,6 @@ pub enum Priority { Critical = 4, } - impl Priority { /// Get numeric value for comparison pub fn value(&self) -> u8 { @@ -178,8 +176,7 @@ impl Priority { } /// Status of an intention -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -#[derive(Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] pub enum IntentionStatus { /// Intention is active and being monitored #[default] @@ -196,7 +193,6 @@ pub enum IntentionStatus { Snoozed, } - /// Pattern for matching trigger conditions #[derive(Debug, Clone, Serialize, Deserialize)] pub enum TriggerPattern { @@ -695,15 +691,17 @@ impl Intention { // Check snoozed if let Some(snoozed_until) = self.snoozed_until - && Utc::now() < snoozed_until { - return false; - } + && Utc::now() < snoozed_until + { + return false; + } // Check minimum interval if let Some(last) = self.last_reminded_at - && (Utc::now() - last) < Duration::minutes(MIN_REMINDER_INTERVAL_MINUTES) { - return false; - } + && (Utc::now() - last) < Duration::minutes(MIN_REMINDER_INTERVAL_MINUTES) + { + return false; + } true } @@ -956,9 +954,17 @@ impl IntentionParser { let when_char_idx = text_lower[..when_byte_idx].chars().count(); let content_part: String = if text_lower.starts_with("remind me to ") { - original.chars().skip(13).take(when_char_idx.saturating_sub(13)).collect() + original + .chars() + .skip(13) + .take(when_char_idx.saturating_sub(13)) + .collect() } else if text_lower.starts_with("remind me ") { - original.chars().skip(10).take(when_char_idx.saturating_sub(10)).collect() + original + .chars() + .skip(10) + .take(when_char_idx.saturating_sub(10)) + .collect() } else { original.chars().take(when_char_idx).collect() }; @@ -1047,8 +1053,6 @@ impl IntentionParser { /// Extract content from text, removing trigger keywords fn extract_content(&self, _text_lower: &str, original: &str, keyword: &str) -> String { - - original .replace(keyword, "") .replace(&keyword.to_uppercase(), "") @@ -1267,9 +1271,10 @@ impl ProspectiveMemory { // Check if snoozed intention should wake if intention.status == IntentionStatus::Snoozed && let Some(until) = intention.snoozed_until - && Utc::now() >= until { - intention.wake(); - } + && Utc::now() >= until + { + intention.wake(); + } continue; } @@ -1277,10 +1282,11 @@ impl ProspectiveMemory { if intention .trigger .is_triggered(context, &context.recent_events) - && intention.should_remind() { - intention.mark_triggered(); - triggered.push(intention.clone()); - } + && intention.should_remind() + { + intention.mark_triggered(); + triggered.push(intention.clone()); + } // Check for deadline escalation if self.config.enable_escalation { diff --git a/crates/vestige-core/src/neuroscience/spreading_activation.rs b/crates/vestige-core/src/neuroscience/spreading_activation.rs index 55a1fad..2daf786 100644 --- a/crates/vestige-core/src/neuroscience/spreading_activation.rs +++ b/crates/vestige-core/src/neuroscience/spreading_activation.rs @@ -57,7 +57,6 @@ pub enum LinkType { UserDefined, } - // ============================================================================ // ASSOCIATION EDGE // ============================================================================ @@ -271,13 +270,7 @@ impl ActivationNetwork { } /// Add an edge between two nodes - pub fn add_edge( - &mut self, - source: String, - target: String, - link_type: LinkType, - strength: f64, - ) { + pub fn add_edge(&mut self, source: String, target: String, link_type: LinkType, strength: f64) { // Ensure both nodes exist self.add_node(source.clone()); self.add_node(target.clone()); @@ -288,9 +281,10 @@ impl ActivationNetwork { // Update node's edge list if let Some(node) = self.nodes.get_mut(&source) - && !node.edges.contains(&target) { - node.edges.push(target); - } + && !node.edges.contains(&target) + { + node.edges.push(target); + } } /// Activate a node and spread activation through the network @@ -314,9 +308,10 @@ impl ActivationNetwork { while let Some((current_id, current_activation, hops, path)) = queue.pop() { // Skip if we've visited this node with higher activation if let Some(&prev_activation) = visited.get(¤t_id) - && prev_activation >= current_activation { - continue; - } + && prev_activation >= current_activation + { + continue; + } visited.insert(current_id.clone(), current_activation); // Check hop limit @@ -499,7 +494,7 @@ mod tests { #[test] fn test_activation_threshold() { let mut network = ActivationNetwork::with_config(ActivationConfig { - decay_factor: 0.1, // Very high decay + decay_factor: 0.1, // Very high decay min_threshold: 0.5, // High threshold ..Default::default() }); diff --git a/crates/vestige-core/src/neuroscience/synaptic_tagging.rs b/crates/vestige-core/src/neuroscience/synaptic_tagging.rs index ea2e38c..c5e9ca1 100644 --- a/crates/vestige-core/src/neuroscience/synaptic_tagging.rs +++ b/crates/vestige-core/src/neuroscience/synaptic_tagging.rs @@ -122,7 +122,6 @@ pub enum DecayFunction { Logarithmic, } - impl DecayFunction { /// Calculate decayed strength /// diff --git a/crates/vestige-core/src/search/hyde.rs b/crates/vestige-core/src/search/hyde.rs index 1e4ebc7..1fea1fa 100644 --- a/crates/vestige-core/src/search/hyde.rs +++ b/crates/vestige-core/src/search/hyde.rs @@ -43,8 +43,10 @@ pub fn classify_intent(query: &str) -> QueryIntent { if lower.contains("how to") || lower.starts_with("how do") || lower.starts_with("steps") { return QueryIntent::HowTo; } - if lower.starts_with("what is") || lower.starts_with("what are") - || lower.starts_with("define") || lower.starts_with("explain") + if lower.starts_with("what is") + || lower.starts_with("what are") + || lower.starts_with("define") + || lower.starts_with("explain") { return QueryIntent::Definition; } @@ -54,8 +56,11 @@ pub fn classify_intent(query: &str) -> QueryIntent { if lower.starts_with("when") || lower.contains("date") || lower.contains("timeline") { return QueryIntent::Temporal; } - if query.contains('(') || query.contains('{') || query.contains("fn ") - || query.contains("class ") || query.contains("::") + if query.contains('(') + || query.contains('{') + || query.contains("fn ") + || query.contains("class ") + || query.contains("::") { return QueryIntent::Technical; } @@ -161,23 +166,38 @@ mod tests { #[test] fn test_classify_definition() { assert_eq!(classify_intent("What is FSRS?"), QueryIntent::Definition); - assert_eq!(classify_intent("explain spaced repetition"), QueryIntent::Definition); + assert_eq!( + classify_intent("explain spaced repetition"), + QueryIntent::Definition + ); } #[test] fn test_classify_howto() { - assert_eq!(classify_intent("how to configure embeddings"), QueryIntent::HowTo); - assert_eq!(classify_intent("How do I search memories?"), QueryIntent::HowTo); + assert_eq!( + classify_intent("how to configure embeddings"), + QueryIntent::HowTo + ); + assert_eq!( + classify_intent("How do I search memories?"), + QueryIntent::HowTo + ); } #[test] fn test_classify_reasoning() { - assert_eq!(classify_intent("why does retention decay?"), QueryIntent::Reasoning); + assert_eq!( + classify_intent("why does retention decay?"), + QueryIntent::Reasoning + ); } #[test] fn test_classify_temporal() { - assert_eq!(classify_intent("when did the last consolidation run"), QueryIntent::Temporal); + assert_eq!( + classify_intent("when did the last consolidation run"), + QueryIntent::Temporal + ); } #[test] @@ -188,7 +208,10 @@ mod tests { #[test] fn test_classify_lookup() { - assert_eq!(classify_intent("vestige memory system"), QueryIntent::Lookup); + assert_eq!( + classify_intent("vestige memory system"), + QueryIntent::Lookup + ); } #[test] @@ -200,10 +223,7 @@ mod tests { #[test] fn test_centroid_embedding() { - let embeddings = vec![ - vec![1.0, 0.0, 0.0], - vec![0.0, 1.0, 0.0], - ]; + let embeddings = vec![vec![1.0, 0.0, 0.0], vec![0.0, 1.0, 0.0]]; let centroid = centroid_embedding(&embeddings); assert_eq!(centroid.len(), 3); // Should be normalized diff --git a/crates/vestige-core/src/search/mod.rs b/crates/vestige-core/src/search/mod.rs index eb79f89..45b5a63 100644 --- a/crates/vestige-core/src/search/mod.rs +++ b/crates/vestige-core/src/search/mod.rs @@ -15,21 +15,21 @@ mod temporal; mod vector; pub use vector::{ - VectorIndex, VectorIndexConfig, VectorIndexStats, VectorSearchError, DEFAULT_CONNECTIVITY, - DEFAULT_DIMENSIONS, + DEFAULT_CONNECTIVITY, DEFAULT_DIMENSIONS, VectorIndex, VectorIndexConfig, VectorIndexStats, + VectorSearchError, }; -pub use keyword::{sanitize_fts5_query, KeywordSearcher}; +pub use keyword::{KeywordSearcher, sanitize_fts5_query}; -pub use hybrid::{linear_combination, reciprocal_rank_fusion, HybridSearchConfig, HybridSearcher}; +pub use hybrid::{HybridSearchConfig, HybridSearcher, linear_combination, reciprocal_rank_fusion}; pub use temporal::TemporalSearcher; // GOD TIER 2026: Reranking for +15-20% precision pub use reranker::{ - Reranker, RerankerConfig, RerankerError, RerankedResult, - DEFAULT_RERANK_COUNT, DEFAULT_RETRIEVAL_COUNT, + DEFAULT_RERANK_COUNT, DEFAULT_RETRIEVAL_COUNT, RerankedResult, Reranker, RerankerConfig, + RerankerError, }; // v2.0: HyDE-inspired query expansion for improved semantic search -pub use hyde::{classify_intent, expand_query, centroid_embedding, QueryIntent}; +pub use hyde::{QueryIntent, centroid_embedding, classify_intent, expand_query}; diff --git a/crates/vestige-core/src/search/vector.rs b/crates/vestige-core/src/search/vector.rs index d71b411..069dd9a 100644 --- a/crates/vestige-core/src/search/vector.rs +++ b/crates/vestige-core/src/search/vector.rs @@ -174,9 +174,9 @@ impl VectorIndex { /// Reserve capacity for a specified number of vectors /// This should be called before adding vectors to avoid segmentation faults pub fn reserve(&self, capacity: usize) -> Result<(), VectorSearchError> { - self.index - .reserve(capacity) - .map_err(|e| VectorSearchError::IndexCreation(format!("Failed to reserve capacity: {}", e))) + self.index.reserve(capacity).map_err(|e| { + VectorSearchError::IndexCreation(format!("Failed to reserve capacity: {}", e)) + }) } /// Add a vector with a string key diff --git a/crates/vestige-core/src/storage/migrations.rs b/crates/vestige-core/src/storage/migrations.rs index b5325b4..370257c 100644 --- a/crates/vestige-core/src/storage/migrations.rs +++ b/crates/vestige-core/src/storage/migrations.rs @@ -49,6 +49,11 @@ pub const MIGRATIONS: &[Migration] = &[ description: "v2.0.0 Cognitive Leap: emotional memory, flashbulb encoding, temporal hierarchy", up: MIGRATION_V9_UP, }, + Migration { + version: 10, + description: "v2.0.5 Intentional Amnesia: active forgetting — top-down suppression (Anderson 2025 + Davis Rac1)", + up: MIGRATION_V10_UP, + }, ]; /// A database migration @@ -315,7 +320,7 @@ const MIGRATION_V4_UP: &str = r#" -- TEMPORAL KNOWLEDGE GRAPH (Like Zep's Graphiti) -- ============================================================================ --- DEPRECATED (v2.1.0): knowledge_edges is unused. All graph edges use +-- DEPRECATED (v2.0.5): knowledge_edges is unused. All graph edges use -- memory_connections (migration V3). This table was designed for bi-temporal -- edge support but was never wired. Retained for schema compatibility with -- existing databases. Do NOT add queries against this table. @@ -608,6 +613,41 @@ ALTER TABLE dream_history ADD COLUMN creative_connections_found INTEGER DEFAULT UPDATE schema_version SET version = 9, applied_at = datetime('now'); "#; +/// V10: v2.0.5 Intentional Amnesia — Top-Down Active Forgetting +/// +/// Adds columns to `knowledge_nodes` for user-initiated suppression distinct +/// from passive FSRS decay and from bottom-up retrieval-induced forgetting +/// (which lives on `memory_states.suppression_until`). These columns are +/// incremented by the `suppress` MCP tool (tool #24) and consumed by the +/// search scoring stage + background Rac1 cascade worker. +/// +/// References: +/// - Anderson et al. (2025). Brain mechanisms underlying the inhibitory +/// control of thought. Nat Rev Neurosci. DOI 10.1038/s41583-025-00929-y +/// - Cervantes-Sandoval & Davis (2020). Rac1 Impairs Forgetting-Induced +/// Cellular Plasticity. Front Cell Neurosci. PMC7477079 +const MIGRATION_V10_UP: &str = r#" +-- Top-down suppression count (Suppression-Induced Forgetting, Anderson 2025). +-- Compounds with each `suppress` call, saturates via the k × count formula +-- in active_forgetting::retrieval_penalty(). +ALTER TABLE knowledge_nodes ADD COLUMN suppression_count INTEGER DEFAULT 0; + +-- Timestamp of the most recent suppression. Used for the 24h labile window +-- (reversal is allowed only while (now - suppressed_at) < labile_hours). +ALTER TABLE knowledge_nodes ADD COLUMN suppressed_at TEXT; + +-- Partial indices — only materialise rows actually involved in suppression. +CREATE INDEX IF NOT EXISTS idx_nodes_suppression_count + ON knowledge_nodes(suppression_count) + WHERE suppression_count > 0; + +CREATE INDEX IF NOT EXISTS idx_nodes_suppressed_at + ON knowledge_nodes(suppressed_at) + WHERE suppressed_at IS NOT NULL; + +UPDATE schema_version SET version = 10, applied_at = datetime('now'); +"#; + /// Get current schema version from database pub fn get_current_version(conn: &rusqlite::Connection) -> rusqlite::Result { conn.query_row( diff --git a/crates/vestige-core/src/storage/sqlite.rs b/crates/vestige-core/src/storage/sqlite.rs index 244e2ec..7de250a 100644 --- a/crates/vestige-core/src/storage/sqlite.rs +++ b/crates/vestige-core/src/storage/sqlite.rs @@ -6,7 +6,7 @@ use chrono::{DateTime, Duration, Utc}; use directories::ProjectDirs; #[cfg(feature = "embeddings")] use lru::LruCache; -use rusqlite::{params, Connection, OptionalExtension}; +use rusqlite::{Connection, OptionalExtension, params}; #[cfg(feature = "embeddings")] use std::num::NonZeroUsize; use std::path::PathBuf; @@ -14,22 +14,20 @@ use std::sync::Mutex; use uuid::Uuid; use crate::fsrs::{ - retrievability_with_decay, DEFAULT_DECAY, - FSRSScheduler, FSRSState, LearningState, Rating, + DEFAULT_DECAY, FSRSScheduler, FSRSState, LearningState, Rating, retrievability_with_decay, }; +use crate::fts::sanitize_fts5_query; use crate::memory::{ - ConsolidationResult, IngestInput, KnowledgeNode, MemoryStats, - RecallInput, SearchMode, + ConsolidationResult, IngestInput, KnowledgeNode, MemoryStats, RecallInput, SearchMode, }; #[cfg(all(feature = "embeddings", feature = "vector-search"))] use crate::memory::{EmbeddingResult, MatchType, SearchResult, SimilarityResult}; -use crate::fts::sanitize_fts5_query; #[cfg(feature = "embeddings")] -use crate::embeddings::{matryoshka_truncate, Embedding, EmbeddingService, EMBEDDING_DIMENSIONS}; +use crate::embeddings::{EMBEDDING_DIMENSIONS, Embedding, EmbeddingService, matryoshka_truncate}; #[cfg(feature = "vector-search")] -use crate::search::{linear_combination, VectorIndex}; +use crate::search::{VectorIndex, linear_combination}; #[cfg(all(feature = "embeddings", feature = "vector-search"))] use crate::search::hyde; @@ -208,11 +206,12 @@ impl Storage { /// Load existing embeddings into vector index #[cfg(all(feature = "embeddings", feature = "vector-search"))] fn load_embeddings_into_index(&self) -> Result<()> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader - .prepare("SELECT node_id, embedding FROM node_embeddings")?; + let mut stmt = reader.prepare("SELECT node_id, embedding FROM node_embeddings")?; let embeddings: Vec<(String, Vec)> = stmt .query_map([], |row| Ok((row.get(0)?, row.get(1)?)))? @@ -243,7 +242,11 @@ impl Storage { } } if load_failures > 0 { - tracing::error!(count = load_failures, "Vector index: {} embeddings failed to load", load_failures); + tracing::error!( + count = load_failures, + "Vector index: {} embeddings failed to load", + load_failures + ); } Ok(()) @@ -254,7 +257,9 @@ impl Storage { let now = Utc::now(); let id = Uuid::new_v4().to_string(); - let fsrs_state = self.scheduler.lock() + let fsrs_state = self + .scheduler + .lock() .map_err(|_| StorageError::Init("Scheduler lock poisoned".into()))? .new_card(); @@ -271,7 +276,9 @@ impl Storage { let valid_until_str = input.valid_until.map(|dt| dt.to_rfc3339()); { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO knowledge_nodes ( @@ -335,10 +342,7 @@ impl Storage { /// /// This solves the "bad vs good similar memory" problem. #[cfg(all(feature = "embeddings", feature = "vector-search"))] - pub fn smart_ingest( - &self, - input: IngestInput, - ) -> Result { + pub fn smart_ingest(&self, input: IngestInput) -> Result { use crate::advanced::prediction_error::{ CandidateMemory, GateDecision, PredictionErrorGate, UpdateType, }; @@ -395,7 +399,12 @@ impl Storage { let decision = gate.evaluate(&input.content, &new_embedding.vector, &candidates); match decision { - GateDecision::Create { prediction_error, related_memory_ids, reason, .. } => { + GateDecision::Create { + prediction_error, + related_memory_ids, + reason, + .. + } => { // Create new memory let node = self.ingest(input)?; Ok(SmartIngestResult { @@ -407,16 +416,25 @@ impl Storage { reason: if related_memory_ids.is_empty() { format!("Created new memory: {:?}", reason) } else { - format!("Created new memory: {:?}. Semantically similar (not linked): {:?}", reason, related_memory_ids) + format!( + "Created new memory: {:?}. Semantically similar (not linked): {:?}", + reason, related_memory_ids + ) }, }) } - GateDecision::Update { target_id, similarity, update_type, prediction_error } => { + GateDecision::Update { + target_id, + similarity, + update_type, + prediction_error, + } => { match update_type { UpdateType::Reinforce => { // Just strengthen the existing memory self.strengthen_on_access(&target_id)?; - let node = self.get_node(&target_id)? + let node = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; Ok(SmartIngestResult { decision: "reinforce".to_string(), @@ -424,12 +442,14 @@ impl Storage { superseded_id: None, similarity: Some(similarity), prediction_error: Some(prediction_error), - reason: "Content nearly identical - reinforced existing memory".to_string(), + reason: "Content nearly identical - reinforced existing memory" + .to_string(), }) } UpdateType::Merge | UpdateType::Append => { // Update the existing memory with merged content - let existing = self.get_node(&target_id)? + let existing = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; let merged_content = format!( @@ -442,7 +462,8 @@ impl Storage { self.update_node_content(&target_id, &merged_content)?; self.strengthen_on_access(&target_id)?; - let node = self.get_node(&target_id)? + let node = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; Ok(SmartIngestResult { @@ -457,7 +478,8 @@ impl Storage { UpdateType::Replace => { // Replace content entirely self.update_node_content(&target_id, &input.content)?; - let node = self.get_node(&target_id)? + let node = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; Ok(SmartIngestResult { @@ -471,17 +493,16 @@ impl Storage { } UpdateType::AddContext => { // Add as context without modifying main content - let existing = self.get_node(&target_id)? + let existing = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; - let merged_content = format!( - "{}\n\n---\nContext: {}", - existing.content, - input.content - ); + let merged_content = + format!("{}\n\n---\nContext: {}", existing.content, input.content); self.update_node_content(&target_id, &merged_content)?; - let node = self.get_node(&target_id)? + let node = self + .get_node(&target_id)? .ok_or_else(|| StorageError::NotFound(target_id.clone()))?; Ok(SmartIngestResult { @@ -495,7 +516,12 @@ impl Storage { } } } - GateDecision::Supersede { old_memory_id, similarity, supersede_reason, prediction_error } => { + GateDecision::Supersede { + old_memory_id, + similarity, + supersede_reason, + prediction_error, + } => { // Demote the old memory and create new self.demote_memory(&old_memory_id)?; @@ -511,7 +537,11 @@ impl Storage { reason: format!("New memory supersedes old: {:?}", supersede_reason), }) } - GateDecision::Merge { memory_ids, avg_similarity, strategy } => { + GateDecision::Merge { + memory_ids, + avg_similarity, + strategy, + } => { // For now, create new and link to existing let node = self.ingest(input)?; @@ -521,7 +551,11 @@ impl Storage { superseded_id: None, similarity: Some(avg_similarity), prediction_error: Some(1.0 - avg_similarity), - reason: format!("Created new memory linked to {} similar memories ({:?})", memory_ids.len(), strategy), + reason: format!( + "Created new memory linked to {} similar memories ({:?})", + memory_ids.len(), + strategy + ), }) } } @@ -530,28 +564,29 @@ impl Storage { /// Get the embedding vector for a node #[cfg(all(feature = "embeddings", feature = "vector-search"))] pub fn get_node_embedding(&self, node_id: &str) -> Result>> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT embedding FROM node_embeddings WHERE node_id = ?1" - )?; + let mut stmt = + reader.prepare("SELECT embedding FROM node_embeddings WHERE node_id = ?1")?; let embedding_bytes: Option> = stmt .query_row(params![node_id], |row| row.get(0)) .optional()?; - Ok(embedding_bytes.and_then(|bytes| { - crate::embeddings::Embedding::from_bytes(&bytes).map(|e| e.vector) - })) + Ok(embedding_bytes + .and_then(|bytes| crate::embeddings::Embedding::from_bytes(&bytes).map(|e| e.vector))) } /// Get all embedding vectors for duplicate detection #[cfg(all(feature = "embeddings", feature = "vector-search"))] pub fn get_all_embeddings(&self) -> Result)>> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader - .prepare("SELECT node_id, embedding FROM node_embeddings")?; + let mut stmt = reader.prepare("SELECT node_id, embedding FROM node_embeddings")?; let results: Vec<(String, Vec)> = stmt .query_map([], |row| { @@ -561,8 +596,7 @@ impl Storage { })? .filter_map(|r| r.ok()) .filter_map(|(id, bytes)| { - crate::embeddings::Embedding::from_bytes(&bytes) - .map(|e| (id, e.vector)) + crate::embeddings::Embedding::from_bytes(&bytes).map(|e| (id, e.vector)) }) .collect(); @@ -574,7 +608,9 @@ impl Storage { let now = Utc::now(); { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET content = ?1, updated_at = ?2 WHERE id = ?3", @@ -613,7 +649,9 @@ impl Storage { let now = Utc::now(); { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO node_embeddings (node_id, embedding, dimensions, model, created_at) @@ -646,14 +684,13 @@ impl Storage { /// Get a node by ID pub fn get_node(&self, id: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader - .prepare("SELECT * FROM knowledge_nodes WHERE id = ?1")?; + let mut stmt = reader.prepare("SELECT * FROM knowledge_nodes WHERE id = ?1")?; - let node = stmt - .query_row(params![id], Self::row_to_node) - .optional()?; + let node = stmt.query_row(params![id], Self::row_to_node).optional()?; Ok(node) } @@ -717,6 +754,15 @@ impl Storage { let has_embedding: Option = row.get("has_embedding").ok(); let embedding_model: Option = row.get("embedding_model").ok().flatten(); + // v2.0.5 Active Forgetting columns (Migration V10) + let suppression_count: i32 = row.get("suppression_count").unwrap_or(0); + let suppressed_at_str: Option = row.get("suppressed_at").ok().flatten(); + let suppressed_at = suppressed_at_str.and_then(|s| { + DateTime::parse_from_rfc3339(&s) + .map(|dt| dt.with_timezone(&Utc)) + .ok() + }); + Ok(KnowledgeNode { id: row.get("id")?, content: row.get("content")?, @@ -746,7 +792,13 @@ impl Storage { times_useful: row.get("times_useful").ok(), emotional_valence: row.get("emotional_valence").ok(), flashbulb: row.get::<_, Option>("flashbulb").ok().flatten(), - temporal_level: row.get::<_, Option>("temporal_level").ok().flatten(), + temporal_level: row + .get::<_, Option>("temporal_level") + .ok() + .flatten(), + // v2.0.5 Active Forgetting + suppression_count, + suppressed_at, }) } @@ -787,7 +839,9 @@ impl Storage { ) -> Result> { let sanitized_query = sanitize_fts5_query(query); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT n.* FROM knowledge_nodes n @@ -831,7 +885,9 @@ impl Storage { scheduled_days: 0, }; - let scheduler = self.scheduler.lock() + let scheduler = self + .scheduler + .lock() .map_err(|_| StorageError::Init("Scheduler lock poisoned".into()))?; let elapsed_days = scheduler.days_since_review(¤t_state.last_review); @@ -841,8 +897,7 @@ impl Storage { None }; - let result = scheduler - .review(¤t_state, rating, elapsed_days, sentiment_boost); + let result = scheduler.review(¤t_state, rating, elapsed_days, sentiment_boost); drop(scheduler); let now = Utc::now(); @@ -859,7 +914,9 @@ impl Storage { (new_retrieval_strength * 0.7) + ((new_storage_strength / 10.0).min(1.0) * 0.3); { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET @@ -907,7 +964,9 @@ impl Storage { // Primary boost on the accessed node { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET @@ -942,7 +1001,9 @@ impl Storage { drop(index); if let Ok(neighbors) = neighbors_result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; for (neighbor_id, similarity) in neighbors { if neighbor_id == id || similarity < 0.7 { @@ -981,7 +1042,9 @@ impl Storage { /// /// Increments `times_useful` and recomputes `utility_score = times_useful / times_retrieved`. pub fn mark_memory_useful(&self, id: &str) -> Result<()> { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET @@ -999,7 +1062,9 @@ impl Storage { /// Log a memory access event for ACT-R activation computation fn log_access(&self, node_id: &str, access_type: &str) -> Result<()> { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO memory_access_log (node_id, access_type, accessed_at) @@ -1017,7 +1082,9 @@ impl Storage { // Strong boost: +0.2 retrieval, +0.1 retention { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET @@ -1047,7 +1114,9 @@ impl Storage { // Strong penalty: -0.3 retrieval, -0.15 retention, halve stability { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET @@ -1066,11 +1135,218 @@ impl Storage { .ok_or_else(|| StorageError::NotFound(id.to_string())) } + // ======================================================================== + // Active Forgetting (v2.0.5 — Anderson 2025 + Davis Rac1) + // ======================================================================== + + /// Top-down memory suppression (Suppression-Induced Forgetting). + /// + /// Distinct from `delete` (which removes the row) and from + /// `demote_memory` (which is a single thumb-down hit). Each call + /// compounds: `suppression_count` is incremented, `suppressed_at` is + /// bumped to now, and FSRS state is dealt a strong blow: + /// + /// - `retrieval_strength -= 0.35` (stronger than demote's -0.30) + /// - `retention_strength -= 0.20` + /// - `stability *= 0.4` + /// + /// Reversible within a 24-hour labile window via + /// [`Self::reverse_suppression`]. + /// + /// Reference: Anderson et al. (2025). Brain mechanisms underlying the + /// inhibitory control of thought. *Nature Reviews Neuroscience*. + /// DOI: 10.1038/s41583-025-00929-y + pub fn suppress_memory(&self, id: &str) -> Result { + let now = Utc::now(); + { + let writer = self + .writer + .lock() + .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; + writer.execute( + "UPDATE knowledge_nodes SET + last_accessed = ?1, + suppression_count = COALESCE(suppression_count, 0) + 1, + suppressed_at = ?1, + retrieval_strength = MAX(0.05, retrieval_strength - 0.35), + retention_strength = MAX(0.05, retention_strength - 0.20), + stability = stability * 0.4 + WHERE id = ?2", + params![now.to_rfc3339(), id], + )?; + } + + let _ = self.log_access(id, "suppress"); + + self.get_node(id)? + .ok_or_else(|| StorageError::NotFound(id.to_string())) + } + + /// Reverse a previous suppression if within the 24-hour labile window. + /// + /// Returns `Err(StorageError::NotFound)` if the memory has never been + /// suppressed, or `Err(StorageError::Init)` with a "labile window expired" + /// message if more than `labile_hours` have passed. Matches Nader + /// reconsolidation semantics on a 24h axis. + pub fn reverse_suppression(&self, id: &str, labile_hours: i64) -> Result { + let node = self + .get_node(id)? + .ok_or_else(|| StorageError::NotFound(id.to_string()))?; + + let suppressed_at = node.suppressed_at.ok_or_else(|| { + StorageError::Init(format!( + "memory {} has no active suppression to reverse", + id + )) + })?; + + let elapsed = Utc::now() - suppressed_at; + if elapsed >= chrono::Duration::hours(labile_hours) { + return Err(StorageError::Init(format!( + "labile window expired ({}h since suppression; limit {}h)", + elapsed.num_hours(), + labile_hours + ))); + } + + { + let writer = self + .writer + .lock() + .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; + writer.execute( + "UPDATE knowledge_nodes SET + suppression_count = MAX(0, COALESCE(suppression_count, 0) - 1), + suppressed_at = CASE + WHEN COALESCE(suppression_count, 0) - 1 <= 0 THEN NULL + ELSE suppressed_at + END, + retrieval_strength = MIN(1.0, retrieval_strength + 0.15), + retention_strength = MIN(1.0, retention_strength + 0.10), + stability = stability * 1.25 + WHERE id = ?1", + params![id], + )?; + } + + let _ = self.log_access(id, "reverse_suppress"); + + self.get_node(id)? + .ok_or_else(|| StorageError::NotFound(id.to_string())) + } + + /// Count memories currently in a suppressed state (suppression_count > 0). + pub fn count_suppressed(&self) -> Result { + let reader = self + .reader + .lock() + .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; + let count: i64 = reader.query_row( + "SELECT COUNT(*) FROM knowledge_nodes WHERE COALESCE(suppression_count, 0) > 0", + [], + |row| row.get(0), + )?; + Ok(count.max(0) as usize) + } + + /// Fetch memories suppressed within the last `window_hours` (still within + /// the labile window). Used by the Rac1 cascade sweep. + pub fn get_recently_suppressed(&self, window_hours: i64) -> Result> { + let cutoff = (Utc::now() - chrono::Duration::hours(window_hours)).to_rfc3339(); + let reader = self + .reader + .lock() + .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; + let mut stmt = reader.prepare( + "SELECT * FROM knowledge_nodes + WHERE suppressed_at IS NOT NULL AND suppressed_at >= ?1", + )?; + let rows = stmt.query_map(params![cutoff], Self::row_to_node)?; + let mut result = Vec::new(); + for row in rows { + result.push(row?); + } + Ok(result) + } + + /// Apply one-hop Rac1 cascade from a single suppressed seed memory: + /// walk `memory_connections` edges and attenuate neighbor FSRS state + /// proportional to edge strength. + /// + /// Returns the number of neighbors affected. + /// + /// Reference: Cervantes-Sandoval & Davis (2020). Rac1 Impairs Forgetting- + /// Induced Cellular Plasticity in Mushroom Body Output Neurons. + /// *Front Cell Neurosci*. PMC7477079 + pub fn apply_rac1_cascade(&self, seed_id: &str) -> Result { + use crate::neuroscience::active_forgetting::ActiveForgettingSystem; + let sys = ActiveForgettingSystem::new(); + + let edges = self.get_connections_for_memory(seed_id)?; + if edges.is_empty() { + return Ok(0); + } + + let writer = self + .writer + .lock() + .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; + + let mut affected = 0usize; + for edge in edges.iter().take(100) { + let neighbor_id = if edge.source_id == seed_id { + &edge.target_id + } else { + &edge.source_id + }; + + // Never cascade back into the suppressed seed + if neighbor_id == seed_id { + continue; + } + + let stability_factor = sys.cascade_stability_factor(edge.strength); + let retrieval_decrement = sys.cascade_retrieval_decrement(edge.strength); + + let rows = writer.execute( + "UPDATE knowledge_nodes SET + stability = MAX(0.1, stability * ?1), + retrieval_strength = MAX(0.05, retrieval_strength - ?2) + WHERE id = ?3 AND COALESCE(suppression_count, 0) = 0", + params![stability_factor, retrieval_decrement, neighbor_id], + )?; + affected += rows; + } + + Ok(affected) + } + + /// Sweep all recently-suppressed memories and apply Rac1 cascade to each. + /// Intended to run from the background consolidation loop every tick. + /// + /// Returns `(seeds_processed, neighbors_affected)`. + pub fn run_rac1_cascade_sweep(&self) -> Result<(usize, usize)> { + // 72h keeps the cascade window slightly longer than the 24h labile + // reversibility window — so suppressions that lock in continue to + // propagate for 48h after they become irreversible. + let seeds = self.get_recently_suppressed(72)?; + let mut total_affected = 0usize; + for seed in &seeds { + match self.apply_rac1_cascade(&seed.id) { + Ok(n) => total_affected += n, + Err(e) => tracing::warn!("Rac1 cascade failed for {}: {}", seed.id, e), + } + } + Ok((seeds.len(), total_affected)) + } + /// Get memories due for review pub fn get_review_queue(&self, limit: i32) -> Result> { let now = Utc::now().to_rfc3339(); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM knowledge_nodes @@ -1110,7 +1386,9 @@ impl Storage { scheduled_days: 0, }; - let scheduler = self.scheduler.lock() + let scheduler = self + .scheduler + .lock() .map_err(|_| StorageError::Init("Scheduler lock poisoned".into()))?; let elapsed_days = scheduler.days_since_review(¤t_state.last_review); @@ -1121,12 +1399,13 @@ impl Storage { pub fn get_stats(&self) -> Result { let now = Utc::now().to_rfc3339(); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let total: i64 = - reader - .query_row("SELECT COUNT(*) FROM knowledge_nodes", [], |row| row.get(0))?; + reader.query_row("SELECT COUNT(*) FROM knowledge_nodes", [], |row| row.get(0))?; let due: i64 = reader.query_row( "SELECT COUNT(*) FROM knowledge_nodes WHERE next_review <= ?1", @@ -1199,17 +1478,19 @@ impl Storage { /// Delete a node pub fn delete_node(&self, id: &str) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; - let rows = writer - .execute("DELETE FROM knowledge_nodes WHERE id = ?1", params![id])?; + let rows = writer.execute("DELETE FROM knowledge_nodes WHERE id = ?1", params![id])?; // Clean up vector index to prevent stale search results #[cfg(all(feature = "embeddings", feature = "vector-search"))] if rows > 0 - && let Ok(mut index) = self.vector_index.lock() { - let _ = index.remove(id); - } + && let Ok(mut index) = self.vector_index.lock() + { + let _ = index.remove(id); + } Ok(rows > 0) } @@ -1218,7 +1499,9 @@ impl Storage { pub fn search(&self, query: &str, limit: i32) -> Result> { let sanitized_query = sanitize_fts5_query(query); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT n.* FROM knowledge_nodes n @@ -1239,7 +1522,9 @@ impl Storage { /// Get all nodes (paginated) pub fn get_all_nodes(&self, limit: i32, offset: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM knowledge_nodes @@ -1266,7 +1551,9 @@ impl Storage { tag_filter: Option<&str>, limit: i32, ) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; match tag_filter { Some(tag) => { @@ -1337,7 +1624,9 @@ impl Storage { fn get_query_embedding(&self, query: &str) -> Result> { // Check cache first { - let mut cache = self.query_cache.lock() + let mut cache = self + .query_cache + .lock() .map_err(|_| StorageError::Init("Query cache lock poisoned".to_string()))?; if let Some(cached) = cache.get(query) { return Ok(cached.clone()); @@ -1345,12 +1634,16 @@ impl Storage { } // Not in cache, compute embedding - let embedding = self.embedding_service.embed(query) + let embedding = self + .embedding_service + .embed(query) .map_err(|e| StorageError::Init(format!("Failed to embed query: {}", e)))?; // Store in cache { - let mut cache = self.query_cache.lock() + let mut cache = self + .query_cache + .lock() .map_err(|_| StorageError::Init("Query cache lock poisoned".to_string()))?; cache.put(query.to_string(), embedding.vector.clone()); } @@ -1440,7 +1733,12 @@ impl Storage { }; let combined = if !semantic_results.is_empty() { - linear_combination(&keyword_results, &semantic_results, keyword_weight, semantic_weight) + linear_combination( + &keyword_results, + &semantic_results, + keyword_weight, + semantic_weight, + ) } else { keyword_results.clone() }; @@ -1505,12 +1803,16 @@ impl Storage { // ACT-R activation as importance signal (pre-computed during consolidation) let activation: f64 = self - .reader.lock() - .map(|r| r.query_row( - "SELECT COALESCE(activation, 0.0) FROM knowledge_nodes WHERE id = ?1", - params![result.node.id], - |row| row.get(0), - ).unwrap_or(0.0)) + .reader + .lock() + .map(|r| { + r.query_row( + "SELECT COALESCE(activation, 0.0) FROM knowledge_nodes WHERE id = ?1", + params![result.node.id], + |row| row.get(0), + ) + .unwrap_or(0.0) + }) .unwrap_or(0.0); // Normalize ACT-R activation [-2, 5] → [0, 1] let importance = ((activation + 2.0) / 7.0).clamp(0.0, 1.0); @@ -1548,9 +1850,8 @@ impl Storage { if let Some(includes) = include_types { if !includes.is_empty() { - let placeholders: Vec = (0..includes.len()) - .map(|i| format!("?{}", i + 3)) - .collect(); + let placeholders: Vec = + (0..includes.len()).map(|i| format!("?{}", i + 3)).collect(); type_clause = format!(" AND n.node_type IN ({})", placeholders.join(",")); type_values = includes.iter().map(|s| s.as_str()).collect(); } else { @@ -1558,9 +1859,8 @@ impl Storage { } } else if let Some(excludes) = exclude_types { if !excludes.is_empty() { - let placeholders: Vec = (0..excludes.len()) - .map(|i| format!("?{}", i + 3)) - .collect(); + let placeholders: Vec = + (0..excludes.len()).map(|i| format!("?{}", i + 3)).collect(); type_clause = format!(" AND n.node_type NOT IN ({})", placeholders.join(",")); type_values = excludes.iter().map(|s| s.as_str()).collect(); } else { @@ -1579,7 +1879,9 @@ impl Storage { type_clause ); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare(&sql)?; @@ -1671,7 +1973,9 @@ impl Storage { let mut result = EmbeddingResult::default(); let nodes: Vec<(String, String)> = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; if let Some(ids) = node_ids { let placeholders = ids.iter().map(|_| "?").collect::>().join(","); @@ -1696,8 +2000,7 @@ impl Storage { } result_nodes } else if force { - let mut stmt = reader - .prepare("SELECT id, content FROM knowledge_nodes")?; + let mut stmt = reader.prepare("SELECT id, content FROM knowledge_nodes")?; let rows = stmt.query_map([], |row| { Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?)) })?; @@ -1717,7 +2020,8 @@ impl Storage { for (id, content) in nodes { if !force { let has_emb: i32 = self - .reader.lock() + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))? .query_row( "SELECT COALESCE(has_embedding, 0) FROM knowledge_nodes WHERE id = ?1", @@ -1752,7 +2056,9 @@ impl Storage { ) -> Result> { let timestamp = point_in_time.to_rfc3339(); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM knowledge_nodes @@ -1821,7 +2127,9 @@ impl Storage { ), }; - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare(query)?; let params_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect(); @@ -1852,7 +2160,9 @@ impl Storage { loop { // Read batch using reader let batch: Vec<(String, String, f64, f64, f64, f64)> = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; reader .prepare( @@ -1884,7 +2194,9 @@ impl Storage { // Write batch using writer transaction { - let mut writer = self.writer.lock() + let mut writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let tx = writer.transaction()?; @@ -1900,12 +2212,12 @@ impl Storage { let effective_stability = stability * (1.0 + sentiment_mag * 0.5); // Real FSRS-6 retrievability with personalized w20 - let new_retrieval = retrievability_with_decay( - effective_stability, days_since, w20, - ); + let new_retrieval = + retrievability_with_decay(effective_stability, days_since, w20); // Use SleepConsolidation for retention calculation - let new_retention = sleep.calculate_retention(*storage_strength, new_retrieval); + let new_retention = + sleep.calculate_retention(*storage_strength, new_retrieval); tx.execute( "UPDATE knowledge_nodes SET retrieval_strength = ?1, retention_strength = ?2 WHERE id = ?3", @@ -1926,7 +2238,9 @@ impl Storage { /// Read personalized w20 from fsrs_config table fn get_fsrs_w20(&self) -> Result { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; reader .query_row( @@ -1960,20 +2274,24 @@ impl Storage { let mut promoted = 0i64; { let candidates: Vec<(String, f64, f64)> = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; reader .prepare( "SELECT id, sentiment_magnitude, storage_strength FROM knowledge_nodes - WHERE storage_strength < 10.0" + WHERE storage_strength < 10.0", )? .query_map([], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))? .filter_map(|r| r.ok()) .collect() }; - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; for (id, sentiment_mag, storage_strength) in &candidates { if sleep.should_promote(*sentiment_mag, *storage_strength) { @@ -2088,24 +2406,25 @@ impl Storage { { let service = crate::neuroscience::memory_states::StateUpdateService::new(); let all_nodes = self.get_all_nodes(500, 0).unwrap_or_default(); - let mut lifecycles: Vec = all_nodes - .iter() - .map(|n| { - let mut lc = crate::neuroscience::memory_states::MemoryLifecycle::new(); - lc.last_access = n.last_accessed; - lc.access_count = n.reps as u32; - lc.state = if n.retention_strength > 0.7 { - crate::neuroscience::memory_states::MemoryState::Active - } else if n.retention_strength > 0.3 { - crate::neuroscience::memory_states::MemoryState::Dormant - } else if n.retention_strength > 0.1 { - crate::neuroscience::memory_states::MemoryState::Silent - } else { - crate::neuroscience::memory_states::MemoryState::Unavailable - }; - lc - }) - .collect(); + let mut lifecycles: Vec = + all_nodes + .iter() + .map(|n| { + let mut lc = crate::neuroscience::memory_states::MemoryLifecycle::new(); + lc.last_access = n.last_accessed; + lc.access_count = n.reps as u32; + lc.state = if n.retention_strength > 0.7 { + crate::neuroscience::memory_states::MemoryState::Active + } else if n.retention_strength > 0.3 { + crate::neuroscience::memory_states::MemoryState::Dormant + } else if n.retention_strength > 0.1 { + crate::neuroscience::memory_states::MemoryState::Silent + } else { + crate::neuroscience::memory_states::MemoryState::Unavailable + }; + lc + }) + .collect(); let batch_result = service.batch_update(&mut lifecycles); _state_transitions = batch_result.total_transitions as i64; } @@ -2141,11 +2460,12 @@ impl Storage { // 16. FTS5 index optimization — merge segments for faster keyword search // 17. Run PRAGMA optimize to refresh query planner statistics { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; - let _ = writer.execute_batch( - "INSERT INTO knowledge_fts(knowledge_fts) VALUES('optimize');" - ); + let _ = writer + .execute_batch("INSERT INTO knowledge_fts(knowledge_fts) VALUES('optimize');"); let _ = writer.execute_batch("PRAGMA optimize;"); } @@ -2191,7 +2511,9 @@ impl Storage { // Record consolidation history { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let _ = writer.execute( "INSERT INTO consolidation_history (completed_at, duration_ms, memories_replayed, duplicates_merged, activations_computed, w20_optimized) @@ -2249,8 +2571,10 @@ impl Storage { if consumed.contains(&all_embeddings[j].0) { continue; } - let sim = - crate::embeddings::cosine_similarity(&all_embeddings[i].1, &all_embeddings[j].1); + let sim = crate::embeddings::cosine_similarity( + &all_embeddings[i].1, + &all_embeddings[j].1, + ); if sim >= SIMILARITY_THRESHOLD { cluster.push((j, sim)); } @@ -2262,7 +2586,9 @@ impl Storage { // Find the strongest node (highest retention_strength) let anchor_id = &all_embeddings[i].0; - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let anchor_retention: f64 = reader .query_row( @@ -2358,7 +2684,9 @@ impl Storage { let now = Utc::now(); let node_ids: Vec = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; reader .prepare("SELECT DISTINCT node_id FROM memory_access_log")? @@ -2372,7 +2700,9 @@ impl Storage { } let mut count = 0i64; - let mut writer = self.writer.lock() + let mut writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let tx = writer.transaction()?; @@ -2418,7 +2748,9 @@ impl Storage { /// Prune old access log entries (keep last 90 days) fn prune_access_log(&self) -> Result { let cutoff = (Utc::now() - Duration::days(90)).to_rfc3339(); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let deleted = writer.execute( "DELETE FROM memory_access_log WHERE accessed_at < ?1", @@ -2432,15 +2764,15 @@ impl Storage { fn optimize_w20_if_ready(&self) -> Result> { use crate::fsrs::{FSRSOptimizer, ReviewLog}; - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let access_count: i64 = reader - .query_row( - "SELECT COUNT(*) FROM memory_access_log", - [], - |row| row.get(0), - ) + .query_row("SELECT COUNT(*) FROM memory_access_log", [], |row| { + row.get(0) + }) .unwrap_or(0); if access_count < 100 { @@ -2508,7 +2840,9 @@ impl Storage { // Save to config { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO fsrs_config (key, value, updated_at) @@ -2517,7 +2851,10 @@ impl Storage { )?; } - tracing::info!(w20 = optimized_w20, "Personalized w20 optimized from access history"); + tracing::info!( + w20 = optimized_w20, + "Personalized w20 optimized from access history" + ); Ok(Some(optimized_w20)) } @@ -2526,13 +2863,16 @@ impl Storage { #[cfg(all(feature = "embeddings", feature = "vector-search"))] fn generate_missing_embeddings(&self) -> Result { if !self.embedding_service.is_ready() - && let Err(e) = self.embedding_service.init() { - tracing::warn!("Could not initialize embedding model: {}", e); - return Ok(0); - } + && let Err(e) = self.embedding_service.init() + { + tracing::warn!("Could not initialize embedding model: {}", e); + return Ok(0); + } let nodes: Vec<(String, String)> = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; reader .prepare( @@ -2569,7 +2909,7 @@ pub struct IntentionRecord { pub id: String, pub content: String, pub trigger_type: String, - pub trigger_data: String, // JSON + pub trigger_data: String, // JSON pub priority: i32, pub status: String, pub created_at: DateTime, @@ -2633,7 +2973,7 @@ pub struct ConnectionRecord { #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct MemoryStateRecord { pub memory_id: String, - pub state: String, // 'active', 'dormant', 'silent', 'unavailable' + pub state: String, // 'active', 'dormant', 'silent', 'unavailable' pub last_access: DateTime, pub access_count: i32, pub state_entered_at: DateTime, @@ -2694,9 +3034,12 @@ impl Storage { /// Save an intention to the database pub fn save_intention(&self, intention: &IntentionRecord) -> Result<()> { let tags_json = serde_json::to_string(&intention.tags).unwrap_or_else(|_| "[]".to_string()); - let related_json = serde_json::to_string(&intention.related_memories).unwrap_or_else(|_| "[]".to_string()); + let related_json = + serde_json::to_string(&intention.related_memories).unwrap_or_else(|_| "[]".to_string()); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO intentions ( @@ -2729,11 +3072,11 @@ impl Storage { /// Get an intention by ID pub fn get_intention(&self, id: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM intentions WHERE id = ?1" - )?; + let mut stmt = reader.prepare("SELECT * FROM intentions WHERE id = ?1")?; stmt.query_row(params![id], Self::row_to_intention) .optional() @@ -2742,7 +3085,9 @@ impl Storage { /// Get all active intentions pub fn get_active_intentions(&self) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM intentions WHERE status = 'active' ORDER BY priority DESC, created_at ASC" @@ -2758,10 +3103,12 @@ impl Storage { /// Get intentions by status pub fn get_intentions_by_status(&self, status: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( - "SELECT * FROM intentions WHERE status = ?1 ORDER BY priority DESC, created_at ASC" + "SELECT * FROM intentions WHERE status = ?1 ORDER BY priority DESC, created_at ASC", )?; let rows = stmt.query_map(params![status], Self::row_to_intention)?; @@ -2775,9 +3122,15 @@ impl Storage { /// Update intention status pub fn update_intention_status(&self, id: &str, status: &str) -> Result { let now = Utc::now(); - let fulfilled_at = if status == "fulfilled" { Some(now.to_rfc3339()) } else { None }; + let fulfilled_at = if status == "fulfilled" { + Some(now.to_rfc3339()) + } else { + None + }; - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE intentions SET status = ?1, fulfilled_at = ?2 WHERE id = ?3", @@ -2788,7 +3141,9 @@ impl Storage { /// Delete an intention pub fn delete_intention(&self, id: &str) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute("DELETE FROM intentions WHERE id = ?1", params![id])?; Ok(rows > 0) @@ -2797,7 +3152,9 @@ impl Storage { /// Get overdue intentions pub fn get_overdue_intentions(&self) -> Result> { let now = Utc::now().to_rfc3339(); - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM intentions WHERE status = 'active' AND deadline IS NOT NULL AND deadline < ?1 ORDER BY deadline ASC" @@ -2813,7 +3170,9 @@ impl Storage { /// Snooze an intention pub fn snooze_intention(&self, id: &str, until: DateTime) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE intentions SET status = 'snoozed', snoozed_until = ?1 WHERE id = ?2", @@ -2829,7 +3188,11 @@ impl Storage { let related: Vec = serde_json::from_str(&related_json).unwrap_or_default(); let parse_opt_dt = |s: Option| -> Option> { - s.and_then(|v| DateTime::parse_from_rfc3339(&v).ok().map(|dt| dt.with_timezone(&Utc))) + s.and_then(|v| { + DateTime::parse_from_rfc3339(&v) + .ok() + .map(|dt| dt.with_timezone(&Utc)) + }) }; Ok(IntentionRecord { @@ -2861,10 +3224,13 @@ impl Storage { /// Save an insight to the database pub fn save_insight(&self, insight: &InsightRecord) -> Result<()> { - let source_json = serde_json::to_string(&insight.source_memories).unwrap_or_else(|_| "[]".to_string()); + let source_json = + serde_json::to_string(&insight.source_memories).unwrap_or_else(|_| "[]".to_string()); let tags_json = serde_json::to_string(&insight.tags).unwrap_or_else(|_| "[]".to_string()); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO insights ( @@ -2889,11 +3255,12 @@ impl Storage { /// Get insights with optional limit pub fn get_insights(&self, limit: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM insights ORDER BY generated_at DESC LIMIT ?1" - )?; + let mut stmt = + reader.prepare("SELECT * FROM insights ORDER BY generated_at DESC LIMIT ?1")?; let rows = stmt.query_map(params![limit], Self::row_to_insight)?; let mut result = Vec::new(); @@ -2905,11 +3272,12 @@ impl Storage { /// Get insights without feedback (pending review) pub fn get_pending_insights(&self) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM insights WHERE feedback IS NULL ORDER BY novelty_score DESC" - )?; + let mut stmt = reader + .prepare("SELECT * FROM insights WHERE feedback IS NULL ORDER BY novelty_score DESC")?; let rows = stmt.query_map([], Self::row_to_insight)?; let mut result = Vec::new(); @@ -2921,7 +3289,9 @@ impl Storage { /// Mark insight feedback pub fn mark_insight_feedback(&self, id: &str, feedback: &str) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE insights SET feedback = ?1 WHERE id = ?2", @@ -2932,7 +3302,9 @@ impl Storage { /// Clear all insights pub fn clear_insights(&self) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let count: i32 = writer.query_row("SELECT COUNT(*) FROM insights", [], |row| row.get(0))?; writer.execute("DELETE FROM insights", [])?; @@ -2967,7 +3339,9 @@ impl Storage { /// Save a memory connection pub fn save_connection(&self, connection: &ConnectionRecord) -> Result<()> { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO memory_connections ( @@ -2988,7 +3362,9 @@ impl Storage { /// Get connections for a memory pub fn get_connections_for_memory(&self, memory_id: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM memory_connections WHERE source_id = ?1 OR target_id = ?1 ORDER BY strength DESC" @@ -3004,11 +3380,11 @@ impl Storage { /// Get all connections (for building activation network) pub fn get_all_connections(&self) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM memory_connections ORDER BY strength DESC" - )?; + let mut stmt = reader.prepare("SELECT * FROM memory_connections ORDER BY strength DESC")?; let rows = stmt.query_map([], Self::row_to_connection)?; let mut result = Vec::new(); @@ -3019,9 +3395,16 @@ impl Storage { } /// Strengthen a connection - pub fn strengthen_connection(&self, source_id: &str, target_id: &str, boost: f64) -> Result { + pub fn strengthen_connection( + &self, + source_id: &str, + target_id: &str, + boost: f64, + ) -> Result { let now = Utc::now().to_rfc3339(); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE memory_connections SET @@ -3036,7 +3419,9 @@ impl Storage { /// Apply decay to all connections pub fn apply_connection_decay(&self, decay_factor: f64) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE memory_connections SET strength = strength * ?1", @@ -3047,7 +3432,9 @@ impl Storage { /// Prune weak connections below threshold pub fn prune_weak_connections(&self, min_strength: f64) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "DELETE FROM memory_connections WHERE strength < ?1", @@ -3078,9 +3465,12 @@ impl Storage { /// Save or update memory state pub fn save_memory_state(&self, state: &MemoryStateRecord) -> Result<()> { - let suppressed_json = serde_json::to_string(&state.suppressed_by).unwrap_or_else(|_| "[]".to_string()); + let suppressed_json = + serde_json::to_string(&state.suppressed_by).unwrap_or_else(|_| "[]".to_string()); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT OR REPLACE INTO memory_states ( @@ -3102,11 +3492,11 @@ impl Storage { /// Get memory state pub fn get_memory_state(&self, memory_id: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM memory_states WHERE memory_id = ?1" - )?; + let mut stmt = reader.prepare("SELECT * FROM memory_states WHERE memory_id = ?1")?; stmt.query_row(params![memory_id], Self::row_to_memory_state) .optional() @@ -3115,11 +3505,11 @@ impl Storage { /// Get memories by state pub fn get_memories_by_state(&self, state: &str) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT memory_id FROM memory_states WHERE state = ?1" - )?; + let mut stmt = reader.prepare("SELECT memory_id FROM memory_states WHERE state = ?1")?; let rows = stmt.query_map(params![state], |row| row.get::<_, String>(0))?; let mut result = Vec::new(); @@ -3130,13 +3520,20 @@ impl Storage { } /// Update memory state - pub fn update_memory_state(&self, memory_id: &str, new_state: &str, reason: &str) -> Result { + pub fn update_memory_state( + &self, + memory_id: &str, + new_state: &str, + reason: &str, + ) -> Result { let now = Utc::now(); // Get old state for transition record if let Some(old_record) = self.get_memory_state(memory_id)? { // Record state transition - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO state_transitions (memory_id, from_state, to_state, reason_type, timestamp) @@ -3145,7 +3542,9 @@ impl Storage { )?; } - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let rows = writer.execute( "UPDATE memory_states SET state = ?1, state_entered_at = ?2 WHERE memory_id = ?3", @@ -3158,7 +3557,9 @@ impl Storage { pub fn record_memory_access(&self, memory_id: &str) -> Result<()> { let now = Utc::now(); - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; // Check if state exists (writer can read too) @@ -3193,7 +3594,11 @@ impl Storage { let suppressed_by: Vec = serde_json::from_str(&suppressed_json).unwrap_or_default(); let parse_opt_dt = |s: Option| -> Option> { - s.and_then(|v| DateTime::parse_from_rfc3339(&v).ok().map(|dt| dt.with_timezone(&Utc))) + s.and_then(|v| { + DateTime::parse_from_rfc3339(&v) + .ok() + .map(|dt| dt.with_timezone(&Utc)) + }) }; Ok(MemoryStateRecord { @@ -3203,9 +3608,11 @@ impl Storage { .map(|dt| dt.with_timezone(&Utc)) .unwrap_or_else(|_| Utc::now()), access_count: row.get("access_count").unwrap_or(1), - state_entered_at: DateTime::parse_from_rfc3339(&row.get::<_, String>("state_entered_at")?) - .map(|dt| dt.with_timezone(&Utc)) - .unwrap_or_else(|_| Utc::now()), + state_entered_at: DateTime::parse_from_rfc3339( + &row.get::<_, String>("state_entered_at")?, + ) + .map(|dt| dt.with_timezone(&Utc)) + .unwrap_or_else(|_| Utc::now()), suppression_until: parse_opt_dt(row.get("suppression_until").ok().flatten()), suppressed_by, }) @@ -3217,7 +3624,9 @@ impl Storage { /// Save consolidation history record pub fn save_consolidation_history(&self, record: &ConsolidationHistoryRecord) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO consolidation_history ( @@ -3239,26 +3648,34 @@ impl Storage { /// Get last consolidation timestamp pub fn get_last_consolidation(&self) -> Result>> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let result: Option = reader.query_row( - "SELECT MAX(completed_at) FROM consolidation_history", - [], - |row| row.get(0), - ).ok().flatten(); + let result: Option = reader + .query_row( + "SELECT MAX(completed_at) FROM consolidation_history", + [], + |row| row.get(0), + ) + .ok() + .flatten(); Ok(result.and_then(|s| { - DateTime::parse_from_rfc3339(&s).ok().map(|dt| dt.with_timezone(&Utc)) + DateTime::parse_from_rfc3339(&s) + .ok() + .map(|dt| dt.with_timezone(&Utc)) })) } /// Get consolidation history pub fn get_consolidation_history(&self, limit: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM consolidation_history ORDER BY completed_at DESC LIMIT ?1" - )?; + let mut stmt = reader + .prepare("SELECT * FROM consolidation_history ORDER BY completed_at DESC LIMIT ?1")?; let rows = stmt.query_map(params![limit], |row| { Ok(ConsolidationHistoryRecord { @@ -3288,7 +3705,9 @@ impl Storage { /// Save a dream history record pub fn save_dream_history(&self, record: &DreamHistoryRecord) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO dream_history ( @@ -3319,58 +3738,69 @@ impl Storage { /// Get last dream timestamp pub fn get_last_dream(&self) -> Result>> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let result: Option = reader.query_row( - "SELECT MAX(dreamed_at) FROM dream_history", - [], - |row| row.get(0), - ).ok().flatten(); + let result: Option = reader + .query_row("SELECT MAX(dreamed_at) FROM dream_history", [], |row| { + row.get(0) + }) + .ok() + .flatten(); Ok(result.and_then(|s| { - DateTime::parse_from_rfc3339(&s).ok().map(|dt| dt.with_timezone(&Utc)) + DateTime::parse_from_rfc3339(&s) + .ok() + .map(|dt| dt.with_timezone(&Utc)) })) } /// Get dream history (most recent first) pub fn get_dream_history(&self, limit: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT dreamed_at, duration_ms, memories_replayed, connections_found, insights_generated, memories_strengthened, memories_compressed, phase_nrem1_ms, phase_nrem3_ms, phase_rem_ms, phase_integration_ms, summaries_generated, emotional_memories_processed, creative_connections_found - FROM dream_history ORDER BY dreamed_at DESC LIMIT ?1" + FROM dream_history ORDER BY dreamed_at DESC LIMIT ?1", )?; - let records = stmt.query_map(params![limit], |row| { - let dreamed_at_str: String = row.get(0)?; - let dreamed_at = DateTime::parse_from_rfc3339(&dreamed_at_str) - .map(|dt| dt.with_timezone(&Utc)) - .unwrap_or_else(|_| Utc::now()); - Ok(DreamHistoryRecord { - dreamed_at, - duration_ms: row.get(1)?, - memories_replayed: row.get(2)?, - connections_found: row.get(3)?, - insights_generated: row.get(4)?, - memories_strengthened: row.get(5)?, - memories_compressed: row.get(6)?, - phase_nrem1_ms: row.get(7)?, - phase_nrem3_ms: row.get(8)?, - phase_rem_ms: row.get(9)?, - phase_integration_ms: row.get(10)?, - summaries_generated: row.get(11)?, - emotional_memories_processed: row.get(12)?, - creative_connections_found: row.get(13)?, - }) - })?.collect::, _>>()?; + let records = stmt + .query_map(params![limit], |row| { + let dreamed_at_str: String = row.get(0)?; + let dreamed_at = DateTime::parse_from_rfc3339(&dreamed_at_str) + .map(|dt| dt.with_timezone(&Utc)) + .unwrap_or_else(|_| Utc::now()); + Ok(DreamHistoryRecord { + dreamed_at, + duration_ms: row.get(1)?, + memories_replayed: row.get(2)?, + connections_found: row.get(3)?, + insights_generated: row.get(4)?, + memories_strengthened: row.get(5)?, + memories_compressed: row.get(6)?, + phase_nrem1_ms: row.get(7)?, + phase_nrem3_ms: row.get(8)?, + phase_rem_ms: row.get(9)?, + phase_integration_ms: row.get(10)?, + summaries_generated: row.get(11)?, + emotional_memories_processed: row.get(12)?, + creative_connections_found: row.get(13)?, + }) + })? + .collect::, _>>()?; Ok(records) } /// Count memories created since a given timestamp pub fn count_memories_since(&self, since: DateTime) -> Result { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let count: i64 = reader.query_row( "SELECT COUNT(*) FROM knowledge_nodes WHERE created_at >= ?1", @@ -3397,13 +3827,17 @@ impl Storage { let name = entry.file_name(); let name_str = name.to_string_lossy(); // Parse vestige-YYYYMMDD-HHMMSS.db - if let Some(ts_part) = name_str.strip_prefix("vestige-").and_then(|s| s.strip_suffix(".db")) - && let Ok(naive) = chrono::NaiveDateTime::parse_from_str(ts_part, "%Y%m%d-%H%M%S") { - let dt = naive.and_utc(); - if latest.as_ref().is_none_or(|l| dt > *l) { - latest = Some(dt); - } + if let Some(ts_part) = name_str + .strip_prefix("vestige-") + .and_then(|s| s.strip_suffix(".db")) + && let Ok(naive) = + chrono::NaiveDateTime::parse_from_str(ts_part, "%Y%m%d-%H%M%S") + { + let dt = naive.and_utc(); + if latest.as_ref().is_none_or(|l| dt > *l) { + latest = Some(dt); } + } } } @@ -3415,11 +3849,17 @@ impl Storage { // ======================================================================== /// Get state transitions for a memory - pub fn get_state_transitions(&self, memory_id: &str, limit: i32) -> Result> { - let reader = self.reader.lock() + pub fn get_state_transitions( + &self, + memory_id: &str, + limit: i32, + ) -> Result> { + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( - "SELECT * FROM state_transitions WHERE memory_id = ?1 ORDER BY timestamp DESC LIMIT ?2" + "SELECT * FROM state_transitions WHERE memory_id = ?1 ORDER BY timestamp DESC LIMIT ?2", )?; let rows = stmt.query_map(params![memory_id, limit], |row| { @@ -3445,14 +3885,18 @@ impl Storage { /// Create a consistent backup using VACUUM INTO pub fn backup_to(&self, path: &std::path::Path) -> Result<()> { - let path_str = path.to_str().ok_or_else(|| { - StorageError::Init("Invalid backup path encoding".to_string()) - })?; + let path_str = path + .to_str() + .ok_or_else(|| StorageError::Init("Invalid backup path encoding".to_string()))?; // Validate path: reject control characters (except tab) for defense-in-depth if path_str.bytes().any(|b| b < 0x20 && b != b'\t') { - return Err(StorageError::Init("Backup path contains invalid characters".to_string())); + return Err(StorageError::Init( + "Backup path contains invalid characters".to_string(), + )); } - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; // VACUUM INTO doesn't support parameterized queries; escape single quotes reader.execute_batch(&format!("VACUUM INTO '{}'", path_str.replace('\'', "''")))?; @@ -3465,7 +3909,9 @@ impl Storage { /// Get average retention across all memories pub fn get_avg_retention(&self) -> Result { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let avg: f64 = reader.query_row( "SELECT COALESCE(AVG(retention_strength), 0.0) FROM knowledge_nodes", @@ -3477,7 +3923,9 @@ impl Storage { /// Get retention distribution in buckets (0-20%, 20-40%, 40-60%, 60-80%, 80-100%) pub fn get_retention_distribution(&self) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT @@ -3491,7 +3939,7 @@ impl Storage { COUNT(*) as count FROM knowledge_nodes GROUP BY bucket - ORDER BY bucket" + ORDER BY bucket", )?; let rows = stmt.query_map([], |row| { @@ -3507,12 +3955,16 @@ impl Storage { /// Get retention trend (improving/declining/stable) from retention snapshots pub fn get_retention_trend(&self) -> Result { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let snapshots: Vec = reader.prepare( - "SELECT avg_retention FROM retention_snapshots ORDER BY snapshot_at DESC LIMIT 5" - )?.query_map([], |row| row.get(0))? + let snapshots: Vec = reader + .prepare( + "SELECT avg_retention FROM retention_snapshots ORDER BY snapshot_at DESC LIMIT 5", + )? + .query_map([], |row| row.get(0))? .filter_map(|r| r.ok()) .collect(); @@ -3535,8 +3987,16 @@ impl Storage { } /// Save a retention snapshot (called during consolidation) - pub fn save_retention_snapshot(&self, avg_retention: f64, total: i64, below_target: i64, gc_triggered: bool) -> Result<()> { - let writer = self.writer.lock() + pub fn save_retention_snapshot( + &self, + avg_retention: f64, + total: i64, + below_target: i64, + gc_triggered: bool, + ) -> Result<()> { + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "INSERT INTO retention_snapshots (snapshot_at, avg_retention, total_memories, memories_below_target, gc_triggered) @@ -3548,7 +4008,9 @@ impl Storage { /// Count memories below a given retention threshold pub fn count_memories_below_retention(&self, threshold: f64) -> Result { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let count: i64 = reader.query_row( "SELECT COUNT(*) FROM knowledge_nodes WHERE retention_strength < ?1", @@ -3565,7 +4027,9 @@ impl Storage { // Collect IDs first for vector index cleanup #[cfg(all(feature = "embeddings", feature = "vector-search"))] let doomed_ids: Vec = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT id FROM knowledge_nodes WHERE retention_strength < ?1 AND created_at < ?2", @@ -3575,7 +4039,9 @@ impl Storage { .collect() }; - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let deleted = writer.execute( "DELETE FROM knowledge_nodes WHERE retention_strength < ?1 AND created_at < ?2", @@ -3586,11 +4052,12 @@ impl Storage { // Clean up vector index #[cfg(all(feature = "embeddings", feature = "vector-search"))] if deleted > 0 - && let Ok(mut index) = self.vector_index.lock() { - for id in &doomed_ids { - let _ = index.remove(id); - } + && let Ok(mut index) = self.vector_index.lock() + { + for id in &doomed_ids { + let _ = index.remove(id); } + } Ok(deleted) } @@ -3602,14 +4069,16 @@ impl Storage { // Find memories with 3+ accesses in last 24h let candidates: Vec = { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT node_id, COUNT(*) as access_count FROM memory_access_log WHERE accessed_at >= ?1 GROUP BY node_id - HAVING access_count >= 3" + HAVING access_count >= 3", )?; stmt.query_map(params![twenty_four_hours_ago], |row| row.get(0))? .filter_map(|r| r.ok()) @@ -3620,7 +4089,9 @@ impl Storage { return Ok(0); } - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let mut promoted = 0i64; for id in &candidates { @@ -3642,7 +4113,9 @@ impl Storage { /// Set waking tag on a memory (marks it for preferential dream replay) pub fn set_waking_tag(&self, memory_id: &str) -> Result<()> { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; writer.execute( "UPDATE knowledge_nodes SET waking_tag = TRUE, waking_tag_at = ?1 WHERE id = ?2", @@ -3653,7 +4126,9 @@ impl Storage { /// Clear waking tags (called after dream processes them) pub fn clear_waking_tags(&self) -> Result { - let writer = self.writer.lock() + let writer = self + .writer + .lock() .map_err(|_| StorageError::Init("Writer lock poisoned".into()))?; let cleared = writer.execute( "UPDATE knowledge_nodes SET waking_tag = FALSE, waking_tag_at = NULL WHERE waking_tag = TRUE", @@ -3664,7 +4139,9 @@ impl Storage { /// Get waking-tagged memories for preferential dream replay pub fn get_waking_tagged_memories(&self, limit: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT * FROM knowledge_nodes WHERE waking_tag = TRUE ORDER BY waking_tag_at DESC LIMIT ?1" @@ -3679,21 +4156,30 @@ impl Storage { /// Get the memory with the most connections (best center node for graph visualization) pub fn get_most_connected_memory(&self) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; let mut stmt = reader.prepare( "SELECT id, COUNT(*) as cnt FROM ( SELECT source_id as id FROM memory_connections UNION ALL SELECT target_id as id FROM memory_connections - ) GROUP BY id ORDER BY cnt DESC LIMIT 1" + ) GROUP BY id ORDER BY cnt DESC LIMIT 1", )?; - let result = stmt.query_row([], |row| row.get::<_, String>(0)).optional()?; + let result = stmt + .query_row([], |row| row.get::<_, String>(0)) + .optional()?; Ok(result) } /// Get memories with their connection data for graph visualization - pub fn get_memory_subgraph(&self, center_id: &str, depth: u32, max_nodes: usize) -> Result<(Vec, Vec)> { + pub fn get_memory_subgraph( + &self, + center_id: &str, + depth: u32, + max_nodes: usize, + ) -> Result<(Vec, Vec)> { let mut visited_ids: std::collections::HashSet = std::collections::HashSet::new(); let mut frontier = vec![center_id.to_string()]; visited_ids.insert(center_id.to_string()); @@ -3704,7 +4190,11 @@ impl Storage { for id in &frontier { let connections = self.get_connections_for_memory(id)?; for conn in &connections { - let other_id = if conn.source_id == *id { &conn.target_id } else { &conn.source_id }; + let other_id = if conn.source_id == *id { + &conn.target_id + } else { + &conn.source_id + }; if visited_ids.insert(other_id.clone()) { next_frontier.push(other_id.clone()); if visited_ids.len() >= max_nodes { @@ -3742,11 +4232,12 @@ impl Storage { /// Get recent state transitions across all memories (system-wide changelog) pub fn get_recent_state_transitions(&self, limit: i32) -> Result> { - let reader = self.reader.lock() + let reader = self + .reader + .lock() .map_err(|_| StorageError::Init("Reader lock poisoned".into()))?; - let mut stmt = reader.prepare( - "SELECT * FROM state_transitions ORDER BY timestamp DESC LIMIT ?1" - )?; + let mut stmt = + reader.prepare("SELECT * FROM state_transitions ORDER BY timestamp DESC LIMIT ?1")?; let rows = stmt.query_map(params![limit], |row| { Ok(StateTransitionRecord { @@ -3908,11 +4399,13 @@ mod tests { let before = Utc::now() - Duration::seconds(10); for i in 0..5 { - storage.ingest(IngestInput { - content: format!("Count test memory {}", i), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: format!("Count test memory {}", i), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); } let count = storage.count_memories_since(before).unwrap(); @@ -3934,33 +4427,41 @@ mod tests { let storage = create_test_storage(); // Ingest nodes of different types all containing the word "quantum" - storage.ingest(IngestInput { - content: "Quantum mechanics is fundamental to physics".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); - storage.ingest(IngestInput { - content: "Quantum computing uses qubits for calculation".to_string(), - node_type: "concept".to_string(), - ..Default::default() - }).unwrap(); - storage.ingest(IngestInput { - content: "Quantum entanglement was demonstrated in the lab".to_string(), - node_type: "event".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: "Quantum mechanics is fundamental to physics".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); + storage + .ingest(IngestInput { + content: "Quantum computing uses qubits for calculation".to_string(), + node_type: "concept".to_string(), + ..Default::default() + }) + .unwrap(); + storage + .ingest(IngestInput { + content: "Quantum entanglement was demonstrated in the lab".to_string(), + node_type: "event".to_string(), + ..Default::default() + }) + .unwrap(); // Search with include_types = ["fact"] — should only return the fact let include = vec!["fact".to_string()]; - let results = storage.hybrid_search_filtered( - "quantum", 10, 0.3, 0.7, - Some(&include), None, - ).unwrap(); + let results = storage + .hybrid_search_filtered("quantum", 10, 0.3, 0.7, Some(&include), None) + .unwrap(); assert!(!results.is_empty(), "should return at least one result"); for r in &results { - assert_eq!(r.node.node_type, "fact", - "include_types=[fact] should only return facts, got: {}", r.node.node_type); + assert_eq!( + r.node.node_type, "fact", + "include_types=[fact] should only return facts, got: {}", + r.node.node_type + ); } } @@ -3968,28 +4469,33 @@ mod tests { fn test_keyword_search_with_exclude_types() { let storage = create_test_storage(); - storage.ingest(IngestInput { - content: "Photosynthesis converts sunlight to energy".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); - storage.ingest(IngestInput { - content: "Photosynthesis is a complex biochemical process".to_string(), - node_type: "reflection".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: "Photosynthesis converts sunlight to energy".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); + storage + .ingest(IngestInput { + content: "Photosynthesis is a complex biochemical process".to_string(), + node_type: "reflection".to_string(), + ..Default::default() + }) + .unwrap(); // Search with exclude_types = ["reflection"] — should skip the reflection let exclude = vec!["reflection".to_string()]; - let results = storage.hybrid_search_filtered( - "photosynthesis", 10, 0.3, 0.7, - None, Some(&exclude), - ).unwrap(); + let results = storage + .hybrid_search_filtered("photosynthesis", 10, 0.3, 0.7, None, Some(&exclude)) + .unwrap(); assert!(!results.is_empty(), "should return at least one result"); for r in &results { - assert_ne!(r.node.node_type, "reflection", - "exclude_types=[reflection] should not return reflections"); + assert_ne!( + r.node.node_type, "reflection", + "exclude_types=[reflection] should not return reflections" + ); } } @@ -3997,24 +4503,27 @@ mod tests { fn test_include_types_takes_precedence_over_exclude() { let storage = create_test_storage(); - storage.ingest(IngestInput { - content: "Gravity holds planets in orbit around stars".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); - storage.ingest(IngestInput { - content: "Gravity waves were first detected by LIGO".to_string(), - node_type: "event".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: "Gravity holds planets in orbit around stars".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); + storage + .ingest(IngestInput { + content: "Gravity waves were first detected by LIGO".to_string(), + node_type: "event".to_string(), + ..Default::default() + }) + .unwrap(); // When both are provided, include_types wins let include = vec!["fact".to_string()]; let exclude = vec!["fact".to_string()]; - let results = storage.hybrid_search_filtered( - "gravity", 10, 0.3, 0.7, - Some(&include), Some(&exclude), - ).unwrap(); + let results = storage + .hybrid_search_filtered("gravity", 10, 0.3, 0.7, Some(&include), Some(&exclude)) + .unwrap(); // include_types takes precedence — facts should be returned assert!(!results.is_empty()); @@ -4027,21 +4536,24 @@ mod tests { fn test_type_filter_with_no_matches_returns_empty() { let storage = create_test_storage(); - storage.ingest(IngestInput { - content: "DNA carries genetic information in cells".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: "DNA carries genetic information in cells".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); // Search for a type that doesn't exist among matches let include = vec!["person".to_string()]; - let results = storage.hybrid_search_filtered( - "DNA", 10, 0.3, 0.7, - Some(&include), None, - ).unwrap(); + let results = storage + .hybrid_search_filtered("DNA", 10, 0.3, 0.7, Some(&include), None) + .unwrap(); - assert!(results.is_empty(), - "filtering for a non-matching type should return empty results"); + assert!( + results.is_empty(), + "filtering for a non-matching type should return empty results" + ); } #[test] @@ -4049,11 +4561,13 @@ mod tests { // Ensure the original hybrid_search (no type filters) still works let storage = create_test_storage(); - storage.ingest(IngestInput { - content: "Neurons transmit electrical signals in the brain".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap(); + storage + .ingest(IngestInput { + content: "Neurons transmit electrical signals in the brain".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap(); let results = storage.hybrid_search("neurons", 10, 0.3, 0.7).unwrap(); assert!(!results.is_empty()); diff --git a/crates/vestige-mcp/Cargo.toml b/crates/vestige-mcp/Cargo.toml index f93ef2c..a8851f8 100644 --- a/crates/vestige-mcp/Cargo.toml +++ b/crates/vestige-mcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vestige-mcp" -version = "2.0.4" +version = "2.0.5" edition = "2024" description = "Cognitive memory MCP server for Claude - FSRS-6, spreading activation, synaptic tagging, 3D dashboard, and 130 years of memory research" authors = ["samvallad33"] diff --git a/crates/vestige-mcp/src/bin/cli.rs b/crates/vestige-mcp/src/bin/cli.rs index ecb278e..eeffe54 100644 --- a/crates/vestige-mcp/src/bin/cli.rs +++ b/crates/vestige-mcp/src/bin/cli.rs @@ -18,7 +18,9 @@ use vestige_core::{IngestInput, Storage}; #[command(author = "samvallad33")] #[command(version = env!("CARGO_PKG_VERSION"))] #[command(about = "CLI for the Vestige cognitive memory system")] -#[command(long_about = "Vestige is a cognitive memory system based on 130 years of memory research.\n\nIt implements FSRS-6, spreading activation, synaptic tagging, and more.")] +#[command( + long_about = "Vestige is a cognitive memory system based on 130 years of memory research.\n\nIt implements FSRS-6, spreading activation, synaptic tagging, and more." +)] struct Cli { #[command(subcommand)] command: Commands, @@ -171,21 +173,49 @@ fn run_stats(show_tagging: bool, show_states: bool) -> anyhow::Result<()> { // Basic stats println!("{}: {}", "Total Memories".white().bold(), stats.total_nodes); - println!("{}: {}", "Due for Review".white().bold(), stats.nodes_due_for_review); - println!("{}: {:.1}%", "Average Retention".white().bold(), stats.average_retention * 100.0); - println!("{}: {:.2}", "Average Storage Strength".white().bold(), stats.average_storage_strength); - println!("{}: {:.2}", "Average Retrieval Strength".white().bold(), stats.average_retrieval_strength); - println!("{}: {}", "With Embeddings".white().bold(), stats.nodes_with_embeddings); + println!( + "{}: {}", + "Due for Review".white().bold(), + stats.nodes_due_for_review + ); + println!( + "{}: {:.1}%", + "Average Retention".white().bold(), + stats.average_retention * 100.0 + ); + println!( + "{}: {:.2}", + "Average Storage Strength".white().bold(), + stats.average_storage_strength + ); + println!( + "{}: {:.2}", + "Average Retrieval Strength".white().bold(), + stats.average_retrieval_strength + ); + println!( + "{}: {}", + "With Embeddings".white().bold(), + stats.nodes_with_embeddings + ); if let Some(model) = &stats.embedding_model { println!("{}: {}", "Embedding Model".white().bold(), model); } if let Some(oldest) = stats.oldest_memory { - println!("{}: {}", "Oldest Memory".white().bold(), oldest.format("%Y-%m-%d %H:%M:%S")); + println!( + "{}: {}", + "Oldest Memory".white().bold(), + oldest.format("%Y-%m-%d %H:%M:%S") + ); } if let Some(newest) = stats.newest_memory { - println!("{}: {}", "Newest Memory".white().bold(), newest.format("%Y-%m-%d %H:%M:%S")); + println!( + "{}: {}", + "Newest Memory".white().bold(), + newest.format("%Y-%m-%d %H:%M:%S") + ); } // Embedding coverage @@ -194,7 +224,11 @@ fn run_stats(show_tagging: bool, show_states: bool) -> anyhow::Result<()> { } else { 0.0 }; - println!("{}: {:.1}%", "Embedding Coverage".white().bold(), embedding_coverage); + println!( + "{}: {:.1}%", + "Embedding Coverage".white().bold(), + embedding_coverage + ); // Tagging distribution (retention levels) if show_tagging { @@ -205,9 +239,18 @@ fn run_stats(show_tagging: bool, show_states: bool) -> anyhow::Result<()> { let total = memories.len(); if total > 0 { - let high = memories.iter().filter(|m| m.retention_strength >= 0.7).count(); - let medium = memories.iter().filter(|m| m.retention_strength >= 0.4 && m.retention_strength < 0.7).count(); - let low = memories.iter().filter(|m| m.retention_strength < 0.4).count(); + let high = memories + .iter() + .filter(|m| m.retention_strength >= 0.7) + .count(); + let medium = memories + .iter() + .filter(|m| m.retention_strength >= 0.4 && m.retention_strength < 0.7) + .count(); + let low = memories + .iter() + .filter(|m| m.retention_strength < 0.4) + .count(); print_distribution_bar("High (>=70%)", high, total, "green"); print_distribution_bar("Medium (40-70%)", medium, total, "yellow"); @@ -220,7 +263,10 @@ fn run_stats(show_tagging: bool, show_states: bool) -> anyhow::Result<()> { // State distribution if show_states { println!(); - println!("{}", "=== Cognitive State Distribution ===".magenta().bold()); + println!( + "{}", + "=== Cognitive State Distribution ===".magenta().bold() + ); let memories = storage.get_all_nodes(500, 0)?; let total = memories.len(); @@ -248,7 +294,9 @@ fn run_stats(show_tagging: bool, show_states: bool) -> anyhow::Result<()> { } /// Compute cognitive state distribution for memories -fn compute_state_distribution(memories: &[vestige_core::KnowledgeNode]) -> (usize, usize, usize, usize) { +fn compute_state_distribution( + memories: &[vestige_core::KnowledgeNode], +) -> (usize, usize, usize, usize) { let mut active = 0; let mut dormant = 0; let mut silent = 0; @@ -297,10 +345,7 @@ fn print_distribution_bar(label: &str, count: usize, total: usize, color: &str) println!( " {:15} [{:30}] {:>4} ({:>5.1}%)", - label, - colored_bar, - count, - percentage + label, colored_bar, count, percentage ); } @@ -332,8 +377,16 @@ fn run_health() -> anyhow::Result<()> { println!("{}: {}", "Status".white().bold(), colored_status); println!("{}: {}", "Total Memories".white(), stats.total_nodes); - println!("{}: {}", "Due for Review".white(), stats.nodes_due_for_review); - println!("{}: {:.1}%", "Average Retention".white(), stats.average_retention * 100.0); + println!( + "{}: {}", + "Due for Review".white(), + stats.nodes_due_for_review + ); + println!( + "{}: {:.1}%", + "Average Retention".white(), + stats.average_retention * 100.0 + ); // Embedding coverage let embedding_coverage = if stats.total_nodes > 0 { @@ -341,15 +394,27 @@ fn run_health() -> anyhow::Result<()> { } else { 0.0 }; - println!("{}: {:.1}%", "Embedding Coverage".white(), embedding_coverage); - println!("{}: {}", "Embedding Service".white(), - if storage.is_embedding_ready() { "Ready".green() } else { "Not Ready".red() }); + println!( + "{}: {:.1}%", + "Embedding Coverage".white(), + embedding_coverage + ); + println!( + "{}: {}", + "Embedding Service".white(), + if storage.is_embedding_ready() { + "Ready".green() + } else { + "Not Ready".red() + } + ); // Warnings let mut warnings = Vec::new(); if stats.average_retention < 0.5 && stats.total_nodes > 0 { - warnings.push("Low average retention - consider running consolidation or reviewing memories"); + warnings + .push("Low average retention - consider running consolidation or reviewing memories"); } if stats.nodes_due_for_review > 10 { @@ -376,7 +441,8 @@ fn run_health() -> anyhow::Result<()> { let mut recommendations = Vec::new(); if status == "CRITICAL" { - recommendations.push("CRITICAL: Many memories have very low retention. Review important memories."); + recommendations + .push("CRITICAL: Many memories have very low retention. Review important memories."); } if stats.nodes_due_for_review > 5 { @@ -384,7 +450,8 @@ fn run_health() -> anyhow::Result<()> { } if stats.nodes_with_embeddings < stats.total_nodes { - recommendations.push("Run 'vestige consolidate' to generate embeddings for better semantic search."); + recommendations + .push("Run 'vestige consolidate' to generate embeddings for better semantic search."); } if stats.total_nodes > 100 && stats.average_retention < 0.7 { @@ -398,8 +465,16 @@ fn run_health() -> anyhow::Result<()> { println!(); println!("{}", "Recommendations:".cyan().bold()); for rec in &recommendations { - let icon = if rec.starts_with("CRITICAL") { "!".red().bold() } else { ">".cyan() }; - let text = if rec.starts_with("CRITICAL") { rec.red().to_string() } else { rec.to_string() }; + let icon = if rec.starts_with("CRITICAL") { + "!".red().bold() + } else { + ">".cyan() + }; + let text = if rec.starts_with("CRITICAL") { + rec.red().to_string() + } else { + rec.to_string() + }; println!(" {} {}", icon, text); } @@ -416,11 +491,27 @@ fn run_consolidate() -> anyhow::Result<()> { let storage = Storage::new(None)?; let result = storage.run_consolidation()?; - println!("{}: {}", "Nodes Processed".white().bold(), result.nodes_processed); - println!("{}: {}", "Nodes Promoted".white().bold(), result.nodes_promoted); + println!( + "{}: {}", + "Nodes Processed".white().bold(), + result.nodes_processed + ); + println!( + "{}: {}", + "Nodes Promoted".white().bold(), + result.nodes_promoted + ); println!("{}: {}", "Nodes Pruned".white().bold(), result.nodes_pruned); - println!("{}: {}", "Decay Applied".white().bold(), result.decay_applied); - println!("{}: {}", "Embeddings Generated".white().bold(), result.embeddings_generated); + println!( + "{}: {}", + "Decay Applied".white().bold(), + result.decay_applied + ); + println!( + "{}: {}", + "Embeddings Generated".white().bold(), + result.embeddings_generated + ); println!("{}: {}ms", "Duration".white().bold(), result.duration_ms); println!(); @@ -523,7 +614,11 @@ fn run_restore(backup_path: PathBuf) -> anyhow::Result<()> { let stats = storage.get_stats()?; println!(); println!("{}: {}", "Total Nodes".white(), stats.total_nodes); - println!("{}: {}", "With Embeddings".white(), stats.nodes_with_embeddings); + println!( + "{}: {}", + "With Embeddings".white(), + stats.nodes_with_embeddings + ); Ok(()) } @@ -581,9 +676,10 @@ fn run_backup(output: PathBuf) -> anyhow::Result<()> { // Create parent directories if needed if let Some(parent) = output.parent() - && !parent.exists() { - std::fs::create_dir_all(parent)?; - } + && !parent.exists() + { + std::fs::create_dir_all(parent)?; + } // Copy the database file println!("Copying database..."); @@ -630,8 +726,9 @@ fn run_export( // Parse since date if provided let since_date = match &since { Some(date_str) => { - let naive = NaiveDate::parse_from_str(date_str, "%Y-%m-%d") - .map_err(|e| anyhow::anyhow!("Invalid date '{}': {}. Use YYYY-MM-DD format.", date_str, e))?; + let naive = NaiveDate::parse_from_str(date_str, "%Y-%m-%d").map_err(|e| { + anyhow::anyhow!("Invalid date '{}': {}. Use YYYY-MM-DD format.", date_str, e) + })?; Some( naive .and_hms_opt(0, 0, 0) @@ -645,7 +742,12 @@ fn run_export( // Parse tags filter let tag_filter: Vec = tags .as_deref() - .map(|t| t.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect()) + .map(|t| { + t.split(',') + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + .collect() + }) .unwrap_or_default(); let storage = Storage::new(None)?; @@ -657,9 +759,10 @@ fn run_export( .filter(|node| { // Date filter if let Some(ref since_dt) = since_date - && node.created_at < *since_dt { - return false; - } + && node.created_at < *since_dt + { + return false; + } // Tag filter: node must contain ALL specified tags if !tag_filter.is_empty() { for tag in &tag_filter { @@ -689,9 +792,10 @@ fn run_export( // Create parent directories if needed if let Some(parent) = output.parent() - && !parent.exists() { - std::fs::create_dir_all(parent)?; - } + && !parent.exists() + { + std::fs::create_dir_all(parent)?; + } let file = std::fs::File::create(&output)?; let mut writer = BufWriter::new(file); @@ -770,7 +874,11 @@ fn run_gc( }) .collect(); - println!("{}: {}", "Min retention threshold".white().bold(), min_retention); + println!( + "{}: {}", + "Min retention threshold".white().bold(), + min_retention + ); if let Some(max_days) = max_age_days { println!("{}: {} days", "Max age".white().bold(), max_days); } @@ -783,7 +891,10 @@ fn run_gc( if candidates.is_empty() { println!(); - println!("{}", "No memories match the garbage collection criteria.".green()); + println!( + "{}", + "No memories match the garbage collection criteria.".green() + ); return Ok(()); } @@ -853,7 +964,12 @@ fn run_gc( Ok(true) => deleted += 1, Ok(false) => errors += 1, // node was already gone Err(e) => { - eprintln!(" {} Failed to delete {}: {}", "ERR".red(), &node.id[..8], e); + eprintln!( + " {} Failed to delete {}: {}", + "ERR".red(), + &node.id[..8], + e + ); errors += 1; } } @@ -960,7 +1076,10 @@ fn run_ingest( fn run_dashboard(port: u16, open_browser: bool) -> anyhow::Result<()> { println!("{}", "=== Vestige Dashboard ===".cyan().bold()); println!(); - println!("Starting dashboard at {}...", format!("http://127.0.0.1:{}", port).cyan()); + println!( + "Starting dashboard at {}...", + format!("http://127.0.0.1:{}", port).cyan() + ); let storage = Storage::new(None)?; @@ -1025,8 +1144,19 @@ fn run_serve(port: u16, with_dashboard: bool, dashboard_port: u16) -> anyhow::Re let dc = Arc::clone(&cognitive); let dtx = event_tx.clone(); tokio::spawn(async move { - match vestige_mcp::dashboard::start_background_with_event_tx(ds, Some(dc), dtx, dashboard_port).await { - Ok(_) => println!(" {} Dashboard: http://127.0.0.1:{}", ">".cyan(), dashboard_port), + match vestige_mcp::dashboard::start_background_with_event_tx( + ds, + Some(dc), + dtx, + dashboard_port, + ) + .await + { + Ok(_) => println!( + " {} Dashboard: http://127.0.0.1:{}", + ">".cyan(), + dashboard_port + ), Err(e) => eprintln!(" {} Dashboard failed: {}", "!".yellow(), e), } }); @@ -1037,7 +1167,12 @@ fn run_serve(port: u16, with_dashboard: bool, dashboard_port: u16) -> anyhow::Re .map_err(|e| anyhow::anyhow!("Failed to create auth token: {}", e))?; let bind = std::env::var("VESTIGE_HTTP_BIND").unwrap_or_else(|_| "127.0.0.1".to_string()); - println!(" {} HTTP transport: http://{}:{}/mcp", ">".cyan(), bind, port); + println!( + " {} HTTP transport: http://{}:{}/mcp", + ">".cyan(), + bind, + port + ); println!(" {} Auth token: {}...", ">".cyan(), &token[..8]); println!(); println!("{}", "Press Ctrl+C to stop.".dimmed()); diff --git a/crates/vestige-mcp/src/bin/restore.rs b/crates/vestige-mcp/src/bin/restore.rs index afb7f85..6e24800 100644 --- a/crates/vestige-mcp/src/bin/restore.rs +++ b/crates/vestige-mcp/src/bin/restore.rs @@ -65,7 +65,12 @@ fn main() -> anyhow::Result<()> { match storage.ingest(input) { Ok(_node) => { success_count += 1; - println!("[{}/{}] OK: {}", i + 1, total, truncate(&memory.content, 60)); + println!( + "[{}/{}] OK: {}", + i + 1, + total, + truncate(&memory.content, 60) + ); } Err(e) => { println!("[{}/{}] FAIL: {}", i + 1, total, e); @@ -73,7 +78,10 @@ fn main() -> anyhow::Result<()> { } } - println!("\nRestore complete: {}/{} memories restored", success_count, total); + println!( + "\nRestore complete: {}/{} memories restored", + success_count, total + ); // Show stats let stats = storage.get_stats()?; diff --git a/crates/vestige-mcp/src/cognitive.rs b/crates/vestige-mcp/src/cognitive.rs index 6f9c174..86aadcf 100644 --- a/crates/vestige-mcp/src/cognitive.rs +++ b/crates/vestige-mcp/src/cognitive.rs @@ -4,24 +4,43 @@ //! Each module is initialized once at startup and shared via Arc> //! across all tool invocations. +use vestige_core::neuroscience::predictive_retrieval::PredictiveMemory; +use vestige_core::neuroscience::prospective_memory::{IntentionParser, ProspectiveMemory}; +use vestige_core::search::TemporalSearcher; use vestige_core::{ + AccessibilityCalculator, // Neuroscience modules - ActivationNetwork, SynapticTaggingSystem, HippocampalIndex, ContextMatcher, - AccessibilityCalculator, CompetitionManager, StateUpdateService, - ImportanceSignals, NoveltySignal, ArousalSignal, RewardSignal, AttentionSignal, - EmotionalMemory, LinkType, + ActivationNetwork, + ActivityTracker, + AdaptiveEmbedder, + ArousalSignal, + AttentionSignal, + CompetitionManager, + ConsolidationScheduler, + ContextMatcher, + CrossProjectLearner, + EmotionalMemory, + HippocampalIndex, + ImportanceSignals, // Advanced modules - ImportanceTracker, ReconsolidationManager, IntentDetector, ActivityTracker, - MemoryDreamer, MemoryChainBuilder, MemoryCompressor, CrossProjectLearner, - AdaptiveEmbedder, SpeculativeRetriever, ConsolidationScheduler, + ImportanceTracker, + IntentDetector, + LinkType, + MemoryChainBuilder, + MemoryCompressor, + MemoryDreamer, + NoveltySignal, + ReconsolidationManager, // Search modules - Reranker, RerankerConfig, + Reranker, + RerankerConfig, + RewardSignal, + SpeculativeRetriever, + StateUpdateService, // Storage Storage, + SynapticTaggingSystem, }; -use vestige_core::search::TemporalSearcher; -use vestige_core::neuroscience::predictive_retrieval::PredictiveMemory; -use vestige_core::neuroscience::prospective_memory::{ProspectiveMemory, IntentionParser}; /// Stateful cognitive engine holding all neuroscience modules. /// @@ -151,9 +170,9 @@ impl CognitiveEngine { #[cfg(test)] mod tests { use super::*; - use vestige_core::{ConnectionRecord, IngestInput}; use chrono::Utc; use tempfile::TempDir; + use vestige_core::{ConnectionRecord, IngestInput}; fn create_test_storage() -> (Storage, TempDir) { let dir = TempDir::new().unwrap(); @@ -162,16 +181,18 @@ mod tests { } fn ingest_memory(storage: &Storage, content: &str) -> String { - let result = storage.ingest(IngestInput { - content: content.to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + let result = storage + .ingest(IngestInput { + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); result.id } @@ -195,15 +216,17 @@ mod tests { // Save a connection between them let now = Utc::now(); - storage.save_connection(&ConnectionRecord { - source_id: id1.clone(), - target_id: id2.clone(), - strength: 0.85, - link_type: "semantic".to_string(), - created_at: now, - last_activated: now, - activation_count: 1, - }).unwrap(); + storage + .save_connection(&ConnectionRecord { + source_id: id1.clone(), + target_id: id2.clone(), + strength: 0.85, + link_type: "semantic".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); // Hydrate engine let mut engine = CognitiveEngine::new(); @@ -211,7 +234,11 @@ mod tests { // Verify activation network has the connection let assocs = engine.activation_network.get_associations(&id1); - assert!(!assocs.is_empty(), "Hydrated engine should have associations for {}", id1); + assert!( + !assocs.is_empty(), + "Hydrated engine should have associations for {}", + id1 + ); assert!( assocs.iter().any(|a| a.memory_id == id2), "Should find connection to {}", @@ -228,29 +255,37 @@ mod tests { let id3 = ingest_memory(&storage, "Event C was caused by A"); let now = Utc::now(); - storage.save_connection(&ConnectionRecord { - source_id: id1.clone(), - target_id: id2.clone(), - strength: 0.7, - link_type: "temporal".to_string(), - created_at: now, - last_activated: now, - activation_count: 1, - }).unwrap(); - storage.save_connection(&ConnectionRecord { - source_id: id1.clone(), - target_id: id3.clone(), - strength: 0.9, - link_type: "causal".to_string(), - created_at: now, - last_activated: now, - activation_count: 1, - }).unwrap(); + storage + .save_connection(&ConnectionRecord { + source_id: id1.clone(), + target_id: id2.clone(), + strength: 0.7, + link_type: "temporal".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); + storage + .save_connection(&ConnectionRecord { + source_id: id1.clone(), + target_id: id3.clone(), + strength: 0.9, + link_type: "causal".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); let mut engine = CognitiveEngine::new(); engine.hydrate(&storage); let assocs = engine.activation_network.get_associations(&id1); - assert!(assocs.len() >= 2, "Should have at least 2 associations, got {}", assocs.len()); + assert!( + assocs.len() >= 2, + "Should have at least 2 associations, got {}", + assocs.len() + ); } } diff --git a/crates/vestige-mcp/src/dashboard/events.rs b/crates/vestige-mcp/src/dashboard/events.rs index 15b624c..be875b0 100644 --- a/crates/vestige-mcp/src/dashboard/events.rs +++ b/crates/vestige-mcp/src/dashboard/events.rs @@ -38,6 +38,24 @@ pub enum VestigeEvent { new_retention: f64, timestamp: DateTime, }, + // v2.0.5: Active forgetting — top-down suppression (Anderson 2025 + Davis Rac1) + MemorySuppressed { + id: String, + suppression_count: i32, + estimated_cascade: usize, + reversible_until: DateTime, + timestamp: DateTime, + }, + MemoryUnsuppressed { + id: String, + remaining_count: i32, + timestamp: DateTime, + }, + Rac1CascadeSwept { + seeds: usize, + neighbors_affected: usize, + timestamp: DateTime, + }, // -- Search -- SearchPerformed { @@ -119,6 +137,9 @@ pub enum VestigeEvent { uptime_secs: u64, memory_count: usize, avg_retention: f64, + /// v2.0.5: memories with suppression_count > 0 (actively forgetting) + #[serde(default)] + suppressed_count: usize, timestamp: DateTime, }, } diff --git a/crates/vestige-mcp/src/dashboard/handlers.rs b/crates/vestige-mcp/src/dashboard/handlers.rs index af65cc6..b999cae 100644 --- a/crates/vestige-mcp/src/dashboard/handlers.rs +++ b/crates/vestige-mcp/src/dashboard/handlers.rs @@ -38,7 +38,8 @@ pub async fn list_memories( if let Some(query) = params.q.as_ref().filter(|q| !q.trim().is_empty()) { // Use hybrid search - let results = state.storage + let results = state + .storage .hybrid_search(query, limit, 0.3, 0.7) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -76,7 +77,8 @@ pub async fn list_memories( } // No search query — list all memories - let mut nodes = state.storage + let mut nodes = state + .storage .get_all_nodes(limit, offset) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -121,7 +123,8 @@ pub async fn get_memory( State(state): State, Path(id): Path, ) -> Result, StatusCode> { - let node = state.storage + let node = state + .storage .get_node(&id) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; @@ -152,7 +155,8 @@ pub async fn delete_memory( State(state): State, Path(id): Path, ) -> Result, StatusCode> { - let deleted = state.storage + let deleted = state + .storage .delete_node(&id) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -172,7 +176,8 @@ pub async fn promote_memory( State(state): State, Path(id): Path, ) -> Result, StatusCode> { - let node = state.storage + let node = state + .storage .promote_memory(&id) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -194,7 +199,8 @@ pub async fn demote_memory( State(state): State, Path(id): Path, ) -> Result, StatusCode> { - let node = state.storage + let node = state + .storage .demote_memory(&id) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -212,10 +218,9 @@ pub async fn demote_memory( } /// Get system stats -pub async fn get_stats( - State(state): State, -) -> Result, StatusCode> { - let stats = state.storage +pub async fn get_stats(State(state): State) -> Result, StatusCode> { + let stats = state + .storage .get_stats() .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -254,12 +259,14 @@ pub async fn get_timeline( let limit = params.limit.unwrap_or(200).clamp(1, 500); let start = Utc::now() - Duration::days(days); - let nodes = state.storage + let nodes = state + .storage .query_time_range(Some(start), Some(Utc::now()), limit) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; // Group by day - let mut by_day: std::collections::BTreeMap> = std::collections::BTreeMap::new(); + let mut by_day: std::collections::BTreeMap> = + std::collections::BTreeMap::new(); for node in &nodes { let date = node.created_at.format("%Y-%m-%d").to_string(); let content_preview: String = { @@ -299,10 +306,9 @@ pub async fn get_timeline( } /// Health check -pub async fn health_check( - State(state): State, -) -> Result, StatusCode> { - let stats = state.storage +pub async fn health_check(State(state): State) -> Result, StatusCode> { + let stats = state + .storage .get_stats() .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -353,32 +359,38 @@ pub async fn get_graph( let center_id = if let Some(ref id) = params.center_id { id.clone() } else if let Some(ref query) = params.query { - let results = state.storage + let results = state + .storage .search(query, 1) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - results.first() + results + .first() .map(|n| n.id.clone()) .ok_or(StatusCode::NOT_FOUND)? } else { // Default: most connected memory (for a rich initial graph) - let most_connected = state.storage + let most_connected = state + .storage .get_most_connected_memory() .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; if let Some(id) = most_connected { id } else { // Fallback: most recent memory - let recent = state.storage + let recent = state + .storage .get_all_nodes(1, 0) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - recent.first() + recent + .first() .map(|n| n.id.clone()) .ok_or(StatusCode::NOT_FOUND)? } }; // Get subgraph - let (nodes, edges) = state.storage + let (nodes, edges) = state + .storage .get_memory_subgraph(¢er_id, depth, max_nodes) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; @@ -387,7 +399,8 @@ pub async fn get_graph( } // Build nodes JSON with timestamps for recency calculation - let nodes_json: Vec = nodes.iter() + let nodes_json: Vec = nodes + .iter() .map(|n| { let label = if n.content.chars().count() > 80 { format!("{}...", n.content.chars().take(77).collect::()) @@ -407,7 +420,8 @@ pub async fn get_graph( }) .collect(); - let edges_json: Vec = edges.iter() + let edges_json: Vec = edges + .iter() .map(|e| { serde_json::json!({ "source": e.source_id, @@ -498,10 +512,11 @@ pub async fn search_memories( // ============================================================================ /// Trigger a dream cycle via CognitiveEngine -pub async fn trigger_dream( - State(state): State, -) -> Result, StatusCode> { - let cognitive = state.cognitive.as_ref().ok_or(StatusCode::SERVICE_UNAVAILABLE)?; +pub async fn trigger_dream(State(state): State) -> Result, StatusCode> { + let cognitive = state + .cognitive + .as_ref() + .ok_or(StatusCode::SERVICE_UNAVAILABLE)?; let start = std::time::Instant::now(); let memory_count: usize = 50; @@ -715,9 +730,7 @@ pub async fn explore_connections( } /// Predict which memories will be needed -pub async fn predict_memories( - State(state): State, -) -> Result, StatusCode> { +pub async fn predict_memories(State(state): State) -> Result, StatusCode> { // Get recent memories as predictions based on activity let recent = state .storage @@ -756,7 +769,9 @@ pub async fn score_importance( if let Some(ref cognitive) = state.cognitive { let context = vestige_core::ImportanceContext::current(); let cog = cognitive.lock().await; - let score = cog.importance_signals.compute_importance(&req.content, &context); + let score = cog + .importance_signals + .compute_importance(&req.content, &context); drop(cog); let composite = score.composite; @@ -789,7 +804,11 @@ pub async fn score_importance( // Fallback: basic heuristic scoring let word_count = req.content.split_whitespace().count(); let has_code = req.content.contains("```") || req.content.contains("fn "); - let composite = if has_code { 0.7 } else { (word_count as f64 / 100.0).min(0.8) }; + let composite = if has_code { + 0.7 + } else { + (word_count as f64 / 100.0).min(0.8) + }; Ok(Json(serde_json::json!({ "composite": composite, @@ -907,17 +926,35 @@ pub async fn list_intentions( let intentions = if status_filter == "all" { // Get all statuses - let mut all = state.storage.get_active_intentions() - .unwrap_or_default(); - all.extend(state.storage.get_intentions_by_status("fulfilled").unwrap_or_default()); - all.extend(state.storage.get_intentions_by_status("cancelled").unwrap_or_default()); - all.extend(state.storage.get_intentions_by_status("snoozed").unwrap_or_default()); + let mut all = state.storage.get_active_intentions().unwrap_or_default(); + all.extend( + state + .storage + .get_intentions_by_status("fulfilled") + .unwrap_or_default(), + ); + all.extend( + state + .storage + .get_intentions_by_status("cancelled") + .unwrap_or_default(), + ); + all.extend( + state + .storage + .get_intentions_by_status("snoozed") + .unwrap_or_default(), + ); all } else if status_filter == "active" { - state.storage.get_active_intentions() + state + .storage + .get_active_intentions() .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? } else { - state.storage.get_intentions_by_status(&status_filter) + state + .storage + .get_intentions_by_status(&status_filter) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? }; diff --git a/crates/vestige-mcp/src/dashboard/mod.rs b/crates/vestige-mcp/src/dashboard/mod.rs index d236041..4a235a6 100644 --- a/crates/vestige-mcp/src/dashboard/mod.rs +++ b/crates/vestige-mcp/src/dashboard/mod.rs @@ -11,8 +11,8 @@ pub mod state; pub mod static_files; pub mod websocket; -use axum::routing::{delete, get, post}; use axum::Router; +use axum::routing::{delete, get, post}; use std::net::SocketAddr; use std::sync::Arc; use tokio::sync::Mutex; @@ -47,7 +47,6 @@ pub fn build_router_with_event_tx( } fn build_router_inner(state: AppState, port: u16) -> (Router, AppState) { - #[allow(unused_mut)] let mut origins = vec![ format!("http://127.0.0.1:{}", port) @@ -61,8 +60,16 @@ fn build_router_inner(state: AppState, port: u16) -> (Router, AppState) { // SvelteKit dev server — only in debug builds #[cfg(debug_assertions)] { - origins.push("http://localhost:5173".parse::().expect("valid origin")); - origins.push("http://127.0.0.1:5173".parse::().expect("valid origin")); + origins.push( + "http://localhost:5173" + .parse::() + .expect("valid origin"), + ); + origins.push( + "http://127.0.0.1:5173" + .parse::() + .expect("valid origin"), + ); } let cors = CorsLayer::new() @@ -116,7 +123,10 @@ fn build_router_inner(state: AppState, port: u16) -> (Router, AppState) { let router = Router::new() // SvelteKit Dashboard v2.0 (embedded static build) .route("/dashboard", get(static_files::serve_dashboard_spa)) - .route("/dashboard/{*path}", get(static_files::serve_dashboard_asset)) + .route( + "/dashboard/{*path}", + get(static_files::serve_dashboard_asset), + ) // Legacy embedded HTML (keep for backward compat) .route("/", get(handlers::serve_dashboard)) .route("/graph", get(handlers::serve_graph)) @@ -143,7 +153,10 @@ fn build_router_inner(state: AppState, port: u16) -> (Router, AppState) { .route("/api/predict", post(handlers::predict_memories)) .route("/api/importance", post(handlers::score_importance)) .route("/api/consolidate", post(handlers::trigger_consolidation)) - .route("/api/retention-distribution", get(handlers::retention_distribution)) + .route( + "/api/retention-distribution", + get(handlers::retention_distribution), + ) // Intentions (v2.0) .route("/api/intentions", get(handlers::list_intentions)) .layer( diff --git a/crates/vestige-mcp/src/dashboard/state.rs b/crates/vestige-mcp/src/dashboard/state.rs index c1ae661..5a41266 100644 --- a/crates/vestige-mcp/src/dashboard/state.rs +++ b/crates/vestige-mcp/src/dashboard/state.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use std::time::Instant; -use tokio::sync::{broadcast, Mutex}; +use tokio::sync::{Mutex, broadcast}; use vestige_core::Storage; -use crate::cognitive::CognitiveEngine; use super::events::VestigeEvent; +use crate::cognitive::CognitiveEngine; /// Broadcast channel capacity — how many events can buffer before old ones drop. const EVENT_CHANNEL_CAPACITY: usize = 1024; @@ -22,10 +22,7 @@ pub struct AppState { impl AppState { /// Create a new AppState with event broadcasting. - pub fn new( - storage: Arc, - cognitive: Option>>, - ) -> Self { + pub fn new(storage: Arc, cognitive: Option>>) -> Self { let (event_tx, _) = broadcast::channel(EVENT_CHANNEL_CAPACITY); Self { storage, diff --git a/crates/vestige-mcp/src/dashboard/static_files.rs b/crates/vestige-mcp/src/dashboard/static_files.rs index 1bc9ba3..c780965 100644 --- a/crates/vestige-mcp/src/dashboard/static_files.rs +++ b/crates/vestige-mcp/src/dashboard/static_files.rs @@ -4,9 +4,9 @@ //! using `include_dir!`. This serves it at `/dashboard/` prefix. use axum::extract::Path; -use axum::http::{header, StatusCode}; +use axum::http::{StatusCode, header}; use axum::response::{Html, IntoResponse, Response}; -use include_dir::{include_dir, Dir}; +use include_dir::{Dir, include_dir}; /// Embed the entire SvelteKit build output into the binary. /// Build with: cd apps/dashboard && pnpm build @@ -16,11 +16,11 @@ static DASHBOARD_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../apps/das /// Serve the SvelteKit dashboard index pub async fn serve_dashboard_spa() -> impl IntoResponse { match DASHBOARD_DIR.get_file("index.html") { - Some(file) => Html( - String::from_utf8_lossy(file.contents()).to_string(), + Some(file) => Html(String::from_utf8_lossy(file.contents()).to_string()).into_response(), + None => ( + StatusCode::NOT_FOUND, + "Dashboard not built. Run: cd apps/dashboard && pnpm build", ) - .into_response(), - None => (StatusCode::NOT_FOUND, "Dashboard not built. Run: cd apps/dashboard && pnpm build") .into_response(), } } diff --git a/crates/vestige-mcp/src/dashboard/websocket.rs b/crates/vestige-mcp/src/dashboard/websocket.rs index 88d428c..97471ef 100644 --- a/crates/vestige-mcp/src/dashboard/websocket.rs +++ b/crates/vestige-mcp/src/dashboard/websocket.rs @@ -3,8 +3,8 @@ //! Clients connect to `/ws` and receive all VestigeEvents as JSON. //! Also sends heartbeats every 5 seconds with system stats. -use axum::extract::ws::{Message, WebSocket, WebSocketUpgrade}; use axum::extract::State; +use axum::extract::ws::{Message, WebSocket, WebSocketUpgrade}; use axum::http::{HeaderMap, StatusCode}; use axum::response::IntoResponse; use chrono::Utc; @@ -26,10 +26,11 @@ pub async fn ws_handler( // Non-browser clients (curl, wscat) won't have Origin — allowed since localhost-only. match headers.get("origin").and_then(|v| v.to_str().ok()) { Some(origin) => { - let allowed = origin.starts_with("http://127.0.0.1:") - || origin.starts_with("http://localhost:"); + let allowed = + origin.starts_with("http://127.0.0.1:") || origin.starts_with("http://localhost:"); #[cfg(debug_assertions)] - let allowed = allowed || origin == "http://localhost:5173" || origin == "http://127.0.0.1:5173"; + let allowed = + allowed || origin == "http://localhost:5173" || origin == "http://127.0.0.1:5173"; if !allowed { warn!("Rejected WebSocket connection from origin: {}", origin); return StatusCode::FORBIDDEN.into_response(); @@ -85,10 +86,14 @@ async fn handle_socket(socket: WebSocket, state: AppState) { .map(|s| (s.total_nodes as usize, s.average_retention)) .unwrap_or((0, 0.0)); + // v2.0.5: live count of memories being actively forgotten + let suppressed_count = heartbeat_state.storage.count_suppressed().unwrap_or(0); + let event = VestigeEvent::Heartbeat { uptime_secs: uptime, memory_count, avg_retention, + suppressed_count, timestamp: Utc::now(), }; diff --git a/crates/vestige-mcp/src/main.rs b/crates/vestige-mcp/src/main.rs index 7a38c33..4ac6237 100644 --- a/crates/vestige-mcp/src/main.rs +++ b/crates/vestige-mcp/src/main.rs @@ -35,7 +35,7 @@ use std::io; use std::path::PathBuf; use std::sync::Arc; use tokio::sync::Mutex; -use tracing::{error, info, warn, Level}; +use tracing::{Level, error, info, warn}; use tracing_subscriber::EnvFilter; // Use vestige-core for the cognitive science engine @@ -82,8 +82,12 @@ fn parse_args() -> Config { println!(" --http-port HTTP transport port (default: 3928)"); println!(); println!("ENVIRONMENT:"); - println!(" RUST_LOG Log level filter (e.g., debug, info, warn, error)"); - println!(" VESTIGE_AUTH_TOKEN Override the bearer token for HTTP transport"); + println!( + " RUST_LOG Log level filter (e.g., debug, info, warn, error)" + ); + println!( + " VESTIGE_AUTH_TOKEN Override the bearer token for HTTP transport" + ); println!(" VESTIGE_HTTP_PORT HTTP transport port (default: 3928)"); println!(" VESTIGE_DASHBOARD_ENABLED Enable dashboard (default: disabled)"); println!(" VESTIGE_DASHBOARD_PORT Dashboard port (default: 3927)"); @@ -153,7 +157,11 @@ fn parse_args() -> Config { i += 1; } - Config { data_dir, http_port, dashboard_enabled } + Config { + data_dir, + http_port, + dashboard_enabled, + } } #[tokio::main] @@ -163,16 +171,16 @@ async fn main() { // Initialize logging to stderr (stdout is for JSON-RPC) tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::from_default_env() - .add_directive(Level::INFO.into()) - ) + .with_env_filter(EnvFilter::from_default_env().add_directive(Level::INFO.into())) .with_writer(io::stderr) .with_target(false) .with_ansi(false) .init(); - info!("Vestige MCP Server v{} starting...", env!("CARGO_PKG_VERSION")); + info!( + "Vestige MCP Server v{} starting...", + env!("CARGO_PKG_VERSION") + ); // Initialize storage with optional custom data directory let storage = match Storage::new(config.data_dir) { @@ -185,7 +193,9 @@ async fn main() { if let Err(e) = s.init_embeddings() { error!("Failed to initialize embedding service: {}", e); error!("Smart ingest will fall back to regular ingest without deduplication"); - error!("Hint: Check FASTEMBED_CACHE_PATH or ensure ~/.cache/vestige/fastembed is writable"); + error!( + "Hint: Check FASTEMBED_CACHE_PATH or ensure ~/.cache/vestige/fastembed is writable" + ); } else { info!("Embedding service initialized successfully"); } @@ -233,7 +243,10 @@ async fn main() { true } Err(e) => { - warn!("Could not read consolidation history: {} — running anyway", e); + warn!( + "Could not read consolidation history: {} — running anyway", + e + ); true } }; @@ -255,6 +268,23 @@ async fn main() { warn!("Periodic auto-consolidation failed: {}", e); } } + + // v2.0.5: Rac1 cascade sweep — walk recently-suppressed + // memories and fade their co-activated neighbors + // (Cervantes-Sandoval & Davis 2020, PMC7477079). + match storage_clone.run_rac1_cascade_sweep() { + Ok((seeds, affected)) if seeds > 0 || affected > 0 => { + info!( + suppressed_seeds = seeds, + neighbors_affected = affected, + "Rac1 cascade sweep complete" + ); + } + Ok(_) => {} + Err(e) => { + warn!("Rac1 cascade sweep failed: {}", e); + } + } } // Sleep until next check @@ -273,7 +303,8 @@ async fn main() { info!("CognitiveEngine initialized and hydrated"); // Create shared event broadcast channel for dashboard <-> MCP tool events - let (event_tx, _) = tokio::sync::broadcast::channel::(1024); + let (event_tx, _) = + tokio::sync::broadcast::channel::(1024); // Spawn dashboard HTTP server alongside MCP server (now with CognitiveEngine access) if config.dashboard_enabled { @@ -290,7 +321,9 @@ async fn main() { Some(dashboard_cognitive), dashboard_event_tx, dashboard_port, - ).await { + ) + .await + { Ok(_state) => { info!("Dashboard started with WebSocket + CognitiveEngine + shared event bus"); } @@ -312,7 +345,8 @@ async fn main() { match protocol::auth::get_or_create_auth_token() { Ok(token) => { - let bind = std::env::var("VESTIGE_HTTP_BIND").unwrap_or_else(|_| "127.0.0.1".to_string()); + let bind = + std::env::var("VESTIGE_HTTP_BIND").unwrap_or_else(|_| "127.0.0.1".to_string()); eprintln!("Vestige HTTP transport: http://{}:{}/mcp", bind, http_port); eprintln!("Auth token: {}...", &token[..token.len().min(8)]); tokio::spawn(async move { @@ -330,7 +364,10 @@ async fn main() { }); } Err(e) => { - warn!("Could not create auth token, HTTP transport disabled: {}", e); + warn!( + "Could not create auth token, HTTP transport disabled: {}", + e + ); } } } diff --git a/crates/vestige-mcp/src/protocol/http.rs b/crates/vestige-mcp/src/protocol/http.rs index d5369a2..e90c313 100644 --- a/crates/vestige-mcp/src/protocol/http.rs +++ b/crates/vestige-mcp/src/protocol/http.rs @@ -17,17 +17,17 @@ use axum::response::IntoResponse; use axum::routing::{delete, post}; use axum::{Json, Router}; use subtle::ConstantTimeEq; -use tokio::sync::{broadcast, Mutex, RwLock}; +use tokio::sync::{Mutex, RwLock, broadcast}; use tower::ServiceBuilder; use tower::limit::ConcurrencyLimitLayer; use tower_http::cors::CorsLayer; use tracing::{info, warn}; use crate::cognitive::CognitiveEngine; +use crate::dashboard::events::VestigeEvent; use crate::protocol::types::JsonRpcRequest; use crate::server::McpServer; use vestige_core::Storage; -use crate::dashboard::events::VestigeEvent; /// Maximum concurrent sessions. const MAX_SESSIONS: usize = 100; @@ -95,7 +95,11 @@ pub async fn start_http_transport( }); let removed = before - map.len(); if removed > 0 { - info!("Session reaper: removed {} idle sessions ({} active)", removed, map.len()); + info!( + "Session reaper: removed {} idle sessions ({} active)", + removed, + map.len() + ); } } }); @@ -119,8 +123,15 @@ pub async fn start_http_transport( .filter_map(|s| s.parse().ok()) .collect::>(), ) - .allow_methods([axum::http::Method::POST, axum::http::Method::DELETE, axum::http::Method::OPTIONS]) - .allow_headers([axum::http::header::CONTENT_TYPE, axum::http::header::AUTHORIZATION]) + .allow_methods([ + axum::http::Method::POST, + axum::http::Method::DELETE, + axum::http::Method::OPTIONS, + ]) + .allow_headers([ + axum::http::header::CONTENT_TYPE, + axum::http::header::AUTHORIZATION, + ]), ), ) .with_state(state); @@ -156,9 +167,10 @@ fn validate_auth(headers: &HeaderMap, expected: &str) -> Result<(), (StatusCode, .and_then(|v| v.to_str().ok()) .ok_or((StatusCode::UNAUTHORIZED, "Missing Authorization header"))?; - let token = header - .strip_prefix("Bearer ") - .ok_or((StatusCode::UNAUTHORIZED, "Invalid Authorization scheme (expected Bearer)"))?; + let token = header.strip_prefix("Bearer ").ok_or(( + StatusCode::UNAUTHORIZED, + "Invalid Authorization scheme (expected Bearer)", + ))?; // Constant-time comparison: prevents timing side-channel attacks. // We first check lengths match (length itself is not secret since UUIDs @@ -209,11 +221,7 @@ async fn post_mcp( // Take write lock immediately to avoid TOCTOU race on MAX_SESSIONS check. let mut sessions = state.sessions.write().await; if sessions.len() >= MAX_SESSIONS { - return ( - StatusCode::SERVICE_UNAVAILABLE, - "Too many active sessions", - ) - .into_response(); + return (StatusCode::SERVICE_UNAVAILABLE, "Too many active sessions").into_response(); } let server = McpServer::new_with_events( @@ -242,13 +250,23 @@ async fn post_mcp( match response { Some(resp) => { let mut resp_headers = HeaderMap::new(); - resp_headers.insert("mcp-session-id", session_id.parse().unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid"))); + resp_headers.insert( + "mcp-session-id", + session_id + .parse() + .unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid")), + ); (StatusCode::OK, resp_headers, Json(resp)).into_response() } None => { // Notifications return 202 let mut resp_headers = HeaderMap::new(); - resp_headers.insert("mcp-session-id", session_id.parse().unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid"))); + resp_headers.insert( + "mcp-session-id", + session_id + .parse() + .unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid")), + ); (StatusCode::ACCEPTED, resp_headers).into_response() } } @@ -273,11 +291,7 @@ async fn post_mcp( let session = match session { Some(s) => s, None => { - return ( - StatusCode::NOT_FOUND, - "Session not found or expired", - ) - .into_response(); + return (StatusCode::NOT_FOUND, "Session not found or expired").into_response(); } }; @@ -288,7 +302,12 @@ async fn post_mcp( }; let mut resp_headers = HeaderMap::new(); - resp_headers.insert("mcp-session-id", session_id.parse().unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid"))); + resp_headers.insert( + "mcp-session-id", + session_id + .parse() + .unwrap_or_else(|_| axum::http::HeaderValue::from_static("invalid")), + ); match response { Some(resp) => (StatusCode::OK, resp_headers, Json(resp)).into_response(), @@ -308,7 +327,13 @@ async fn delete_mcp( let session_id = match session_id_from_headers(&headers) { Some(id) => id, - None => return (StatusCode::BAD_REQUEST, "Missing or invalid Mcp-Session-Id header").into_response(), + None => { + return ( + StatusCode::BAD_REQUEST, + "Missing or invalid Mcp-Session-Id header", + ) + .into_response(); + } }; let mut sessions = state.sessions.write().await; diff --git a/crates/vestige-mcp/src/protocol/types.rs b/crates/vestige-mcp/src/protocol/types.rs index a29355f..57f5a10 100644 --- a/crates/vestige-mcp/src/protocol/types.rs +++ b/crates/vestige-mcp/src/protocol/types.rs @@ -25,7 +25,6 @@ pub struct JsonRpcRequest { pub params: Option, } - /// JSON-RPC Response #[derive(Debug, Clone, Serialize, Deserialize)] pub struct JsonRpcResponse { @@ -129,7 +128,10 @@ impl JsonRpcError { #[allow(dead_code)] // Reserved for future resource handling pub fn resource_not_found(uri: &str) -> Self { - Self::new(ErrorCode::ResourceNotFound, &format!("Resource not found: {}", uri)) + Self::new( + ErrorCode::ResourceNotFound, + &format!("Resource not found: {}", uri), + ) } } diff --git a/crates/vestige-mcp/src/resources/memory.rs b/crates/vestige-mcp/src/resources/memory.rs index 1c52dd7..6148932 100644 --- a/crates/vestige-mcp/src/resources/memory.rs +++ b/crates/vestige-mcp/src/resources/memory.rs @@ -35,15 +35,10 @@ pub async fn read(storage: &Arc, uri: &str) -> Result { fn parse_query_param(query: Option<&str>, key: &str, default: i32) -> i32 { query .and_then(|q| { - q.split('&') - .find_map(|pair| { - let (k, v) = pair.split_once('=')?; - if k == key { - v.parse().ok() - } else { - None - } - }) + q.split('&').find_map(|pair| { + let (k, v) = pair.split_once('=')?; + if k == key { v.parse().ok() } else { None } + }) }) .unwrap_or(default) .clamp(1, 100) @@ -228,7 +223,10 @@ async fn read_intentions(storage: &Arc) -> Result { }) .collect(); - let overdue_count = items.iter().filter(|i| i["isOverdue"].as_bool().unwrap_or(false)).count(); + let overdue_count = items + .iter() + .filter(|i| i["isOverdue"].as_bool().unwrap_or(false)) + .count(); let result = serde_json::json!({ "total": intentions.len(), @@ -241,7 +239,9 @@ async fn read_intentions(storage: &Arc) -> Result { } async fn read_triggered_intentions(storage: &Arc) -> Result { - let overdue = storage.get_overdue_intentions().map_err(|e| e.to_string())?; + let overdue = storage + .get_overdue_intentions() + .map_err(|e| e.to_string())?; let now = chrono::Utc::now(); let items: Vec = overdue @@ -289,7 +289,10 @@ async fn read_insights(storage: &Arc) -> Result { let insights = storage.get_insights(50).map_err(|e| e.to_string())?; let pending: Vec<_> = insights.iter().filter(|i| i.feedback.is_none()).collect(); - let accepted: Vec<_> = insights.iter().filter(|i| i.feedback.as_deref() == Some("accepted")).collect(); + let accepted: Vec<_> = insights + .iter() + .filter(|i| i.feedback.as_deref() == Some("accepted")) + .collect(); let items: Vec = insights .iter() @@ -319,8 +322,12 @@ async fn read_insights(storage: &Arc) -> Result { } async fn read_consolidation_log(storage: &Arc) -> Result { - let history = storage.get_consolidation_history(20).map_err(|e| e.to_string())?; - let last_run = storage.get_last_consolidation().map_err(|e| e.to_string())?; + let history = storage + .get_consolidation_history(20) + .map_err(|e| e.to_string())?; + let last_run = storage + .get_last_consolidation() + .map_err(|e| e.to_string())?; let items: Vec = history .iter() diff --git a/crates/vestige-mcp/src/server.rs b/crates/vestige-mcp/src/server.rs index b2c30ce..4f3f1e3 100644 --- a/crates/vestige-mcp/src/server.rs +++ b/crates/vestige-mcp/src/server.rs @@ -3,19 +3,19 @@ //! Handles the main MCP server logic, routing requests to appropriate //! tool and resource handlers. -use std::collections::HashMap; -use std::sync::atomic::{AtomicU64, Ordering}; -use std::sync::Arc; use chrono::Utc; -use tokio::sync::{broadcast, Mutex}; +use std::collections::HashMap; +use std::sync::Arc; +use std::sync::atomic::{AtomicU64, Ordering}; +use tokio::sync::{Mutex, broadcast}; use tracing::{debug, info, warn}; use crate::cognitive::CognitiveEngine; use crate::dashboard::events::VestigeEvent; use crate::protocol::messages::{ - CallToolRequest, CallToolResult, InitializeRequest, InitializeResult, - ListResourcesResult, ListToolsResult, ReadResourceRequest, ReadResourceResult, - ResourceDescription, ServerCapabilities, ServerInfo, ToolDescription, + CallToolRequest, CallToolResult, InitializeRequest, InitializeResult, ListResourcesResult, + ListToolsResult, ReadResourceRequest, ReadResourceResult, ResourceDescription, + ServerCapabilities, ServerInfo, ToolDescription, }; use crate::protocol::types::{JsonRpcError, JsonRpcRequest, JsonRpcResponse, MCP_VERSION}; use crate::resources; @@ -72,8 +72,14 @@ impl McpServer { debug!("Handling request: {}", request.method); // Check initialization for non-initialize requests - if !self.initialized && request.method != "initialize" && request.method != "notifications/initialized" { - warn!("Rejecting request '{}': server not initialized", request.method); + if !self.initialized + && request.method != "initialize" + && request.method != "notifications/initialized" + { + warn!( + "Rejecting request '{}': server not initialized", + request.method + ); return Some(JsonRpcResponse::error( request.id, JsonRpcError::server_not_initialized(), @@ -109,21 +115,28 @@ impl McpServer { params: Option, ) -> Result { let request: InitializeRequest = match params { - Some(p) => serde_json::from_value(p).map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, + Some(p) => serde_json::from_value(p) + .map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, None => InitializeRequest::default(), }; // Version negotiation: use client's version if older than server's // Claude Desktop rejects servers with newer protocol versions let negotiated_version = if request.protocol_version.as_str() < MCP_VERSION { - info!("Client requested older protocol version {}, using it", request.protocol_version); + info!( + "Client requested older protocol version {}, using it", + request.protocol_version + ); request.protocol_version.clone() } else { MCP_VERSION.to_string() }; self.initialized = true; - info!("MCP session initialized with protocol version {}", negotiated_version); + info!( + "MCP session initialized with protocol version {}", + negotiated_version + ); let result = InitializeResult { protocol_version: negotiated_version, @@ -306,6 +319,15 @@ impl McpServer { description: Some("Alias for deep_reference. Connect the dots across memories with cognitive reasoning.".to_string()), input_schema: tools::cross_reference::schema(), }, + // ================================================================ + // ACTIVE FORGETTING (v2.0.5) — top-down suppression + // Anderson et al. 2025 Nat Rev Neurosci + Davis Rac1 + // ================================================================ + ToolDescription { + name: "suppress".to_string(), + description: Some("Actively suppress a memory via top-down inhibitory control (Anderson 2025 SIF + Davis Rac1). Distinct from delete: the memory persists but is inhibited from retrieval and actively decays. Each call compounds. A background Rac1 worker cascades decay to co-activated neighbors. Reversible within 24 hours via reverse=true.".to_string()), + input_schema: tools::suppress::schema(), + }, ]; let result = ListToolsResult { tools }; @@ -318,7 +340,8 @@ impl McpServer { params: Option, ) -> Result { let request: CallToolRequest = match params { - Some(p) => serde_json::from_value(p).map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, + Some(p) => serde_json::from_value(p) + .map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, None => return Err(JsonRpcError::invalid_params("Missing tool call parameters")), }; @@ -329,43 +352,68 @@ impl McpServer { } // Save args for event emission (tool dispatch consumes request.arguments) - let saved_args = if self.event_tx.is_some() { request.arguments.clone() } else { None }; + let saved_args = if self.event_tx.is_some() { + request.arguments.clone() + } else { + None + }; let result = match request.name.as_str() { // ================================================================ // UNIFIED TOOLS (v1.1+) - Preferred API // ================================================================ - "search" => tools::search_unified::execute(&self.storage, &self.cognitive, request.arguments).await, - "memory" => tools::memory_unified::execute(&self.storage, &self.cognitive, request.arguments).await, - "codebase" => tools::codebase_unified::execute(&self.storage, &self.cognitive, request.arguments).await, - "intention" => tools::intention_unified::execute(&self.storage, &self.cognitive, request.arguments).await, + "search" => { + tools::search_unified::execute(&self.storage, &self.cognitive, request.arguments) + .await + } + "memory" => { + tools::memory_unified::execute(&self.storage, &self.cognitive, request.arguments) + .await + } + "codebase" => { + tools::codebase_unified::execute(&self.storage, &self.cognitive, request.arguments) + .await + } + "intention" => { + tools::intention_unified::execute(&self.storage, &self.cognitive, request.arguments) + .await + } // ================================================================ // Core memory (v1.7: smart_ingest absorbs ingest + checkpoint) // ================================================================ - "smart_ingest" => tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments).await, + "smart_ingest" => { + tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments) + .await + } // ================================================================ // DEPRECATED (v1.7): ingest → smart_ingest // ================================================================ "ingest" => { warn!("Tool 'ingest' is deprecated in v1.7. Use 'smart_ingest' instead."); - tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments).await + tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments) + .await } // ================================================================ // DEPRECATED (v1.7): session_checkpoint → smart_ingest (batch mode) // ================================================================ "session_checkpoint" => { - warn!("Tool 'session_checkpoint' is deprecated in v1.7. Use 'smart_ingest' with 'items' parameter instead."); - tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments).await + warn!( + "Tool 'session_checkpoint' is deprecated in v1.7. Use 'smart_ingest' with 'items' parameter instead." + ); + tools::smart_ingest::execute(&self.storage, &self.cognitive, request.arguments) + .await } // ================================================================ // DEPRECATED (v1.7): promote_memory → memory(action='promote') // ================================================================ "promote_memory" => { - warn!("Tool 'promote_memory' is deprecated in v1.7. Use 'memory' with action='promote' instead."); + warn!( + "Tool 'promote_memory' is deprecated in v1.7. Use 'memory' with action='promote' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -379,7 +427,9 @@ impl McpServer { tools::memory_unified::execute(&self.storage, &self.cognitive, unified_args).await } "demote_memory" => { - warn!("Tool 'demote_memory' is deprecated in v1.7. Use 'memory' with action='demote' instead."); + warn!( + "Tool 'demote_memory' is deprecated in v1.7. Use 'memory' with action='demote' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -398,17 +448,34 @@ impl McpServer { // ================================================================ "health_check" => { warn!("Tool 'health_check' is deprecated in v1.7. Use 'system_status' instead."); - tools::maintenance::execute_system_status(&self.storage, &self.cognitive, request.arguments).await + tools::maintenance::execute_system_status( + &self.storage, + &self.cognitive, + request.arguments, + ) + .await } "stats" => { warn!("Tool 'stats' is deprecated in v1.7. Use 'system_status' instead."); - tools::maintenance::execute_system_status(&self.storage, &self.cognitive, request.arguments).await + tools::maintenance::execute_system_status( + &self.storage, + &self.cognitive, + request.arguments, + ) + .await } // ================================================================ // SYSTEM STATUS (v1.7: replaces health_check + stats) // ================================================================ - "system_status" => tools::maintenance::execute_system_status(&self.storage, &self.cognitive, request.arguments).await, + "system_status" => { + tools::maintenance::execute_system_status( + &self.storage, + &self.cognitive, + request.arguments, + ) + .await + } "mark_reviewed" => tools::review::execute(&self.storage, request.arguments).await, @@ -416,15 +483,21 @@ impl McpServer { // DEPRECATED: Search tools - redirect to unified 'search' // ================================================================ "recall" | "semantic_search" | "hybrid_search" => { - warn!("Tool '{}' is deprecated. Use 'search' instead.", request.name); - tools::search_unified::execute(&self.storage, &self.cognitive, request.arguments).await + warn!( + "Tool '{}' is deprecated. Use 'search' instead.", + request.name + ); + tools::search_unified::execute(&self.storage, &self.cognitive, request.arguments) + .await } // ================================================================ // DEPRECATED: Memory tools - redirect to unified 'memory' // ================================================================ "get_knowledge" => { - warn!("Tool 'get_knowledge' is deprecated. Use 'memory' with action='get' instead."); + warn!( + "Tool 'get_knowledge' is deprecated. Use 'memory' with action='get' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let id = args.get("id").cloned().unwrap_or(serde_json::Value::Null); @@ -438,7 +511,9 @@ impl McpServer { tools::memory_unified::execute(&self.storage, &self.cognitive, unified_args).await } "delete_knowledge" => { - warn!("Tool 'delete_knowledge' is deprecated. Use 'memory' with action='delete' instead."); + warn!( + "Tool 'delete_knowledge' is deprecated. Use 'memory' with action='delete' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let id = args.get("id").cloned().unwrap_or(serde_json::Value::Null); @@ -452,10 +527,15 @@ impl McpServer { tools::memory_unified::execute(&self.storage, &self.cognitive, unified_args).await } "get_memory_state" => { - warn!("Tool 'get_memory_state' is deprecated. Use 'memory' with action='state' instead."); + warn!( + "Tool 'get_memory_state' is deprecated. Use 'memory' with action='state' instead." + ); let unified_args = match request.arguments { Some(ref args) => { - let id = args.get("memory_id").cloned().unwrap_or(serde_json::Value::Null); + let id = args + .get("memory_id") + .cloned() + .unwrap_or(serde_json::Value::Null); Some(serde_json::json!({ "action": "state", "id": id @@ -470,7 +550,9 @@ impl McpServer { // DEPRECATED: Codebase tools - redirect to unified 'codebase' // ================================================================ "remember_pattern" => { - warn!("Tool 'remember_pattern' is deprecated. Use 'codebase' with action='remember_pattern' instead."); + warn!( + "Tool 'remember_pattern' is deprecated. Use 'codebase' with action='remember_pattern' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -484,12 +566,17 @@ impl McpServer { tools::codebase_unified::execute(&self.storage, &self.cognitive, unified_args).await } "remember_decision" => { - warn!("Tool 'remember_decision' is deprecated. Use 'codebase' with action='remember_decision' instead."); + warn!( + "Tool 'remember_decision' is deprecated. Use 'codebase' with action='remember_decision' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); if let Some(obj) = new_args.as_object_mut() { - obj.insert("action".to_string(), serde_json::json!("remember_decision")); + obj.insert( + "action".to_string(), + serde_json::json!("remember_decision"), + ); } Some(new_args) } @@ -498,7 +585,9 @@ impl McpServer { tools::codebase_unified::execute(&self.storage, &self.cognitive, unified_args).await } "get_codebase_context" => { - warn!("Tool 'get_codebase_context' is deprecated. Use 'codebase' with action='get_context' instead."); + warn!( + "Tool 'get_codebase_context' is deprecated. Use 'codebase' with action='get_context' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -516,7 +605,9 @@ impl McpServer { // DEPRECATED: Intention tools - redirect to unified 'intention' // ================================================================ "set_intention" => { - warn!("Tool 'set_intention' is deprecated. Use 'intention' with action='set' instead."); + warn!( + "Tool 'set_intention' is deprecated. Use 'intention' with action='set' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -527,10 +618,13 @@ impl McpServer { } None => Some(serde_json::json!({"action": "set"})), }; - tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args).await + tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args) + .await } "check_intentions" => { - warn!("Tool 'check_intentions' is deprecated. Use 'intention' with action='check' instead."); + warn!( + "Tool 'check_intentions' is deprecated. Use 'intention' with action='check' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -541,13 +635,19 @@ impl McpServer { } None => Some(serde_json::json!({"action": "check"})), }; - tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args).await + tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args) + .await } "complete_intention" => { - warn!("Tool 'complete_intention' is deprecated. Use 'intention' with action='update', status='complete' instead."); + warn!( + "Tool 'complete_intention' is deprecated. Use 'intention' with action='update', status='complete' instead." + ); let unified_args = match request.arguments { Some(ref args) => { - let id = args.get("intentionId").cloned().unwrap_or(serde_json::Value::Null); + let id = args + .get("intentionId") + .cloned() + .unwrap_or(serde_json::Value::Null); Some(serde_json::json!({ "action": "update", "id": id, @@ -556,14 +656,23 @@ impl McpServer { } None => None, }; - tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args).await + tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args) + .await } "snooze_intention" => { - warn!("Tool 'snooze_intention' is deprecated. Use 'intention' with action='update', status='snooze' instead."); + warn!( + "Tool 'snooze_intention' is deprecated. Use 'intention' with action='update', status='snooze' instead." + ); let unified_args = match request.arguments { Some(ref args) => { - let id = args.get("intentionId").cloned().unwrap_or(serde_json::Value::Null); - let minutes = args.get("minutes").cloned().unwrap_or(serde_json::json!(30)); + let id = args + .get("intentionId") + .cloned() + .unwrap_or(serde_json::Value::Null); + let minutes = args + .get("minutes") + .cloned() + .unwrap_or(serde_json::json!(30)); Some(serde_json::json!({ "action": "update", "id": id, @@ -573,10 +682,13 @@ impl McpServer { } None => None, }; - tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args).await + tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args) + .await } "list_intentions" => { - warn!("Tool 'list_intentions' is deprecated. Use 'intention' with action='list' instead."); + warn!( + "Tool 'list_intentions' is deprecated. Use 'intention' with action='list' instead." + ); let unified_args = match request.arguments { Some(ref args) => { let mut new_args = args.clone(); @@ -590,15 +702,20 @@ impl McpServer { } None => Some(serde_json::json!({"action": "list"})), }; - tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args).await + tools::intention_unified::execute(&self.storage, &self.cognitive, unified_args) + .await } // ================================================================ // Neuroscience tools (internal, not in tools/list) // ================================================================ - "list_by_state" => tools::memory_states::execute_list(&self.storage, request.arguments).await, + "list_by_state" => { + tools::memory_states::execute_list(&self.storage, request.arguments).await + } "state_stats" => tools::memory_states::execute_stats(&self.storage).await, - "trigger_importance" => tools::tagging::execute_trigger(&self.storage, request.arguments).await, + "trigger_importance" => { + tools::tagging::execute_trigger(&self.storage, request.arguments).await + } "find_tagged" => tools::tagging::execute_find(&self.storage, request.arguments).await, "tagging_stats" => tools::tagging::execute_stats(&self.storage).await, "match_context" => tools::context::execute(&self.storage, request.arguments).await, @@ -606,7 +723,9 @@ impl McpServer { // ================================================================ // Feedback (internal, still used by request_feedback) // ================================================================ - "request_feedback" => tools::feedback::execute_request_feedback(&self.storage, request.arguments).await, + "request_feedback" => { + tools::feedback::execute_request_feedback(&self.storage, request.arguments).await + } // ================================================================ // TEMPORAL TOOLS (v1.2+) @@ -630,7 +749,9 @@ impl McpServer { // ================================================================ // AUTO-SAVE & DEDUP TOOLS (v1.3+) // ================================================================ - "importance_score" => tools::importance::execute(&self.storage, &self.cognitive, request.arguments).await, + "importance_score" => { + tools::importance::execute(&self.storage, &self.cognitive, request.arguments).await + } "find_duplicates" => tools::dedup::execute(&self.storage, request.arguments).await, // ================================================================ @@ -638,26 +759,45 @@ impl McpServer { // ================================================================ "dream" => { self.emit(VestigeEvent::DreamStarted { - memory_count: self.storage.get_stats().map(|s| s.total_nodes as usize).unwrap_or(0), + memory_count: self + .storage + .get_stats() + .map(|s| s.total_nodes as usize) + .unwrap_or(0), timestamp: chrono::Utc::now(), }); tools::dream::execute(&self.storage, &self.cognitive, request.arguments).await } - "explore_connections" => tools::explore::execute(&self.storage, &self.cognitive, request.arguments).await, - "predict" => tools::predict::execute(&self.storage, &self.cognitive, request.arguments).await, + "explore_connections" => { + tools::explore::execute(&self.storage, &self.cognitive, request.arguments).await + } + "predict" => { + tools::predict::execute(&self.storage, &self.cognitive, request.arguments).await + } "restore" => tools::restore::execute(&self.storage, request.arguments).await, // ================================================================ // CONTEXT PACKETS (v1.8+) // ================================================================ - "session_context" => tools::session_context::execute(&self.storage, &self.cognitive, request.arguments).await, + "session_context" => { + tools::session_context::execute(&self.storage, &self.cognitive, request.arguments) + .await + } // ================================================================ // AUTONOMIC TOOLS (v1.9+) // ================================================================ "memory_health" => tools::health::execute(&self.storage, request.arguments).await, "memory_graph" => tools::graph::execute(&self.storage, request.arguments).await, - "deep_reference" | "cross_reference" => tools::cross_reference::execute(&self.storage, &self.cognitive, request.arguments).await, + "deep_reference" | "cross_reference" => { + tools::cross_reference::execute(&self.storage, &self.cognitive, request.arguments) + .await + } + + // ================================================================ + // ACTIVE FORGETTING (v2.0.5) — top-down suppression + // ================================================================ + "suppress" => tools::suppress::execute(&self.storage, request.arguments).await, name => { return Err(JsonRpcError::method_not_found_with_message(&format!( @@ -680,11 +820,13 @@ impl McpServer { let call_result = CallToolResult { content: vec![crate::protocol::messages::ToolResultContent { content_type: "text".to_string(), - text: serde_json::to_string_pretty(&content).unwrap_or_else(|_| content.to_string()), + text: serde_json::to_string_pretty(&content) + .unwrap_or_else(|_| content.to_string()), }], is_error: Some(false), }; - serde_json::to_value(call_result).map_err(|e| JsonRpcError::internal_error(&e.to_string())) + serde_json::to_value(call_result) + .map_err(|e| JsonRpcError::internal_error(&e.to_string())) } Err(e) => { let call_result = CallToolResult { @@ -694,13 +836,16 @@ impl McpServer { }], is_error: Some(true), }; - serde_json::to_value(call_result).map_err(|e| JsonRpcError::internal_error(&e.to_string())) + serde_json::to_value(call_result) + .map_err(|e| JsonRpcError::internal_error(&e.to_string())) } }; // Inline consolidation trigger: uses ConsolidationScheduler instead of fixed count let count = self.tool_call_count.fetch_add(1, Ordering::Relaxed) + 1; - let should_consolidate = self.cognitive.try_lock() + let should_consolidate = self + .cognitive + .try_lock() .ok() .map(|cog| cog.consolidation_scheduler.should_consolidate()) .unwrap_or(count.is_multiple_of(100)); // Fallback to count-based if lock unavailable @@ -799,7 +944,9 @@ impl McpServer { ResourceDescription { uri: "memory://intentions".to_string(), name: "Active Intentions".to_string(), - description: Some("Future intentions (prospective memory) waiting to be triggered".to_string()), + description: Some( + "Future intentions (prospective memory) waiting to be triggered".to_string(), + ), mime_type: Some("application/json".to_string()), }, ResourceDescription { @@ -820,7 +967,8 @@ impl McpServer { params: Option, ) -> Result { let request: ReadResourceRequest = match params { - Some(p) => serde_json::from_value(p).map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, + Some(p) => serde_json::from_value(p) + .map_err(|e| JsonRpcError::invalid_params(&e.to_string()))?, None => return Err(JsonRpcError::invalid_params("Missing resource URI")), }; @@ -847,7 +995,8 @@ impl McpServer { blob: None, }], }; - serde_json::to_value(result).map_err(|e| JsonRpcError::internal_error(&e.to_string())) + serde_json::to_value(result) + .map_err(|e| JsonRpcError::internal_error(&e.to_string())) } Err(e) => Err(JsonRpcError::internal_error(&e)), } @@ -870,25 +1019,49 @@ impl McpServer { "smart_ingest" | "ingest" | "session_checkpoint" => { // Single mode: result has "decision" (create/update/supersede/reinforce/merge/replace/add_context) if let Some(decision) = result.get("decision").and_then(|a| a.as_str()) { - let id = result.get("nodeId").or(result.get("id")) - .and_then(|v| v.as_str()).unwrap_or("").to_string(); - let preview = result.get("contentPreview").or(result.get("content")) - .and_then(|v| v.as_str()).unwrap_or("").to_string(); + let id = result + .get("nodeId") + .or(result.get("id")) + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + let preview = result + .get("contentPreview") + .or(result.get("content")) + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); match decision { "create" => { - let node_type = result.get("nodeType") - .and_then(|v| v.as_str()).unwrap_or("fact").to_string(); - let tags = result.get("tags") + let node_type = result + .get("nodeType") + .and_then(|v| v.as_str()) + .unwrap_or("fact") + .to_string(); + let tags = result + .get("tags") .and_then(|v| v.as_array()) - .map(|arr| arr.iter().filter_map(|t| t.as_str().map(String::from)).collect()) + .map(|arr| { + arr.iter() + .filter_map(|t| t.as_str().map(String::from)) + .collect() + }) .unwrap_or_default(); self.emit(VestigeEvent::MemoryCreated { - id, content_preview: preview, node_type, tags, timestamp: now, + id, + content_preview: preview, + node_type, + tags, + timestamp: now, }); } - "update" | "supersede" | "reinforce" | "merge" | "replace" | "add_context" => { + "update" | "supersede" | "reinforce" | "merge" | "replace" + | "add_context" => { self.emit(VestigeEvent::MemoryUpdated { - id, content_preview: preview, field: decision.to_string(), timestamp: now, + id, + content_preview: preview, + field: decision.to_string(), + timestamp: now, }); } _ => {} @@ -898,19 +1071,31 @@ impl McpServer { if let Some(results) = result.get("results").and_then(|r| r.as_array()) { for item in results { let decision = item.get("decision").and_then(|a| a.as_str()).unwrap_or(""); - let id = item.get("nodeId").or(item.get("id")) - .and_then(|v| v.as_str()).unwrap_or("").to_string(); - let preview = item.get("contentPreview") - .and_then(|v| v.as_str()).unwrap_or("").to_string(); + let id = item + .get("nodeId") + .or(item.get("id")) + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + let preview = item + .get("contentPreview") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); if decision == "create" { self.emit(VestigeEvent::MemoryCreated { - id, content_preview: preview, - node_type: "fact".to_string(), tags: vec![], timestamp: now, + id, + content_preview: preview, + node_type: "fact".to_string(), + tags: vec![], + timestamp: now, }); } else if !decision.is_empty() { self.emit(VestigeEvent::MemoryUpdated { - id, content_preview: preview, - field: decision.to_string(), timestamp: now, + id, + content_preview: preview, + field: decision.to_string(), + timestamp: now, }); } } @@ -918,35 +1103,53 @@ impl McpServer { } // -- memory: get/delete/promote/demote -- - "memory" | "promote_memory" | "demote_memory" | "delete_knowledge" | "get_memory_state" => { - let action = args.as_ref() + "memory" | "promote_memory" | "demote_memory" | "delete_knowledge" + | "get_memory_state" => { + let action = args + .as_ref() .and_then(|a| a.get("action")) .and_then(|a| a.as_str()) - .unwrap_or(if tool_name == "promote_memory" { "promote" } - else if tool_name == "demote_memory" { "demote" } - else if tool_name == "delete_knowledge" { "delete" } - else { "" }); - let id = args.as_ref() + .unwrap_or(if tool_name == "promote_memory" { + "promote" + } else if tool_name == "demote_memory" { + "demote" + } else if tool_name == "delete_knowledge" { + "delete" + } else { + "" + }); + let id = args + .as_ref() .and_then(|a| a.get("id")) - .and_then(|v| v.as_str()).unwrap_or("").to_string(); + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); match action { "delete" => { self.emit(VestigeEvent::MemoryDeleted { id, timestamp: now }); } "promote" => { - let retention = result.get("newRetention") + let retention = result + .get("newRetention") .or(result.get("retrievalStrength")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); self.emit(VestigeEvent::MemoryPromoted { - id, new_retention: retention, timestamp: now, + id, + new_retention: retention, + timestamp: now, }); } "demote" => { - let retention = result.get("newRetention") + let retention = result + .get("newRetention") .or(result.get("retrievalStrength")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); self.emit(VestigeEvent::MemoryDemoted { - id, new_retention: retention, timestamp: now, + id, + new_retention: retention, + timestamp: now, }); } _ => {} @@ -955,86 +1158,144 @@ impl McpServer { // -- search -- "search" | "recall" | "semantic_search" | "hybrid_search" => { - let query = args.as_ref() + let query = args + .as_ref() .and_then(|a| a.get("query")) - .and_then(|v| v.as_str()).unwrap_or("").to_string(); + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); let results = result.get("results").and_then(|r| r.as_array()); let result_count = results.map(|r| r.len()).unwrap_or(0); let result_ids: Vec = results - .map(|r| r.iter() - .filter_map(|item| item.get("id").and_then(|v| v.as_str()).map(String::from)) - .collect()) + .map(|r| { + r.iter() + .filter_map(|item| { + item.get("id").and_then(|v| v.as_str()).map(String::from) + }) + .collect() + }) .unwrap_or_default(); - let duration_ms = result.get("durationMs") + let duration_ms = result + .get("durationMs") .or(result.get("duration_ms")) - .and_then(|v| v.as_u64()).unwrap_or(0); + .and_then(|v| v.as_u64()) + .unwrap_or(0); self.emit(VestigeEvent::SearchPerformed { - query, result_count, result_ids, duration_ms, timestamp: now, + query, + result_count, + result_ids, + duration_ms, + timestamp: now, }); } // -- dream -- "dream" => { - let replayed = result.get("memoriesReplayed") + let replayed = result + .get("memoriesReplayed") .or(result.get("memories_replayed")) - .and_then(|v| v.as_u64()).unwrap_or(0) as usize; - let connections = result.get("connectionsFound") + .and_then(|v| v.as_u64()) + .unwrap_or(0) as usize; + let connections = result + .get("connectionsFound") .or(result.get("connections_found")) - .and_then(|v| v.as_u64()).unwrap_or(0) as usize; - let insights = result.get("insightsGenerated") + .and_then(|v| v.as_u64()) + .unwrap_or(0) as usize; + let insights = result + .get("insightsGenerated") .or(result.get("insights")) - .and_then(|v| v.as_array()).map(|a| a.len()).unwrap_or(0); - let duration_ms = result.get("durationMs") + .and_then(|v| v.as_array()) + .map(|a| a.len()) + .unwrap_or(0); + let duration_ms = result + .get("durationMs") .or(result.get("duration_ms")) - .and_then(|v| v.as_u64()).unwrap_or(0); + .and_then(|v| v.as_u64()) + .unwrap_or(0); self.emit(VestigeEvent::DreamCompleted { - memories_replayed: replayed, connections_found: connections, - insights_generated: insights, duration_ms, timestamp: now, + memories_replayed: replayed, + connections_found: connections, + insights_generated: insights, + duration_ms, + timestamp: now, }); } // -- consolidate -- "consolidate" => { - let processed = result.get("nodesProcessed") + let processed = result + .get("nodesProcessed") .or(result.get("nodes_processed")) - .and_then(|v| v.as_u64()).unwrap_or(0) as usize; - let decay = result.get("decayApplied") + .and_then(|v| v.as_u64()) + .unwrap_or(0) as usize; + let decay = result + .get("decayApplied") .or(result.get("decay_applied")) - .and_then(|v| v.as_u64()).unwrap_or(0) as usize; - let embeddings = result.get("embeddingsGenerated") + .and_then(|v| v.as_u64()) + .unwrap_or(0) as usize; + let embeddings = result + .get("embeddingsGenerated") .or(result.get("embeddings_generated")) - .and_then(|v| v.as_u64()).unwrap_or(0) as usize; - let duration_ms = result.get("durationMs") + .and_then(|v| v.as_u64()) + .unwrap_or(0) as usize; + let duration_ms = result + .get("durationMs") .or(result.get("duration_ms")) - .and_then(|v| v.as_u64()).unwrap_or(0); + .and_then(|v| v.as_u64()) + .unwrap_or(0); self.emit(VestigeEvent::ConsolidationCompleted { - nodes_processed: processed, decay_applied: decay, - embeddings_generated: embeddings, duration_ms, timestamp: now, + nodes_processed: processed, + decay_applied: decay, + embeddings_generated: embeddings, + duration_ms, + timestamp: now, }); } // -- importance_score -- "importance_score" => { - let preview = args.as_ref() + let preview = args + .as_ref() .and_then(|a| a.get("content")) .and_then(|v| v.as_str()) - .map(|s| if s.len() > 100 { format!("{}...", &s[..s.floor_char_boundary(100)]) } else { s.to_string() }) + .map(|s| { + if s.len() > 100 { + format!("{}...", &s[..s.floor_char_boundary(100)]) + } else { + s.to_string() + } + }) .unwrap_or_default(); - let composite = result.get("compositeScore") + let composite = result + .get("compositeScore") .or(result.get("composite_score")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); let channels = result.get("channels").or(result.get("breakdown")); - let novelty = channels.and_then(|c| c.get("novelty")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); - let arousal = channels.and_then(|c| c.get("arousal")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); - let reward = channels.and_then(|c| c.get("reward")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); - let attention = channels.and_then(|c| c.get("attention")) - .and_then(|v| v.as_f64()).unwrap_or(0.0); + let novelty = channels + .and_then(|c| c.get("novelty")) + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); + let arousal = channels + .and_then(|c| c.get("arousal")) + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); + let reward = channels + .and_then(|c| c.get("reward")) + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); + let attention = channels + .and_then(|c| c.get("attention")) + .and_then(|v| v.as_f64()) + .unwrap_or(0.0); self.emit(VestigeEvent::ImportanceScored { - content_preview: preview, composite_score: composite, - novelty, arousal, reward, attention, timestamp: now, + content_preview: preview, + composite_score: composite, + novelty, + arousal, + reward, + attention, + timestamp: now, }); } @@ -1087,14 +1348,17 @@ mod tests { let (mut server, _dir) = test_server().await; assert!(!server.initialized); - let request = make_request("initialize", Some(serde_json::json!({ - "protocolVersion": "2024-11-05", - "capabilities": {}, - "clientInfo": { - "name": "test-client", - "version": "1.0.0" - } - }))); + let request = make_request( + "initialize", + Some(serde_json::json!({ + "protocolVersion": "2024-11-05", + "capabilities": {}, + "clientInfo": { + "name": "test-client", + "version": "1.0.0" + } + })), + ); let response = server.handle_request(request).await; assert!(response.is_some()); @@ -1201,13 +1465,10 @@ mod tests { let result = response.result.unwrap(); let tools = result["tools"].as_array().unwrap(); - // v2.0.4: 23 tools (4 unified + 1 core + 2 temporal + 5 maintenance + 2 auto-save + 3 cognitive + 1 restore + 1 session_context + 2 autonomic + 1 deep_reference + 1 cross_reference alias) - assert_eq!(tools.len(), 23, "Expected exactly 23 tools in v2.0.4+"); + // v2.0.5: 24 tools (4 unified + 1 core + 2 temporal + 5 maintenance + 2 auto-save + 3 cognitive + 1 restore + 1 session_context + 2 autonomic + 1 deep_reference + 1 cross_reference alias + 1 suppress) + assert_eq!(tools.len(), 24, "Expected exactly 24 tools in v2.0.5+"); - let tool_names: Vec<&str> = tools - .iter() - .map(|t| t["name"].as_str().unwrap()) - .collect(); + let tool_names: Vec<&str> = tools.iter().map(|t| t["name"].as_str().unwrap()).collect(); // Unified tools assert!(tool_names.contains(&"search")); @@ -1217,12 +1478,24 @@ mod tests { // Core memory (smart_ingest absorbs ingest + checkpoint in v1.7) assert!(tool_names.contains(&"smart_ingest")); - assert!(!tool_names.contains(&"ingest"), "ingest should be removed in v1.7"); - assert!(!tool_names.contains(&"session_checkpoint"), "session_checkpoint should be removed in v1.7"); + assert!( + !tool_names.contains(&"ingest"), + "ingest should be removed in v1.7" + ); + assert!( + !tool_names.contains(&"session_checkpoint"), + "session_checkpoint should be removed in v1.7" + ); // Feedback merged into memory tool (v1.7) - assert!(!tool_names.contains(&"promote_memory"), "promote_memory should be removed in v1.7"); - assert!(!tool_names.contains(&"demote_memory"), "demote_memory should be removed in v1.7"); + assert!( + !tool_names.contains(&"promote_memory"), + "promote_memory should be removed in v1.7" + ); + assert!( + !tool_names.contains(&"demote_memory"), + "demote_memory should be removed in v1.7" + ); // Temporal tools (v1.2) assert!(tool_names.contains(&"memory_timeline")); @@ -1230,8 +1503,14 @@ mod tests { // Maintenance tools (v1.7: system_status replaces health_check + stats) assert!(tool_names.contains(&"system_status")); - assert!(!tool_names.contains(&"health_check"), "health_check should be removed in v1.7"); - assert!(!tool_names.contains(&"stats"), "stats should be removed in v1.7"); + assert!( + !tool_names.contains(&"health_check"), + "health_check should be removed in v1.7" + ); + assert!( + !tool_names.contains(&"stats"), + "stats should be removed in v1.7" + ); assert!(tool_names.contains(&"consolidate")); assert!(tool_names.contains(&"backup")); assert!(tool_names.contains(&"export")); @@ -1257,6 +1536,9 @@ mod tests { // Deep reference + cross_reference alias (v2.0.4) assert!(tool_names.contains(&"deep_reference")); assert!(tool_names.contains(&"cross_reference")); + + // Active forgetting (v2.0.5) — Anderson 2025 + Davis Rac1 + assert!(tool_names.contains(&"suppress")); } #[tokio::test] @@ -1274,8 +1556,14 @@ mod tests { for tool in tools { assert!(tool["name"].is_string(), "Tool should have a name"); - assert!(tool["description"].is_string(), "Tool should have a description"); - assert!(tool["inputSchema"].is_object(), "Tool should have an input schema"); + assert!( + tool["description"].is_string(), + "Tool should have a description" + ); + assert!( + tool["inputSchema"].is_object(), + "Tool should have an input schema" + ); } } @@ -1328,7 +1616,10 @@ mod tests { for resource in resources { assert!(resource["uri"].is_string(), "Resource should have a URI"); assert!(resource["name"].is_string(), "Resource should have a name"); - assert!(resource["description"].is_string(), "Resource should have a description"); + assert!( + resource["description"].is_string(), + "Resource should have a description" + ); } } @@ -1360,10 +1651,13 @@ mod tests { let init_request = make_request("initialize", None); server.handle_request(init_request).await; - let request = make_request("tools/call", Some(serde_json::json!({ - "name": "nonexistent_tool", - "arguments": {} - }))); + let request = make_request( + "tools/call", + Some(serde_json::json!({ + "name": "nonexistent_tool", + "arguments": {} + })), + ); let response = server.handle_request(request).await.unwrap(); assert!(response.error.is_some()); @@ -1414,9 +1708,12 @@ mod tests { let init_request = make_request("initialize", None); server.handle_request(init_request).await; - let request = make_request("tools/call", Some(serde_json::json!({ - "invalid": "params" - }))); + let request = make_request( + "tools/call", + Some(serde_json::json!({ + "invalid": "params" + })), + ); let response = server.handle_request(request).await.unwrap(); assert!(response.error.is_some()); diff --git a/crates/vestige-mcp/src/tools/changelog.rs b/crates/vestige-mcp/src/tools/changelog.rs index f615acb..e2c4928 100644 --- a/crates/vestige-mcp/src/tools/changelog.rs +++ b/crates/vestige-mcp/src/tools/changelog.rs @@ -54,10 +54,7 @@ struct ChangelogArgs { } /// Execute memory_changelog tool -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: ChangelogArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => ChangelogArgs { @@ -80,11 +77,7 @@ pub async fn execute( } /// Per-memory changelog: state transition audit trail -fn execute_per_memory( - storage: &Storage, - memory_id: &str, - limit: i32, -) -> Result { +fn execute_per_memory(storage: &Storage, memory_id: &str, limit: i32) -> Result { // Validate UUID format Uuid::parse_str(memory_id) .map_err(|_| format!("Invalid memory_id '{}'. Must be a valid UUID.", memory_id))?; @@ -126,10 +119,7 @@ fn execute_per_memory( } /// System-wide changelog: consolidations + recent state transitions -fn execute_system_wide( - storage: &Storage, - limit: i32, -) -> Result { +fn execute_system_wide(storage: &Storage, limit: i32) -> Result { // Get consolidation history let consolidations = storage .get_consolidation_history(limit) @@ -141,9 +131,7 @@ fn execute_system_wide( .map_err(|e| e.to_string())?; // Get dream history (Bug #9 fix — dreams were invisible to audit trail) - let dreams = storage - .get_dream_history(limit) - .unwrap_or_default(); + let dreams = storage.get_dream_history(limit).unwrap_or_default(); // Build unified event list let mut events: Vec<(DateTime, Value)> = Vec::new(); @@ -296,8 +284,7 @@ mod tests { #[tokio::test] async fn test_changelog_per_memory_nonexistent() { let (storage, _dir) = test_storage().await; - let args = - serde_json::json!({ "memory_id": "00000000-0000-0000-0000-000000000000" }); + let args = serde_json::json!({ "memory_id": "00000000-0000-0000-0000-000000000000" }); let result = execute(&storage, Some(args)).await; assert!(result.is_err()); assert!(result.unwrap_err().contains("not found")); diff --git a/crates/vestige-mcp/src/tools/checkpoint.rs b/crates/vestige-mcp/src/tools/checkpoint.rs index b31becc..69cab08 100644 --- a/crates/vestige-mcp/src/tools/checkpoint.rs +++ b/crates/vestige-mcp/src/tools/checkpoint.rs @@ -7,7 +7,6 @@ use serde::Deserialize; use serde_json::Value; use std::sync::Arc; - use vestige_core::{IngestInput, Storage}; /// Input schema for session_checkpoint tool @@ -63,10 +62,7 @@ struct CheckpointItem { source: Option, } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: CheckpointArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), diff --git a/crates/vestige-mcp/src/tools/codebase.rs b/crates/vestige-mcp/src/tools/codebase.rs index 22fe3d4..3d51a4b 100644 --- a/crates/vestige-mcp/src/tools/codebase.rs +++ b/crates/vestige-mcp/src/tools/codebase.rs @@ -7,7 +7,6 @@ use serde::Deserialize; use serde_json::Value; use std::sync::Arc; - use vestige_core::{IngestInput, Storage}; /// Input schema for remember_pattern tool @@ -114,10 +113,7 @@ struct ContextArgs { limit: Option, } -pub async fn execute_pattern( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_pattern(storage: &Arc, args: Option) -> Result { let args: PatternArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -206,7 +202,11 @@ pub async fn execute_decision( } // Build tags - let mut tags = vec!["decision".to_string(), "architecture".to_string(), "codebase".to_string()]; + let mut tags = vec![ + "decision".to_string(), + "architecture".to_string(), + "codebase".to_string(), + ]; if let Some(ref codebase) = args.codebase { tags.push(format!("codebase:{}", codebase)); } @@ -231,10 +231,7 @@ pub async fn execute_decision( })) } -pub async fn execute_context( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_context(storage: &Arc, args: Option) -> Result { let args: ContextArgs = args .map(serde_json::from_value) .transpose() diff --git a/crates/vestige-mcp/src/tools/codebase_unified.rs b/crates/vestige-mcp/src/tools/codebase_unified.rs index 61c7536..726ab4b 100644 --- a/crates/vestige-mcp/src/tools/codebase_unified.rs +++ b/crates/vestige-mcp/src/tools/codebase_unified.rs @@ -161,7 +161,8 @@ async fn execute_remember_pattern( // ==================================================================== if let Ok(cog) = cognitive.try_lock() { let codebase_name = args.codebase.as_deref().unwrap_or("default"); - cog.cross_project.record_project_memory(&node_id, codebase_name, None); + cog.cross_project + .record_project_memory(&node_id, codebase_name, None); // Also index in hippocampal index for fast retrieval let _ = cog.hippocampal_index.index_memory( @@ -256,7 +257,8 @@ async fn execute_remember_decision( // ==================================================================== if let Ok(cog) = cognitive.try_lock() { let codebase_name = args.codebase.as_deref().unwrap_or("default"); - cog.cross_project.record_project_memory(&node_id, codebase_name, None); + cog.cross_project + .record_project_memory(&node_id, codebase_name, None); // Index in hippocampal index let _ = cog.hippocampal_index.index_memory( @@ -285,10 +287,7 @@ async fn execute_get_context( let limit = args.limit.unwrap_or(10).clamp(1, 50); // Build tag filter for codebase - let tag_filter = args - .codebase - .as_ref() - .map(|cb| format!("codebase:{}", cb)); + let tag_filter = args.codebase.as_ref().map(|cb| format!("codebase:{}", cb)); // Query patterns by node_type and tag let patterns = storage @@ -377,18 +376,24 @@ mod tests { // Check action enum values let action_enum = &schema["properties"]["action"]["enum"]; - assert!(action_enum - .as_array() - .unwrap() - .contains(&serde_json::json!("remember_pattern"))); - assert!(action_enum - .as_array() - .unwrap() - .contains(&serde_json::json!("remember_decision"))); - assert!(action_enum - .as_array() - .unwrap() - .contains(&serde_json::json!("get_context"))); + assert!( + action_enum + .as_array() + .unwrap() + .contains(&serde_json::json!("remember_pattern")) + ); + assert!( + action_enum + .as_array() + .unwrap() + .contains(&serde_json::json!("remember_decision")) + ); + assert!( + action_enum + .as_array() + .unwrap() + .contains(&serde_json::json!("get_context")) + ); } // === INTEGRATION TESTS === diff --git a/crates/vestige-mcp/src/tools/context.rs b/crates/vestige-mcp/src/tools/context.rs index 211c2c5..20b3fd1 100644 --- a/crates/vestige-mcp/src/tools/context.rs +++ b/crates/vestige-mcp/src/tools/context.rs @@ -7,7 +7,6 @@ use chrono::Utc; use serde_json::Value; use std::sync::Arc; - use vestige_core::{RecallInput, SearchMode, Storage}; /// Input schema for match_context tool @@ -50,19 +49,18 @@ pub fn schema() -> Value { }) } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args = args.ok_or("Missing arguments")?; - let query = args["query"] - .as_str() - .ok_or("query is required")?; + let query = args["query"].as_str().ok_or("query is required")?; let topics: Vec = args["topics"] .as_array() - .map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect()) + .map(|arr| { + arr.iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect() + }) .unwrap_or_default(); let project = args["project"].as_str().map(String::from); @@ -83,11 +81,11 @@ pub async fn execute( search_mode: SearchMode::Hybrid, valid_at: None, }; - let candidates = storage.recall(recall_input) - .map_err(|e| e.to_string())?; + let candidates = storage.recall(recall_input).map_err(|e| e.to_string())?; // Score by context match (simplified implementation) - let mut scored_results: Vec<_> = candidates.into_iter() + let mut scored_results: Vec<_> = candidates + .into_iter() .map(|mem| { // Calculate context score based on: // 1. Temporal proximity (how recent) @@ -98,8 +96,14 @@ pub async fn execute( let tag_overlap = if topics.is_empty() { 0.5 // Neutral if no topics specified } else { - let matching = mem.tags.iter() - .filter(|t| topics.iter().any(|topic| topic.to_lowercase().contains(&t.to_lowercase()))) + let matching = mem + .tags + .iter() + .filter(|t| { + topics + .iter() + .any(|topic| topic.to_lowercase().contains(&t.to_lowercase())) + }) .count(); matching as f64 / topics.len().max(1) as f64 }; @@ -136,7 +140,8 @@ pub async fn execute( scored_results.sort_by(|a, b| b.2.partial_cmp(&a.2).unwrap_or(std::cmp::Ordering::Equal)); scored_results.truncate(limit as usize); - let results: Vec = scored_results.into_iter() + let results: Vec = scored_results + .into_iter() .map(|(mem, ctx_score, combined)| { serde_json::json!({ "id": mem.id, diff --git a/crates/vestige-mcp/src/tools/cross_reference.rs b/crates/vestige-mcp/src/tools/cross_reference.rs index 257122b..fdfd0cc 100644 --- a/crates/vestige-mcp/src/tools/cross_reference.rs +++ b/crates/vestige-mcp/src/tools/cross_reference.rs @@ -72,20 +72,64 @@ fn compute_trust(retention: f64, stability: f64, reps: i32, lapses: i32) -> f64 #[derive(Debug, Clone, PartialEq)] enum QueryIntent { - FactCheck, // "Is X true?" → find support/contradiction evidence - Timeline, // "When did X happen?" → temporal ordering + pattern detection - RootCause, // "Why did X happen?" → causal chain backward - Comparison, // "How does X differ from Y?" → diff two memory clusters - Synthesis, // Default: "What do I know about X?" → cluster + best per cluster + FactCheck, // "Is X true?" → find support/contradiction evidence + Timeline, // "When did X happen?" → temporal ordering + pattern detection + RootCause, // "Why did X happen?" → causal chain backward + Comparison, // "How does X differ from Y?" → diff two memory clusters + Synthesis, // Default: "What do I know about X?" → cluster + best per cluster } fn classify_intent(query: &str) -> QueryIntent { let q = query.to_lowercase(); let patterns: &[(QueryIntent, &[&str])] = &[ - (QueryIntent::RootCause, &["why did", "root cause", "what caused", "because of", "reason for", "why is", "why was"]), - (QueryIntent::Timeline, &["when did", "timeline", "history of", "over time", "how has", "evolution of", "sequence of"]), - (QueryIntent::Comparison, &["differ", "compare", "versus", " vs ", "difference between", "changed from"]), - (QueryIntent::FactCheck, &["is it true", "did i", "was there", "verify", "confirm", "is this correct", "should i use", "should we"]), + ( + QueryIntent::RootCause, + &[ + "why did", + "root cause", + "what caused", + "because of", + "reason for", + "why is", + "why was", + ], + ), + ( + QueryIntent::Timeline, + &[ + "when did", + "timeline", + "history of", + "over time", + "how has", + "evolution of", + "sequence of", + ], + ), + ( + QueryIntent::Comparison, + &[ + "differ", + "compare", + "versus", + " vs ", + "difference between", + "changed from", + ], + ), + ( + QueryIntent::FactCheck, + &[ + "is it true", + "did i", + "was there", + "verify", + "confirm", + "is this correct", + "should i use", + "should we", + ], + ), ]; for (intent, keywords) in patterns { if keywords.iter().any(|kw| q.contains(kw)) { @@ -118,9 +162,15 @@ struct RelationAssessment { /// Assess the relationship between two memories using embedding similarity, /// correction signals, temporal ordering, and trust comparison. /// No LLM needed — pure algorithmic assessment. -fn assess_relation(a_content: &str, b_content: &str, a_trust: f64, b_trust: f64, - a_date: chrono::DateTime, b_date: chrono::DateTime, - topic_sim: f32) -> RelationAssessment { +fn assess_relation( + a_content: &str, + b_content: &str, + a_trust: f64, + b_trust: f64, + a_date: chrono::DateTime, + b_date: chrono::DateTime, + topic_sim: f32, +) -> RelationAssessment { // Irrelevant: different topics if topic_sim < 0.15 { return RelationAssessment { @@ -136,12 +186,21 @@ fn assess_relation(a_content: &str, b_content: &str, a_trust: f64, b_trust: f64, // Supersession: same topic + newer + higher trust if topic_sim > 0.4 && time_delta_days > 0 && trust_diff > 0.05 && !has_correction { - let (newer, older) = if b_date > a_date { ("B", "A") } else { ("A", "B") }; + let (newer, older) = if b_date > a_date { + ("B", "A") + } else { + ("A", "B") + }; return RelationAssessment { relation: Relation::Supersedes, confidence: topic_sim as f64 * (0.5 + trust_diff.min(0.5)), - reasoning: format!("{} supersedes {} (newer by {}d, trust +{:.0}%)", - newer, older, time_delta_days, trust_diff * 100.0), + reasoning: format!( + "{} supersedes {} (newer by {}d, trust +{:.0}%)", + newer, + older, + time_delta_days, + trust_diff * 100.0 + ), }; } @@ -150,7 +209,10 @@ fn assess_relation(a_content: &str, b_content: &str, a_trust: f64, b_trust: f64, return RelationAssessment { relation: Relation::Contradicts, confidence: topic_sim as f64 * 0.8, - reasoning: format!("Contradiction detected (similarity {:.2}, correction signals present)", topic_sim), + reasoning: format!( + "Contradiction detected (similarity {:.2}, correction signals present)", + topic_sim + ), }; } @@ -159,7 +221,10 @@ fn assess_relation(a_content: &str, b_content: &str, a_trust: f64, b_trust: f64, return RelationAssessment { relation: Relation::Supports, confidence: topic_sim as f64, - reasoning: format!("Topically aligned (similarity {:.2}), consistent stance", topic_sim), + reasoning: format!( + "Topically aligned (similarity {:.2}), consistent stance", + topic_sim + ), }; } @@ -188,29 +253,19 @@ fn generate_reasoning_chain( // Intent-specific opening match intent { QueryIntent::FactCheck => { - chain.push_str(&format!( - "FACT CHECK: \"{}\"\n\n", query - )); + chain.push_str(&format!("FACT CHECK: \"{}\"\n\n", query)); } QueryIntent::Timeline => { - chain.push_str(&format!( - "TIMELINE: \"{}\"\n\n", query - )); + chain.push_str(&format!("TIMELINE: \"{}\"\n\n", query)); } QueryIntent::RootCause => { - chain.push_str(&format!( - "ROOT CAUSE ANALYSIS: \"{}\"\n\n", query - )); + chain.push_str(&format!("ROOT CAUSE ANALYSIS: \"{}\"\n\n", query)); } QueryIntent::Comparison => { - chain.push_str(&format!( - "COMPARISON: \"{}\"\n\n", query - )); + chain.push_str(&format!("COMPARISON: \"{}\"\n\n", query)); } QueryIntent::Synthesis => { - chain.push_str(&format!( - "SYNTHESIS: \"{}\"\n\n", query - )); + chain.push_str(&format!("SYNTHESIS: \"{}\"\n\n", query)); } } @@ -223,7 +278,8 @@ fn generate_reasoning_chain( )); // Superseded memories — with reasoning arrows - let superseded: Vec<_> = relations.iter() + let superseded: Vec<_> = relations + .iter() .filter(|(_, _, r)| matches!(r.relation, Relation::Supersedes)) .collect(); for (preview, trust, rel) in &superseded { @@ -236,11 +292,13 @@ fn generate_reasoning_chain( } // Supporting evidence - let supporting: Vec<_> = relations.iter() + let supporting: Vec<_> = relations + .iter() .filter(|(_, _, r)| matches!(r.relation, Relation::Supports)) .collect(); if !supporting.is_empty() { - chain.push_str(&format!("SUPPORTED BY {} MEMOR{}:\n", + chain.push_str(&format!( + "SUPPORTED BY {} MEMOR{}:\n", supporting.len(), if supporting.len() == 1 { "Y" } else { "IES" }, )); @@ -254,11 +312,15 @@ fn generate_reasoning_chain( } // Contradicting evidence - let contradicting: Vec<_> = relations.iter() + let contradicting: Vec<_> = relations + .iter() .filter(|(_, _, r)| matches!(r.relation, Relation::Contradicts)) .collect(); if !contradicting.is_empty() { - chain.push_str(&format!("CONTRADICTING EVIDENCE ({}):\n", contradicting.len())); + chain.push_str(&format!( + "CONTRADICTING EVIDENCE ({}):\n", + contradicting.len() + )); for (preview, trust, rel) in contradicting.iter().take(3) { chain.push_str(&format!( " ! (trust {:.0}%): \"{}\"\n -> {}\n", @@ -284,36 +346,61 @@ fn generate_reasoning_chain( // ============================================================================ const NEGATION_PAIRS: &[(&str, &str)] = &[ - ("don't", "do"), ("never", "always"), ("avoid", "use"), - ("wrong", "right"), ("incorrect", "correct"), - ("deprecated", "recommended"), ("outdated", "current"), - ("removed", "added"), ("disabled", "enabled"), - ("not ", ""), ("no longer", ""), + ("don't", "do"), + ("never", "always"), + ("avoid", "use"), + ("wrong", "right"), + ("incorrect", "correct"), + ("deprecated", "recommended"), + ("outdated", "current"), + ("removed", "added"), + ("disabled", "enabled"), + ("not ", ""), + ("no longer", ""), ]; const CORRECTION_SIGNALS: &[&str] = &[ - "actually", "correction", "update:", "updated:", "fixed", - "was wrong", "changed to", "now uses", "replaced by", - "superseded", "no longer", "instead of", "switched to", "migrated to", + "actually", + "correction", + "update:", + "updated:", + "fixed", + "was wrong", + "changed to", + "now uses", + "replaced by", + "superseded", + "no longer", + "instead of", + "switched to", + "migrated to", ]; fn appears_contradictory(a: &str, b: &str) -> bool { let a_lower = a.to_lowercase(); let b_lower = b.to_lowercase(); - let a_words: std::collections::HashSet<&str> = a_lower.split_whitespace().filter(|w| w.len() > 3).collect(); - let b_words: std::collections::HashSet<&str> = b_lower.split_whitespace().filter(|w| w.len() > 3).collect(); + let a_words: std::collections::HashSet<&str> = + a_lower.split_whitespace().filter(|w| w.len() > 3).collect(); + let b_words: std::collections::HashSet<&str> = + b_lower.split_whitespace().filter(|w| w.len() > 3).collect(); let shared_words = a_words.intersection(&b_words).count(); - if shared_words < 2 { return false; } + if shared_words < 2 { + return false; + } for (neg, _) in NEGATION_PAIRS { if (a_lower.contains(neg) && !b_lower.contains(neg)) || (b_lower.contains(neg) && !a_lower.contains(neg)) - { return true; } + { + return true; + } } for signal in CORRECTION_SIGNALS { - if a_lower.contains(signal) || b_lower.contains(signal) { return true; } + if a_lower.contains(signal) || b_lower.contains(signal) { + return true; + } } false } @@ -321,12 +408,20 @@ fn appears_contradictory(a: &str, b: &str) -> bool { fn topic_overlap(a: &str, b: &str) -> f32 { let a_lower = a.to_lowercase(); let b_lower = b.to_lowercase(); - let a_words: std::collections::HashSet<&str> = a_lower.split_whitespace().filter(|w| w.len() > 3).collect(); - let b_words: std::collections::HashSet<&str> = b_lower.split_whitespace().filter(|w| w.len() > 3).collect(); - if a_words.is_empty() || b_words.is_empty() { return 0.0; } + let a_words: std::collections::HashSet<&str> = + a_lower.split_whitespace().filter(|w| w.len() > 3).collect(); + let b_words: std::collections::HashSet<&str> = + b_lower.split_whitespace().filter(|w| w.len() > 3).collect(); + if a_words.is_empty() || b_words.is_empty() { + return 0.0; + } let intersection = a_words.intersection(&b_words).count(); let union = a_words.union(&b_words).count(); - if union == 0 { 0.0 } else { intersection as f32 / union as f32 } + if union == 0 { + 0.0 + } else { + intersection as f32 / union as f32 + } } // ============================================================================ @@ -389,7 +484,10 @@ pub async fn execute( let mut ranked = results; if let Ok(mut cog) = cognitive.try_lock() { - let candidates: Vec<_> = ranked.iter().map(|r| (r.clone(), r.node.content.clone())).collect(); + let candidates: Vec<_> = ranked + .iter() + .map(|r| (r.clone(), r.node.content.clone())) + .collect(); if let Ok(reranked) = cog.reranker.rerank(&args.query, candidates, Some(depth)) { ranked = reranked.into_iter().map(|rr| rr.item).collect(); } @@ -399,7 +497,8 @@ pub async fn execute( // STAGE 2: Spreading Activation Expansion // ==================================================================== let mut activation_expanded = 0usize; - let existing_ids: std::collections::HashSet = ranked.iter().map(|r| r.node.id.clone()).collect(); + let existing_ids: std::collections::HashSet = + ranked.iter().map(|r| r.node.id.clone()).collect(); if let Ok(mut cog) = cognitive.try_lock() { let mut expanded_ids = Vec::new(); @@ -431,24 +530,27 @@ pub async fn execute( // STAGE 3: FSRS-6 Trust Scoring // ==================================================================== - let scored: Vec = ranked.iter().map(|r| { - let trust = compute_trust( - r.node.retention_strength, - r.node.stability, - r.node.reps, - r.node.lapses, - ); - ScoredMemory { - id: r.node.id.clone(), - content: r.node.content.clone(), - tags: r.node.tags.clone(), - trust, - updated_at: r.node.updated_at, - created_at: r.node.created_at, - retention: r.node.retention_strength, - combined_score: r.combined_score, - } - }).collect(); + let scored: Vec = ranked + .iter() + .map(|r| { + let trust = compute_trust( + r.node.retention_strength, + r.node.stability, + r.node.reps, + r.node.lapses, + ); + ScoredMemory { + id: r.node.id.clone(), + content: r.node.content.clone(), + tags: r.node.tags.clone(), + trust, + updated_at: r.node.updated_at, + created_at: r.node.created_at, + retention: r.node.retention_strength, + combined_score: r.combined_score, + } + }) + .collect(); // ==================================================================== // STAGE 4: Temporal Supersession @@ -488,14 +590,20 @@ pub async fn execute( let a = &scored[i]; let b = &scored[j]; let overlap = topic_overlap(&a.content, &b.content); - if overlap < 0.15 { continue; } + if overlap < 0.15 { + continue; + } let is_contradiction = appears_contradictory(&a.content, &b.content); - if !is_contradiction { continue; } + if !is_contradiction { + continue; + } // Only flag as real contradiction if BOTH have decent trust let min_trust = a.trust.min(b.trust); - if min_trust < 0.3 { continue; } // Low-trust memory isn't worth flagging + if min_trust < 0.3 { + continue; + } // Low-trust memory isn't worth flagging let (stronger, weaker) = if a.trust >= b.trust { (a, b) } else { (b, a) }; contradictions.push(serde_json::json!({ @@ -521,9 +629,12 @@ pub async fn execute( // ==================================================================== let mut related_insights: Vec = Vec::new(); if let Ok(insights) = storage.get_insights(20) { - let memory_ids: std::collections::HashSet<&str> = scored.iter().map(|s| s.id.as_str()).collect(); + let memory_ids: std::collections::HashSet<&str> = + scored.iter().map(|s| s.id.as_str()).collect(); for insight in insights { - let overlaps = insight.source_memories.iter() + let overlaps = insight + .source_memories + .iter() .any(|src_id| memory_ids.contains(src_id.as_str())); if overlaps { related_insights.push(serde_json::json!({ @@ -540,27 +651,35 @@ pub async fn execute( // STAGE 7: Relation Assessment (per-pair, using trust + temporal + similarity) // ==================================================================== let mut pair_relations: Vec<(String, f64, RelationAssessment)> = Vec::new(); - if let Some(primary) = scored.iter() + if let Some(primary) = scored + .iter() .filter(|s| !superseded_ids.contains(&s.id)) - .max_by(|a, b| a.trust.partial_cmp(&b.trust).unwrap_or(std::cmp::Ordering::Equal)) + .max_by(|a, b| { + a.trust + .partial_cmp(&b.trust) + .unwrap_or(std::cmp::Ordering::Equal) + }) { for other in scored.iter().filter(|s| s.id != primary.id).take(15) { // Use combined_score as a proxy for semantic similarity (already reranked) // Fall back to topic_overlap for keyword-level comparison let sim = topic_overlap(&primary.content, &other.content); - let effective_sim = if other.combined_score > 0.2 { sim.max(0.3) } else { sim }; + let effective_sim = if other.combined_score > 0.2 { + sim.max(0.3) + } else { + sim + }; let rel = assess_relation( - &primary.content, &other.content, - primary.trust, other.trust, - primary.updated_at, other.updated_at, + &primary.content, + &other.content, + primary.trust, + other.trust, + primary.updated_at, + other.updated_at, effective_sim, ); if !matches!(rel.relation, Relation::Irrelevant) { - pair_relations.push(( - other.content.chars().take(100).collect(), - other.trust, - rel, - )); + pair_relations.push((other.content.chars().take(100).collect(), other.trust, rel)); } } } @@ -595,25 +714,32 @@ pub async fn execute( .partial_cmp(&composite(a)) .unwrap_or(std::cmp::Ordering::Equal) }); - let evidence: Vec = non_superseded.iter() + let evidence: Vec = non_superseded + .iter() .take(10) .enumerate() - .map(|(i, s)| serde_json::json!({ - "id": s.id, - "preview": s.content.chars().take(200).collect::(), - "trust": (s.trust * 100.0).round() / 100.0, - "date": s.updated_at.to_rfc3339(), - "role": if i == 0 { "primary" } else { "supporting" }, - })) + .map(|(i, s)| { + serde_json::json!({ + "id": s.id, + "preview": s.content.chars().take(200).collect::(), + "trust": (s.trust * 100.0).round() / 100.0, + "date": s.updated_at.to_rfc3339(), + "role": if i == 0 { "primary" } else { "supporting" }, + }) + }) .collect(); // Build evolution timeline - let mut evolution: Vec = by_date.iter().rev() - .map(|s| serde_json::json!({ - "date": s.updated_at.format("%b %d, %Y").to_string(), - "preview": s.content.chars().take(100).collect::(), - "trust": (s.trust * 100.0).round() / 100.0, - })) + let mut evolution: Vec = by_date + .iter() + .rev() + .map(|s| { + serde_json::json!({ + "date": s.updated_at.format("%b %d, %Y").to_string(), + "preview": s.content.chars().take(100).collect::(), + "trust": (s.trust * 100.0).round() / 100.0, + }) + }) .collect(); evolution.truncate(15); // cap timeline length @@ -639,12 +765,15 @@ pub async fn execute( if contradictions.is_empty() { format!( "High confidence ({:.0}%). Recommended memory (trust {:.0}%, {}) is the most reliable source.", - confidence * 100.0, rec.trust * 100.0, rec.updated_at.format("%b %d, %Y") + confidence * 100.0, + rec.trust * 100.0, + rec.updated_at.format("%b %d, %Y") ) } else { format!( "WARNING: {} contradiction(s) detected. Recommended memory has trust {:.0}% but conflicts exist. Review contradictions below.", - contradictions.len(), rec.trust * 100.0 + contradictions.len(), + rec.trust * 100.0 ) } } else { @@ -683,11 +812,21 @@ pub async fn execute( }); } - if !evidence.is_empty() { response["evidence"] = serde_json::json!(evidence); } - if !contradictions.is_empty() { response["contradictions"] = serde_json::json!(contradictions); } - if !superseded.is_empty() { response["superseded"] = serde_json::json!(superseded); } - if !evolution.is_empty() { response["evolution"] = serde_json::json!(evolution); } - if !related_insights.is_empty() { response["related_insights"] = serde_json::json!(related_insights); } + if !evidence.is_empty() { + response["evidence"] = serde_json::json!(evidence); + } + if !contradictions.is_empty() { + response["contradictions"] = serde_json::json!(contradictions); + } + if !superseded.is_empty() { + response["superseded"] = serde_json::json!(superseded); + } + if !evolution.is_empty() { + response["evolution"] = serde_json::json!(evolution); + } + if !related_insights.is_empty() { + response["related_insights"] = serde_json::json!(related_insights); + } Ok(response) } @@ -849,7 +988,11 @@ mod tests { fn test_trust_score_medium() { // Medium everything let trust = compute_trust(0.6, 15.0, 5, 2); - assert!(trust > 0.4 && trust < 0.7, "Expected 0.4-0.7, got {}", trust); + assert!( + trust > 0.4 && trust < 0.7, + "Expected 0.4-0.7, got {}", + trust + ); } #[test] @@ -861,7 +1004,10 @@ mod tests { #[test] fn test_contradiction_requires_shared_words() { - assert!(!appears_contradictory("not sure about weather", "Rust is fast")); + assert!(!appears_contradictory( + "not sure about weather", + "Rust is fast" + )); } #[test] @@ -874,7 +1020,10 @@ mod tests { #[test] fn test_topic_overlap_similar() { - let overlap = topic_overlap("Vestige uses USearch for vector search", "Vestige vector search powered by USearch HNSW"); + let overlap = topic_overlap( + "Vestige uses USearch for vector search", + "Vestige vector search powered by USearch HNSW", + ); assert!(overlap > 0.3); } @@ -895,32 +1044,62 @@ mod tests { #[test] fn test_intent_fact_check() { - assert_eq!(classify_intent("Is it true that Vestige uses USearch?"), QueryIntent::FactCheck); - assert_eq!(classify_intent("Did I switch to port 3002?"), QueryIntent::FactCheck); - assert_eq!(classify_intent("Should I use prefix caching?"), QueryIntent::FactCheck); + assert_eq!( + classify_intent("Is it true that Vestige uses USearch?"), + QueryIntent::FactCheck + ); + assert_eq!( + classify_intent("Did I switch to port 3002?"), + QueryIntent::FactCheck + ); + assert_eq!( + classify_intent("Should I use prefix caching?"), + QueryIntent::FactCheck + ); } #[test] fn test_intent_timeline() { - assert_eq!(classify_intent("When did the port change happen?"), QueryIntent::Timeline); - assert_eq!(classify_intent("How has the AIMO3 score evolved over time?"), QueryIntent::Timeline); + assert_eq!( + classify_intent("When did the port change happen?"), + QueryIntent::Timeline + ); + assert_eq!( + classify_intent("How has the AIMO3 score evolved over time?"), + QueryIntent::Timeline + ); } #[test] fn test_intent_root_cause() { - assert_eq!(classify_intent("Why did the build fail?"), QueryIntent::RootCause); - assert_eq!(classify_intent("What caused the score regression?"), QueryIntent::RootCause); + assert_eq!( + classify_intent("Why did the build fail?"), + QueryIntent::RootCause + ); + assert_eq!( + classify_intent("What caused the score regression?"), + QueryIntent::RootCause + ); } #[test] fn test_intent_comparison() { - assert_eq!(classify_intent("How does USearch differ from FAISS?"), QueryIntent::Comparison); - assert_eq!(classify_intent("Compare FSRS versus SM-2"), QueryIntent::Comparison); + assert_eq!( + classify_intent("How does USearch differ from FAISS?"), + QueryIntent::Comparison + ); + assert_eq!( + classify_intent("Compare FSRS versus SM-2"), + QueryIntent::Comparison + ); } #[test] fn test_intent_synthesis_default() { - assert_eq!(classify_intent("Tell me about Sam's projects"), QueryIntent::Synthesis); + assert_eq!( + classify_intent("Tell me about Sam's projects"), + QueryIntent::Synthesis + ); assert_eq!(classify_intent("What is Vestige?"), QueryIntent::Synthesis); } @@ -928,8 +1107,15 @@ mod tests { #[test] fn test_relation_irrelevant() { - let rel = assess_relation("Rust is fast", "The weather is nice", 0.8, 0.8, - Utc::now(), Utc::now(), 0.05); + let rel = assess_relation( + "Rust is fast", + "The weather is nice", + 0.8, + 0.8, + Utc::now(), + Utc::now(), + 0.05, + ); assert!(matches!(rel.relation, Relation::Irrelevant)); } @@ -938,7 +1124,12 @@ mod tests { let rel = assess_relation( "Vestige uses USearch for vector search", "USearch provides fast HNSW indexing for Vestige", - 0.8, 0.7, Utc::now(), Utc::now(), 0.6); + 0.8, + 0.7, + Utc::now(), + Utc::now(), + 0.6, + ); assert!(matches!(rel.relation, Relation::Supports)); } @@ -947,7 +1138,12 @@ mod tests { let rel = assess_relation( "Don't use FAISS for vector search in production anymore", "Use FAISS for vector search in production always", - 0.8, 0.5, Utc::now(), Utc::now(), 0.7); + 0.8, + 0.5, + Utc::now(), + Utc::now(), + 0.7, + ); assert!(matches!(rel.relation, Relation::Contradicts)); } } diff --git a/crates/vestige-mcp/src/tools/dedup.rs b/crates/vestige-mcp/src/tools/dedup.rs index 7985bd5..8456629 100644 --- a/crates/vestige-mcp/src/tools/dedup.rs +++ b/crates/vestige-mcp/src/tools/dedup.rs @@ -9,7 +9,6 @@ use serde_json::Value; use std::collections::HashMap; use std::sync::Arc; - use vestige_core::Storage; #[cfg(all(feature = "embeddings", feature = "vector-search"))] use vestige_core::cosine_similarity; @@ -89,10 +88,7 @@ impl UnionFind { } } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: DedupArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => DedupArgs { @@ -108,7 +104,6 @@ pub async fn execute( #[cfg(all(feature = "embeddings", feature = "vector-search"))] { - // Load all embeddings let all_embeddings = storage .get_all_embeddings() @@ -191,10 +186,8 @@ pub async fn execute( } // Only keep clusters with >1 member, sorted by size descending - let mut clusters: Vec> = cluster_map - .into_values() - .filter(|c| c.len() > 1) - .collect(); + let mut clusters: Vec> = + cluster_map.into_values().filter(|c| c.len() > 1).collect(); clusters.sort_by_key(|b| std::cmp::Reverse(b.len())); clusters.truncate(limit); diff --git a/crates/vestige-mcp/src/tools/dream.rs b/crates/vestige-mcp/src/tools/dream.rs index ac9c479..357315f 100644 --- a/crates/vestige-mcp/src/tools/dream.rs +++ b/crates/vestige-mcp/src/tools/dream.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use tokio::sync::Mutex; -use chrono::Utc; use crate::cognitive::CognitiveEngine; +use chrono::Utc; use vestige_core::{DreamHistoryRecord, InsightRecord, LinkType, Storage}; pub fn schema() -> serde_json::Value { @@ -34,21 +34,24 @@ pub async fn execute( .min(500) as usize; // Cap at 500 to prevent O(N^2) hang // v1.9.0: Waking SWR tagging — preferential replay of tagged memories (70/30 split) - let tagged_nodes = storage.get_waking_tagged_memories(memory_count as i32) + let tagged_nodes = storage + .get_waking_tagged_memories(memory_count as i32) .unwrap_or_default(); let tagged_count = tagged_nodes.len(); // Calculate how many tagged vs random to include let tagged_target = (memory_count * 7 / 10).min(tagged_count); // 70% tagged - let _random_target = memory_count.saturating_sub(tagged_target); // 30% random (used for logging) + let _random_target = memory_count.saturating_sub(tagged_target); // 30% random (used for logging) // Build the dream memory set: tagged memories first, then fill with random - let tagged_ids: std::collections::HashSet = tagged_nodes.iter() + let tagged_ids: std::collections::HashSet = tagged_nodes + .iter() .take(tagged_target) .map(|n| n.id.clone()) .collect(); - let random_nodes = storage.get_all_nodes(memory_count as i32, 0) + let random_nodes = storage + .get_all_nodes(memory_count as i32, 0) .map_err(|e| format!("Failed to load memories: {}", e))?; let mut all_nodes: Vec<_> = tagged_nodes.into_iter().take(tagged_target).collect(); @@ -59,8 +62,10 @@ pub async fn execute( } // If still under capacity (e.g., all memories are tagged), fill from remaining tagged if all_nodes.len() < memory_count { - let used_ids: std::collections::HashSet = all_nodes.iter().map(|n| n.id.clone()).collect(); - let remaining_tagged = storage.get_waking_tagged_memories(memory_count as i32) + let used_ids: std::collections::HashSet = + all_nodes.iter().map(|n| n.id.clone()).collect(); + let remaining_tagged = storage + .get_waking_tagged_memories(memory_count as i32) .unwrap_or_default(); for node in remaining_tagged { if !used_ids.contains(&node.id) && all_nodes.len() < memory_count { @@ -77,16 +82,17 @@ pub async fn execute( })); } - let dream_memories: Vec = all_nodes.iter().map(|n| { - vestige_core::DreamMemory { + let dream_memories: Vec = all_nodes + .iter() + .map(|n| vestige_core::DreamMemory { id: n.id.clone(), content: n.content.clone(), embedding: storage.get_node_embedding(&n.id).ok().flatten(), tags: n.tags.clone(), created_at: n.created_at, access_count: n.reps as u32, - } - }).collect(); + }) + .collect(); let cog = cognitive.lock().await; // Capture start time before the dream so we can identify newly discovered @@ -259,17 +265,18 @@ mod tests { async fn ingest_n_memories(storage: &Arc, n: usize) { for i in 0..n { - storage.ingest(vestige_core::IngestInput { - content: format!("Dream test memory number {}", i), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["dream-test".to_string()], - valid_from: None, - valid_until: None, - }) - .unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: format!("Dream test memory number {}", i), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["dream-test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); } } @@ -368,7 +375,10 @@ mod tests { // After dream: dream history should exist { let last = storage.get_last_dream().unwrap(); - assert!(last.is_some(), "Dream should have been persisted to database"); + assert!( + last.is_some(), + "Dream should have been persisted to database" + ); } } @@ -379,20 +389,28 @@ mod tests { // Create enough diverse memories to trigger connection discovery for i in 0..15 { - storage.ingest(vestige_core::IngestInput { - content: format!( - "Memory {} about topic {}: detailed content for connection discovery", - i, - if i % 3 == 0 { "rust" } else if i % 3 == 1 { "cargo" } else { "testing" } - ), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["dream-roundtrip".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: format!( + "Memory {} about topic {}: detailed content for connection discovery", + i, + if i % 3 == 0 { + "rust" + } else if i % 3 == 1 { + "cargo" + } else { + "testing" + } + ), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["dream-roundtrip".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); } let cognitive = test_cognitive(); @@ -403,7 +421,10 @@ mod tests { if persisted > 0 { // Verify connections are queryable from storage let all_conns = storage.get_all_connections().unwrap(); - assert!(!all_conns.is_empty(), "Persisted connections should be queryable"); + assert!( + !all_conns.is_empty(), + "Persisted connections should be queryable" + ); // Verify connection IDs reference valid memories let all_nodes = storage.get_all_nodes(100, 0).unwrap(); @@ -425,7 +446,9 @@ mod tests { // Verify live cognitive engine was hydrated let cog = cognitive.lock().await; let first_conn = &all_conns[0]; - let assocs = cog.activation_network.get_associations(&first_conn.source_id); + let assocs = cog + .activation_network + .get_associations(&first_conn.source_id); assert!( !assocs.is_empty(), "Live cognitive engine should have been hydrated with dream connections" @@ -441,16 +464,18 @@ mod tests { // Ingest memories and collect their IDs let mut ids = Vec::new(); for i in 0..5 { - let result = storage.ingest(vestige_core::IngestInput { - content: format!("Save connection test memory {}", i), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["save-conn-test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + let result = storage + .ingest(vestige_core::IngestInput { + content: format!("Save connection test memory {}", i), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["save-conn-test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); ids.push(result.id); } @@ -459,7 +484,7 @@ mod tests { let mut saved = 0u32; let mut errors = Vec::new(); for i in 0..ids.len() { - for j in (i+1)..ids.len() { + for j in (i + 1)..ids.len() { let record = vestige_core::ConnectionRecord { source_id: ids[i].clone(), target_id: ids[j].clone(), @@ -471,10 +496,7 @@ mod tests { }; match storage.save_connection(&record) { Ok(_) => saved += 1, - Err(e) => errors.push(format!( - "{} -> {}: {}", - ids[i], ids[j], e - )), + Err(e) => errors.push(format!("{} -> {}: {}", ids[i], ids[j], e)), } } } @@ -510,34 +532,62 @@ mod tests { // Ingest memories with known high-similarity content (shared tags + similar text) let topics = [ - ("Rust borrow checker prevents data races at compile time", vec!["rust", "safety"]), - ("Rust ownership model ensures memory safety without GC", vec!["rust", "safety"]), - ("Cargo is the Rust package manager and build system", vec!["rust", "cargo"]), - ("Cargo.toml defines dependencies for Rust projects", vec!["rust", "cargo"]), - ("Unit tests in Rust use #[test] attribute", vec!["rust", "testing"]), - ("Integration tests in Rust live in the tests/ directory", vec!["rust", "testing"]), - ("Clippy is a Rust linter that catches common mistakes", vec!["rust", "tooling"]), - ("Rustfmt formats Rust code according to style guidelines", vec!["rust", "tooling"]), + ( + "Rust borrow checker prevents data races at compile time", + vec!["rust", "safety"], + ), + ( + "Rust ownership model ensures memory safety without GC", + vec!["rust", "safety"], + ), + ( + "Cargo is the Rust package manager and build system", + vec!["rust", "cargo"], + ), + ( + "Cargo.toml defines dependencies for Rust projects", + vec!["rust", "cargo"], + ), + ( + "Unit tests in Rust use #[test] attribute", + vec!["rust", "testing"], + ), + ( + "Integration tests in Rust live in the tests/ directory", + vec!["rust", "testing"], + ), + ( + "Clippy is a Rust linter that catches common mistakes", + vec!["rust", "tooling"], + ), + ( + "Rustfmt formats Rust code according to style guidelines", + vec!["rust", "tooling"], + ), ]; for (content, tags) in &topics { - storage.ingest(vestige_core::IngestInput { - content: content.to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: tags.iter().map(|t| t.to_string()).collect(), - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: tags.iter().map(|t| t.to_string()).collect(), + valid_from: None, + valid_until: None, + }) + .unwrap(); } let cognitive = test_cognitive(); let result = execute(&storage, &cognitive, None).await.unwrap(); assert_eq!(result["status"], "dreamed"); - let found = result["stats"]["new_connections_found"].as_u64().unwrap_or(0); + let found = result["stats"]["new_connections_found"] + .as_u64() + .unwrap_or(0); let persisted = result["connectionsPersisted"].as_u64().unwrap_or(0); // Dream should discover connections between these related memories @@ -572,23 +622,52 @@ mod tests { // Create diverse tagged memories to encourage insight generation let topics = [ - ("Rust borrow checker prevents data races", vec!["rust", "safety"]), - ("Rust ownership model ensures memory safety", vec!["rust", "safety"]), - ("Cargo manages Rust project dependencies", vec!["rust", "cargo"]), - ("Cargo.toml defines project configuration", vec!["rust", "cargo"]), - ("Unit tests use the #[test] attribute", vec!["rust", "testing"]), - ("Integration tests live in the tests directory", vec!["rust", "testing"]), - ("Clippy catches common Rust mistakes", vec!["rust", "tooling"]), - ("Rustfmt automatically formats code", vec!["rust", "tooling"]), + ( + "Rust borrow checker prevents data races", + vec!["rust", "safety"], + ), + ( + "Rust ownership model ensures memory safety", + vec!["rust", "safety"], + ), + ( + "Cargo manages Rust project dependencies", + vec!["rust", "cargo"], + ), + ( + "Cargo.toml defines project configuration", + vec!["rust", "cargo"], + ), + ( + "Unit tests use the #[test] attribute", + vec!["rust", "testing"], + ), + ( + "Integration tests live in the tests directory", + vec!["rust", "testing"], + ), + ( + "Clippy catches common Rust mistakes", + vec!["rust", "tooling"], + ), + ( + "Rustfmt automatically formats code", + vec!["rust", "tooling"], + ), ]; for (content, tags) in &topics { - storage.ingest(vestige_core::IngestInput { - content: content.to_string(), - node_type: "fact".to_string(), - source: None, sentiment_score: 0.0, sentiment_magnitude: 0.0, - tags: tags.iter().map(|t| t.to_string()).collect(), - valid_from: None, valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: tags.iter().map(|t| t.to_string()).collect(), + valid_from: None, + valid_until: None, + }) + .unwrap(); } let result = execute(&storage, &test_cognitive(), None).await.unwrap(); @@ -599,19 +678,30 @@ mod tests { // If insights were generated, they should be persisted if !response_insights.is_empty() { - assert!(persisted_count > 0, "Generated insights should be persisted to database"); + assert!( + persisted_count > 0, + "Generated insights should be persisted to database" + ); let stored = storage.get_insights(100).unwrap(); assert_eq!( - stored.len(), persisted_count as usize, - "All {} persisted insights should be retrievable", persisted_count + stored.len(), + persisted_count as usize, + "All {} persisted insights should be retrievable", + persisted_count ); // Verify insight fields for insight in &stored { assert!(!insight.id.is_empty(), "Insight ID should not be empty"); - assert!(!insight.insight.is_empty(), "Insight text should not be empty"); + assert!( + !insight.insight.is_empty(), + "Insight text should not be empty" + ); assert!(insight.confidence >= 0.0 && insight.confidence <= 1.0); assert!(insight.novelty_score >= 0.0); - assert!(insight.feedback.is_none(), "Fresh insight should have no feedback"); + assert!( + insight.feedback.is_none(), + "Fresh insight should have no feedback" + ); assert_eq!(insight.applied_count, 0); } } diff --git a/crates/vestige-mcp/src/tools/explore.rs b/crates/vestige-mcp/src/tools/explore.rs index 50fdd24..441afd3 100644 --- a/crates/vestige-mcp/src/tools/explore.rs +++ b/crates/vestige-mcp/src/tools/explore.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use tokio::sync::Mutex; use crate::cognitive::CognitiveEngine; -use vestige_core::advanced::{Connection, ConnectionType, MemoryChainBuilder, MemoryNode}; use vestige_core::Storage; +use vestige_core::advanced::{Connection, ConnectionType, MemoryChainBuilder, MemoryNode}; pub fn schema() -> serde_json::Value { serde_json::json!({ @@ -41,8 +41,14 @@ pub async fn execute( args: Option, ) -> Result { let args = args.ok_or("Missing arguments")?; - let action = args.get("action").and_then(|v| v.as_str()).ok_or("Missing 'action'")?; - let from = args.get("from").and_then(|v| v.as_str()).ok_or("Missing 'from'")?; + let action = args + .get("action") + .and_then(|v| v.as_str()) + .ok_or("Missing 'action'")?; + let from = args + .get("from") + .and_then(|v| v.as_str()) + .ok_or("Missing 'from'")?; let to = args.get("to").and_then(|v| v.as_str()); let limit = args.get("limit").and_then(|v| v.as_u64()).unwrap_or(10) as usize; @@ -64,36 +70,34 @@ pub async fn execute( }; match chain_opt { - Some(chain) => { - Ok(serde_json::json!({ - "action": "chain", - "from": from_owned, - "to": to_owned, - "steps": chain.steps.iter().map(|s| serde_json::json!({ - "memory_id": s.memory_id, - "memory_preview": s.memory_preview, - "connection_type": format!("{:?}", s.connection_type), - "connection_strength": s.connection_strength, - "reasoning": s.reasoning, - })).collect::>(), - "confidence": chain.confidence, - "total_hops": chain.total_hops, - })) - } - None => { - Ok(serde_json::json!({ - "action": "chain", - "from": from_owned, - "to": to_owned, - "steps": [], - "message": "No chain found between these memories" - })) - } + Some(chain) => Ok(serde_json::json!({ + "action": "chain", + "from": from_owned, + "to": to_owned, + "steps": chain.steps.iter().map(|s| serde_json::json!({ + "memory_id": s.memory_id, + "memory_preview": s.memory_preview, + "connection_type": format!("{:?}", s.connection_type), + "connection_strength": s.connection_strength, + "reasoning": s.reasoning, + })).collect::>(), + "confidence": chain.confidence, + "total_hops": chain.total_hops, + })), + None => Ok(serde_json::json!({ + "action": "chain", + "from": from_owned, + "to": to_owned, + "steps": [], + "message": "No chain found between these memories" + })), } } "associations" => { let activation_assocs = cog.activation_network.get_associations(from); - let hippocampal_assocs = cog.hippocampal_index.get_associations(from, 2) + let hippocampal_assocs = cog + .hippocampal_index + .get_associations(from, 2) .unwrap_or_default(); let from_owned = from.to_string(); drop(cog); // release lock consistently (matches chain/bridges pattern) @@ -120,20 +124,22 @@ pub async fn execute( all_associations.truncate(limit); // Fallback: if in-memory modules are empty, query storage directly - if all_associations.is_empty() && let Ok(connections) = storage.get_connections_for_memory(&from_owned) { - for conn in connections.iter().take(limit) { - let other_id = if conn.source_id == from_owned { - &conn.target_id - } else { - &conn.source_id - }; - all_associations.push(serde_json::json!({ - "memory_id": other_id, - "strength": conn.strength, - "link_type": conn.link_type, - "source": "persistent_graph", - })); - } + if all_associations.is_empty() + && let Ok(connections) = storage.get_connections_for_memory(&from_owned) + { + for conn in connections.iter().take(limit) { + let other_id = if conn.source_id == from_owned { + &conn.target_id + } else { + &conn.source_id + }; + all_associations.push(serde_json::json!({ + "memory_id": other_id, + "strength": conn.strength, + "link_type": conn.link_type, + "source": "persistent_graph", + })); + } } Ok(serde_json::json!({ @@ -167,12 +173,19 @@ pub async fn execute( "count": limited.len(), })) } - _ => Err(format!("Unknown action: '{}'. Expected: chain, associations, bridges", action)), + _ => Err(format!( + "Unknown action: '{}'. Expected: chain, associations, bridges", + action + )), } } /// Build a temporary MemoryChainBuilder from persisted connections for fallback queries. -fn build_temp_chain_builder(storage: &Arc, from_id: &str, to_id: &str) -> MemoryChainBuilder { +fn build_temp_chain_builder( + storage: &Arc, + from_id: &str, + to_id: &str, +) -> MemoryChainBuilder { let mut builder = MemoryChainBuilder::new(); // Load connections involving either endpoint @@ -191,7 +204,9 @@ fn build_temp_chain_builder(storage: &Arc, from_id: &str, to_id: &str) let mut seen_ids = std::collections::HashSet::new(); for conn in &all_conns { for id in [&conn.source_id, &conn.target_id] { - if seen_ids.insert(id.clone()) && let Ok(Some(node)) = storage.get_node(id) { + if seen_ids.insert(id.clone()) + && let Ok(Some(node)) = storage.get_node(id) + { builder.add_memory(MemoryNode { id: node.id.clone(), content_preview: node.content.chars().take(100).collect(), @@ -389,39 +404,47 @@ mod tests { let (storage, _dir) = test_storage().await; // Create two memories and a direct connection in storage - let id1 = storage.ingest(vestige_core::IngestInput { - content: "Memory about Rust".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap().id; + let id1 = storage + .ingest(vestige_core::IngestInput { + content: "Memory about Rust".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap() + .id; - let id2 = storage.ingest(vestige_core::IngestInput { - content: "Memory about Cargo".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap().id; + let id2 = storage + .ingest(vestige_core::IngestInput { + content: "Memory about Cargo".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap() + .id; // Save connection directly to storage (bypassing cognitive engine) let now = chrono::Utc::now(); - storage.save_connection(&vestige_core::ConnectionRecord { - source_id: id1.clone(), - target_id: id2.clone(), - strength: 0.9, - link_type: "semantic".to_string(), - created_at: now, - last_activated: now, - activation_count: 1, - }).unwrap(); + storage + .save_connection(&vestige_core::ConnectionRecord { + source_id: id1.clone(), + target_id: id2.clone(), + strength: 0.9, + link_type: "semantic".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); // Execute with empty cognitive engine — should fall back to storage let cognitive = test_cognitive(); @@ -447,22 +470,36 @@ mod tests { // Create 3 memories: A -> B -> C let make = |content: &str| vestige_core::IngestInput { - content: content.to_string(), node_type: "fact".to_string(), - source: None, sentiment_score: 0.0, sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], valid_from: None, valid_until: None, + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, }; let id_a = storage.ingest(make("Memory A about databases")).unwrap().id; let id_b = storage.ingest(make("Memory B about indexes")).unwrap().id; - let id_c = storage.ingest(make("Memory C about performance")).unwrap().id; + let id_c = storage + .ingest(make("Memory C about performance")) + .unwrap() + .id; // Save connections A->B and B->C to storage let now = chrono::Utc::now(); for (src, tgt) in [(&id_a, &id_b), (&id_b, &id_c)] { - storage.save_connection(&vestige_core::ConnectionRecord { - source_id: src.clone(), target_id: tgt.clone(), - strength: 0.9, link_type: "semantic".to_string(), - created_at: now, last_activated: now, activation_count: 1, - }).unwrap(); + storage + .save_connection(&vestige_core::ConnectionRecord { + source_id: src.clone(), + target_id: tgt.clone(), + strength: 0.9, + link_type: "semantic".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); } // Execute chain with empty cognitive engine — should fall back to storage @@ -472,7 +509,10 @@ mod tests { let value = result.unwrap(); assert_eq!(value["action"], "chain"); let steps = value["steps"].as_array().unwrap(); - assert!(!steps.is_empty(), "Chain should find path A->B->C via storage fallback"); + assert!( + !steps.is_empty(), + "Chain should find path A->B->C via storage fallback" + ); } #[tokio::test] @@ -481,9 +521,14 @@ mod tests { // Create 3 memories: A -> B -> C (B is the bridge) let make = |content: &str| vestige_core::IngestInput { - content: content.to_string(), node_type: "fact".to_string(), - source: None, sentiment_score: 0.0, sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], valid_from: None, valid_until: None, + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, }; let id_a = storage.ingest(make("Bridge test memory A")).unwrap().id; let id_b = storage.ingest(make("Bridge test memory B")).unwrap().id; @@ -491,11 +536,17 @@ mod tests { let now = chrono::Utc::now(); for (src, tgt) in [(&id_a, &id_b), (&id_b, &id_c)] { - storage.save_connection(&vestige_core::ConnectionRecord { - source_id: src.clone(), target_id: tgt.clone(), - strength: 0.9, link_type: "semantic".to_string(), - created_at: now, last_activated: now, activation_count: 1, - }).unwrap(); + storage + .save_connection(&vestige_core::ConnectionRecord { + source_id: src.clone(), + target_id: tgt.clone(), + strength: 0.9, + link_type: "semantic".to_string(), + created_at: now, + last_activated: now, + activation_count: 1, + }) + .unwrap(); } // Execute bridges with empty cognitive engine @@ -505,6 +556,9 @@ mod tests { let value = result.unwrap(); assert_eq!(value["action"], "bridges"); let bridges = value["bridges"].as_array().unwrap(); - assert!(!bridges.is_empty(), "Should find B as bridge between A and C via storage fallback"); + assert!( + !bridges.is_empty(), + "Should find B as bridge between A and C via storage fallback" + ); } } diff --git a/crates/vestige-mcp/src/tools/feedback.rs b/crates/vestige-mcp/src/tools/feedback.rs index e21cc97..438e594 100644 --- a/crates/vestige-mcp/src/tools/feedback.rs +++ b/crates/vestige-mcp/src/tools/feedback.rs @@ -73,19 +73,23 @@ pub async fn execute_promote( // Validate UUID uuid::Uuid::parse_str(&args.id).map_err(|_| "Invalid node ID format".to_string())?; - // Get node before for comparison - let before = storage.get_node(&args.id).map_err(|e| e.to_string())? + let before = storage + .get_node(&args.id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", args.id))?; - let node = storage.promote_memory(&args.id).map_err(|e| e.to_string())?; + let node = storage + .promote_memory(&args.id) + .map_err(|e| e.to_string())?; // ==================================================================== // COGNITIVE FEEDBACK PIPELINE (promote) // ==================================================================== if let Ok(mut cog) = cognitive.try_lock() { // 5A. Reward signal — record positive outcome - cog.reward_signal.record_outcome(&args.id, OutcomeType::Helpful); + cog.reward_signal + .record_outcome(&args.id, OutcomeType::Helpful); // 5B. Importance tracking — mark as helpful retrieval cog.importance_tracker.on_retrieved(&args.id, true); @@ -143,9 +147,10 @@ pub async fn execute_demote( // Validate UUID uuid::Uuid::parse_str(&args.id).map_err(|_| "Invalid node ID format".to_string())?; - // Get node before for comparison - let before = storage.get_node(&args.id).map_err(|e| e.to_string())? + let before = storage + .get_node(&args.id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", args.id))?; let node = storage.demote_memory(&args.id).map_err(|e| e.to_string())?; @@ -155,7 +160,8 @@ pub async fn execute_demote( // ==================================================================== if let Ok(mut cog) = cognitive.try_lock() { // 5A. Reward signal — record negative outcome - cog.reward_signal.record_outcome(&args.id, OutcomeType::NotHelpful); + cog.reward_signal + .record_outcome(&args.id, OutcomeType::NotHelpful); // 5B. Importance tracking — mark as unhelpful retrieval cog.importance_tracker.on_retrieved(&args.id, false); @@ -237,8 +243,9 @@ pub async fn execute_request_feedback( // Validate UUID uuid::Uuid::parse_str(&args.id).map_err(|_| "Invalid node ID format".to_string())?; - - let node = storage.get_node(&args.id).map_err(|e| e.to_string())? + let node = storage + .get_node(&args.id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", args.id))?; // Truncate content for display @@ -319,10 +326,12 @@ mod tests { assert_eq!(schema["type"], "object"); assert!(schema["properties"]["id"].is_object()); assert!(schema["properties"]["reason"].is_object()); - assert!(schema["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("id"))); + assert!( + schema["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("id")) + ); } #[test] @@ -330,10 +339,12 @@ mod tests { let schema = demote_schema(); assert_eq!(schema["type"], "object"); assert!(schema["properties"]["id"].is_object()); - assert!(schema["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("id"))); + assert!( + schema["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("id")) + ); } #[test] @@ -342,10 +353,12 @@ mod tests { assert_eq!(schema["type"], "object"); assert!(schema["properties"]["id"].is_object()); assert!(schema["properties"]["context"].is_object()); - assert!(schema["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("id"))); + assert!( + schema["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("id")) + ); } // === PROMOTE TESTS === @@ -370,8 +383,7 @@ mod tests { #[tokio::test] async fn test_promote_nonexistent_node_fails() { let (storage, _dir) = test_storage().await; - let args = - serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); + let args = serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); let result = execute_promote(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_err()); assert!(result.unwrap_err().contains("Node not found")); @@ -454,8 +466,7 @@ mod tests { #[tokio::test] async fn test_demote_nonexistent_node_fails() { let (storage, _dir) = test_storage().await; - let args = - serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); + let args = serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); let result = execute_demote(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_err()); assert!(result.unwrap_err().contains("Node not found")); @@ -510,8 +521,7 @@ mod tests { #[tokio::test] async fn test_request_feedback_nonexistent_node_fails() { let (storage, _dir) = test_storage().await; - let args = - serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); + let args = serde_json::json!({ "id": "00000000-0000-0000-0000-000000000000" }); let result = execute_request_feedback(&storage, Some(args)).await; assert!(result.is_err()); } diff --git a/crates/vestige-mcp/src/tools/graph.rs b/crates/vestige-mcp/src/tools/graph.rs index 183c725..13ca746 100644 --- a/crates/vestige-mcp/src/tools/graph.rs +++ b/crates/vestige-mcp/src/tools/graph.rs @@ -125,52 +125,72 @@ pub async fn execute( storage: &Arc, args: Option, ) -> Result { - let depth = args.as_ref() + let depth = args + .as_ref() .and_then(|a| a.get("depth")) .and_then(|v| v.as_u64()) .unwrap_or(2) .min(3) as u32; - let max_nodes = args.as_ref() + let max_nodes = args + .as_ref() .and_then(|a| a.get("max_nodes")) .and_then(|v| v.as_u64()) .unwrap_or(50) .min(200) as usize; // Determine center node - let center_id = if let Some(id) = args.as_ref().and_then(|a| a.get("center_id")).and_then(|v| v.as_str()) { + let center_id = if let Some(id) = args + .as_ref() + .and_then(|a| a.get("center_id")) + .and_then(|v| v.as_str()) + { id.to_string() - } else if let Some(query) = args.as_ref().and_then(|a| a.get("query")).and_then(|v| v.as_str()) { + } else if let Some(query) = args + .as_ref() + .and_then(|a| a.get("query")) + .and_then(|v| v.as_str()) + { // Search for center node - let results = storage.search(query, 1) + let results = storage + .search(query, 1) .map_err(|e| format!("Search failed: {}", e))?; - results.first() + results + .first() .map(|n| n.id.clone()) .ok_or_else(|| "No memories found matching query".to_string())? } else { // Default: use the most recent memory - let recent = storage.get_all_nodes(1, 0) + let recent = storage + .get_all_nodes(1, 0) .map_err(|e| format!("Failed to get recent node: {}", e))?; - recent.first() + recent + .first() .map(|n| n.id.clone()) .ok_or_else(|| "No memories in database".to_string())? }; // Get subgraph - let (nodes, edges) = storage.get_memory_subgraph(¢er_id, depth, max_nodes) + let (nodes, edges) = storage + .get_memory_subgraph(¢er_id, depth, max_nodes) .map_err(|e| format!("Failed to get subgraph: {}", e))?; if nodes.is_empty() || !nodes.iter().any(|n| n.id == center_id) { - return Err(format!("Memory '{}' not found or has no accessible data", center_id)); + return Err(format!( + "Memory '{}' not found or has no accessible data", + center_id + )); } // Build index map for FR layout - let id_to_idx: std::collections::HashMap<&str, usize> = nodes.iter() + let id_to_idx: std::collections::HashMap<&str, usize> = nodes + .iter() .enumerate() .map(|(i, n)| (n.id.as_str(), i)) .collect(); - let layout_edges: Vec<(usize, usize, f64)> = edges.iter() + let layout_edges: Vec<(usize, usize, f64)> = edges + .iter() .filter_map(|e| { let u = id_to_idx.get(e.source_id.as_str())?; let v = id_to_idx.get(e.target_id.as_str())?; @@ -182,7 +202,8 @@ pub async fn execute( let positions = fruchterman_reingold(nodes.len(), &layout_edges, 800.0, 600.0, 50); // Build response - let nodes_json: Vec = nodes.iter() + let nodes_json: Vec = nodes + .iter() .enumerate() .map(|(i, n)| { let (x, y) = positions.get(i).copied().unwrap_or((400.0, 300.0)); @@ -199,11 +220,15 @@ pub async fn execute( "x": (x * 100.0).round() / 100.0, "y": (y * 100.0).round() / 100.0, "isCenter": n.id == center_id, + // v2.0.5 Active Forgetting — dashboard uses these to dim suppressed nodes + "suppression_count": n.suppression_count, + "suppressed_at": n.suppressed_at.map(|t| t.to_rfc3339()), }) }) .collect(); - let edges_json: Vec = edges.iter() + let edges_json: Vec = edges + .iter() .map(|e| { serde_json::json!({ "source": e.source_id, @@ -293,16 +318,18 @@ mod tests { #[tokio::test] async fn test_graph_with_center_id() { let (storage, _dir) = test_storage().await; - let node = storage.ingest(vestige_core::IngestInput { - content: "Graph test memory".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + let node = storage + .ingest(vestige_core::IngestInput { + content: "Graph test memory".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); let args = serde_json::json!({ "center_id": node.id }); let result = execute(&storage, Some(args)).await; @@ -318,16 +345,18 @@ mod tests { #[tokio::test] async fn test_graph_with_query() { let (storage, _dir) = test_storage().await; - storage.ingest(vestige_core::IngestInput { - content: "Quantum computing fundamentals".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["science".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: "Quantum computing fundamentals".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["science".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); let args = serde_json::json!({ "query": "quantum" }); let result = execute(&storage, Some(args)).await; @@ -339,16 +368,18 @@ mod tests { #[tokio::test] async fn test_graph_node_has_position() { let (storage, _dir) = test_storage().await; - let node = storage.ingest(vestige_core::IngestInput { - content: "Position test memory".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec![], - valid_from: None, - valid_until: None, - }).unwrap(); + let node = storage + .ingest(vestige_core::IngestInput { + content: "Position test memory".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec![], + valid_from: None, + valid_until: None, + }) + .unwrap(); let args = serde_json::json!({ "center_id": node.id }); let result = execute(&storage, Some(args)).await.unwrap(); diff --git a/crates/vestige-mcp/src/tools/health.rs b/crates/vestige-mcp/src/tools/health.rs index 773438a..362f298 100644 --- a/crates/vestige-mcp/src/tools/health.rs +++ b/crates/vestige-mcp/src/tools/health.rs @@ -16,23 +16,28 @@ pub async fn execute( _args: Option, ) -> Result { // Average retention - let avg_retention = storage.get_avg_retention() + let avg_retention = storage + .get_avg_retention() .map_err(|e| format!("Failed to get avg retention: {}", e))?; // Retention distribution - let distribution = storage.get_retention_distribution() + let distribution = storage + .get_retention_distribution() .map_err(|e| format!("Failed to get retention distribution: {}", e))?; - let distribution_json: serde_json::Value = distribution.iter().map(|(bucket, count)| { - serde_json::json!({ "bucket": bucket, "count": count }) - }).collect(); + let distribution_json: serde_json::Value = distribution + .iter() + .map(|(bucket, count)| serde_json::json!({ "bucket": bucket, "count": count })) + .collect(); // Retention trend - let trend = storage.get_retention_trend() + let trend = storage + .get_retention_trend() .unwrap_or_else(|_| "unknown".to_string()); // Total memories and those below key thresholds - let stats = storage.get_stats() + let stats = storage + .get_stats() .map_err(|e| format!("Failed to get stats: {}", e))?; let below_30 = storage.count_memories_below_retention(0.3).unwrap_or(0); @@ -104,16 +109,18 @@ mod tests { let (storage, _dir) = test_storage().await; // Ingest some test memories for i in 0..5 { - storage.ingest(vestige_core::IngestInput { - content: format!("Health test memory {}", i), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["test".to_string()], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: format!("Health test memory {}", i), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); } let result = execute(&storage, None).await; @@ -127,24 +134,24 @@ mod tests { #[tokio::test] async fn test_health_distribution_buckets() { let (storage, _dir) = test_storage().await; - storage.ingest(vestige_core::IngestInput { - content: "Test memory for distribution".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec![], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: "Test memory for distribution".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec![], + valid_from: None, + valid_until: None, + }) + .unwrap(); let result = execute(&storage, None).await.unwrap(); let dist = result["distribution"].as_array().unwrap(); // Should have at least one bucket with data assert!(!dist.is_empty()); - let total: i64 = dist.iter() - .map(|b| b["count"].as_i64().unwrap_or(0)) - .sum(); + let total: i64 = dist.iter().map(|b| b["count"].as_i64().unwrap_or(0)).sum(); assert_eq!(total, 1); } } diff --git a/crates/vestige-mcp/src/tools/importance.rs b/crates/vestige-mcp/src/tools/importance.rs index 10f5bfb..c9048aa 100644 --- a/crates/vestige-mcp/src/tools/importance.rs +++ b/crates/vestige-mcp/src/tools/importance.rs @@ -70,7 +70,9 @@ pub async fn execute( // Use CognitiveEngine's persistent signals (novelty/reward/attention accumulate) let cog = cognitive.lock().await; - let score = cog.importance_signals.compute_importance(&args.content, &context); + let score = cog + .importance_signals + .compute_importance(&args.content, &context); // Also detect emotional markers for richer output let emotional_markers = cog.arousal_signal.detect_emotional_markers(&args.content); @@ -129,10 +131,12 @@ mod tests { let schema = schema(); assert_eq!(schema["type"], "object"); assert!(schema["properties"]["content"].is_object()); - assert!(schema["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("content"))); + assert!( + schema["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("content")) + ); } #[tokio::test] @@ -140,7 +144,12 @@ mod tests { let storage = Arc::new( Storage::new(Some(std::path::PathBuf::from("/tmp/test_importance.db"))).unwrap(), ); - let result = execute(&storage, &test_cognitive(), Some(serde_json::json!({ "content": "" }))).await; + let result = execute( + &storage, + &test_cognitive(), + Some(serde_json::json!({ "content": "" })), + ) + .await; assert!(result.is_err()); } diff --git a/crates/vestige-mcp/src/tools/ingest.rs b/crates/vestige-mcp/src/tools/ingest.rs index 402e24f..d724445 100644 --- a/crates/vestige-mcp/src/tools/ingest.rs +++ b/crates/vestige-mcp/src/tools/ingest.rs @@ -84,7 +84,9 @@ pub async fn execute( if let Ok(cog) = cognitive.try_lock() { // Full 4-channel importance scoring let context = ImportanceContext::current(); - let importance = cog.importance_signals.compute_importance(&args.content, &context); + let importance = cog + .importance_signals + .compute_importance(&args.content, &context); importance_composite = importance.composite; // Standalone novelty check (dopaminergic signal) @@ -136,7 +138,13 @@ pub async fn execute( let node_type = result.node.node_type.clone(); let has_embedding = result.node.has_embedding.unwrap_or(false); - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); Ok(serde_json::json!({ "success": true, @@ -157,7 +165,13 @@ pub async fn execute( let node_type = node.node_type.clone(); let has_embedding = node.has_embedding.unwrap_or(false); - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); Ok(serde_json::json!({ "success": true, @@ -181,7 +195,13 @@ pub async fn execute( let node_type = node.node_type.clone(); let has_embedding = node.has_embedding.unwrap_or(false); - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); Ok(serde_json::json!({ "success": true, @@ -217,16 +237,13 @@ fn run_post_ingest( cog.importance_signals.learn_content(content); // Record in hippocampal index - let _ = cog.hippocampal_index.index_memory( - node_id, - content, - node_type, - Utc::now(), - None, - ); + let _ = cog + .hippocampal_index + .index_memory(node_id, content, node_type, Utc::now(), None); // Cross-project pattern recording - cog.cross_project.record_project_memory(node_id, "default", None); + cog.cross_project + .record_project_memory(node_id, "default", None); } } @@ -421,7 +438,12 @@ mod tests { let schema_value = schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["content"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("content"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("content")) + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/intention_unified.rs b/crates/vestige-mcp/src/tools/intention_unified.rs index b2d3369..5eae9dc 100644 --- a/crates/vestige-mcp/src/tools/intention_unified.rs +++ b/crates/vestige-mcp/src/tools/intention_unified.rs @@ -265,25 +265,34 @@ async fn execute_set( nlp_parsed = true; // Extract trigger info from parsed intention let (t_type, t_data) = match &parsed.trigger { - ProspectiveTrigger::TimeBased { .. } => { - ("time".to_string(), serde_json::json!({"type": "time"}).to_string()) - } + ProspectiveTrigger::TimeBased { .. } => ( + "time".to_string(), + serde_json::json!({"type": "time"}).to_string(), + ), ProspectiveTrigger::DurationBased { after, .. } => { let mins = after.num_minutes(); - ("time".to_string(), serde_json::json!({"type": "time", "in_minutes": mins}).to_string()) - } - ProspectiveTrigger::EventBased { condition, .. } => { - ("event".to_string(), serde_json::json!({"type": "event", "condition": condition}).to_string()) - } - ProspectiveTrigger::ContextBased { context_match } => { - ("context".to_string(), serde_json::json!({"type": "context", "topic": format!("{:?}", context_match)}).to_string()) - } - ProspectiveTrigger::Recurring { .. } => { - ("recurring".to_string(), serde_json::json!({"type": "recurring"}).to_string()) - } - _ => { - ("event".to_string(), serde_json::json!({"type": "event"}).to_string()) + ( + "time".to_string(), + serde_json::json!({"type": "time", "in_minutes": mins}).to_string(), + ) } + ProspectiveTrigger::EventBased { condition, .. } => ( + "event".to_string(), + serde_json::json!({"type": "event", "condition": condition}).to_string(), + ), + ProspectiveTrigger::ContextBased { context_match } => ( + "context".to_string(), + serde_json::json!({"type": "context", "topic": format!("{:?}", context_match)}) + .to_string(), + ), + ProspectiveTrigger::Recurring { .. } => ( + "recurring".to_string(), + serde_json::json!({"type": "recurring"}).to_string(), + ), + _ => ( + "event".to_string(), + serde_json::json!({"type": "event"}).to_string(), + ), }; nlp_trigger_type = Some(t_type); nlp_trigger_data = Some(t_data); @@ -426,7 +435,6 @@ async fn execute_check( let _ = cog.prospective_memory.update_context(prospective_ctx); } - // Get active intentions let intentions = storage.get_active_intentions().map_err(|e| e.to_string())?; @@ -521,10 +529,7 @@ async fn execute_update( storage: &Arc, args: &UnifiedIntentionArgs, ) -> Result { - let intention_id = args - .id - .as_ref() - .ok_or("Missing 'id' for update action")?; + let intention_id = args.id.as_ref().ok_or("Missing 'id' for update action")?; let status = args .status @@ -690,7 +695,9 @@ mod tests { "action": "set", "description": description }); - let result = execute(storage, &test_cognitive(), Some(args)).await.unwrap(); + let result = execute(storage, &test_cognitive(), Some(args)) + .await + .unwrap(); result["intentionId"].as_str().unwrap().to_string() } @@ -742,10 +749,12 @@ mod tests { assert_eq!(value["success"], true); assert_eq!(value["action"], "set"); assert!(value["intentionId"].is_string()); - assert!(value["message"] - .as_str() - .unwrap() - .contains("Intention created")); + assert!( + value["message"] + .as_str() + .unwrap() + .contains("Intention created") + ); } #[tokio::test] @@ -953,7 +962,9 @@ mod tests { "codebase": "payments" } }); - execute(&storage, &test_cognitive(), Some(set_args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(set_args)) + .await + .unwrap(); // Check with matching context let check_args = serde_json::json!({ @@ -984,7 +995,9 @@ mod tests { "at": past_time } }); - execute(&storage, &test_cognitive(), Some(set_args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(set_args)) + .await + .unwrap(); let check_args = serde_json::json!({ "action": "check" }); let result = execute(&storage, &test_cognitive(), Some(check_args)).await; @@ -1183,7 +1196,9 @@ mod tests { "id": intention_id, "status": "complete" }); - execute(&storage, &test_cognitive(), Some(complete_args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(complete_args)) + .await + .unwrap(); // Create another active one create_test_intention(&storage, "Active task").await; @@ -1193,7 +1208,9 @@ mod tests { "action": "list", "filter_status": "fulfilled" }); - let result = execute(&storage, &test_cognitive(), Some(list_args)).await.unwrap(); + let result = execute(&storage, &test_cognitive(), Some(list_args)) + .await + .unwrap(); assert_eq!(result["total"], 1); assert_eq!(result["status"], "fulfilled"); } @@ -1229,14 +1246,18 @@ mod tests { "id": intention_id, "status": "complete" }); - execute(&storage, &test_cognitive(), Some(complete_args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(complete_args)) + .await + .unwrap(); // List all let list_args = serde_json::json!({ "action": "list", "filter_status": "all" }); - let result = execute(&storage, &test_cognitive(), Some(list_args)).await.unwrap(); + let result = execute(&storage, &test_cognitive(), Some(list_args)) + .await + .unwrap(); assert_eq!(result["total"], 2); } @@ -1253,7 +1274,9 @@ mod tests { // 2. Verify it appears in list let list_args = serde_json::json!({ "action": "list" }); - let list_result = execute(&storage, &test_cognitive(), Some(list_args)).await.unwrap(); + let list_result = execute(&storage, &test_cognitive(), Some(list_args)) + .await + .unwrap(); assert_eq!(list_result["total"], 1); // 3. Snooze it @@ -1277,7 +1300,9 @@ mod tests { // 5. Verify it's no longer active let final_list_args = serde_json::json!({ "action": "list" }); - let final_list = execute(&storage, &test_cognitive(), Some(final_list_args)).await.unwrap(); + let final_list = execute(&storage, &test_cognitive(), Some(final_list_args)) + .await + .unwrap(); assert_eq!(final_list["total"], 0); // 6. Verify it's in fulfilled list @@ -1285,7 +1310,9 @@ mod tests { "action": "list", "filter_status": "fulfilled" }); - let fulfilled_list = execute(&storage, &test_cognitive(), Some(fulfilled_args)).await.unwrap(); + let fulfilled_list = execute(&storage, &test_cognitive(), Some(fulfilled_args)) + .await + .unwrap(); assert_eq!(fulfilled_list["total"], 1); } @@ -1299,25 +1326,33 @@ mod tests { "description": "Low priority task", "priority": "low" }); - execute(&storage, &test_cognitive(), Some(args_low)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(args_low)) + .await + .unwrap(); let args_critical = serde_json::json!({ "action": "set", "description": "Critical task", "priority": "critical" }); - execute(&storage, &test_cognitive(), Some(args_critical)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(args_critical)) + .await + .unwrap(); let args_normal = serde_json::json!({ "action": "set", "description": "Normal task", "priority": "normal" }); - execute(&storage, &test_cognitive(), Some(args_normal)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(args_normal)) + .await + .unwrap(); // List and verify ordering (critical should be first due to priority DESC ordering) let list_args = serde_json::json!({ "action": "list" }); - let list_result = execute(&storage, &test_cognitive(), Some(list_args)).await.unwrap(); + let list_result = execute(&storage, &test_cognitive(), Some(list_args)) + .await + .unwrap(); let intentions = list_result["intentions"].as_array().unwrap(); assert!(intentions.len() >= 3); @@ -1335,10 +1370,12 @@ mod tests { let schema_value = schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["action"].is_object()); - assert!(schema_value["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("action"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("action")) + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/intentions.rs b/crates/vestige-mcp/src/tools/intentions.rs index 8060125..169ac43 100644 --- a/crates/vestige-mcp/src/tools/intentions.rs +++ b/crates/vestige-mcp/src/tools/intentions.rs @@ -6,7 +6,7 @@ use serde::Deserialize; use serde_json::Value; use std::sync::Arc; -use chrono::{DateTime, Utc, Duration}; +use chrono::{DateTime, Duration, Utc}; use uuid::Uuid; use vestige_core::{IntentionRecord, Storage}; @@ -221,10 +221,7 @@ struct ListArgs { } /// Execute set_intention tool -pub async fn execute_set( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_set(storage: &Arc, args: Option) -> Result { let args: SetIntentionArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -239,7 +236,10 @@ pub async fn execute_set( // Determine trigger type and data let (trigger_type, trigger_data) = if let Some(trigger) = &args.trigger { - let t_type = trigger.trigger_type.clone().unwrap_or_else(|| "time".to_string()); + let t_type = trigger + .trigger_type + .clone() + .unwrap_or_else(|| "time".to_string()); let data = serde_json::to_string(trigger).unwrap_or_else(|_| "{}".to_string()); (t_type, data) } else { @@ -256,13 +256,17 @@ pub async fn execute_set( // Parse deadline let deadline = args.deadline.and_then(|s| { - DateTime::parse_from_rfc3339(&s).ok().map(|dt| dt.with_timezone(&Utc)) + DateTime::parse_from_rfc3339(&s) + .ok() + .map(|dt| dt.with_timezone(&Utc)) }); // Calculate trigger time if specified let trigger_at = if let Some(trigger) = &args.trigger { if let Some(at) = &trigger.at { - DateTime::parse_from_rfc3339(at).ok().map(|dt| dt.with_timezone(&Utc)) + DateTime::parse_from_rfc3339(at) + .ok() + .map(|dt| dt.with_timezone(&Utc)) } else { trigger.in_minutes.map(|mins| now + Duration::minutes(mins)) } @@ -303,13 +307,13 @@ pub async fn execute_set( } /// Execute check_intentions tool -pub async fn execute_check( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_check(storage: &Arc, args: Option) -> Result { let args: CheckIntentionsArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, - None => CheckIntentionsArgs { context: None, include_snoozed: None }, + None => CheckIntentionsArgs { + context: None, + include_snoozed: None, + }, }; let now = Utc::now(); @@ -344,14 +348,20 @@ pub async fn execute_check( Some("context") => { if let Some(ctx) = &args.context { // Check codebase match - if let (Some(trigger_codebase), Some(current_codebase)) = (&t.codebase, &ctx.codebase) { - current_codebase.to_lowercase().contains(&trigger_codebase.to_lowercase()) + if let (Some(trigger_codebase), Some(current_codebase)) = + (&t.codebase, &ctx.codebase) + { + current_codebase + .to_lowercase() + .contains(&trigger_codebase.to_lowercase()) // Check file pattern match } else if let (Some(pattern), Some(file)) = (&t.file_pattern, &ctx.file) { file.contains(pattern) // Check topic match } else if let (Some(topic), Some(topics)) = (&t.topic, &ctx.topics) { - topics.iter().any(|t| t.to_lowercase().contains(&topic.to_lowercase())) + topics + .iter() + .any(|t| t.to_lowercase().contains(&topic.to_lowercase())) } else { false } @@ -406,7 +416,8 @@ pub async fn execute_complete( None => return Err("Missing intention_id".to_string()), }; - let updated = storage.update_intention_status(&args.intention_id, "fulfilled") + let updated = storage + .update_intention_status(&args.intention_id, "fulfilled") .map_err(|e| e.to_string())?; if updated { @@ -421,10 +432,7 @@ pub async fn execute_complete( } /// Execute snooze_intention tool -pub async fn execute_snooze( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_snooze(storage: &Arc, args: Option) -> Result { let args: SnoozeArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing intention_id".to_string()), @@ -433,7 +441,8 @@ pub async fn execute_snooze( let minutes = args.minutes.unwrap_or(30); let snooze_until = Utc::now() + Duration::minutes(minutes); - let updated = storage.snooze_intention(&args.intention_id, snooze_until) + let updated = storage + .snooze_intention(&args.intention_id, snooze_until) .map_err(|e| e.to_string())?; if updated { @@ -449,13 +458,13 @@ pub async fn execute_snooze( } /// Execute list_intentions tool -pub async fn execute_list( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_list(storage: &Arc, args: Option) -> Result { let args: ListArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, - None => ListArgs { status: None, limit: None }, + None => ListArgs { + status: None, + limit: None, + }, }; let status = args.status.as_deref().unwrap_or("active"); @@ -463,15 +472,29 @@ pub async fn execute_list( let intentions = if status == "all" { // Get all by combining different statuses let mut all = storage.get_active_intentions().map_err(|e| e.to_string())?; - all.extend(storage.get_intentions_by_status("fulfilled").map_err(|e| e.to_string())?); - all.extend(storage.get_intentions_by_status("cancelled").map_err(|e| e.to_string())?); - all.extend(storage.get_intentions_by_status("snoozed").map_err(|e| e.to_string())?); + all.extend( + storage + .get_intentions_by_status("fulfilled") + .map_err(|e| e.to_string())?, + ); + all.extend( + storage + .get_intentions_by_status("cancelled") + .map_err(|e| e.to_string())?, + ); + all.extend( + storage + .get_intentions_by_status("snoozed") + .map_err(|e| e.to_string())?, + ); all } else if status == "active" { // Use get_active_intentions for proper priority ordering storage.get_active_intentions().map_err(|e| e.to_string())? } else { - storage.get_intentions_by_status(status).map_err(|e| e.to_string())? + storage + .get_intentions_by_status(status) + .map_err(|e| e.to_string())? }; let limit = args.limit.unwrap_or(20) as usize; @@ -574,7 +597,12 @@ mod tests { let value = result.unwrap(); assert_eq!(value["success"], true); assert!(value["intentionId"].is_string()); - assert!(value["message"].as_str().unwrap().contains("Intention created")); + assert!( + value["message"] + .as_str() + .unwrap() + .contains("Intention created") + ); } #[tokio::test] @@ -1017,14 +1045,24 @@ mod tests { let schema_value = set_schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["description"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("description"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("description")) + ); } #[test] fn test_complete_schema_has_required_fields() { let schema_value = complete_schema(); assert!(schema_value["properties"]["intentionId"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("intentionId"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("intentionId")) + ); } #[test] @@ -1032,7 +1070,12 @@ mod tests { let schema_value = snooze_schema(); assert!(schema_value["properties"]["intentionId"].is_object()); assert!(schema_value["properties"]["minutes"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("intentionId"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("intentionId")) + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/knowledge.rs b/crates/vestige-mcp/src/tools/knowledge.rs index 1171d76..f26646d 100644 --- a/crates/vestige-mcp/src/tools/knowledge.rs +++ b/crates/vestige-mcp/src/tools/knowledge.rs @@ -42,10 +42,7 @@ struct KnowledgeArgs { id: String, } -pub async fn execute_get( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_get(storage: &Arc, args: Option) -> Result { let args: KnowledgeArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -90,10 +87,7 @@ pub async fn execute_get( } } -pub async fn execute_delete( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_delete(storage: &Arc, args: Option) -> Result { let args: KnowledgeArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), diff --git a/crates/vestige-mcp/src/tools/maintenance.rs b/crates/vestige-mcp/src/tools/maintenance.rs index 9764dce..fcd89d1 100644 --- a/crates/vestige-mcp/src/tools/maintenance.rs +++ b/crates/vestige-mcp/src/tools/maintenance.rs @@ -159,7 +159,8 @@ pub async fn execute_system_status( let mut recommendations = Vec::new(); if status == "critical" { - recommendations.push("CRITICAL: Many memories have very low retention. Review important memories."); + recommendations + .push("CRITICAL: Many memories have very low retention. Review important memories."); } if stats.nodes_due_for_review > 5 { recommendations.push("Review due memories to strengthen retention."); @@ -253,7 +254,6 @@ pub async fn execute_system_status( }; let last_backup = Storage::get_last_backup_timestamp(); - Ok(serde_json::json!({ "tool": "system_status", // Health @@ -336,7 +336,8 @@ pub async fn execute_health_check( let mut recommendations = Vec::new(); if status == "critical" { - recommendations.push("CRITICAL: Many memories have very low retention. Review important memories."); + recommendations + .push("CRITICAL: Many memories have very low retention. Review important memories."); } if stats.nodes_due_for_review > 5 { recommendations.push("Review due memories to strengthen retention."); @@ -505,7 +506,9 @@ pub async fn execute_stats( }) .collect(); if !memories_for_compression.is_empty() { - let groups = cog.compressor.find_compressible_groups(&memories_for_compression); + let groups = cog + .compressor + .find_compressible_groups(&memories_for_compression); Some(serde_json::json!({ "groupCount": groups.len(), "totalCompressible": groups.iter().map(|g| g.len()).sum::(), @@ -566,14 +569,13 @@ pub async fn execute_stats( } /// Backup tool -pub async fn execute_backup( - storage: &Arc, - _args: Option, -) -> Result { +pub async fn execute_backup(storage: &Arc, _args: Option) -> Result { // Determine backup path let vestige_dir = directories::ProjectDirs::from("com", "vestige", "core") .ok_or("Could not determine data directory")?; - let backup_dir = vestige_dir.data_dir().parent() + let backup_dir = vestige_dir + .data_dir() + .parent() .unwrap_or(vestige_dir.data_dir()) .join("backups"); @@ -585,7 +587,8 @@ pub async fn execute_backup( // Use VACUUM INTO for a consistent backup (handles WAL properly) { - storage.backup_to(&backup_path) + storage + .backup_to(&backup_path) .map_err(|e| format!("Failed to create backup: {}", e))?; } @@ -611,10 +614,7 @@ struct ExportArgs { } /// Export tool -pub async fn execute_export( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_export(storage: &Arc, args: Option) -> Result { let args: ExportArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => ExportArgs { @@ -627,7 +627,10 @@ pub async fn execute_export( let format = args.format.unwrap_or_else(|| "json".to_string()); if format != "json" && format != "jsonl" { - return Err(format!("Invalid format '{}'. Must be 'json' or 'jsonl'.", format)); + return Err(format!( + "Invalid format '{}'. Must be 'json' or 'jsonl'.", + format + )); } // Parse since date @@ -648,7 +651,9 @@ pub async fn execute_export( let max_nodes = 100_000; let mut offset = 0; loop { - let batch = storage.get_all_nodes(page_size, offset).map_err(|e| e.to_string())?; + let batch = storage + .get_all_nodes(page_size, offset) + .map_err(|e| e.to_string())?; let batch_len = batch.len(); all_nodes.extend(batch); if batch_len < page_size as usize || all_nodes.len() >= max_nodes { @@ -661,7 +666,10 @@ pub async fn execute_export( let filtered: Vec<&vestige_core::KnowledgeNode> = all_nodes .iter() .filter(|node| { - if since_date.as_ref().is_some_and(|since_dt| node.created_at < *since_dt) { + if since_date + .as_ref() + .is_some_and(|since_dt| node.created_at < *since_dt) + { return false; } if !tag_filter.is_empty() { @@ -678,7 +686,9 @@ pub async fn execute_export( // Determine export path — always constrained to vestige exports directory let vestige_dir = directories::ProjectDirs::from("com", "vestige", "core") .ok_or("Could not determine data directory")?; - let export_dir = vestige_dir.data_dir().parent() + let export_dir = vestige_dir + .data_dir() + .parent() .unwrap_or(vestige_dir.data_dir()) .join("exports"); std::fs::create_dir_all(&export_dir) @@ -725,7 +735,9 @@ pub async fn execute_export( } writer.flush().map_err(|e| e.to_string())?; - let file_size = std::fs::metadata(&export_path).map(|m| m.len()).unwrap_or(0); + let file_size = std::fs::metadata(&export_path) + .map(|m| m.len()) + .unwrap_or(0); Ok(serde_json::json!({ "tool": "export", @@ -746,10 +758,7 @@ struct GcArgs { } /// Garbage collection tool -pub async fn execute_gc( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_gc(storage: &Arc, args: Option) -> Result { let args: GcArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => GcArgs { @@ -771,7 +780,9 @@ pub async fn execute_gc( let max_nodes = 100_000; let mut offset = 0; loop { - let batch = storage.get_all_nodes(page_size, offset).map_err(|e| e.to_string())?; + let batch = storage + .get_all_nodes(page_size, offset) + .map_err(|e| e.to_string())?; let batch_len = batch.len(); all_nodes.extend(batch); if batch_len < page_size as usize || all_nodes.len() >= max_nodes { @@ -903,16 +914,18 @@ mod tests { async fn test_system_status_with_memories() { let (storage, _dir) = test_storage().await; { - storage.ingest(vestige_core::IngestInput { - content: "Test memory for status".to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec![], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: "Test memory for status".to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec![], + valid_from: None, + valid_until: None, + }) + .unwrap(); } let result = execute_system_status(&storage, &test_cognitive(), None).await; assert!(result.is_ok()); @@ -942,7 +955,10 @@ mod tests { assert!(triggers.is_object(), "automationTriggers should be present"); assert!(triggers["lastDreamTimestamp"].is_null(), "No dreams yet"); assert_eq!(triggers["savesSinceLastDream"], 0, "Empty DB = 0 saves"); - assert!(triggers["lastConsolidationTimestamp"].is_null(), "No consolidation yet"); + assert!( + triggers["lastConsolidationTimestamp"].is_null(), + "No consolidation yet" + ); // lastBackupTimestamp depends on filesystem state, just check it exists assert!(triggers.get("lastBackupTimestamp").is_some()); } @@ -952,16 +968,18 @@ mod tests { let (storage, _dir) = test_storage().await; { for i in 0..3 { - storage.ingest(vestige_core::IngestInput { - content: format!("Automation trigger test memory {}", i), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec![], - valid_from: None, - valid_until: None, - }).unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: format!("Automation trigger test memory {}", i), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec![], + valid_from: None, + valid_until: None, + }) + .unwrap(); } } let result = execute_system_status(&storage, &test_cognitive(), None).await; diff --git a/crates/vestige-mcp/src/tools/memory_states.rs b/crates/vestige-mcp/src/tools/memory_states.rs index 92d3c76..dae2583 100644 --- a/crates/vestige-mcp/src/tools/memory_states.rs +++ b/crates/vestige-mcp/src/tools/memory_states.rs @@ -75,19 +75,14 @@ pub fn stats_schema() -> Value { } /// Get the cognitive state of a specific memory -pub async fn execute_get( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_get(storage: &Arc, args: Option) -> Result { let args = args.ok_or("Missing arguments")?; - let memory_id = args["memory_id"] - .as_str() - .ok_or("memory_id is required")?; - + let memory_id = args["memory_id"].as_str().ok_or("memory_id is required")?; // Get the memory - let memory = storage.get_node(memory_id) + let memory = storage + .get_node(memory_id) .map_err(|e| format!("Error: {}", e))? .ok_or("Memory not found")?; @@ -128,19 +123,14 @@ pub async fn execute_get( } /// List memories by state -pub async fn execute_list( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_list(storage: &Arc, args: Option) -> Result { let args = args.unwrap_or(serde_json::json!({})); let state_filter = args["state"].as_str(); let limit = args["limit"].as_i64().unwrap_or(20) as usize; - // Get all memories - let memories = storage.get_all_nodes(500, 0) - .map_err(|e| e.to_string())?; + let memories = storage.get_all_nodes(500, 0).map_err(|e| e.to_string())?; // Categorize by state let mut active = Vec::new(); @@ -199,19 +189,15 @@ pub async fn execute_list( "dormant": { "count": dormant.len(), "memories": dormant.into_iter().take(limit).collect::>() }, "silent": { "count": silent.len(), "memories": silent.into_iter().take(limit).collect::>() }, "unavailable": { "count": unavailable.len(), "memories": unavailable.into_iter().take(limit).collect::>() } - }) + }), }; Ok(result) } /// Get memory state statistics -pub async fn execute_stats( - storage: &Arc, -) -> Result { - - let memories = storage.get_all_nodes(1000, 0) - .map_err(|e| e.to_string())?; +pub async fn execute_stats(storage: &Arc) -> Result { + let memories = storage.get_all_nodes(1000, 0).map_err(|e| e.to_string())?; let total = memories.len(); let mut active_count = 0; @@ -237,7 +223,11 @@ pub async fn execute_stats( } } - let avg_accessibility = if total > 0 { total_accessibility / total as f64 } else { 0.0 }; + let avg_accessibility = if total > 0 { + total_accessibility / total as f64 + } else { + 0.0 + }; Ok(serde_json::json!({ "totalMemories": total, diff --git a/crates/vestige-mcp/src/tools/memory_unified.rs b/crates/vestige-mcp/src/tools/memory_unified.rs index e138b97..2d73b6b 100644 --- a/crates/vestige-mcp/src/tools/memory_unified.rs +++ b/crates/vestige-mcp/src/tools/memory_unified.rs @@ -219,7 +219,6 @@ async fn execute_delete(storage: &Arc, id: &str) -> Result, id: &str) -> Result { - // Get the memory let memory = storage .get_node(id) @@ -270,8 +269,9 @@ async fn execute_promote( id: &str, reason: Option, ) -> Result { - - let before = storage.get_node(id).map_err(|e| e.to_string())? + let before = storage + .get_node(id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", id))?; let node = storage.promote_memory(id).map_err(|e| e.to_string())?; @@ -325,15 +325,17 @@ async fn execute_demote( id: &str, reason: Option, ) -> Result { - - let before = storage.get_node(id).map_err(|e| e.to_string())? + let before = storage + .get_node(id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", id))?; let node = storage.demote_memory(id).map_err(|e| e.to_string())?; // Cognitive feedback pipeline if let Ok(mut cog) = cognitive.try_lock() { - cog.reward_signal.record_outcome(id, OutcomeType::NotHelpful); + cog.reward_signal + .record_outcome(id, OutcomeType::NotHelpful); cog.importance_tracker.on_retrieved(id, false); if cog.reconsolidation.is_labile(id) { cog.reconsolidation.apply_modification( @@ -429,22 +431,34 @@ mod tests { // Test Active state let accessibility = compute_accessibility(0.9, 0.8, 0.7); assert!(accessibility >= ACCESSIBILITY_ACTIVE); - assert!(matches!(state_from_accessibility(accessibility), MemoryState::Active)); + assert!(matches!( + state_from_accessibility(accessibility), + MemoryState::Active + )); // Test Dormant state let accessibility = compute_accessibility(0.5, 0.5, 0.5); - assert!(accessibility >= ACCESSIBILITY_DORMANT && accessibility < ACCESSIBILITY_ACTIVE); - assert!(matches!(state_from_accessibility(accessibility), MemoryState::Dormant)); + assert!((ACCESSIBILITY_DORMANT..ACCESSIBILITY_ACTIVE).contains(&accessibility)); + assert!(matches!( + state_from_accessibility(accessibility), + MemoryState::Dormant + )); // Test Silent state let accessibility = compute_accessibility(0.2, 0.2, 0.2); - assert!(accessibility >= ACCESSIBILITY_SILENT && accessibility < ACCESSIBILITY_DORMANT); - assert!(matches!(state_from_accessibility(accessibility), MemoryState::Silent)); + assert!((ACCESSIBILITY_SILENT..ACCESSIBILITY_DORMANT).contains(&accessibility)); + assert!(matches!( + state_from_accessibility(accessibility), + MemoryState::Silent + )); // Test Unavailable state let accessibility = compute_accessibility(0.05, 0.05, 0.05); assert!(accessibility < ACCESSIBILITY_SILENT); - assert!(matches!(state_from_accessibility(accessibility), MemoryState::Unavailable)); + assert!(matches!( + state_from_accessibility(accessibility), + MemoryState::Unavailable + )); } #[test] @@ -538,7 +552,8 @@ mod tests { #[tokio::test] async fn test_get_nonexistent_memory() { let (storage, _dir) = test_storage().await; - let args = serde_json::json!({ "action": "get", "id": "00000000-0000-0000-0000-000000000000" }); + let args = + serde_json::json!({ "action": "get", "id": "00000000-0000-0000-0000-000000000000" }); let result = execute(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_ok()); let value = result.unwrap(); @@ -562,13 +577,17 @@ mod tests { async fn test_delete_nonexistent_memory() { let (storage, _dir) = test_storage().await; // Ingest+delete a throwaway memory to warm writer after WAL migration - let warmup_id = storage.ingest(vestige_core::IngestInput { - content: "warmup".to_string(), - node_type: "fact".to_string(), - ..Default::default() - }).unwrap().id; + let warmup_id = storage + .ingest(vestige_core::IngestInput { + content: "warmup".to_string(), + node_type: "fact".to_string(), + ..Default::default() + }) + .unwrap() + .id; let _ = storage.delete_node(&warmup_id); - let args = serde_json::json!({ "action": "delete", "id": "00000000-0000-0000-0000-000000000000" }); + let args = + serde_json::json!({ "action": "delete", "id": "00000000-0000-0000-0000-000000000000" }); let result = execute(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_ok()); let value = result.unwrap(); @@ -581,7 +600,9 @@ mod tests { let (storage, _dir) = test_storage().await; let id = ingest_memory(&storage).await; let del_args = serde_json::json!({ "action": "delete", "id": id }); - execute(&storage, &test_cognitive(), Some(del_args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(del_args)) + .await + .unwrap(); let get_args = serde_json::json!({ "action": "get", "id": id }); let result = execute(&storage, &test_cognitive(), Some(get_args)).await; let value = result.unwrap(); @@ -612,7 +633,8 @@ mod tests { #[tokio::test] async fn test_state_nonexistent_memory_fails() { let (storage, _dir) = test_storage().await; - let args = serde_json::json!({ "action": "state", "id": "00000000-0000-0000-0000-000000000000" }); + let args = + serde_json::json!({ "action": "state", "id": "00000000-0000-0000-0000-000000000000" }); let result = execute(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_err()); assert!(result.unwrap_err().contains("not found")); @@ -629,7 +651,10 @@ mod tests { fn test_accessibility_boundary_zero() { let a = compute_accessibility(0.0, 0.0, 0.0); assert_eq!(a, 0.0); - assert!(matches!(state_from_accessibility(a), MemoryState::Unavailable)); + assert!(matches!( + state_from_accessibility(a), + MemoryState::Unavailable + )); } // ======================================================================== @@ -708,7 +733,8 @@ mod tests { #[tokio::test] async fn test_demote_nonexistent_node_fails() { let (storage, _dir) = test_storage().await; - let args = serde_json::json!({ "action": "demote", "id": "00000000-0000-0000-0000-000000000000" }); + let args = + serde_json::json!({ "action": "demote", "id": "00000000-0000-0000-0000-000000000000" }); let result = execute(&storage, &test_cognitive(), Some(args)).await; assert!(result.is_err()); assert!(result.unwrap_err().contains("Node not found")); @@ -761,9 +787,24 @@ mod tests { assert_eq!(value["success"], true); assert_eq!(value["action"], "edit"); assert_eq!(value["nodeId"], id); - assert!(value["oldContentPreview"].as_str().unwrap().contains("Memory unified test content")); - assert!(value["newContentPreview"].as_str().unwrap().contains("Updated memory content")); - assert!(value["note"].as_str().unwrap().contains("FSRS state preserved")); + assert!( + value["oldContentPreview"] + .as_str() + .unwrap() + .contains("Memory unified test content") + ); + assert!( + value["newContentPreview"] + .as_str() + .unwrap() + .contains("Updated memory content") + ); + assert!( + value["note"] + .as_str() + .unwrap() + .contains("FSRS state preserved") + ); } #[tokio::test] @@ -780,7 +821,9 @@ mod tests { "id": id, "content": "Completely new content after edit" }); - execute(&storage, &test_cognitive(), Some(args)).await.unwrap(); + execute(&storage, &test_cognitive(), Some(args)) + .await + .unwrap(); // Verify FSRS state preserved let after = storage.get_node(&id).unwrap().unwrap(); diff --git a/crates/vestige-mcp/src/tools/mod.rs b/crates/vestige-mcp/src/tools/mod.rs index c621cf7..6d2d674 100644 --- a/crates/vestige-mcp/src/tools/mod.rs +++ b/crates/vestige-mcp/src/tools/mod.rs @@ -34,12 +34,15 @@ pub mod restore; pub mod session_context; // v1.9: Autonomic tools -pub mod health; pub mod graph; +pub mod health; // v2.1: Cross-reference (connect the dots) pub mod cross_reference; +// v2.0.5: Active Forgetting — Anderson 2025 + Davis Rac1 +pub mod suppress; + // Deprecated/internal tools — not advertised in the public MCP tools/list, // but some functions are actively dispatched for backwards compatibility // and internal cognitive operations. #[allow(dead_code)] suppresses warnings diff --git a/crates/vestige-mcp/src/tools/predict.rs b/crates/vestige-mcp/src/tools/predict.rs index 4ebf741..020f54a 100644 --- a/crates/vestige-mcp/src/tools/predict.rs +++ b/crates/vestige-mcp/src/tools/predict.rs @@ -57,23 +57,30 @@ pub async fn execute( project_context: context .and_then(|c| c.get("codebase")) .and_then(|v| v.as_str()) - .map(|name| vestige_core::neuroscience::predictive_retrieval::ProjectContext { - name: name.to_string(), - path: String::new(), - technologies: Vec::new(), - primary_language: None, - }), + .map( + |name| vestige_core::neuroscience::predictive_retrieval::ProjectContext { + name: name.to_string(), + path: String::new(), + technologies: Vec::new(), + primary_language: None, + }, + ), }; // Get predictions from predictive memory - let predictions = cog.predictive_memory.predict_needed_memories(&session_ctx) + let predictions = cog + .predictive_memory + .predict_needed_memories(&session_ctx) .unwrap_or_default(); - let suggestions = cog.predictive_memory.get_proactive_suggestions(0.3) + let suggestions = cog + .predictive_memory + .get_proactive_suggestions(0.3) .unwrap_or_default(); - let top_interests = cog.predictive_memory.get_top_interests(10) + let top_interests = cog + .predictive_memory + .get_top_interests(10) .unwrap_or_default(); - let accuracy = cog.predictive_memory.prediction_accuracy() - .unwrap_or(0.0); + let accuracy = cog.predictive_memory.prediction_accuracy().unwrap_or(0.0); // Build speculative context let speculative_context = vestige_core::PredictionContext { @@ -91,7 +98,9 @@ pub async fn execute( .map(PathBuf::from), timestamp: Some(chrono::Utc::now()), }; - let speculative = cog.speculative_retriever.predict_needed(&speculative_context); + let speculative = cog + .speculative_retriever + .predict_needed(&speculative_context); Ok(serde_json::json!({ "predictions": predictions.iter().map(|p| serde_json::json!({ diff --git a/crates/vestige-mcp/src/tools/recall.rs b/crates/vestige-mcp/src/tools/recall.rs index 23c4ac7..28ff8c4 100644 --- a/crates/vestige-mcp/src/tools/recall.rs +++ b/crates/vestige-mcp/src/tools/recall.rs @@ -44,10 +44,7 @@ struct RecallArgs { min_retention: Option, } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: RecallArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -101,8 +98,8 @@ pub async fn execute( #[cfg(test)] mod tests { use super::*; - use vestige_core::IngestInput; use tempfile::TempDir; + use vestige_core::IngestInput; /// Create a test storage instance with a temporary database async fn test_storage() -> (Arc, TempDir) { @@ -266,7 +263,8 @@ mod tests { #[tokio::test] async fn test_recall_returns_matching_content() { let (storage, _dir) = test_storage().await; - let node_id = ingest_test_content(&storage, "Python is a dynamic programming language.").await; + let node_id = + ingest_test_content(&storage, "Python is a dynamic programming language.").await; let args = serde_json::json!({ "query": "python" }); let result = execute(&storage, Some(args)).await; @@ -370,7 +368,12 @@ mod tests { let schema_value = schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["query"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("query"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("query")) + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/restore.rs b/crates/vestige-mcp/src/tools/restore.rs index 90ed1df..4d77252 100644 --- a/crates/vestige-mcp/src/tools/restore.rs +++ b/crates/vestige-mcp/src/tools/restore.rs @@ -8,7 +8,6 @@ use serde::Deserialize; use serde_json::Value; use std::sync::Arc; - use vestige_core::{IngestInput, Storage}; /// Input schema for restore tool @@ -51,10 +50,7 @@ struct MemoryBackup { source: Option, } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: RestoreArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -71,25 +67,26 @@ pub async fn execute( // Try parsing as wrapped format first (MCP response wrapper), // then fall back to direct RecallResult - let memories: Vec = - if let Ok(wrapper) = serde_json::from_str::>(&backup_content) { - if let Some(first) = wrapper.first() { - let recall: RecallResult = serde_json::from_str(&first.text) - .map_err(|e| format!("Failed to parse backup contents: {}", e))?; - recall.results - } else { - return Err("Empty backup file".to_string()); - } - } else if let Ok(recall) = serde_json::from_str::(&backup_content) { + let memories: Vec = if let Ok(wrapper) = + serde_json::from_str::>(&backup_content) + { + if let Some(first) = wrapper.first() { + let recall: RecallResult = serde_json::from_str(&first.text) + .map_err(|e| format!("Failed to parse backup contents: {}", e))?; recall.results - } else if let Ok(nodes) = serde_json::from_str::>(&backup_content) { - nodes } else { - return Err( - "Unrecognized backup format. Expected MCP wrapper, RecallResult, or array of memories." - .to_string(), - ); - }; + return Err("Empty backup file".to_string()); + } + } else if let Ok(recall) = serde_json::from_str::(&backup_content) { + recall.results + } else if let Ok(nodes) = serde_json::from_str::>(&backup_content) { + nodes + } else { + return Err( + "Unrecognized backup format. Expected MCP wrapper, RecallResult, or array of memories." + .to_string(), + ); + }; let total = memories.len(); if total == 0 { @@ -108,7 +105,10 @@ pub async fn execute( for memory in &memories { let input = IngestInput { content: memory.content.clone(), - node_type: memory.node_type.clone().unwrap_or_else(|| "fact".to_string()), + node_type: memory + .node_type + .clone() + .unwrap_or_else(|| "fact".to_string()), source: memory.source.clone(), sentiment_score: 0.0, sentiment_magnitude: 0.0, @@ -157,10 +157,12 @@ mod tests { let s = schema(); assert_eq!(s["type"], "object"); assert!(s["properties"]["path"].is_object()); - assert!(s["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("path"))); + assert!( + s["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("path")) + ); } #[tokio::test] diff --git a/crates/vestige-mcp/src/tools/review.rs b/crates/vestige-mcp/src/tools/review.rs index 3f13835..f5a0025 100644 --- a/crates/vestige-mcp/src/tools/review.rs +++ b/crates/vestige-mcp/src/tools/review.rs @@ -6,7 +6,6 @@ use serde::Deserialize; use serde_json::Value; use std::sync::Arc; - use vestige_core::{Rating, Storage}; /// Input schema for mark_reviewed tool @@ -37,10 +36,7 @@ struct ReviewArgs { rating: Option, } -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: ReviewArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -54,15 +50,18 @@ pub async fn execute( return Err("Rating must be between 1 and 4".to_string()); } - let rating = Rating::from_i32(rating_value) - .ok_or_else(|| "Invalid rating value".to_string())?; - + let rating = + Rating::from_i32(rating_value).ok_or_else(|| "Invalid rating value".to_string())?; // Get node before review for comparison - let before = storage.get_node(&args.id).map_err(|e| e.to_string())? + let before = storage + .get_node(&args.id) + .map_err(|e| e.to_string())? .ok_or_else(|| format!("Node not found: {}", args.id))?; - let node = storage.mark_reviewed(&args.id, rating).map_err(|e| e.to_string())?; + let node = storage + .mark_reviewed(&args.id, rating) + .map_err(|e| e.to_string())?; let rating_name = match rating { Rating::Again => "Again", @@ -97,8 +96,8 @@ pub async fn execute( #[cfg(test)] mod tests { use super::*; - use vestige_core::IngestInput; use tempfile::TempDir; + use vestige_core::IngestInput; /// Create a test storage instance with a temporary database async fn test_storage() -> (Arc, TempDir) { @@ -438,7 +437,12 @@ mod tests { let schema_value = schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["id"].is_object()); - assert!(schema_value["required"].as_array().unwrap().contains(&serde_json::json!("id"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("id")) + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/search.rs b/crates/vestige-mcp/src/tools/search.rs index 9235b64..7653cec 100644 --- a/crates/vestige-mcp/src/tools/search.rs +++ b/crates/vestige-mcp/src/tools/search.rs @@ -101,7 +101,6 @@ pub async fn execute_semantic( return Err("Query cannot be empty".to_string()); } - // Check if embeddings are ready if !storage.is_embedding_ready() { return Ok(serde_json::json!({ @@ -140,10 +139,7 @@ pub async fn execute_semantic( })) } -pub async fn execute_hybrid( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_hybrid(storage: &Arc, args: Option) -> Result { let args: HybridSearchArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => return Err("Missing arguments".to_string()), @@ -153,7 +149,6 @@ pub async fn execute_hybrid( return Err("Query cannot be empty".to_string()); } - let results = storage .hybrid_search( &args.query, diff --git a/crates/vestige-mcp/src/tools/search_unified.rs b/crates/vestige-mcp/src/tools/search_unified.rs index 8cadbe2..bfe419e 100644 --- a/crates/vestige-mcp/src/tools/search_unified.rs +++ b/crates/vestige-mcp/src/tools/search_unified.rs @@ -191,15 +191,16 @@ pub async fn execute( .hybrid_search_filtered( &args.query, keyword_first_limit, - 1.0, // keyword_weight = 1.0 (keyword-only) - 0.0, // semantic_weight = 0.0 + 1.0, // keyword_weight = 1.0 (keyword-only) + 0.0, // semantic_weight = 0.0 args.include_types.as_deref(), args.exclude_types.as_deref(), ) .map_err(|e| e.to_string())?; // Collect keyword-priority results (keyword_score >= threshold) - let mut keyword_priority_ids: std::collections::HashSet = std::collections::HashSet::new(); + let mut keyword_priority_ids: std::collections::HashSet = + std::collections::HashSet::new(); let mut keyword_priority_results: Vec = Vec::new(); for r in keyword_first_results { if r.keyword_score.unwrap_or(0.0) >= keyword_priority_threshold @@ -214,7 +215,7 @@ pub async fn execute( // STAGE 1: Hybrid search with Nx over-fetch for reranking pool // ==================================================================== let overfetch_multiplier = match retrieval_mode { - "precise" => 1, // No overfetch — return exactly what's asked + "precise" => 1, // No overfetch — return exactly what's asked "exhaustive" => 5, // Deep overfetch for maximum recall _ => 3, // Balanced default }; @@ -251,7 +252,10 @@ pub async fn execute( // Dedup: merge Stage 0 keyword-priority results into Stage 1 results // ==================================================================== for kp in &keyword_priority_results { - if let Some(existing) = filtered_results.iter_mut().find(|r| r.node.id == kp.node.id) { + if let Some(existing) = filtered_results + .iter_mut() + .find(|r| r.node.id == kp.node.id) + { // Preserve keyword_score from Stage 0 (keyword-only search is authoritative) if kp.keyword_score.unwrap_or(0.0) > existing.keyword_score.unwrap_or(0.0) { existing.keyword_score = kp.keyword_score; @@ -305,7 +309,10 @@ pub async fn execute( let reranked_results: Vec = if rerank_candidates.is_empty() { Vec::new() } else if let Ok(mut cog) = cognitive.try_lock() { - if let Ok(reranked) = cog.reranker.rerank(&args.query, rerank_candidates, Some(limit_usize)) { + if let Ok(reranked) = + cog.reranker + .rerank(&args.query, rerank_candidates, Some(limit_usize)) + { reranked.into_iter().map(|rr| rr.item).collect() } else { // Reranker failed — fall back to original order for non-bypass candidates @@ -343,8 +350,8 @@ pub async fn execute( ); // Blend: 85% relevance + 15% temporal signal let temporal_factor = recency * validity; - result.combined_score = - result.combined_score * 0.85 + (result.combined_score * temporal_factor as f32) * 0.15; + result.combined_score = result.combined_score * 0.85 + + (result.combined_score * temporal_factor as f32) * 0.15; } } @@ -368,9 +375,21 @@ pub async fn execute( MemoryState::Unavailable }; - let adjusted = cog + let mut adjusted = cog .accessibility_calc .calculate(&lifecycle, result.combined_score as f64); + + // v2.0.5: Active forgetting penalty (Anderson 2025 SIF). + // Each prior suppress call compounds a retrieval-score penalty, + // saturating at 80%. Applied AFTER accessibility so the penalty + // stacks on top of any passive FSRS decay. + if result.node.suppression_count > 0 { + let sys = + vestige_core::neuroscience::active_forgetting::ActiveForgettingSystem::new(); + let penalty = sys.retrieval_penalty(result.node.suppression_count); + adjusted *= 1.0 - penalty; + } + result.combined_score = adjusted as f32; } } @@ -381,14 +400,16 @@ pub async fn execute( if let Some(ref topics) = args.context_topics && !topics.is_empty() { - let retrieval_ctx = EncodingContext::new() - .with_topical(TopicalContext::with_topics(topics.clone())); + let retrieval_ctx = + EncodingContext::new().with_topical(TopicalContext::with_topics(topics.clone())); if let Ok(cog) = cognitive.try_lock() { for result in &mut filtered_results { // Build encoding context from memory's tags let encoding_ctx = EncodingContext::new() .with_topical(TopicalContext::with_topics(result.node.tags.clone())); - let context_score = cog.context_matcher.match_contexts(&encoding_ctx, &retrieval_ctx); + let context_score = cog + .context_matcher + .match_contexts(&encoding_ctx, &retrieval_ctx); // Blend: context match boosts relevance up to +30% result.combined_score *= 1.0 + (context_score as f32 * 0.3); } @@ -403,7 +424,9 @@ pub async fn execute( } else { EncodingContext::new() }; - let reinstatement = cog.context_matcher.reinstate_context(&first.node.id, ¤t_ctx); + let reinstatement = cog + .context_matcher + .reinstate_context(&first.node.id, ¤t_ctx); Some(serde_json::json!({ "memoryId": reinstatement.memory_id, "temporalHint": reinstatement.temporal_hint, @@ -438,7 +461,10 @@ pub async fn execute( if let Some(result) = cog.competition_mgr.run_competition(&candidates, 0.7) { // Apply suppression: losers get penalized for suppressed_id in &result.suppressed_ids { - if let Some(r) = filtered_results.iter_mut().find(|r| &r.node.id == suppressed_id) { + if let Some(r) = filtered_results + .iter_mut() + .find(|r| &r.node.id == suppressed_id) + { r.combined_score *= 0.85; // 15% suppression penalty suppressed_count += 1; } @@ -503,7 +529,10 @@ pub async fn execute( // ==================================================================== // Auto-strengthen on access (Testing Effect) // ==================================================================== - let ids: Vec<&str> = filtered_results.iter().map(|r| r.node.id.as_str()).collect(); + let ids: Vec<&str> = filtered_results + .iter() + .map(|r| r.node.id.as_str()) + .collect(); let _ = storage.strengthen_batch_on_access(&ids); // Drop storage lock before acquiring cognitive for side effects @@ -525,9 +554,9 @@ pub async fn execute( cog.speculative_retriever.record_access( &result.node.id, - None, // file_context - Some(args.query.as_str()), // query_context - None, // was_helpful (unknown yet) + None, // file_context + Some(args.query.as_str()), // query_context + None, // was_helpful (unknown yet) ); // 7C. Mark labile for reconsolidation window (5 min) @@ -580,7 +609,11 @@ pub async fn execute( } // Check learning mode via attention signal - let learning_mode = cognitive.try_lock().ok().map(|cog| cog.attention_signal.is_learning_mode()).unwrap_or(false); + let learning_mode = cognitive + .try_lock() + .ok() + .map(|cog| cog.attention_signal.is_learning_mode()) + .unwrap_or(false); let mut response = serde_json::json!({ "query": args.query, @@ -593,7 +626,9 @@ pub async fn execute( // Helpful hint when no results found if formatted.is_empty() { - response["hint"] = serde_json::json!("No memories found. Use smart_ingest to add memories, or try a broader query."); + response["hint"] = serde_json::json!( + "No memories found. Use smart_ingest to add memories, or try a broader query." + ); } // Include associations if any were found @@ -1038,10 +1073,12 @@ mod tests { let schema_value = schema(); assert_eq!(schema_value["type"], "object"); assert!(schema_value["properties"]["query"].is_object()); - assert!(schema_value["required"] - .as_array() - .unwrap() - .contains(&serde_json::json!("query"))); + assert!( + schema_value["required"] + .as_array() + .unwrap() + .contains(&serde_json::json!("query")) + ); } #[test] @@ -1172,8 +1209,14 @@ mod tests { // Summary should have content AND timestamps (v2.1: dates always visible) assert!(first["content"].is_string()); assert!(first["id"].is_string()); - assert!(first["createdAt"].is_string(), "summary must include createdAt"); - assert!(first["updatedAt"].is_string(), "summary must include updatedAt"); + assert!( + first["createdAt"].is_string(), + "summary must include createdAt" + ); + assert!( + first["updatedAt"].is_string(), + "summary must include updatedAt" + ); } } @@ -1199,7 +1242,10 @@ mod tests { for i in 0..10 { ingest_test_content( &storage, - &format!("Budget test content number {} with some extra text to increase size.", i), + &format!( + "Budget test content number {} with some extra text to increase size.", + i + ), ) .await; } diff --git a/crates/vestige-mcp/src/tools/session_context.rs b/crates/vestige-mcp/src/tools/session_context.rs index f93d681..e7414eb 100644 --- a/crates/vestige-mcp/src/tools/session_context.rs +++ b/crates/vestige-mcp/src/tools/session_context.rs @@ -110,7 +110,9 @@ pub async fn execute( let include_status = args.include_status.unwrap_or(true); let include_intentions = args.include_intentions.unwrap_or(true); let include_predictions = args.include_predictions.unwrap_or(true); - let queries = args.queries.unwrap_or_else(|| vec!["user preferences".to_string()]); + let queries = args + .queries + .unwrap_or_else(|| vec!["user preferences".to_string()]); let mut context_parts: Vec = Vec::new(); let mut expandable_ids: Vec = Vec::new(); @@ -275,34 +277,33 @@ pub async fn execute( if include_predictions { let cog = cognitive.lock().await; - let session_ctx = vestige_core::neuroscience::predictive_retrieval::SessionContext { - started_at: Utc::now(), - current_focus: args - .context - .as_ref() - .and_then(|c| c.topics.as_ref()) - .and_then(|t| t.first()) - .cloned(), - active_files: args - .context - .as_ref() - .and_then(|c| c.file.as_ref()) - .map(|f| vec![f.clone()]) - .unwrap_or_default(), - accessed_memories: Vec::new(), - recent_queries: Vec::new(), - detected_intent: None, - project_context: args - .context - .as_ref() - .and_then(|c| c.codebase.as_ref()) - .map(|name| vestige_core::neuroscience::predictive_retrieval::ProjectContext { - name: name.to_string(), - path: String::new(), - technologies: Vec::new(), - primary_language: None, - }), - }; + let session_ctx = + vestige_core::neuroscience::predictive_retrieval::SessionContext { + started_at: Utc::now(), + current_focus: args + .context + .as_ref() + .and_then(|c| c.topics.as_ref()) + .and_then(|t| t.first()) + .cloned(), + active_files: args + .context + .as_ref() + .and_then(|c| c.file.as_ref()) + .map(|f| vec![f.clone()]) + .unwrap_or_default(), + accessed_memories: Vec::new(), + recent_queries: Vec::new(), + detected_intent: None, + project_context: args.context.as_ref().and_then(|c| c.codebase.as_ref()).map( + |name| vestige_core::neuroscience::predictive_retrieval::ProjectContext { + name: name.to_string(), + path: String::new(), + technologies: Vec::new(), + primary_language: None, + }, + ), + }; let predictions = cog .predictive_memory @@ -335,41 +336,45 @@ pub async fn execute( // 5. Codebase patterns/decisions (if codebase specified) // ==================================================================== if let Some(ref ctx) = args.context - && let Some(ref codebase) = ctx.codebase { - let codebase_tag = format!("codebase:{}", codebase); - let mut cb_lines: Vec = Vec::new(); + && let Some(ref codebase) = ctx.codebase + { + let codebase_tag = format!("codebase:{}", codebase); + let mut cb_lines: Vec = Vec::new(); - // Get patterns - if let Ok(patterns) = storage.get_nodes_by_type_and_tag("pattern", Some(&codebase_tag), 3) { - for p in &patterns { - let line = format!("- [pattern] {}", first_sentence(&p.content)); - let line_len = line.len() + 1; - if char_count + line_len <= budget_chars { - cb_lines.push(line); - char_count += line_len; - } + // Get patterns + if let Ok(patterns) = storage.get_nodes_by_type_and_tag("pattern", Some(&codebase_tag), 3) { + for p in &patterns { + let line = format!("- [pattern] {}", first_sentence(&p.content)); + let line_len = line.len() + 1; + if char_count + line_len <= budget_chars { + cb_lines.push(line); + char_count += line_len; } } - - // Get decisions - if let Ok(decisions) = - storage.get_nodes_by_type_and_tag("decision", Some(&codebase_tag), 3) - { - for d in &decisions { - let line = format!("- [decision] {}", first_sentence(&d.content)); - let line_len = line.len() + 1; - if char_count + line_len <= budget_chars { - cb_lines.push(line); - char_count += line_len; - } - } - } - - if !cb_lines.is_empty() { - context_parts.push(format!("**Codebase ({}):**\n{}", codebase, cb_lines.join("\n"))); - } } + // Get decisions + if let Ok(decisions) = storage.get_nodes_by_type_and_tag("decision", Some(&codebase_tag), 3) + { + for d in &decisions { + let line = format!("- [decision] {}", first_sentence(&d.content)); + let line_len = line.len() + 1; + if char_count + line_len <= budget_chars { + cb_lines.push(line); + char_count += line_len; + } + } + } + + if !cb_lines.is_empty() { + context_parts.push(format!( + "**Codebase ({}):**\n{}", + codebase, + cb_lines.join("\n") + )); + } + } + // ==================================================================== // 6. Assemble final response // ==================================================================== @@ -405,9 +410,10 @@ fn check_intention_triggered( match trigger.trigger_type.as_deref() { Some("time") => { if let Some(ref at) = trigger.at - && let Ok(trigger_time) = DateTime::parse_from_rfc3339(at) { - return trigger_time.with_timezone(&Utc) <= now; - } + && let Ok(trigger_time) = DateTime::parse_from_rfc3339(at) + { + return trigger_time.with_timezone(&Utc) <= now; + } if let Some(mins) = trigger.in_minutes { let trigger_time = intention.created_at + Duration::minutes(mins); return trigger_time <= now; @@ -420,22 +426,23 @@ fn check_intention_triggered( && current_cb .to_lowercase() .contains(&trigger_cb.to_lowercase()) - { - return true; - } + { + return true; + } // Check file pattern match if let (Some(pattern), Some(file)) = (&trigger.file_pattern, &ctx.file) - && file.contains(pattern.as_str()) { - return true; - } + && file.contains(pattern.as_str()) + { + return true; + } // Check topic match if let (Some(topic), Some(topics)) = (&trigger.topic, &ctx.topics) && topics .iter() .any(|t| t.to_lowercase().contains(&topic.to_lowercase())) - { - return true; - } + { + return true; + } false } _ => false, @@ -537,7 +544,12 @@ mod tests { #[tokio::test] async fn test_with_queries() { let (storage, _dir) = test_storage().await; - ingest_test_content(&storage, "Sam prefers Rust and TypeScript for all projects.", vec![]).await; + ingest_test_content( + &storage, + "Sam prefers Rust and TypeScript for all projects.", + vec![], + ) + .await; let args = serde_json::json!({ "queries": ["Sam preferences", "project context"] @@ -574,12 +586,16 @@ mod tests { assert!(result.is_ok()); let value = result.unwrap(); - let ctx = value["context"].as_str().unwrap(); + assert!(value["context"].is_string()); // Context should be within budget (200 tokens * 4 = 800 chars + header overhead) // The actual char count of context should be reasonable let tokens_used = value["tokensUsed"].as_u64().unwrap(); // Allow some overhead for the header - assert!(tokens_used <= 300, "tokens_used {} should be near budget 200", tokens_used); + assert!( + tokens_used <= 300, + "tokens_used {} should be near budget 200", + tokens_used + ); } #[tokio::test] @@ -649,7 +665,8 @@ mod tests { let (storage, _dir) = test_storage().await; // Ingest a pattern with codebase tag let input = IngestInput { - content: "Code pattern: Use Arc> for shared state in async contexts.".to_string(), + content: "Code pattern: Use Arc> for shared state in async contexts." + .to_string(), node_type: "pattern".to_string(), source: None, sentiment_score: 0.0, @@ -681,7 +698,10 @@ mod tests { #[test] fn test_first_sentence_period() { - assert_eq!(first_sentence("Hello world. More text here."), "Hello world."); + assert_eq!( + first_sentence("Hello world. More text here."), + "Hello world." + ); } #[test] diff --git a/crates/vestige-mcp/src/tools/smart_ingest.rs b/crates/vestige-mcp/src/tools/smart_ingest.rs index 900c99f..72dc3a6 100644 --- a/crates/vestige-mcp/src/tools/smart_ingest.rs +++ b/crates/vestige-mcp/src/tools/smart_ingest.rs @@ -22,7 +22,7 @@ use tokio::sync::Mutex; use crate::cognitive::CognitiveEngine; use vestige_core::{ - ContentType, ImportanceContext, ImportanceEventType, ImportanceEvent, IngestInput, Storage, + ContentType, ImportanceContext, ImportanceEvent, ImportanceEventType, IngestInput, Storage, }; /// Input schema for smart_ingest tool @@ -136,7 +136,9 @@ pub async fn execute( } // Single mode: content is required - let content = args.content.ok_or("Missing 'content' field. Provide 'content' for single mode or 'items' for batch mode.")?; + let content = args.content.ok_or( + "Missing 'content' field. Provide 'content' for single mode or 'items' for batch mode.", + )?; // Validate content if content.trim().is_empty() { @@ -156,7 +158,9 @@ pub async fn execute( if let Ok(cog) = cognitive.try_lock() { // 4A. Full 4-channel importance scoring let context = ImportanceContext::current(); - let importance = cog.importance_signals.compute_importance(&content, &context); + let importance = cog + .importance_signals + .compute_importance(&content, &context); importance_composite = importance.composite; // 4B. Intent detection → auto-tag @@ -201,7 +205,13 @@ pub async fn execute( let has_embedding = node.has_embedding.unwrap_or(false); // Post-ingest cognitive side effects - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); return Ok(serde_json::json!({ "success": true, @@ -225,7 +235,13 @@ pub async fn execute( let has_embedding = result.node.has_embedding.unwrap_or(false); // Post-ingest cognitive side effects - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); Ok(serde_json::json!({ "success": true, @@ -258,7 +274,13 @@ pub async fn execute( let node_content = node.content.clone(); let node_type = node.node_type.clone(); - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); Ok(serde_json::json!({ "success": true, @@ -331,7 +353,9 @@ async fn execute_batch( if let Ok(cog) = cognitive.try_lock() { let context = ImportanceContext::current(); - let importance = cog.importance_signals.compute_importance(&item.content, &context); + let importance = cog + .importance_signals + .compute_importance(&item.content, &context); importance_composite = importance.composite; let intent_result = cog.intent_detector.detect_intent(); @@ -373,7 +397,13 @@ async fn execute_batch( let node_type = node.node_type.clone(); created += 1; - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); results.push(serde_json::json!({ "index": i, @@ -411,7 +441,13 @@ async fn execute_batch( } // Post-ingest cognitive side effects - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); results.push(serde_json::json!({ "index": i, @@ -443,7 +479,13 @@ async fn execute_batch( let node_type = node.node_type.clone(); created += 1; - run_post_ingest(cognitive, &node_id, &node_content, &node_type, importance_composite); + run_post_ingest( + cognitive, + &node_id, + &node_content, + &node_type, + importance_composite, + ); results.push(serde_json::json!({ "index": i, @@ -514,7 +556,8 @@ fn run_post_ingest( ); // 4G. Cross-project pattern recording - cog.cross_project.record_project_memory(node_id, "default", None); + cog.cross_project + .record_project_memory(node_id, "default", None); } } @@ -576,8 +619,13 @@ mod tests { let value = result.unwrap(); assert_eq!(value["success"], true); assert_eq!(value["decision"], "create"); - assert!(value["reason"].as_str().unwrap().contains("Forced") || - value["reason"].as_str().unwrap().contains("Embeddings not available")); + assert!( + value["reason"].as_str().unwrap().contains("Forced") + || value["reason"] + .as_str() + .unwrap() + .contains("Embeddings not available") + ); } #[test] @@ -729,7 +777,12 @@ mod tests { #[tokio::test] async fn test_batch_empty_items_fails() { let (storage, _dir) = test_storage().await; - let result = execute(&storage, &test_cognitive(), Some(serde_json::json!({ "items": [] }))).await; + let result = execute( + &storage, + &test_cognitive(), + Some(serde_json::json!({ "items": [] })), + ) + .await; assert!(result.is_err()); assert!(result.unwrap_err().contains("empty")); } @@ -738,14 +791,16 @@ mod tests { async fn test_batch_ingest() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": "First batch item", "tags": ["test"] }, { "content": "Second batch item", "tags": ["test"] } ] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["mode"], "batch"); @@ -756,7 +811,8 @@ mod tests { async fn test_batch_skips_empty_content() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": "Valid item" }, @@ -764,7 +820,8 @@ mod tests { { "content": "Another valid item" } ] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["summary"]["skipped"], 1); @@ -784,7 +841,12 @@ mod tests { let items: Vec = (0..21) .map(|i| serde_json::json!({ "content": format!("Item {}", i) })) .collect(); - let result = execute(&storage, &test_cognitive(), Some(serde_json::json!({ "items": items }))).await; + let result = execute( + &storage, + &test_cognitive(), + Some(serde_json::json!({ "items": items })), + ) + .await; assert!(result.is_err()); assert!(result.unwrap_err().contains("Maximum 20 items")); } @@ -795,7 +857,12 @@ mod tests { let items: Vec = (0..20) .map(|i| serde_json::json!({ "content": format!("Item {}", i) })) .collect(); - let result = execute(&storage, &test_cognitive(), Some(serde_json::json!({ "items": items }))).await; + let result = execute( + &storage, + &test_cognitive(), + Some(serde_json::json!({ "items": items })), + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["summary"]["total"], 20); @@ -805,14 +872,16 @@ mod tests { async fn test_batch_skips_whitespace_only_content() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": " \t\n " }, { "content": "Valid content" } ] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["summary"]["skipped"], 1); @@ -823,11 +892,13 @@ mod tests { async fn test_batch_single_item_succeeds() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [{ "content": "Single item" }] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["summary"]["total"], 1); @@ -838,7 +909,8 @@ mod tests { async fn test_batch_items_with_all_fields() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [{ "content": "Full fields item", @@ -847,7 +919,8 @@ mod tests { "source": "test-suite" }] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["summary"]["created"], 1); @@ -857,7 +930,8 @@ mod tests { async fn test_batch_results_array_matches_items() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": "First" }, @@ -865,7 +939,8 @@ mod tests { { "content": "Third" } ] })), - ).await; + ) + .await; let value = result.unwrap(); let results = value["results"].as_array().unwrap(); assert_eq!(results.len(), 3); @@ -879,14 +954,16 @@ mod tests { async fn test_batch_success_true_when_only_skipped() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": "" }, { "content": " " } ] })), - ).await; + ) + .await; let value = result.unwrap(); assert_eq!(value["success"], true); // skipped ≠ errors assert_eq!(value["summary"]["errors"], 0); @@ -897,11 +974,13 @@ mod tests { async fn test_batch_has_importance_scores() { let (storage, _dir) = test_storage().await; let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [{ "content": "Important batch memory content" }] })), - ).await; + ) + .await; let value = result.unwrap(); let results = value["results"].as_array().unwrap(); assert!(results[0]["importanceScore"].is_number()); @@ -912,7 +991,8 @@ mod tests { let (storage, _dir) = test_storage().await; // Three items with very similar content + global forceCreate let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "forceCreate": true, "items": [ @@ -921,7 +1001,8 @@ mod tests { { "content": "Physics question about quantum mechanics and wave behavior" } ] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); assert_eq!(value["mode"], "batch"); @@ -941,7 +1022,8 @@ mod tests { let (storage, _dir) = test_storage().await; // Mix of forced and non-forced items let result = execute( - &storage, &test_cognitive(), + &storage, + &test_cognitive(), Some(serde_json::json!({ "items": [ { "content": "Forced item one", "forceCreate": true }, @@ -949,7 +1031,8 @@ mod tests { { "content": "Forced item three", "forceCreate": true } ] })), - ).await; + ) + .await; assert!(result.is_ok()); let value = result.unwrap(); let results = value["results"].as_array().unwrap(); diff --git a/crates/vestige-mcp/src/tools/stats.rs b/crates/vestige-mcp/src/tools/stats.rs index aaf37fd..f9f31aa 100644 --- a/crates/vestige-mcp/src/tools/stats.rs +++ b/crates/vestige-mcp/src/tools/stats.rs @@ -57,15 +57,23 @@ pub async fn execute_health(storage: &Arc) -> Result { let mut warnings = Vec::new(); if stats.average_retention < 0.5 && stats.total_nodes > 0 { - warnings.push("Low average retention - consider running consolidation or reviewing memories".to_string()); + warnings.push( + "Low average retention - consider running consolidation or reviewing memories" + .to_string(), + ); } if stats.nodes_due_for_review > 10 { - warnings.push(format!("{} memories are due for review", stats.nodes_due_for_review)); + warnings.push(format!( + "{} memories are due for review", + stats.nodes_due_for_review + )); } if stats.total_nodes > 0 && stats.nodes_with_embeddings == 0 { - warnings.push("No embeddings generated - semantic search unavailable. Run consolidation.".to_string()); + warnings.push( + "No embeddings generated - semantic search unavailable. Run consolidation.".to_string(), + ); } let embedding_coverage = if stats.total_nodes > 0 { @@ -75,7 +83,10 @@ pub async fn execute_health(storage: &Arc) -> Result { }; if embedding_coverage < 50.0 && stats.total_nodes > 10 { - warnings.push(format!("Only {:.1}% of memories have embeddings", embedding_coverage)); + warnings.push(format!( + "Only {:.1}% of memories have embeddings", + embedding_coverage + )); } Ok(serde_json::json!({ @@ -90,10 +101,7 @@ pub async fn execute_health(storage: &Arc) -> Result { })) } -fn get_recommendations( - stats: &MemoryStats, - status: &str, -) -> Vec { +fn get_recommendations(stats: &MemoryStats, status: &str) -> Vec { let mut recommendations = Vec::new(); if status == "critical" { @@ -105,11 +113,15 @@ fn get_recommendations( } if stats.nodes_with_embeddings < stats.total_nodes { - recommendations.push("Run 'run_consolidation' to generate embeddings for better semantic search.".to_string()); + recommendations.push( + "Run 'run_consolidation' to generate embeddings for better semantic search." + .to_string(), + ); } if stats.total_nodes > 100 && stats.average_retention < 0.7 { - recommendations.push("Consider running periodic consolidation to maintain memory health.".to_string()); + recommendations + .push("Consider running periodic consolidation to maintain memory health.".to_string()); } if recommendations.is_empty() { diff --git a/crates/vestige-mcp/src/tools/suppress.rs b/crates/vestige-mcp/src/tools/suppress.rs new file mode 100644 index 0000000..f06debc --- /dev/null +++ b/crates/vestige-mcp/src/tools/suppress.rs @@ -0,0 +1,313 @@ +//! `suppress` MCP Tool (v2.0.5) — Top-Down Active Forgetting +//! +//! Actively suppress a memory via top-down inhibitory control. Distinct from +//! `memory.delete` (which removes the row) and `memory.demote` (which is a +//! one-shot thumb-down). Each call compounds: suppression_count increments, +//! FSRS state is dealt a strong blow, and a background Rac1 cascade worker +//! (in the existing consolidation loop) will fade co-activated neighbors. +//! +//! Reversible within a 24-hour labile window via `reverse: true`. +//! +//! References: +//! - Anderson et al. (2025). Brain mechanisms underlying the inhibitory +//! control of thought. Nat Rev Neurosci. DOI 10.1038/s41583-025-00929-y +//! - Cervantes-Sandoval & Davis (2020). Rac1 Impairs Forgetting-Induced +//! Cellular Plasticity. Front Cell Neurosci. PMC7477079 + +use serde::{Deserialize, Serialize}; +use serde_json::{Value, json}; +use std::sync::Arc; + +use vestige_core::Storage; +use vestige_core::neuroscience::active_forgetting::{ActiveForgettingSystem, DEFAULT_LABILE_HOURS}; + +/// Input schema for the `suppress` tool. +pub fn schema() -> Value { + json!({ + "type": "object", + "description": "Actively suppress a memory via top-down inhibitory control (Anderson 2025 SIF + Davis Rac1). Distinct from delete: the memory persists but is inhibited from retrieval and actively decays. Each call compounds suppression strength. A background Rac1 worker cascades accelerated decay to co-activated neighbors over the next 72 hours. Reversible within 24 hours via reverse=true.", + "properties": { + "id": { + "type": "string", + "description": "Memory UUID to suppress (or reverse-suppress)" + }, + "reason": { + "type": "string", + "description": "Optional free-form note explaining why this memory is being suppressed. Logged for audit." + }, + "reverse": { + "type": "boolean", + "default": false, + "description": "If true, reverse a previous suppression. Only works within the 24-hour labile window." + } + }, + "required": ["id"] + }) +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +struct SuppressArgs { + id: String, + #[serde(default)] + reason: Option, + #[serde(default)] + reverse: bool, +} + +pub async fn execute(storage: &Arc, args: Option) -> Result { + let args: SuppressArgs = match args { + Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, + None => return Err("Missing arguments".to_string()), + }; + + if args.id.trim().is_empty() { + return Err("'id' must not be empty".to_string()); + } + // Basic UUID sanity check — don't reject if missing, but warn + if uuid::Uuid::parse_str(&args.id).is_err() { + return Err(format!("Invalid memory ID format: {}", args.id)); + } + + let sys = ActiveForgettingSystem::new(); + + if args.reverse { + // Reverse path — only allowed within labile window. + match storage.reverse_suppression(&args.id, sys.labile_hours) { + Ok(node) => { + let still_suppressed = node.suppression_count > 0; + Ok(json!({ + "success": true, + "action": "reverse", + "id": args.id, + "suppressionCount": node.suppression_count, + "stillSuppressed": still_suppressed, + "retentionStrength": node.retention_strength, + "retrievalStrength": node.retrieval_strength, + "stability": node.stability, + "message": if still_suppressed { + format!( + "Reversal applied. {} suppression(s) remain on this memory.", + node.suppression_count + ) + } else { + "Suppression fully reversed. Memory is no longer inhibited.".to_string() + }, + })) + } + Err(e) => Err(format!("Reverse failed: {}", e)), + } + } else { + // Forward path — suppress + log reason + tell the user what will happen. + let before_count = storage + .get_node(&args.id) + .map_err(|e| format!("Failed to load memory: {}", e))? + .map(|n| n.suppression_count) + .unwrap_or(0); + + let node = storage + .suppress_memory(&args.id) + .map_err(|e| format!("Suppress failed: {}", e))?; + + // Count how many neighbors will be cascaded over the coming 72h. + // We don't run the cascade synchronously — it happens in the + // background consolidation loop via `run_rac1_cascade_sweep`. But we + // can give the user an estimate. + let edges = storage + .get_connections_for_memory(&args.id) + .unwrap_or_default(); + let estimated_cascade = edges.len().min(100); + + let reversible_until = node + .suppressed_at + .map(|t| sys.reversible_until(t)) + .unwrap_or_else(chrono::Utc::now); + let retrieval_penalty = sys.retrieval_penalty(node.suppression_count); + + tracing::info!( + id = %args.id, + count = node.suppression_count, + reason = args.reason.as_deref().unwrap_or(""), + "Memory suppressed" + ); + + Ok(json!({ + "success": true, + "action": "suppress", + "id": args.id, + "suppressionCount": node.suppression_count, + "priorCount": before_count, + "retrievalPenalty": retrieval_penalty, + "retentionStrength": node.retention_strength, + "retrievalStrength": node.retrieval_strength, + "stability": node.stability, + "estimatedCascadeNeighbors": estimated_cascade, + "reversibleUntil": reversible_until.to_rfc3339(), + "labileWindowHours": DEFAULT_LABILE_HOURS, + "reason": args.reason, + "message": format!( + "Actively forgetting. Suppression #{} applied. ~{} co-activated neighbors will fade over the next 72h via Rac1 cascade. Reversible for {}h.", + node.suppression_count, estimated_cascade, DEFAULT_LABILE_HOURS + ), + "citation": "Anderson et al. 2025, Nat Rev Neurosci, DOI: 10.1038/s41583-025-00929-y" + })) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + use vestige_core::IngestInput; + + fn test_storage() -> (Arc, TempDir) { + let dir = TempDir::new().unwrap(); + let storage = Storage::new(Some(dir.path().join("test.db"))).unwrap(); + (Arc::new(storage), dir) + } + + fn ingest(storage: &Storage, content: &str) -> String { + storage + .ingest(IngestInput { + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap() + .id + } + + #[test] + fn test_schema_is_valid() { + let s = schema(); + assert_eq!(s["type"], "object"); + assert!(s["properties"]["id"].is_object()); + assert!(s["properties"]["reverse"].is_object()); + assert_eq!(s["required"][0], "id"); + } + + #[tokio::test] + async fn test_suppress_missing_args() { + let (storage, _dir) = test_storage(); + let result = execute(&storage, None).await; + assert!(result.is_err()); + assert!(result.unwrap_err().contains("Missing arguments")); + } + + #[tokio::test] + async fn test_suppress_invalid_uuid() { + let (storage, _dir) = test_storage(); + let args = json!({"id": "not-a-uuid"}); + let result = execute(&storage, Some(args)).await; + assert!(result.is_err()); + assert!(result.unwrap_err().contains("Invalid memory ID")); + } + + #[tokio::test] + async fn test_suppress_increments_count() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Jake is my roommate"); + + // First call + let r1 = execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + assert_eq!(r1["suppressionCount"], 1); + assert_eq!(r1["priorCount"], 0); + + // Second call — compounds + let r2 = execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + assert_eq!(r2["suppressionCount"], 2); + assert_eq!(r2["priorCount"], 1); + } + + #[tokio::test] + async fn test_suppress_applies_fsrs_penalty() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Jake"); + + let before = storage.get_node(&id).unwrap().unwrap(); + let result = execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + + // Stability should be heavily reduced + let after_stability = result["stability"].as_f64().unwrap(); + assert!(after_stability < before.stability); + // Retention should be reduced + let after_retention = result["retentionStrength"].as_f64().unwrap(); + assert!(after_retention < before.retention_strength); + } + + #[tokio::test] + async fn test_suppress_is_not_delete() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Jake"); + + execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + + // Memory must still be retrievable via get_node + let node = storage.get_node(&id).unwrap(); + assert!(node.is_some(), "Suppressed memory must still exist"); + assert_eq!(node.unwrap().suppression_count, 1); + } + + #[tokio::test] + async fn test_reverse_within_window_decrements() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Jake"); + + execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + + // Now reverse — count should drop from 2 to 1 + let r = execute(&storage, Some(json!({"id": id.clone(), "reverse": true}))) + .await + .unwrap(); + assert_eq!(r["suppressionCount"], 1); + assert_eq!(r["stillSuppressed"], true); + + // Reverse again — should go to 0 + let r = execute(&storage, Some(json!({"id": id.clone(), "reverse": true}))) + .await + .unwrap(); + assert_eq!(r["suppressionCount"], 0); + assert_eq!(r["stillSuppressed"], false); + } + + #[tokio::test] + async fn test_reverse_without_prior_suppression_fails() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Fresh memory"); + + let result = execute(&storage, Some(json!({"id": id.clone(), "reverse": true}))).await; + assert!(result.is_err()); + assert!(result.unwrap_err().contains("no active suppression")); + } + + #[tokio::test] + async fn test_suppress_records_timestamp() { + let (storage, _dir) = test_storage(); + let id = ingest(&storage, "Jake"); + + execute(&storage, Some(json!({"id": id.clone()}))) + .await + .unwrap(); + + let node = storage.get_node(&id).unwrap().unwrap(); + assert!(node.suppressed_at.is_some(), "suppressed_at must be set"); + } +} diff --git a/crates/vestige-mcp/src/tools/tagging.rs b/crates/vestige-mcp/src/tools/tagging.rs index e69c020..fd38888 100644 --- a/crates/vestige-mcp/src/tools/tagging.rs +++ b/crates/vestige-mcp/src/tools/tagging.rs @@ -7,8 +7,8 @@ use serde_json::Value; use std::sync::Arc; use vestige_core::{ - CaptureWindow, ImportanceEvent, ImportanceEventType, - SynapticTaggingConfig, SynapticTaggingSystem, Storage, + CaptureWindow, ImportanceEvent, ImportanceEventType, Storage, SynapticTaggingConfig, + SynapticTaggingSystem, }; /// Input schema for trigger_importance tool @@ -69,27 +69,22 @@ pub fn stats_schema() -> Value { } /// Trigger an importance event to retroactively strengthen recent memories -pub async fn execute_trigger( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_trigger(storage: &Arc, args: Option) -> Result { let args = args.ok_or("Missing arguments")?; let event_type_str = args["event_type"] .as_str() .ok_or("event_type is required")?; - let memory_id = args["memory_id"] - .as_str() - .ok_or("memory_id is required")?; + let memory_id = args["memory_id"].as_str().ok_or("memory_id is required")?; let description = args["description"].as_str(); let hours_back = args["hours_back"].as_f64().unwrap_or(9.0); let hours_forward = args["hours_forward"].as_f64().unwrap_or(2.0); - // Verify the trigger memory exists - let trigger_memory = storage.get_node(memory_id) + let trigger_memory = storage + .get_node(memory_id) .map_err(|e| format!("Error: {}", e))? .ok_or("Memory not found")?; @@ -121,8 +116,7 @@ pub async fn execute_trigger( let mut stc = SynapticTaggingSystem::with_config(config); // Get recent memories to tag - let recent = storage.get_all_nodes(100, 0) - .map_err(|e| e.to_string())?; + let recent = storage.get_all_nodes(100, 0).map_err(|e| e.to_string())?; // Tag all recent memories for mem in &recent { @@ -155,32 +149,30 @@ pub async fn execute_trigger( } /// Find memories with active synaptic tags -pub async fn execute_find( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute_find(storage: &Arc, args: Option) -> Result { let args = args.unwrap_or(serde_json::json!({})); let min_strength = args["min_strength"].as_f64().unwrap_or(0.3); let limit = args["limit"].as_i64().unwrap_or(20) as usize; - // Get memories with high retention (proxy for "tagged") - let memories = storage.get_all_nodes(200, 0) - .map_err(|e| e.to_string())?; + let memories = storage.get_all_nodes(200, 0).map_err(|e| e.to_string())?; // Filter by retention strength (tagged memories have higher retention) - let tagged: Vec = memories.into_iter() + let tagged: Vec = memories + .into_iter() .filter(|m| m.retention_strength >= min_strength) .take(limit) - .map(|m| serde_json::json!({ - "id": m.id, - "content": m.content, - "retentionStrength": m.retention_strength, - "storageStrength": m.storage_strength, - "lastAccessed": m.last_accessed.to_rfc3339(), - "tags": m.tags - })) + .map(|m| { + serde_json::json!({ + "id": m.id, + "content": m.content, + "retentionStrength": m.retention_strength, + "storageStrength": m.storage_strength, + "lastAccessed": m.last_accessed.to_rfc3339(), + "tags": m.tags + }) + }) .collect(); Ok(serde_json::json!({ @@ -192,17 +184,22 @@ pub async fn execute_find( } /// Get synaptic tagging statistics -pub async fn execute_stats( - storage: &Arc, -) -> Result { - - let memories = storage.get_all_nodes(500, 0) - .map_err(|e| e.to_string())?; +pub async fn execute_stats(storage: &Arc) -> Result { + let memories = storage.get_all_nodes(500, 0).map_err(|e| e.to_string())?; let total = memories.len(); - let high_retention = memories.iter().filter(|m| m.retention_strength >= 0.7).count(); - let medium_retention = memories.iter().filter(|m| m.retention_strength >= 0.4 && m.retention_strength < 0.7).count(); - let low_retention = memories.iter().filter(|m| m.retention_strength < 0.4).count(); + let high_retention = memories + .iter() + .filter(|m| m.retention_strength >= 0.7) + .count(); + let medium_retention = memories + .iter() + .filter(|m| m.retention_strength >= 0.4 && m.retention_strength < 0.7) + .count(); + let low_retention = memories + .iter() + .filter(|m| m.retention_strength < 0.4) + .count(); let avg_retention = if total > 0 { memories.iter().map(|m| m.retention_strength).sum::() / total as f64 diff --git a/crates/vestige-mcp/src/tools/timeline.rs b/crates/vestige-mcp/src/tools/timeline.rs index c049b91..d52588d 100644 --- a/crates/vestige-mcp/src/tools/timeline.rs +++ b/crates/vestige-mcp/src/tools/timeline.rs @@ -9,7 +9,6 @@ use serde_json::Value; use std::collections::BTreeMap; use std::sync::Arc; - use vestige_core::Storage; use super::search_unified::format_node; @@ -88,10 +87,7 @@ fn parse_datetime(s: &str) -> Result, String> { } /// Execute memory_timeline tool -pub async fn execute( - storage: &Arc, - args: Option, -) -> Result { +pub async fn execute(storage: &Arc, args: Option) -> Result { let args: TimelineArgs = match args { Some(v) => serde_json::from_value(v).map_err(|e| format!("Invalid arguments: {}", e))?, None => TimelineArgs { @@ -130,7 +126,6 @@ pub async fn execute( let limit = args.limit.unwrap_or(50).clamp(1, 200); - // Query memories in time range let mut results = storage .query_time_range(start, end, limit) @@ -195,17 +190,18 @@ mod tests { } async fn ingest_test_memory(storage: &Arc, content: &str) { - storage.ingest(vestige_core::IngestInput { - content: content.to_string(), - node_type: "fact".to_string(), - source: None, - sentiment_score: 0.0, - sentiment_magnitude: 0.0, - tags: vec!["timeline-test".to_string()], - valid_from: None, - valid_until: None, - }) - .unwrap(); + storage + .ingest(vestige_core::IngestInput { + content: content.to_string(), + node_type: "fact".to_string(), + source: None, + sentiment_score: 0.0, + sentiment_magnitude: 0.0, + tags: vec!["timeline-test".to_string()], + valid_from: None, + valid_until: None, + }) + .unwrap(); } #[test] diff --git a/packages/vestige-init/package.json b/packages/vestige-init/package.json index a7a8cee..27e3147 100644 --- a/packages/vestige-init/package.json +++ b/packages/vestige-init/package.json @@ -1,6 +1,6 @@ { "name": "@vestige/init", - "version": "2.0.1", + "version": "2.0.5", "description": "Give your AI a brain in 10 seconds — zero-config Vestige v2.0 installer with 3D dashboard", "bin": { "vestige-init": "bin/init.js" diff --git a/packages/vestige-mcp-npm/.gitignore b/packages/vestige-mcp-npm/.gitignore index 7c5d56c..d5d2535 100644 --- a/packages/vestige-mcp-npm/.gitignore +++ b/packages/vestige-mcp-npm/.gitignore @@ -3,5 +3,7 @@ bin/vestige bin/vestige.exe bin/vestige-mcp bin/vestige-mcp.exe +bin/vestige-restore +bin/vestige-restore.exe bin/*.tar.gz bin/*.zip diff --git a/packages/vestige-mcp-npm/package.json b/packages/vestige-mcp-npm/package.json index e50754d..1ee2332 100644 --- a/packages/vestige-mcp-npm/package.json +++ b/packages/vestige-mcp-npm/package.json @@ -1,6 +1,6 @@ { "name": "vestige-mcp-server", - "version": "2.0.1", + "version": "2.0.5", "description": "Vestige MCP Server — Cognitive memory for AI with FSRS-6, 3D dashboard, and 29 brain modules", "bin": { "vestige-mcp": "bin/vestige-mcp.js", diff --git a/tests/e2e/src/assertions/mod.rs b/tests/e2e/src/assertions/mod.rs index cf8d1ae..0de53e4 100644 --- a/tests/e2e/src/assertions/mod.rs +++ b/tests/e2e/src/assertions/mod.rs @@ -271,16 +271,11 @@ macro_rules! assert_search_count { #[macro_export] macro_rules! assert_search_order { ($results:expr, $expected_first:expr) => { - assert!( - !$results.is_empty(), - "Expected non-empty search results" - ); + assert!(!$results.is_empty(), "Expected non-empty search results"); assert_eq!( - $results[0].id, - $expected_first, + $results[0].id, $expected_first, "Expected first result to be {}, got {}", - $expected_first, - $results[0].id + $expected_first, $results[0].id ); }; } diff --git a/tests/e2e/src/harness/db_manager.rs b/tests/e2e/src/harness/db_manager.rs index f5ce71c..345a94c 100644 --- a/tests/e2e/src/harness/db_manager.rs +++ b/tests/e2e/src/harness/db_manager.rs @@ -6,9 +6,9 @@ //! - Database snapshots and restoration //! - Concurrent test isolation -use vestige_core::{KnowledgeNode, Rating, Storage}; use std::path::PathBuf; use tempfile::TempDir; +use vestige_core::{KnowledgeNode, Rating, Storage}; /// Helper to create IngestInput (works around non_exhaustive) #[allow(clippy::too_many_arguments)] @@ -107,10 +107,7 @@ impl TestDatabaseManager { /// Get the number of nodes in the database pub fn node_count(&self) -> i64 { - self.storage - .get_stats() - .map(|s| s.total_nodes) - .unwrap_or(0) + self.storage.get_stats().map(|s| s.total_nodes).unwrap_or(0) } // ======================================================================== @@ -257,10 +254,7 @@ impl TestDatabaseManager { /// Take a snapshot of current database state pub fn take_snapshot(&mut self) { - let nodes = self - .storage - .get_all_nodes(10000, 0) - .unwrap_or_default(); + let nodes = self.storage.get_all_nodes(10000, 0).unwrap_or_default(); self.snapshot = Some(nodes); } @@ -322,8 +316,8 @@ impl TestDatabaseManager { let _ = std::fs::remove_file(&self.db_path); // Recreate storage - self.storage = Storage::new(Some(self.db_path.clone())) - .expect("Failed to recreate storage"); + self.storage = + Storage::new(Some(self.db_path.clone())).expect("Failed to recreate storage"); } } diff --git a/tests/e2e/src/mocks/fixtures.rs b/tests/e2e/src/mocks/fixtures.rs index 05d2a22..6929e56 100644 --- a/tests/e2e/src/mocks/fixtures.rs +++ b/tests/e2e/src/mocks/fixtures.rs @@ -183,7 +183,13 @@ impl TestDataFactory { /// Create a batch of memories pub fn create_batch(storage: &mut Storage, count: usize) -> Vec { - Self::create_batch_with_config(storage, BatchConfig { count, ..Default::default() }) + Self::create_batch_with_config( + storage, + BatchConfig { + count, + ..Default::default() + }, + ) } /// Create a batch with custom configuration @@ -212,9 +218,15 @@ impl TestDataFactory { let (valid_from, valid_until) = if config.with_temporal { let now = Utc::now(); if i % 3 == 0 { - (Some(now - Duration::days(30)), Some(now + Duration::days(30))) + ( + Some(now - Duration::days(30)), + Some(now + Duration::days(30)), + ) } else if i % 3 == 1 { - (Some(now - Duration::days(60)), Some(now - Duration::days(30))) + ( + Some(now - Duration::days(60)), + Some(now - Duration::days(30)), + ) } else { (None, None) } @@ -273,12 +285,7 @@ impl TestDataFactory { } // Emotional memory (decay should be affected by sentiment) - let emotional = Self::create_emotional_memory( - storage, - "Important life event", - 0.9, - 0.95, - ); + let emotional = Self::create_emotional_memory(storage, "Important life event", 0.9, 0.95); if let Some(node) = emotional { metadata.insert("emotional".to_string(), node.id.clone()); ids.push(node.id); @@ -445,12 +452,8 @@ impl TestDataFactory { } // No bounds (always valid) - if let Some(node) = Self::create_temporal_memory( - storage, - "Always valid memory", - None, - None, - ) { + if let Some(node) = Self::create_temporal_memory(storage, "Always valid memory", None, None) + { metadata.insert("always_valid".to_string(), node.id.clone()); ids.push(node.id); } @@ -469,8 +472,15 @@ impl TestDataFactory { /// Get a random node type pub fn random_node_type(seed: usize) -> &'static str { const TYPES: [&str; 9] = [ - "fact", "concept", "procedure", "event", "relationship", - "quote", "code", "question", "insight", + "fact", + "concept", + "procedure", + "event", + "relationship", + "quote", + "code", + "question", + "insight", ]; TYPES[seed % TYPES.len()] } @@ -478,10 +488,26 @@ impl TestDataFactory { /// Generate lorem ipsum-like content pub fn lorem_content(words: usize, seed: usize) -> String { const WORDS: [&str; 20] = [ - "the", "memory", "learning", "knowledge", "algorithm", - "data", "system", "process", "function", "method", - "class", "object", "variable", "constant", "type", - "structure", "pattern", "design", "architecture", "code", + "the", + "memory", + "learning", + "knowledge", + "algorithm", + "data", + "system", + "process", + "function", + "method", + "class", + "object", + "variable", + "constant", + "type", + "structure", + "pattern", + "design", + "architecture", + "code", ]; (0..words) @@ -493,8 +519,16 @@ impl TestDataFactory { /// Generate tags pub fn generate_tags(count: usize, seed: usize) -> Vec { const TAGS: [&str; 10] = [ - "important", "review", "todo", "concept", "fact", - "code", "note", "idea", "question", "reference", + "important", + "review", + "todo", + "concept", + "fact", + "code", + "note", + "idea", + "question", + "reference", ]; (0..count) diff --git a/tests/e2e/src/mocks/mock_embedding.rs b/tests/e2e/src/mocks/mock_embedding.rs index 93f0363..02957f5 100644 --- a/tests/e2e/src/mocks/mock_embedding.rs +++ b/tests/e2e/src/mocks/mock_embedding.rs @@ -145,7 +145,11 @@ impl MockEmbeddingService { // Map word to a sparse set of dimensions for i in 0..16 { let dim = ((word_hash >> (i * 4)) as usize) % MOCK_EMBEDDING_DIM; - let sign = if (word_hash >> (i + 48)) & 1 == 0 { 1.0 } else { -1.0 }; + let sign = if (word_hash >> (i + 48)) & 1 == 0 { + 1.0 + } else { + -1.0 + }; let magnitude = ((word_hash >> (i * 2)) as f32 % 100.0) / 100.0 + 0.5; embedding[dim] += sign * magnitude; } @@ -342,9 +346,15 @@ mod tests { let query = service.embed("programming code"); let candidates = vec![ - ("doc1".to_string(), service.embed("python programming language")), + ( + "doc1".to_string(), + service.embed("python programming language"), + ), ("doc2".to_string(), service.embed("cooking recipes")), - ("doc3".to_string(), service.embed("software development code")), + ( + "doc3".to_string(), + service.embed("software development code"), + ), ]; let result = service.find_most_similar(&query, &candidates); diff --git a/tests/e2e/tests/cognitive/comparative_benchmarks.rs b/tests/e2e/tests/cognitive/comparative_benchmarks.rs index 957feb1..bac2582 100644 --- a/tests/e2e/tests/cognitive/comparative_benchmarks.rs +++ b/tests/e2e/tests/cognitive/comparative_benchmarks.rs @@ -17,12 +17,12 @@ use chrono::{DateTime, Duration, Utc}; use std::collections::{HashMap, HashSet}; -use vestige_core::neuroscience::spreading_activation::{ - ActivatedMemory, ActivationConfig, ActivationNetwork, LinkType, -}; use vestige_core::neuroscience::hippocampal_index::{ BarcodeGenerator, ContentPointer, ContentType, HippocampalIndex, HippocampalIndexConfig, - IndexQuery, MemoryBarcode, MemoryIndex, INDEX_EMBEDDING_DIM, + INDEX_EMBEDDING_DIM, IndexQuery, MemoryBarcode, MemoryIndex, +}; +use vestige_core::neuroscience::spreading_activation::{ + ActivatedMemory, ActivationConfig, ActivationNetwork, LinkType, }; use vestige_core::neuroscience::synaptic_tagging::{ CaptureWindow, DecayFunction, ImportanceEvent, ImportanceEventType, SynapticTaggingConfig, @@ -36,9 +36,9 @@ use vestige_core::neuroscience::synaptic_tagging::{ /// SM-2 state for a card #[derive(Debug, Clone)] struct SM2State { - easiness_factor: f64, // EF, starts at 2.5 - interval: i32, // Days until next review - repetitions: i32, // Number of successful reviews + easiness_factor: f64, // EF, starts at 2.5 + interval: i32, // Days until next review + repetitions: i32, // Number of successful reviews } impl Default for SM2State { @@ -73,8 +73,9 @@ fn sm2_review(state: &SM2State, grade: SM2Grade) -> SM2State { let q = grade.as_i32(); // Update easiness factor - let mut new_ef = state.easiness_factor + (0.1 - (5 - q) as f64 * (0.08 + (5 - q) as f64 * 0.02)); - new_ef = new_ef.max(1.3); // EF never goes below 1.3 + let mut new_ef = + state.easiness_factor + (0.1 - (5 - q) as f64 * (0.08 + (5 - q) as f64 * 0.02)); + new_ef = new_ef.max(1.3); // EF never goes below 1.3 if q < 3 { // Failed - restart learning @@ -117,9 +118,8 @@ fn sm2_retention(interval: i32, elapsed_days: i32) -> f64 { /// FSRS-6 default weights const FSRS6_WEIGHTS: [f64; 21] = [ - 0.212, 1.2931, 2.3065, 8.2956, 6.4133, 0.8334, 3.0194, 0.001, - 1.8722, 0.1666, 0.796, 1.4835, 0.0614, 0.2629, 1.6483, 0.6014, - 1.8729, 0.5425, 0.0912, 0.0658, 0.1542, + 0.212, 1.2931, 2.3065, 8.2956, 6.4133, 0.8334, 3.0194, 0.001, 1.8722, 0.1666, 0.796, 1.4835, + 0.0614, 0.2629, 1.6483, 0.6014, 1.8729, 0.5425, 0.0912, 0.0658, 0.1542, ]; /// FSRS-6 state @@ -160,7 +160,9 @@ fn fsrs6_retrievability(stability: f64, elapsed_days: f64, w20: f64) -> f64 { return 1.0; } let factor = fsrs6_factor(w20); - (1.0 + factor * elapsed_days / stability).powf(-w20).clamp(0.0, 1.0) + (1.0 + factor * elapsed_days / stability) + .powf(-w20) + .clamp(0.0, 1.0) } /// FSRS-6 interval calculation @@ -183,24 +185,32 @@ fn fsrs6_review(state: &FSRS6State, grade: FSRS6Grade, elapsed_days: f64) -> FSR let new_stability = match grade { FSRS6Grade::Again => { // Lapse formula - w[11] * state.difficulty.powf(-w[12]) + w[11] + * state.difficulty.powf(-w[12]) * ((state.stability + 1.0).powf(w[13]) - 1.0) * (w[14] * (1.0 - r)).exp() } _ => { // Recall formula - let hard_penalty = if matches!(grade, FSRS6Grade::Hard) { w[15] } else { 1.0 }; - let easy_bonus = if matches!(grade, FSRS6Grade::Easy) { w[16] } else { 1.0 }; + let hard_penalty = if matches!(grade, FSRS6Grade::Hard) { + w[15] + } else { + 1.0 + }; + let easy_bonus = if matches!(grade, FSRS6Grade::Easy) { + w[16] + } else { + 1.0 + }; - state.stability * ( - w[8].exp() - * (11.0 - state.difficulty) - * state.stability.powf(-w[9]) - * ((w[10] * (1.0 - r)).exp() - 1.0) - * hard_penalty - * easy_bonus - + 1.0 - ) + state.stability + * (w[8].exp() + * (11.0 - state.difficulty) + * state.stability.powf(-w[9]) + * ((w[10] * (1.0 - r)).exp() - 1.0) + * hard_penalty + * easy_bonus + + 1.0) } }; @@ -209,8 +219,8 @@ fn fsrs6_review(state: &FSRS6State, grade: FSRS6Grade, elapsed_days: f64) -> FSR let delta = -w[6] * (g - 3.0); let mean_reversion = (10.0 - state.difficulty) / 9.0; let d0 = w[4] - (w[5] * 2.0).exp() + 1.0; - let new_difficulty = (w[7] * d0 + (1.0 - w[7]) * (state.difficulty + delta * mean_reversion)) - .clamp(1.0, 10.0); + let new_difficulty = + (w[7] * d0 + (1.0 - w[7]) * (state.difficulty + delta * mean_reversion)).clamp(1.0, 10.0); FSRS6State { difficulty: new_difficulty, @@ -226,7 +236,7 @@ fn fsrs6_review(state: &FSRS6State, grade: FSRS6Grade, elapsed_days: f64) -> FSR /// Leitner box state #[derive(Debug, Clone)] struct LeitnerState { - box_number: i32, // 1-5 + box_number: i32, // 1-5 } impl Default for LeitnerState { @@ -288,7 +298,9 @@ impl SimilaritySearch { } fn search(&self, query_embedding: &[f32], top_k: usize) -> Vec<(String, f64)> { - let mut results: Vec<(String, f64)> = self.embeddings.iter() + let mut results: Vec<(String, f64)> = self + .embeddings + .iter() .map(|(id, emb)| { let sim = cosine_similarity(query_embedding, emb); (id.clone(), sim) @@ -331,9 +343,8 @@ fn test_fsrs6_vs_sm2_efficiency() { // Simulate SM-2 let mut sm2_reviews = 0; - let mut sm2_states: Vec<(SM2State, i32)> = (0..NUM_CARDS) - .map(|_| (SM2State::default(), 0)) - .collect(); + let mut sm2_states: Vec<(SM2State, i32)> = + (0..NUM_CARDS).map(|_| (SM2State::default(), 0)).collect(); for day in 1..=DAYS { for (state, next_review) in sm2_states.iter_mut() { @@ -349,9 +360,8 @@ fn test_fsrs6_vs_sm2_efficiency() { // Simulate FSRS-6 let mut fsrs_reviews = 0; - let mut fsrs_states: Vec<(FSRS6State, i32)> = (0..NUM_CARDS) - .map(|_| (FSRS6State::default(), 0)) - .collect(); + let mut fsrs_states: Vec<(FSRS6State, i32)> = + (0..NUM_CARDS).map(|_| (FSRS6State::default(), 0)).collect(); for day in 1..=DAYS { for (state, next_review) in fsrs_states.iter_mut() { @@ -432,7 +442,7 @@ fn test_fsrs6_vs_sm2_reviews_same_retention() { // SM-2: Interval growth is linear with EF // After n successful reviews: interval ≈ previous * 2.5 - let sm2_intervals = vec![1, 6, 15, 38, 95]; // Approximate SM-2 progression + let sm2_intervals = vec![1, 6, 15, 38, 95]; // Approximate SM-2 progression // FSRS-6: Stability grows based on forgetting curve parameters // This allows for more nuanced interval optimization @@ -469,13 +479,13 @@ fn test_fsrs6_vs_sm2_reviews_same_retention() { // Test the core FSRS-6 innovation: difficulty modulation // Create a "hard" card and compare stability growth let mut hard_state = FSRS6State { - difficulty: 8.0, // Hard card + difficulty: 8.0, // Hard card stability: FSRS6State::default().stability, reps: 0, }; let mut easy_state = FSRS6State { - difficulty: 2.0, // Easy card + difficulty: 2.0, // Easy card stability: FSRS6State::default().stability, reps: 0, }; @@ -593,7 +603,7 @@ fn test_fsrs6_vs_leitner() { /// get shorter intervals, and users with flatter curves (lower w20) get longer. #[test] fn test_fsrs6_personalization_improvement() { - let default_w20 = FSRS6_WEIGHTS[20]; // 0.1542 + let default_w20 = FSRS6_WEIGHTS[20]; // 0.1542 // User with faster forgetting (higher w20 = steeper curve) let fast_forgetter_w20 = 0.35; @@ -629,7 +639,7 @@ fn test_fsrs6_personalization_improvement() { // The key insight: w20 affects optimal interval calculation // For same desired_retention (0.9), different w20 gives different intervals - let desired_retention = 0.85; // Target 85% to see interval differences + let desired_retention = 0.85; // Target 85% to see interval differences let default_interval = fsrs6_interval(stability, desired_retention, default_w20); let fast_interval = fsrs6_interval(stability, desired_retention, fast_forgetter_w20); let slow_interval = fsrs6_interval(stability, desired_retention, slow_forgetter_w20); @@ -638,7 +648,9 @@ fn test_fsrs6_personalization_improvement() { assert!( default_interval > 0 && fast_interval > 0 && slow_interval > 0, "All intervals should be positive: default={}, fast={}, slow={}", - default_interval, fast_interval, slow_interval + default_interval, + fast_interval, + slow_interval ); // The total range of intervals demonstrates personalization value @@ -747,34 +759,55 @@ fn test_fsrs6_hard_penalty_effectiveness() { fn test_spreading_vs_similarity_1_hop() { // Setup spreading activation network let mut network = ActivationNetwork::new(); - network.add_edge("rust".to_string(), "cargo".to_string(), LinkType::Semantic, 0.9); - network.add_edge("rust".to_string(), "ownership".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "rust".to_string(), + "cargo".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "rust".to_string(), + "ownership".to_string(), + LinkType::Semantic, + 0.85, + ); // Setup similarity search with similar embeddings let mut sim_search = SimilaritySearch::new(); sim_search.add("rust", vec![1.0, 0.0, 0.0]); - sim_search.add("cargo", vec![0.9, 0.1, 0.0]); // Similar to rust - sim_search.add("ownership", vec![0.85, 0.15, 0.0]); // Similar to rust - sim_search.add("python", vec![0.0, 1.0, 0.0]); // Unrelated + sim_search.add("cargo", vec![0.9, 0.1, 0.0]); // Similar to rust + sim_search.add("ownership", vec![0.85, 0.15, 0.0]); // Similar to rust + sim_search.add("python", vec![0.0, 1.0, 0.0]); // Unrelated // Spreading activation let spreading_results = network.activate("rust", 1.0); - let spreading_found: HashSet<_> = spreading_results.iter() + let spreading_found: HashSet<_> = spreading_results + .iter() .map(|r| r.memory_id.as_str()) .collect(); // Similarity search let sim_results = sim_search.search(&[1.0, 0.0, 0.0], 3); - let sim_found: HashSet<_> = sim_results.iter() + let sim_found: HashSet<_> = sim_results + .iter() .filter(|(_, score)| *score > 0.8) .map(|(id, _)| id.as_str()) .collect(); // At 1-hop, both should find the direct connections - assert!(spreading_found.contains("cargo"), "Spreading should find cargo"); - assert!(spreading_found.contains("ownership"), "Spreading should find ownership"); + assert!( + spreading_found.contains("cargo"), + "Spreading should find cargo" + ); + assert!( + spreading_found.contains("ownership"), + "Spreading should find ownership" + ); assert!(sim_found.contains("cargo"), "Similarity should find cargo"); - assert!(sim_found.contains("ownership"), "Similarity should find ownership"); + assert!( + sim_found.contains("ownership"), + "Similarity should find ownership" + ); } /// Test 2-hop: Spreading activation finds indirect connections. @@ -790,23 +823,35 @@ fn test_spreading_vs_similarity_2_hop() { // Create a chain: rust -> tokio -> async_runtime // rust and async_runtime have NO direct similarity - network.add_edge("rust".to_string(), "tokio".to_string(), LinkType::Semantic, 0.9); - network.add_edge("tokio".to_string(), "async_runtime".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "rust".to_string(), + "tokio".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "tokio".to_string(), + "async_runtime".to_string(), + LinkType::Semantic, + 0.85, + ); // Similarity search - embeddings show NO similarity between rust and async_runtime let mut sim_search = SimilaritySearch::new(); sim_search.add("rust", vec![1.0, 0.0, 0.0, 0.0]); - sim_search.add("tokio", vec![0.7, 0.7, 0.0, 0.0]); // Bridge - sim_search.add("async_runtime", vec![0.0, 1.0, 0.0, 0.0]); // No similarity to rust + sim_search.add("tokio", vec![0.7, 0.7, 0.0, 0.0]); // Bridge + sim_search.add("async_runtime", vec![0.0, 1.0, 0.0, 0.0]); // No similarity to rust // Spreading finds async_runtime through the chain let spreading_results = network.activate("rust", 1.0); - let spreading_found_async = spreading_results.iter() + let spreading_found_async = spreading_results + .iter() .any(|r| r.memory_id == "async_runtime"); // Similarity from "rust" does NOT find async_runtime let sim_results = sim_search.search(&[1.0, 0.0, 0.0, 0.0], 5); - let sim_found_async = sim_results.iter() + let sim_found_async = sim_results + .iter() .any(|(id, score)| id == "async_runtime" && *score > 0.5); assert!( @@ -832,27 +877,52 @@ fn test_spreading_vs_similarity_3_hop() { // Create 3-hop chain: A -> B -> C -> D // Each step has semantic connection, but A and D have ZERO direct similarity - network.add_edge("concept_a".to_string(), "concept_b".to_string(), LinkType::Semantic, 0.9); - network.add_edge("concept_b".to_string(), "concept_c".to_string(), LinkType::Semantic, 0.9); - network.add_edge("concept_c".to_string(), "concept_d".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "concept_a".to_string(), + "concept_b".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "concept_b".to_string(), + "concept_c".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "concept_c".to_string(), + "concept_d".to_string(), + LinkType::Semantic, + 0.9, + ); // Embeddings: A and D are orthogonal (zero similarity) let mut sim_search = SimilaritySearch::new(); sim_search.add("concept_a", vec![1.0, 0.0, 0.0, 0.0]); sim_search.add("concept_b", vec![0.7, 0.7, 0.0, 0.0]); sim_search.add("concept_c", vec![0.0, 0.7, 0.7, 0.0]); - sim_search.add("concept_d", vec![0.0, 0.0, 0.0, 1.0]); // Orthogonal to A + sim_search.add("concept_d", vec![0.0, 0.0, 0.0, 1.0]); // Orthogonal to A // Spreading finds D let spreading_results = network.activate("concept_a", 1.0); - let d_result = spreading_results.iter().find(|r| r.memory_id == "concept_d"); + let d_result = spreading_results + .iter() + .find(|r| r.memory_id == "concept_d"); - assert!(d_result.is_some(), "Spreading MUST find concept_d at 3 hops"); - assert_eq!(d_result.unwrap().distance, 3, "Should be exactly 3 hops away"); + assert!( + d_result.is_some(), + "Spreading MUST find concept_d at 3 hops" + ); + assert_eq!( + d_result.unwrap().distance, + 3, + "Should be exactly 3 hops away" + ); // Similarity CANNOT find D from A let sim_results = sim_search.search(&[1.0, 0.0, 0.0, 0.0], 10); - let sim_d_score = sim_results.iter() + let sim_d_score = sim_results + .iter() .find(|(id, _)| id == "concept_d") .map(|(_, score)| *score) .unwrap_or(0.0); @@ -873,9 +943,24 @@ fn test_spreading_finds_chains_similarity_misses() { // Chain: "memory_leak" -> "reference_counting" -> "Arc_Weak" -> "cyclic_references" // The solution (cyclic_references) is NOT semantically similar to "memory_leak" - network.add_edge("memory_leak".to_string(), "reference_counting".to_string(), LinkType::Causal, 0.9); - network.add_edge("reference_counting".to_string(), "arc_weak".to_string(), LinkType::Semantic, 0.85); - network.add_edge("arc_weak".to_string(), "cyclic_references".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "memory_leak".to_string(), + "reference_counting".to_string(), + LinkType::Causal, + 0.9, + ); + network.add_edge( + "reference_counting".to_string(), + "arc_weak".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "arc_weak".to_string(), + "cyclic_references".to_string(), + LinkType::Semantic, + 0.9, + ); // The problem: "cyclic_references" has zero direct similarity to "memory_leak" // (they use completely different vocabulary) @@ -883,16 +968,18 @@ fn test_spreading_finds_chains_similarity_misses() { sim_search.add("memory_leak", vec![1.0, 0.0, 0.0, 0.0]); sim_search.add("reference_counting", vec![0.5, 0.5, 0.0, 0.0]); sim_search.add("arc_weak", vec![0.0, 0.7, 0.3, 0.0]); - sim_search.add("cyclic_references", vec![0.0, 0.0, 0.0, 1.0]); // Totally different! + sim_search.add("cyclic_references", vec![0.0, 0.0, 0.0, 1.0]); // Totally different! // Spreading activation finds the solution let spreading_results = network.activate("memory_leak", 1.0); - let found_solution = spreading_results.iter() + let found_solution = spreading_results + .iter() .any(|r| r.memory_id == "cyclic_references"); // Similarity search cannot find it let sim_results = sim_search.search(&[1.0, 0.0, 0.0, 0.0], 10); - let sim_found = sim_results.iter() + let sim_found = sim_results + .iter() .any(|(id, score)| id == "cyclic_references" && *score > 0.3); assert!( @@ -911,26 +998,47 @@ fn test_spreading_path_quality() { let mut network = ActivationNetwork::new(); // Create a knowledge graph about Rust error handling - network.add_edge("error_handling".to_string(), "result_type".to_string(), LinkType::Semantic, 0.9); - network.add_edge("result_type".to_string(), "question_mark_operator".to_string(), LinkType::Semantic, 0.85); - network.add_edge("question_mark_operator".to_string(), "early_return".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "error_handling".to_string(), + "result_type".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "result_type".to_string(), + "question_mark_operator".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "question_mark_operator".to_string(), + "early_return".to_string(), + LinkType::Semantic, + 0.8, + ); let results = network.activate("error_handling", 1.0); // Find the path to early_return - let early_return_result = results.iter() + let early_return_result = results + .iter() .find(|r| r.memory_id == "early_return") .expect("Should find early_return"); // Verify the path makes sense - assert_eq!(early_return_result.path.len(), 4, "Path should have 4 nodes"); + assert_eq!( + early_return_result.path.len(), + 4, + "Path should have 4 nodes" + ); assert_eq!(early_return_result.path[0], "error_handling"); assert_eq!(early_return_result.path[1], "result_type"); assert_eq!(early_return_result.path[2], "question_mark_operator"); assert_eq!(early_return_result.path[3], "early_return"); // Activation should decay along the path - let result_type_activation = results.iter() + let result_type_activation = results + .iter() .find(|r| r.memory_id == "result_type") .map(|r| r.activation) .unwrap_or(0.0); @@ -1056,20 +1164,52 @@ fn test_spreading_mixed_link_types() { let mut network = ActivationNetwork::new(); // Create edges with different link types - network.add_edge("event".to_string(), "semantic_relation".to_string(), LinkType::Semantic, 0.9); - network.add_edge("event".to_string(), "temporal_relation".to_string(), LinkType::Temporal, 0.9); - network.add_edge("event".to_string(), "causal_relation".to_string(), LinkType::Causal, 0.9); - network.add_edge("event".to_string(), "spatial_relation".to_string(), LinkType::Spatial, 0.9); + network.add_edge( + "event".to_string(), + "semantic_relation".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "event".to_string(), + "temporal_relation".to_string(), + LinkType::Temporal, + 0.9, + ); + network.add_edge( + "event".to_string(), + "causal_relation".to_string(), + LinkType::Causal, + 0.9, + ); + network.add_edge( + "event".to_string(), + "spatial_relation".to_string(), + LinkType::Spatial, + 0.9, + ); let results = network.activate("event", 1.0); // Should find all related nodes let found_ids: HashSet<_> = results.iter().map(|r| r.memory_id.as_str()).collect(); - assert!(found_ids.contains("semantic_relation"), "Should find semantic relation"); - assert!(found_ids.contains("temporal_relation"), "Should find temporal relation"); - assert!(found_ids.contains("causal_relation"), "Should find causal relation"); - assert!(found_ids.contains("spatial_relation"), "Should find spatial relation"); + assert!( + found_ids.contains("semantic_relation"), + "Should find semantic relation" + ); + assert!( + found_ids.contains("temporal_relation"), + "Should find temporal relation" + ); + assert!( + found_ids.contains("causal_relation"), + "Should find causal relation" + ); + assert!( + found_ids.contains("spatial_relation"), + "Should find spatial relation" + ); // Verify link types are preserved for result in &results { @@ -1094,7 +1234,7 @@ fn test_spreading_mixed_link_types() { #[test] fn test_retroactive_vs_timestamp_importance() { let config = SynapticTaggingConfig { - capture_window: CaptureWindow::new(9.0, 2.0), // 9 hours back, 2 hours forward + capture_window: CaptureWindow::new(9.0, 2.0), // 9 hours back, 2 hours forward prp_threshold: 0.7, tag_lifetime_hours: 12.0, min_tag_strength: 0.3, @@ -1130,7 +1270,8 @@ fn test_retroactive_vs_timestamp_importance() { // (In tests, tag_memory() uses Utc::now(), so temporal_distance ~= 0) for captured in &result.captured_memories { assert!( - captured.temporal_distance_hours >= 0.0 || captured.temporal_distance_hours.abs() < 0.01, + captured.temporal_distance_hours >= 0.0 + || captured.temporal_distance_hours.abs() < 0.01, "Captured memory {} should be encoded at or before event (distance: {:.4}h)", captured.memory_id, captured.temporal_distance_hours @@ -1166,7 +1307,10 @@ fn test_retroactive_captures_related_memories() { ); // Verify cluster properties - assert!(cluster.average_importance > 0.0, "Cluster should have positive importance"); + assert!( + cluster.average_importance > 0.0, + "Cluster should have positive importance" + ); assert_eq!( cluster.trigger_event_type, ImportanceEventType::EmotionalContent @@ -1184,7 +1328,11 @@ fn test_retroactive_window_effectiveness() { (Duration::hours(1), true, "1 hour before"), (Duration::hours(4), true, "4 hours before"), (Duration::hours(8), true, "8 hours before"), - (Duration::hours(10), false, "10 hours before (outside window)"), + ( + Duration::hours(10), + false, + "10 hours before (outside window)", + ), (Duration::minutes(-30), true, "30 minutes after"), (Duration::hours(-3), false, "3 hours after (outside window)"), ]; @@ -1201,7 +1349,11 @@ fn test_retroactive_window_effectiveness() { if should_capture { let prob = window.capture_probability(memory_time, event_time); - assert!(prob.is_some(), "{} should have capture probability", description); + assert!( + prob.is_some(), + "{} should have capture probability", + description + ); assert!( prob.unwrap() > 0.0, "{} should have positive capture probability", @@ -1218,7 +1370,7 @@ fn test_retroactive_semantic_filtering() { capture_window: CaptureWindow::new(9.0, 2.0), prp_threshold: 0.7, tag_lifetime_hours: 12.0, - min_tag_strength: 0.1, // Low threshold to test strength effects + min_tag_strength: 0.1, // Low threshold to test strength effects max_cluster_size: 100, enable_clustering: true, auto_decay: true, @@ -1232,14 +1384,16 @@ fn test_retroactive_semantic_filtering() { stc.tag_memory_with_strength("highly_relevant", 0.95); stc.tag_memory_with_strength("moderately_relevant", 0.6); stc.tag_memory_with_strength("barely_relevant", 0.35); - stc.tag_memory_with_strength("irrelevant", 0.05); // Below threshold + stc.tag_memory_with_strength("irrelevant", 0.05); // Below threshold // Trigger importance event let event = ImportanceEvent::user_flag("trigger", None); let result = stc.trigger_prp(event); // Higher strength memories should be captured with higher consolidated importance - let captured_ids: HashSet<_> = result.captured_memories.iter() + let captured_ids: HashSet<_> = result + .captured_memories + .iter() .map(|c| c.memory_id.as_str()) .collect(); @@ -1253,12 +1407,16 @@ fn test_retroactive_semantic_filtering() { ); // Find consolidated importance values - let highly_relevant_importance = result.captured_memories.iter() + let highly_relevant_importance = result + .captured_memories + .iter() .find(|c| c.memory_id == "highly_relevant") .map(|c| c.consolidated_importance) .unwrap_or(0.0); - let moderately_relevant_importance = result.captured_memories.iter() + let moderately_relevant_importance = result + .captured_memories + .iter() .find(|c| c.memory_id == "moderately_relevant") .map(|c| c.consolidated_importance) .unwrap_or(0.0); @@ -1285,10 +1443,8 @@ fn test_proof_unique_to_vestige() { let mut stc = SynapticTaggingSystem::new(); // Memory 1: Ordinary conversation about vacation (time T) - let _vacation_memory = stc.tag_memory_with_context( - "vacation_mention", - "User mentioned Bob's vacation plans" - ); + let _vacation_memory = + stc.tag_memory_with_context("vacation_mention", "User mentioned Bob's vacation plans"); // Memory 2: Some other ordinary memories stc.tag_memory("unrelated_memory_1"); @@ -1300,14 +1456,16 @@ fn test_proof_unique_to_vestige() { event_type: ImportanceEventType::UserFlag, memory_id: Some("departure_announcement".to_string()), timestamp: Utc::now(), - strength: 1.0, // Maximum importance + strength: 1.0, // Maximum importance context: Some("Bob is leaving - this makes prior context important".to_string()), }; let result = stc.trigger_prp(event); // The vacation memory should be captured! - let vacation_captured = result.captured_memories.iter() + let vacation_captured = result + .captured_memories + .iter() .any(|c| c.memory_id == "vacation_mention"); assert!( @@ -1316,7 +1474,9 @@ fn test_proof_unique_to_vestige() { ); // Verify the capture details - let vacation_capture = result.captured_memories.iter() + let vacation_capture = result + .captured_memories + .iter() .find(|c| c.memory_id == "vacation_mention") .unwrap(); @@ -1324,7 +1484,8 @@ fn test_proof_unique_to_vestige() { // so temporal_distance is ~0 (but conceptually it's a "backward" capture // since the memory existed BEFORE it became important) assert!( - vacation_capture.temporal_distance_hours >= 0.0 || vacation_capture.temporal_distance_hours.abs() < 0.01, + vacation_capture.temporal_distance_hours >= 0.0 + || vacation_capture.temporal_distance_hours.abs() < 0.01, "Memory should be encoded at or before the importance event (distance: {:.4}h)", vacation_capture.temporal_distance_hours ); @@ -1406,7 +1567,7 @@ fn test_index_compression_ratio() { let full_embedding_dim = 384; // Index embedding size - let index_embedding_dim = config.summary_dimensions; // 128 by default + let index_embedding_dim = config.summary_dimensions; // 128 by default // Compression ratio let compression_ratio = full_embedding_dim as f64 / index_embedding_dim as f64; @@ -1425,7 +1586,7 @@ fn test_index_compression_ratio() { ); // Memory savings per memory - let full_size_bytes = full_embedding_dim * 4; // f32 = 4 bytes + let full_size_bytes = full_embedding_dim * 4; // f32 = 4 bytes let index_size_bytes = index_embedding_dim * 4; let savings_per_memory = full_size_bytes - index_size_bytes; @@ -1522,8 +1683,7 @@ fn test_content_pointer_accuracy() { assert_eq!(chunked_ptr.size_bytes, Some(100)); // Test with hash - let hashed_ptr = ContentPointer::sqlite("data", 1, ContentType::Text) - .with_hash(0xDEADBEEF); + let hashed_ptr = ContentPointer::sqlite("data", 1, ContentType::Text).with_hash(0xDEADBEEF); assert_eq!(hashed_ptr.content_hash, Some(0xDEADBEEF)); @@ -1531,19 +1691,24 @@ fn test_content_pointer_accuracy() { let index = HippocampalIndex::new(); let now = Utc::now(); - let barcode = index.index_memory( - "test_memory", - "Test content for pointer verification", - "fact", - now, - None, - ).unwrap(); + let barcode = index + .index_memory( + "test_memory", + "Test content for pointer verification", + "fact", + now, + None, + ) + .unwrap(); // Retrieve and verify let retrieved = index.get_index("test_memory").unwrap().unwrap(); assert_eq!(retrieved.barcode, barcode); - assert!(!retrieved.content_pointers.is_empty(), "Should have content pointer"); + assert!( + !retrieved.content_pointers.is_empty(), + "Should have content pointer" + ); // Verify the default pointer is SQLite let default_ptr = &retrieved.content_pointers[0]; diff --git a/tests/e2e/tests/cognitive/dreams_tests.rs b/tests/e2e/tests/cognitive/dreams_tests.rs index 9835dee..25084b1 100644 --- a/tests/e2e/tests/cognitive/dreams_tests.rs +++ b/tests/e2e/tests/cognitive/dreams_tests.rs @@ -15,11 +15,11 @@ //! 3. **Scheduler & Timing**: Tests for activity detection and idle triggers use chrono::{Duration, Utc}; +use std::collections::HashSet; use vestige_core::advanced::dreams::{ ActivityTracker, ConnectionGraph, ConnectionReason, ConsolidationScheduler, DreamConfig, DreamMemory, InsightType, MemoryDreamer, }; -use std::collections::HashSet; // ============================================================================ // HELPER FUNCTIONS @@ -66,7 +66,6 @@ fn make_memory_with_access( } } - // ============================================================================ // INSIGHT GENERATION TESTS (5 tests) // ============================================================================ @@ -448,11 +447,7 @@ async fn test_consolidation_decay_stage() { let replay = report.stage1_replay.as_ref().unwrap(); // Should replay memories in chronological order - assert_eq!( - replay.sequence.len(), - 3, - "Should replay all 3 memories" - ); + assert_eq!(replay.sequence.len(), 3, "Should replay all 3 memories"); // Older memory should come first in replay sequence assert_eq!( @@ -616,12 +611,7 @@ async fn test_consolidation_transfer_stage() { vec!["important"], 5, ), - make_memory_with_access( - "low_access", - "Rarely accessed memory", - vec!["minor"], - 1, - ), + make_memory_with_access("low_access", "Rarely accessed memory", vec!["minor"], 1), ]; let report = scheduler.run_consolidation_cycle(&memories).await; @@ -911,7 +901,10 @@ fn test_connection_graph_comprehensive() { // Test strengthening assert!(graph.strengthen_connection("a", "b", 0.1)); let new_strength = graph.total_connection_strength("a"); - assert!(new_strength > a_strength, "Strength should increase after reinforcement"); + assert!( + new_strength > a_strength, + "Strength should increase after reinforcement" + ); // Test decay and pruning graph.apply_decay(0.5); diff --git a/tests/e2e/tests/cognitive/neuroscience_tests.rs b/tests/e2e/tests/cognitive/neuroscience_tests.rs index 5fb2db9..8a2506f 100644 --- a/tests/e2e/tests/cognitive/neuroscience_tests.rs +++ b/tests/e2e/tests/cognitive/neuroscience_tests.rs @@ -22,19 +22,39 @@ use chrono::{Duration, Utc}; use vestige_core::{ // Advanced reconsolidation - AccessContext, AccessTrigger, Modification, ReconsolidationManager, RelationshipType, - // FSRS - Rating, retrievability, retrievability_with_decay, initial_difficulty, - next_interval, FSRSScheduler, - // Neuroscience - Synaptic Tagging - SynapticTaggingSystem, ImportanceEvent, ImportanceEventType, - CaptureWindow, DecayFunction, - // Neuroscience - Memory States - MemoryState, MemoryLifecycle, AccessibilityCalculator, - CompetitionManager, CompetitionCandidate, + AccessContext, + AccessTrigger, + AccessibilityCalculator, + ArousalSignal, + AttentionSession, + AttentionSignal, + CaptureWindow, + CompetitionCandidate, + CompetitionManager, + DecayFunction, + FSRSScheduler, + ImportanceContext, + ImportanceEvent, + ImportanceEventType, // Neuroscience - Importance Signals - ImportanceSignals, NoveltySignal, ArousalSignal, RewardSignal, AttentionSignal, - ImportanceContext, AttentionSession, OutcomeType, + ImportanceSignals, + MemoryLifecycle, + // Neuroscience - Memory States + MemoryState, + Modification, + NoveltySignal, + OutcomeType, + // FSRS + Rating, + ReconsolidationManager, + RelationshipType, + RewardSignal, + // Neuroscience - Synaptic Tagging + SynapticTaggingSystem, + initial_difficulty, + next_interval, + retrievability, + retrievability_with_decay, }; // ============================================================================ @@ -91,7 +111,12 @@ fn test_stc_prp_trigger_captures_memories() { // The tagged memory should be captured assert!(result.has_captures()); - assert!(result.captured_memories.iter().any(|c| c.memory_id == "mem-background")); + assert!( + result + .captured_memories + .iter() + .any(|c| c.memory_id == "mem-background") + ); assert!(stc.is_captured("mem-background")); } @@ -140,13 +165,20 @@ fn test_stc_capture_window_probability() { // Memory just before event - high probability (exponential decay with λ=4.605/9) let recent_before = event_time - Duration::hours(1); - let prob_recent = window.capture_probability(recent_before, event_time).unwrap(); + let prob_recent = window + .capture_probability(recent_before, event_time) + .unwrap(); // At 1h out of 9h with exponential decay: e^(-4.605/9 * 1) ≈ 0.6 - assert!(prob_recent > 0.5, "Recent memory should have high capture probability"); + assert!( + prob_recent > 0.5, + "Recent memory should have high capture probability" + ); // Memory 6 hours before event - moderate probability let medium_before = event_time - Duration::hours(6); - let prob_medium = window.capture_probability(medium_before, event_time).unwrap(); + let prob_medium = window + .capture_probability(medium_before, event_time) + .unwrap(); assert!(prob_medium > 0.0 && prob_medium < prob_recent); // Memory outside window - no capture @@ -165,14 +197,26 @@ fn test_stc_decay_functions() { let exp_at_half = exp_decay.apply(1.0, 6.0, 12.0); let exp_at_end = exp_decay.apply(1.0, 12.0, 12.0); - assert!((exp_at_zero - 1.0).abs() < 0.01, "Should be full strength at t=0"); - assert!(exp_at_half > 0.0 && exp_at_half < 0.5, "Significant decay at halfway"); + assert!( + (exp_at_zero - 1.0).abs() < 0.01, + "Should be full strength at t=0" + ); + assert!( + exp_at_half > 0.0 && exp_at_half < 0.5, + "Significant decay at halfway" + ); assert!(exp_at_end < 0.02, "Near zero at lifetime end"); // Linear decay let linear_decay = DecayFunction::Linear; - assert!((linear_decay.apply(1.0, 5.0, 10.0) - 0.5).abs() < 0.01, "Linear: 50% at halfway"); - assert!((linear_decay.apply(1.0, 10.0, 10.0) - 0.0).abs() < 0.01, "Linear: 0% at end"); + assert!( + (linear_decay.apply(1.0, 5.0, 10.0) - 0.5).abs() < 0.01, + "Linear: 50% at halfway" + ); + assert!( + (linear_decay.apply(1.0, 10.0, 10.0) - 0.0).abs() < 0.01, + "Linear: 0% at end" + ); // Power decay (matches FSRS-6) let power_decay = DecayFunction::Power; @@ -259,7 +303,10 @@ fn test_reconsolidation_marks_memory_labile() { let snapshot = vestige_core::MemorySnapshot::capture( "Test content".to_string(), vec!["test".to_string()], - 0.8, 5.0, 0.9, vec![], + 0.8, + 5.0, + 0.9, + vec![], ); manager.mark_labile("mem-123", snapshot); @@ -277,22 +324,30 @@ fn test_reconsolidation_apply_modifications() { let snapshot = vestige_core::MemorySnapshot::capture( "Original content".to_string(), vec!["original".to_string()], - 0.8, 5.0, 0.9, vec![], + 0.8, + 5.0, + 0.9, + vec![], ); manager.mark_labile("mem-123", snapshot); // Apply various modifications - let success1 = manager.apply_modification("mem-123", Modification::AddTag { - tag: "new-tag".to_string(), - }); - let success2 = manager.apply_modification("mem-123", Modification::BoostRetrieval { - boost: 0.1, - }); - let success3 = manager.apply_modification("mem-123", Modification::LinkMemory { - related_memory_id: "mem-456".to_string(), - relationship: RelationshipType::Supports, - }); + let success1 = manager.apply_modification( + "mem-123", + Modification::AddTag { + tag: "new-tag".to_string(), + }, + ); + let success2 = + manager.apply_modification("mem-123", Modification::BoostRetrieval { boost: 0.1 }); + let success3 = manager.apply_modification( + "mem-123", + Modification::LinkMemory { + related_memory_id: "mem-456".to_string(), + relationship: RelationshipType::Supports, + }, + ); assert!(success1 && success2 && success3); assert_eq!(manager.get_stats().total_modifications, 3); @@ -307,16 +362,25 @@ fn test_reconsolidation_finalizes_changes() { let snapshot = vestige_core::MemorySnapshot::capture( "Content".to_string(), vec!["tag".to_string()], - 0.8, 5.0, 0.9, vec![], + 0.8, + 5.0, + 0.9, + vec![], ); manager.mark_labile("mem-123", snapshot); - manager.apply_modification("mem-123", Modification::AddTag { - tag: "new-tag".to_string(), - }); - manager.apply_modification("mem-123", Modification::AddContext { - context: "Important meeting notes".to_string(), - }); + manager.apply_modification( + "mem-123", + Modification::AddTag { + tag: "new-tag".to_string(), + }, + ); + manager.apply_modification( + "mem-123", + Modification::AddContext { + context: "Important meeting notes".to_string(), + }, + ); let result = manager.reconsolidate("mem-123"); @@ -333,10 +397,8 @@ fn test_reconsolidation_finalizes_changes() { #[test] fn test_reconsolidation_tracks_access_context() { let mut manager = ReconsolidationManager::new(); - let snapshot = vestige_core::MemorySnapshot::capture( - "Content".to_string(), - vec![], 0.8, 5.0, 0.9, vec![], - ); + let snapshot = + vestige_core::MemorySnapshot::capture("Content".to_string(), vec![], 0.8, 5.0, 0.9, vec![]); let context = AccessContext { trigger: AccessTrigger::Search, query: Some("test query".to_string()), @@ -357,10 +419,8 @@ fn test_reconsolidation_tracks_access_context() { #[test] fn test_reconsolidation_retrieval_history() { let mut manager = ReconsolidationManager::new(); - let snapshot = vestige_core::MemorySnapshot::capture( - "Content".to_string(), - vec![], 0.8, 5.0, 0.9, vec![], - ); + let snapshot = + vestige_core::MemorySnapshot::capture("Content".to_string(), vec![], 0.8, 5.0, 0.9, vec![]); // Multiple retrievals for _ in 0..3 { @@ -417,8 +477,10 @@ fn test_fsrs_custom_decay_parameter() { let r_high_decay = retrievability_with_decay(stability, elapsed, 0.5); // Lower decay = steeper curve = lower retrievability for same time - assert!(r_low_decay < r_high_decay, - "Lower decay parameter should result in faster forgetting"); + assert!( + r_low_decay < r_high_decay, + "Lower decay parameter should result in faster forgetting" + ); } /// Test interval calculation round-trips with retrievability. @@ -436,7 +498,9 @@ fn test_fsrs_interval_retrievability_roundtrip() { assert!( (actual_r - target_r).abs() < 0.05, "Round-trip: interval={}, actual_R={:.3}, target_R={:.3}", - interval, actual_r, target_r + interval, + actual_r, + target_r ); } @@ -492,7 +556,10 @@ fn test_fsrs_difficulty_mean_reversion() { let high_d_after = result.state.difficulty; // Mean reversion should pull high difficulty down - assert!(high_d_after < high_d_before, "High difficulty should decrease"); + assert!( + high_d_after < high_d_before, + "High difficulty should decrease" + ); // Create card with low difficulty let mut low_d_card = scheduler.new_card(); @@ -502,7 +569,10 @@ fn test_fsrs_difficulty_mean_reversion() { // Again rating should increase difficulty let result = scheduler.review(&low_d_card, Rating::Again, 0.0, None); let low_d_after = result.state.difficulty; - assert!(low_d_after > low_d_before, "Again should increase low difficulty"); + assert!( + low_d_after > low_d_before, + "Again should increase low difficulty" + ); } /// Test scheduler lapse tracking. @@ -541,12 +611,18 @@ fn test_memory_state_accessibility_multipliers() { assert!((MemoryState::Unavailable.accessibility_multiplier() - 0.05).abs() < 0.001); // Active > Dormant > Silent > Unavailable - assert!(MemoryState::Active.accessibility_multiplier() > - MemoryState::Dormant.accessibility_multiplier()); - assert!(MemoryState::Dormant.accessibility_multiplier() > - MemoryState::Silent.accessibility_multiplier()); - assert!(MemoryState::Silent.accessibility_multiplier() > - MemoryState::Unavailable.accessibility_multiplier()); + assert!( + MemoryState::Active.accessibility_multiplier() + > MemoryState::Dormant.accessibility_multiplier() + ); + assert!( + MemoryState::Dormant.accessibility_multiplier() + > MemoryState::Silent.accessibility_multiplier() + ); + assert!( + MemoryState::Silent.accessibility_multiplier() + > MemoryState::Unavailable.accessibility_multiplier() + ); } /// Test state retrievability properties. @@ -589,11 +665,7 @@ fn test_memory_lifecycle_transitions() { fn test_memory_state_competition_suppression() { let mut lifecycle = MemoryLifecycle::new(); - lifecycle.suppress_from_competition( - "winner-123".to_string(), - 0.85, - Duration::hours(2), - ); + lifecycle.suppress_from_competition("winner-123".to_string(), 0.85, Duration::hours(2)); assert_eq!(lifecycle.state, MemoryState::Unavailable); assert!(!lifecycle.is_suppression_expired()); @@ -671,7 +743,10 @@ fn test_memory_state_accessibility_calculator() { assert!(active_threshold < 0.5, "Active has lower threshold"); assert!(silent_threshold > 0.5, "Silent has higher threshold"); - assert!(unavailable_threshold > 1.0, "Unavailable is effectively unreachable"); + assert!( + unavailable_threshold > 1.0, + "Unavailable is effectively unreachable" + ); } // ============================================================================ @@ -713,14 +788,19 @@ fn test_importance_arousal_signal() { let neutral_score = arousal.compute("The meeting is scheduled for tomorrow at 3pm."); // Highly emotional content - let emotional_score = arousal.compute( - "CRITICAL ERROR!!! Production database is DOWN! Data loss imminent!!!" - ); + let emotional_score = + arousal.compute("CRITICAL ERROR!!! Production database is DOWN! Data loss imminent!!!"); - assert!(emotional_score > neutral_score, + assert!( + emotional_score > neutral_score, "Emotional content should have higher arousal: {} vs {}", - emotional_score, neutral_score); - assert!(emotional_score > 0.5, "Highly emotional content should score high"); + emotional_score, + neutral_score + ); + assert!( + emotional_score > 0.5, + "Highly emotional content should score high" + ); // Detect emotional markers let markers = arousal.detect_emotional_markers("URGENT: Critical failure!!!"); @@ -740,14 +820,20 @@ fn test_importance_reward_signal() { reward.record_outcome("mem-helpful", OutcomeType::Helpful); let helpful_score = reward.compute("mem-helpful"); - assert!(helpful_score > 0.5, "Memory with positive outcomes should score high"); + assert!( + helpful_score > 0.5, + "Memory with positive outcomes should score high" + ); // Record negative outcomes reward.record_outcome("mem-unhelpful", OutcomeType::NotHelpful); reward.record_outcome("mem-unhelpful", OutcomeType::NotHelpful); let unhelpful_score = reward.compute("mem-unhelpful"); - assert!(unhelpful_score < 0.5, "Memory with negative outcomes should score low"); + assert!( + unhelpful_score < 0.5, + "Memory with negative outcomes should score low" + ); assert!(helpful_score > unhelpful_score); } @@ -768,11 +854,17 @@ fn test_importance_attention_signal() { edit_count: 2, unique_memories_accessed: 15, viewed_docs: true, - query_topics: vec!["rust".to_string(), "async".to_string(), "memory".to_string()], + query_topics: vec![ + "rust".to_string(), + "async".to_string(), + "memory".to_string(), + ], }; - assert!(attention.detect_learning_mode(&learning_session), - "Should detect learning mode from session patterns"); + assert!( + attention.detect_learning_mode(&learning_session), + "Should detect learning mode from session patterns" + ); // Non-learning session (quick edit) let quick_session = AttentionSession { @@ -786,8 +878,10 @@ fn test_importance_attention_signal() { query_topics: vec![], }; - assert!(!attention.detect_learning_mode(&quick_session), - "Quick edit session should not be learning mode"); + assert!( + !attention.detect_learning_mode(&quick_session), + "Quick edit session should not be learning mode" + ); } /// Test composite importance combines all signals. @@ -806,9 +900,15 @@ fn test_importance_composite_score() { &context, ); - assert!(score.composite > 0.4, "Important content should score moderately high"); + assert!( + score.composite > 0.4, + "Important content should score moderately high" + ); assert!(score.arousal > 0.4, "Emotional content should have arousal"); - assert!(score.encoding_boost >= 1.0, "High importance should boost encoding"); + assert!( + score.encoding_boost >= 1.0, + "High importance should boost encoding" + ); // Verify all components are present assert!(score.novelty >= 0.0 && score.novelty <= 1.0); diff --git a/tests/e2e/tests/cognitive/psychology_tests.rs b/tests/e2e/tests/cognitive/psychology_tests.rs index d89aaed..e794fde 100644 --- a/tests/e2e/tests/cognitive/psychology_tests.rs +++ b/tests/e2e/tests/cognitive/psychology_tests.rs @@ -129,15 +129,15 @@ fn test_serial_position_u_shaped_curve() { // U-shaped curve: high-low-high pattern let items = vec![ - ("pos_1", 0.90), // High (primacy) + ("pos_1", 0.90), // High (primacy) ("pos_2", 0.80), ("pos_3", 0.65), - ("pos_4", 0.55), // Low (middle) - ("pos_5", 0.50), // Low (middle) + ("pos_4", 0.55), // Low (middle) + ("pos_5", 0.50), // Low (middle) ("pos_6", 0.55), ("pos_7", 0.70), ("pos_8", 0.85), - ("pos_9", 0.95), // High (recency) + ("pos_9", 0.95), // High (recency) ]; for (item, strength) in &items { @@ -151,13 +151,35 @@ fn test_serial_position_u_shaped_curve() { let results = network.activate("list_context", 1.0); - let pos_1 = results.iter().find(|r| r.memory_id == "pos_1").map(|r| r.activation).unwrap_or(0.0); - let pos_5 = results.iter().find(|r| r.memory_id == "pos_5").map(|r| r.activation).unwrap_or(0.0); - let pos_9 = results.iter().find(|r| r.memory_id == "pos_9").map(|r| r.activation).unwrap_or(0.0); + let pos_1 = results + .iter() + .find(|r| r.memory_id == "pos_1") + .map(|r| r.activation) + .unwrap_or(0.0); + let pos_5 = results + .iter() + .find(|r| r.memory_id == "pos_5") + .map(|r| r.activation) + .unwrap_or(0.0); + let pos_9 = results + .iter() + .find(|r| r.memory_id == "pos_9") + .map(|r| r.activation) + .unwrap_or(0.0); // U-shape: ends higher than middle - assert!(pos_1 > pos_5, "First position ({}) > middle position ({})", pos_1, pos_5); - assert!(pos_9 > pos_5, "Last position ({}) > middle position ({})", pos_9, pos_5); + assert!( + pos_1 > pos_5, + "First position ({}) > middle position ({})", + pos_1, + pos_5 + ); + assert!( + pos_9 > pos_5, + "Last position ({}) > middle position ({})", + pos_9, + pos_5 + ); } /// Test that rehearsal strengthens primacy items. @@ -168,9 +190,24 @@ fn test_serial_position_rehearsal_strengthens_primacy() { let mut network = ActivationNetwork::new(); // Initial weak connections - network.add_edge("learning".to_string(), "first_concept".to_string(), LinkType::Semantic, 0.3); - network.add_edge("learning".to_string(), "middle_concept".to_string(), LinkType::Semantic, 0.3); - network.add_edge("learning".to_string(), "last_concept".to_string(), LinkType::Semantic, 0.3); + network.add_edge( + "learning".to_string(), + "first_concept".to_string(), + LinkType::Semantic, + 0.3, + ); + network.add_edge( + "learning".to_string(), + "middle_concept".to_string(), + LinkType::Semantic, + 0.3, + ); + network.add_edge( + "learning".to_string(), + "last_concept".to_string(), + LinkType::Semantic, + 0.3, + ); // Simulate rehearsal - first items get more rehearsal // (5 rehearsals for first, 2 for middle, 3 for last) @@ -217,12 +254,12 @@ fn test_serial_position_delay_eliminates_recency() { // After delay: primacy preserved, recency diminished // (modeling that working memory has cleared) let delayed_items = vec![ - ("early_1", 0.85), // Primacy preserved + ("early_1", 0.85), // Primacy preserved ("early_2", 0.75), ("middle_1", 0.50), ("middle_2", 0.45), - ("late_1", 0.40), // Recency lost after delay - ("late_2", 0.35), // (items not transferred to LTM) + ("late_1", 0.40), // Recency lost after delay + ("late_2", 0.35), // (items not transferred to LTM) ]; for (item, strength) in &delayed_items { @@ -271,7 +308,12 @@ fn test_spacing_effect_distributed_vs_massed() { let mut network = ActivationNetwork::new(); // Massed practice: all reinforcements close together (less effective) - network.add_edge("massed".to_string(), "concept_a".to_string(), LinkType::Semantic, 0.2); + network.add_edge( + "massed".to_string(), + "concept_a".to_string(), + LinkType::Semantic, + 0.2, + ); // 5 rapid reinforcements for _ in 0..5 { network.reinforce_edge("massed", "concept_a", 0.1); @@ -279,7 +321,12 @@ fn test_spacing_effect_distributed_vs_massed() { // Spaced practice: reinforcements distributed (more effective) // Simulated by giving higher reinforcement values (representing better encoding) - network.add_edge("spaced".to_string(), "concept_b".to_string(), LinkType::Semantic, 0.2); + network.add_edge( + "spaced".to_string(), + "concept_b".to_string(), + LinkType::Semantic, + 0.2, + ); // 5 spaced reinforcements with better encoding for _ in 0..5 { network.reinforce_edge("spaced", "concept_b", 0.15); // Higher value = better encoding @@ -316,12 +363,22 @@ fn test_spacing_effect_optimal_interval() { let mut network = ActivationNetwork::new(); // Short retention interval: shorter spacing optimal - network.add_edge("short_retention".to_string(), "fact_1".to_string(), LinkType::Semantic, 0.3); + network.add_edge( + "short_retention".to_string(), + "fact_1".to_string(), + LinkType::Semantic, + 0.3, + ); network.reinforce_edge("short_retention", "fact_1", 0.2); network.reinforce_edge("short_retention", "fact_1", 0.2); // Long retention interval: longer spacing optimal (simulated with stronger encoding) - network.add_edge("long_retention".to_string(), "fact_2".to_string(), LinkType::Semantic, 0.3); + network.add_edge( + "long_retention".to_string(), + "fact_2".to_string(), + LinkType::Semantic, + 0.3, + ); network.reinforce_edge("long_retention", "fact_2", 0.25); network.reinforce_edge("long_retention", "fact_2", 0.25); @@ -346,9 +403,24 @@ fn test_spacing_effect_semantic_associations() { let mut network = ActivationNetwork::new(); // Create semantic network with spaced learning - network.add_edge("programming".to_string(), "rust".to_string(), LinkType::Semantic, 0.5); - network.add_edge("rust".to_string(), "ownership".to_string(), LinkType::Semantic, 0.5); - network.add_edge("ownership".to_string(), "borrowing".to_string(), LinkType::Semantic, 0.5); + network.add_edge( + "programming".to_string(), + "rust".to_string(), + LinkType::Semantic, + 0.5, + ); + network.add_edge( + "rust".to_string(), + "ownership".to_string(), + LinkType::Semantic, + 0.5, + ); + network.add_edge( + "ownership".to_string(), + "borrowing".to_string(), + LinkType::Semantic, + 0.5, + ); // Spaced reinforcement of the path for _ in 0..3 { @@ -361,7 +433,10 @@ fn test_spacing_effect_semantic_associations() { // Should reach borrowing through the strengthened path let borrowing_result = results.iter().find(|r| r.memory_id == "borrowing"); - assert!(borrowing_result.is_some(), "Spaced learning should strengthen multi-hop paths"); + assert!( + borrowing_result.is_some(), + "Spaced learning should strengthen multi-hop paths" + ); let borrowing_activation = borrowing_result.unwrap().activation; assert!( @@ -379,7 +454,12 @@ fn test_spacing_effect_expanding_retrieval() { let mut network = ActivationNetwork::new(); // Expanding intervals: each retrieval strengthens more as intervals grow - network.add_edge("expanding".to_string(), "memory".to_string(), LinkType::Semantic, 0.2); + network.add_edge( + "expanding".to_string(), + "memory".to_string(), + LinkType::Semantic, + 0.2, + ); // Simulate expanding intervals with increasing reinforcement let expanding_reinforcements = [0.1, 0.12, 0.15, 0.18, 0.22]; // Increasing gains @@ -411,9 +491,24 @@ fn test_spacing_effect_multi_hop_paths() { let mut network = ActivationNetwork::with_config(config); // Create a learning chain - network.add_edge("topic".to_string(), "subtopic_a".to_string(), LinkType::Semantic, 0.4); - network.add_edge("subtopic_a".to_string(), "detail_1".to_string(), LinkType::Semantic, 0.4); - network.add_edge("detail_1".to_string(), "example".to_string(), LinkType::Semantic, 0.4); + network.add_edge( + "topic".to_string(), + "subtopic_a".to_string(), + LinkType::Semantic, + 0.4, + ); + network.add_edge( + "subtopic_a".to_string(), + "detail_1".to_string(), + LinkType::Semantic, + 0.4, + ); + network.add_edge( + "detail_1".to_string(), + "example".to_string(), + LinkType::Semantic, + 0.4, + ); // Spaced practice on entire chain for _ in 0..4 { @@ -426,11 +521,18 @@ fn test_spacing_effect_multi_hop_paths() { // Example should be reachable with good activation let example_result = results.iter().find(|r| r.memory_id == "example"); - assert!(example_result.is_some(), "Spaced practice should enable deep retrieval"); + assert!( + example_result.is_some(), + "Spaced practice should enable deep retrieval" + ); let example = example_result.unwrap(); assert_eq!(example.distance, 3, "Example should be 3 hops away"); - assert!(example.activation > 0.1, "Example should have sufficient activation: {}", example.activation); + assert!( + example.activation > 0.1, + "Example should have sufficient activation: {}", + example.activation + ); } // ============================================================================ @@ -448,27 +550,58 @@ fn test_context_dependent_matching_context() { let mut network = ActivationNetwork::new(); // Memory encoded in "office" context - network.add_edge("office_context".to_string(), "project_deadline".to_string(), LinkType::Semantic, 0.9); - network.add_edge("office_context".to_string(), "meeting_notes".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "office_context".to_string(), + "project_deadline".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "office_context".to_string(), + "meeting_notes".to_string(), + LinkType::Semantic, + 0.85, + ); // Memory encoded in "home" context - network.add_edge("home_context".to_string(), "grocery_list".to_string(), LinkType::Semantic, 0.9); - network.add_edge("home_context".to_string(), "family_event".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "home_context".to_string(), + "grocery_list".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "home_context".to_string(), + "family_event".to_string(), + LinkType::Semantic, + 0.85, + ); // Recall from office context let office_results = network.activate("office_context", 1.0); let home_results = network.activate("home_context", 1.0); // Office context should find office memories - let found_deadline = office_results.iter().any(|r| r.memory_id == "project_deadline"); + let found_deadline = office_results + .iter() + .any(|r| r.memory_id == "project_deadline"); let found_grocery = office_results.iter().any(|r| r.memory_id == "grocery_list"); - assert!(found_deadline, "Office context should activate office memories"); - assert!(!found_grocery, "Office context should NOT directly activate home memories"); + assert!( + found_deadline, + "Office context should activate office memories" + ); + assert!( + !found_grocery, + "Office context should NOT directly activate home memories" + ); // Home context should find home memories let home_found_grocery = home_results.iter().any(|r| r.memory_id == "grocery_list"); - assert!(home_found_grocery, "Home context should activate home memories"); + assert!( + home_found_grocery, + "Home context should activate home memories" + ); } /// Test encoding specificity principle. @@ -479,12 +612,32 @@ fn test_context_dependent_encoding_specificity() { let mut network = ActivationNetwork::new(); // Highly specific encoding context - network.add_edge("rainy_monday_morning".to_string(), "specific_memory".to_string(), LinkType::Temporal, 0.95); - network.add_edge("rainy_monday_morning".to_string(), "coffee_shop_idea".to_string(), LinkType::Temporal, 0.9); + network.add_edge( + "rainy_monday_morning".to_string(), + "specific_memory".to_string(), + LinkType::Temporal, + 0.95, + ); + network.add_edge( + "rainy_monday_morning".to_string(), + "coffee_shop_idea".to_string(), + LinkType::Temporal, + 0.9, + ); // General context (partial match) - network.add_edge("monday".to_string(), "rainy_monday_morning".to_string(), LinkType::Temporal, 0.6); - network.add_edge("morning".to_string(), "rainy_monday_morning".to_string(), LinkType::Temporal, 0.5); + network.add_edge( + "monday".to_string(), + "rainy_monday_morning".to_string(), + LinkType::Temporal, + 0.6, + ); + network.add_edge( + "morning".to_string(), + "rainy_monday_morning".to_string(), + LinkType::Temporal, + 0.5, + ); // Specific context retrieval let specific_results = network.activate("rainy_monday_morning", 1.0); @@ -520,20 +673,50 @@ fn test_context_dependent_state_dependent() { let mut network = ActivationNetwork::new(); // Memories encoded in different emotional states - network.add_edge("happy_state".to_string(), "positive_memory_1".to_string(), LinkType::Semantic, 0.9); - network.add_edge("happy_state".to_string(), "positive_memory_2".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "happy_state".to_string(), + "positive_memory_1".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "happy_state".to_string(), + "positive_memory_2".to_string(), + LinkType::Semantic, + 0.85, + ); - network.add_edge("stressed_state".to_string(), "work_problem_1".to_string(), LinkType::Semantic, 0.9); - network.add_edge("stressed_state".to_string(), "work_problem_2".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "stressed_state".to_string(), + "work_problem_1".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "stressed_state".to_string(), + "work_problem_2".to_string(), + LinkType::Semantic, + 0.85, + ); // Retrieve from happy state let happy_results = network.activate("happy_state", 1.0); - let found_positive = happy_results.iter().any(|r| r.memory_id == "positive_memory_1"); - let found_work = happy_results.iter().any(|r| r.memory_id == "work_problem_1"); + let found_positive = happy_results + .iter() + .any(|r| r.memory_id == "positive_memory_1"); + let found_work = happy_results + .iter() + .any(|r| r.memory_id == "work_problem_1"); - assert!(found_positive, "Happy state should activate positive memories"); - assert!(!found_work, "Happy state should NOT directly activate stressed memories"); + assert!( + found_positive, + "Happy state should activate positive memories" + ); + assert!( + !found_work, + "Happy state should NOT directly activate stressed memories" + ); } /// Test context reinstatement improves retrieval. @@ -544,20 +727,55 @@ fn test_context_dependent_reinstatement() { let mut network = ActivationNetwork::new(); // Memory with multiple context cues - network.add_edge("library".to_string(), "study_session".to_string(), LinkType::Temporal, 0.8); - network.add_edge("quiet".to_string(), "study_session".to_string(), LinkType::Semantic, 0.7); - network.add_edge("evening".to_string(), "study_session".to_string(), LinkType::Temporal, 0.6); + network.add_edge( + "library".to_string(), + "study_session".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "quiet".to_string(), + "study_session".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "evening".to_string(), + "study_session".to_string(), + LinkType::Temporal, + 0.6, + ); // Study session links to learned material - network.add_edge("study_session".to_string(), "learned_concept".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "study_session".to_string(), + "learned_concept".to_string(), + LinkType::Semantic, + 0.9, + ); // Single context cue let single_cue = network.activate("library", 1.0); // Multiple context cues (reinstatement) - we need to create a combined node - network.add_edge("reinstated_context".to_string(), "library".to_string(), LinkType::Semantic, 0.9); - network.add_edge("reinstated_context".to_string(), "quiet".to_string(), LinkType::Semantic, 0.9); - network.add_edge("reinstated_context".to_string(), "evening".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "reinstated_context".to_string(), + "library".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "reinstated_context".to_string(), + "quiet".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "reinstated_context".to_string(), + "evening".to_string(), + LinkType::Semantic, + 0.9, + ); let reinstated_results = network.activate("reinstated_context", 1.0); @@ -587,10 +805,20 @@ fn test_context_dependent_transfer_appropriate() { let mut network = ActivationNetwork::new(); // Semantic encoding (deep processing) - network.add_edge("meaning_focused".to_string(), "concept_meaning".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "meaning_focused".to_string(), + "concept_meaning".to_string(), + LinkType::Semantic, + 0.9, + ); // Perceptual encoding (shallow processing) - network.add_edge("appearance_focused".to_string(), "concept_appearance".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "appearance_focused".to_string(), + "concept_appearance".to_string(), + LinkType::Semantic, + 0.9, + ); // Semantic retrieval cue let semantic_results = network.activate("meaning_focused", 1.0); @@ -599,15 +827,30 @@ fn test_context_dependent_transfer_appropriate() { let perceptual_results = network.activate("appearance_focused", 1.0); // Matching encoding-retrieval processing should work best - let semantic_found = semantic_results.iter().any(|r| r.memory_id == "concept_meaning"); - let perceptual_found = perceptual_results.iter().any(|r| r.memory_id == "concept_appearance"); + let semantic_found = semantic_results + .iter() + .any(|r| r.memory_id == "concept_meaning"); + let perceptual_found = perceptual_results + .iter() + .any(|r| r.memory_id == "concept_appearance"); - assert!(semantic_found, "Semantic cue should retrieve semantically encoded info"); - assert!(perceptual_found, "Perceptual cue should retrieve perceptually encoded info"); + assert!( + semantic_found, + "Semantic cue should retrieve semantically encoded info" + ); + assert!( + perceptual_found, + "Perceptual cue should retrieve perceptually encoded info" + ); // Cross-retrieval should be weaker (not directly connected) - let cross_found = semantic_results.iter().any(|r| r.memory_id == "concept_appearance"); - assert!(!cross_found, "Semantic cue should NOT directly retrieve perceptual encoding"); + let cross_found = semantic_results + .iter() + .any(|r| r.memory_id == "concept_appearance"); + assert!( + !cross_found, + "Semantic cue should NOT directly retrieve perceptual encoding" + ); } // ============================================================================ @@ -622,26 +865,51 @@ fn test_context_dependent_transfer_appropriate() { #[test] fn test_tot_partial_activation() { let config = ActivationConfig { - decay_factor: 0.6, // Higher decay = weaker far connections + decay_factor: 0.6, // Higher decay = weaker far connections max_hops: 3, - min_threshold: 0.15, // Higher threshold = some items not retrieved + min_threshold: 0.15, // Higher threshold = some items not retrieved allow_cycles: false, }; let mut network = ActivationNetwork::with_config(config); // Target word "serendipity" with various features - network.add_edge("word_search".to_string(), "starts_with_s".to_string(), LinkType::Semantic, 0.8); - network.add_edge("word_search".to_string(), "four_syllables".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_search".to_string(), "meaning_lucky_discovery".to_string(), LinkType::Semantic, 0.85); - network.add_edge("starts_with_s".to_string(), "serendipity".to_string(), LinkType::Semantic, 0.3); // Weak link to target + network.add_edge( + "word_search".to_string(), + "starts_with_s".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "word_search".to_string(), + "four_syllables".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_search".to_string(), + "meaning_lucky_discovery".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "starts_with_s".to_string(), + "serendipity".to_string(), + LinkType::Semantic, + 0.3, + ); // Weak link to target let results = network.activate("word_search", 1.0); // Should find partial information let found_starts_s = results.iter().any(|r| r.memory_id == "starts_with_s"); - let found_meaning = results.iter().any(|r| r.memory_id == "meaning_lucky_discovery"); + let found_meaning = results + .iter() + .any(|r| r.memory_id == "meaning_lucky_discovery"); - assert!(found_starts_s, "Should retrieve partial info (first letter)"); + assert!( + found_starts_s, + "Should retrieve partial info (first letter)" + ); assert!(found_meaning, "Should retrieve partial info (meaning)"); // Target might not be found due to weak link and threshold @@ -669,17 +937,49 @@ fn test_tot_related_words_activated() { // Searching for "archipelago" // Related words get activated instead - network.add_edge("island_chain_concept".to_string(), "archipelago".to_string(), LinkType::Semantic, 0.4); // Weak - network.add_edge("island_chain_concept".to_string(), "peninsula".to_string(), LinkType::Semantic, 0.7); // Related, stronger - network.add_edge("island_chain_concept".to_string(), "atoll".to_string(), LinkType::Semantic, 0.65); // Related - network.add_edge("island_chain_concept".to_string(), "islands".to_string(), LinkType::Semantic, 0.8); // Generic, strong + network.add_edge( + "island_chain_concept".to_string(), + "archipelago".to_string(), + LinkType::Semantic, + 0.4, + ); // Weak + network.add_edge( + "island_chain_concept".to_string(), + "peninsula".to_string(), + LinkType::Semantic, + 0.7, + ); // Related, stronger + network.add_edge( + "island_chain_concept".to_string(), + "atoll".to_string(), + LinkType::Semantic, + 0.65, + ); // Related + network.add_edge( + "island_chain_concept".to_string(), + "islands".to_string(), + LinkType::Semantic, + 0.8, + ); // Generic, strong let results = network.activate("island_chain_concept", 1.0); // Generic/related words should be more activated than target - let archipelago_act = results.iter().find(|r| r.memory_id == "archipelago").map(|r| r.activation).unwrap_or(0.0); - let islands_act = results.iter().find(|r| r.memory_id == "islands").map(|r| r.activation).unwrap_or(0.0); - let peninsula_act = results.iter().find(|r| r.memory_id == "peninsula").map(|r| r.activation).unwrap_or(0.0); + let archipelago_act = results + .iter() + .find(|r| r.memory_id == "archipelago") + .map(|r| r.activation) + .unwrap_or(0.0); + let islands_act = results + .iter() + .find(|r| r.memory_id == "islands") + .map(|r| r.activation) + .unwrap_or(0.0); + let peninsula_act = results + .iter() + .find(|r| r.memory_id == "peninsula") + .map(|r| r.activation) + .unwrap_or(0.0); assert!( islands_act > archipelago_act, @@ -703,10 +1003,25 @@ fn test_tot_phonological_cue_resolution() { // Target: "ephemeral" // Weak semantic link - network.add_edge("temporary_concept".to_string(), "ephemeral".to_string(), LinkType::Semantic, 0.3); + network.add_edge( + "temporary_concept".to_string(), + "ephemeral".to_string(), + LinkType::Semantic, + 0.3, + ); // Strong phonological link - network.add_edge("starts_with_eph".to_string(), "ephemeral".to_string(), LinkType::Semantic, 0.85); - network.add_edge("temporary_concept".to_string(), "starts_with_eph".to_string(), LinkType::Semantic, 0.5); + network.add_edge( + "starts_with_eph".to_string(), + "ephemeral".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "temporary_concept".to_string(), + "starts_with_eph".to_string(), + LinkType::Semantic, + 0.5, + ); // Without phonological cue (just semantic) let semantic_only = network.activate("temporary_concept", 1.0); @@ -741,11 +1056,21 @@ fn test_tot_phonological_cue_resolution() { fn test_tot_age_related_increase() { // "Young" network - strong connections let mut young_network = ActivationNetwork::new(); - young_network.add_edge("cue".to_string(), "target_word".to_string(), LinkType::Semantic, 0.85); + young_network.add_edge( + "cue".to_string(), + "target_word".to_string(), + LinkType::Semantic, + 0.85, + ); // "Older" network - weakened connections let mut older_network = ActivationNetwork::new(); - older_network.add_edge("cue".to_string(), "target_word".to_string(), LinkType::Semantic, 0.45); + older_network.add_edge( + "cue".to_string(), + "target_word".to_string(), + LinkType::Semantic, + 0.45, + ); let young_results = young_network.activate("cue", 1.0); let older_results = older_network.activate("cue", 1.0); @@ -778,8 +1103,18 @@ fn test_tot_blocking_effect() { let mut network = ActivationNetwork::new(); // Target and blocker both connected to cue - network.add_edge("definition_cue".to_string(), "blocker_word".to_string(), LinkType::Semantic, 0.9); // Strong - network.add_edge("definition_cue".to_string(), "target_word".to_string(), LinkType::Semantic, 0.5); // Weaker + network.add_edge( + "definition_cue".to_string(), + "blocker_word".to_string(), + LinkType::Semantic, + 0.9, + ); // Strong + network.add_edge( + "definition_cue".to_string(), + "target_word".to_string(), + LinkType::Semantic, + 0.5, + ); // Weaker let results = network.activate("definition_cue", 1.0); @@ -819,13 +1154,15 @@ fn test_drm_basic_false_memory() { let mut network = ActivationNetwork::new(); // Study list - all semantically related to "sleep" (the critical lure) - let study_words = ["bed", "rest", "awake", "tired", "dream", "pillow", "blanket", "nap"]; + let study_words = [ + "bed", "rest", "awake", "tired", "dream", "pillow", "blanket", "nap", + ]; // Create associations from study words to the critical lure for word in &study_words { network.add_edge( word.to_string(), - "sleep".to_string(), // Critical lure (never studied) + "sleep".to_string(), // Critical lure (never studied) LinkType::Semantic, 0.7, ); @@ -833,7 +1170,12 @@ fn test_drm_basic_false_memory() { // Also link study words to a study context for word in &study_words { - network.add_edge("study_list".to_string(), word.to_string(), LinkType::Temporal, 0.8); + network.add_edge( + "study_list".to_string(), + word.to_string(), + LinkType::Temporal, + 0.8, + ); } // Activate from study context @@ -856,15 +1198,45 @@ fn test_drm_convergent_activation() { let mut network = ActivationNetwork::new(); // Multiple words converging on critical lure - network.add_edge("cold".to_string(), "hot".to_string(), LinkType::Semantic, 0.8); - network.add_edge("warm".to_string(), "hot".to_string(), LinkType::Semantic, 0.85); - network.add_edge("heat".to_string(), "hot".to_string(), LinkType::Semantic, 0.9); - network.add_edge("burn".to_string(), "hot".to_string(), LinkType::Semantic, 0.75); - network.add_edge("fire".to_string(), "hot".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "cold".to_string(), + "hot".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "warm".to_string(), + "hot".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "heat".to_string(), + "hot".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "burn".to_string(), + "hot".to_string(), + LinkType::Semantic, + 0.75, + ); + network.add_edge( + "fire".to_string(), + "hot".to_string(), + LinkType::Semantic, + 0.8, + ); // Study context for word in ["cold", "warm", "heat", "burn", "fire"] { - network.add_edge("study_context".to_string(), word.to_string(), LinkType::Temporal, 0.8); + network.add_edge( + "study_context".to_string(), + word.to_string(), + LinkType::Temporal, + 0.8, + ); } let results = network.activate("study_context", 1.0); @@ -894,20 +1266,80 @@ fn test_drm_semantic_relatedness() { let mut network = ActivationNetwork::new(); // Strongly related list - network.add_edge("strong_list".to_string(), "nurse".to_string(), LinkType::Temporal, 0.8); - network.add_edge("strong_list".to_string(), "hospital".to_string(), LinkType::Temporal, 0.8); - network.add_edge("strong_list".to_string(), "medicine".to_string(), LinkType::Temporal, 0.8); - network.add_edge("nurse".to_string(), "doctor".to_string(), LinkType::Semantic, 0.9); - network.add_edge("hospital".to_string(), "doctor".to_string(), LinkType::Semantic, 0.85); - network.add_edge("medicine".to_string(), "doctor".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "strong_list".to_string(), + "nurse".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "strong_list".to_string(), + "hospital".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "strong_list".to_string(), + "medicine".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "nurse".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "hospital".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "medicine".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.8, + ); // Weakly related list - network.add_edge("weak_list".to_string(), "white".to_string(), LinkType::Temporal, 0.8); - network.add_edge("weak_list".to_string(), "smart".to_string(), LinkType::Temporal, 0.8); - network.add_edge("weak_list".to_string(), "office".to_string(), LinkType::Temporal, 0.8); - network.add_edge("white".to_string(), "doctor".to_string(), LinkType::Semantic, 0.3); // Weak - network.add_edge("smart".to_string(), "doctor".to_string(), LinkType::Semantic, 0.25); // Weak - network.add_edge("office".to_string(), "doctor".to_string(), LinkType::Semantic, 0.2); // Weak + network.add_edge( + "weak_list".to_string(), + "white".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "weak_list".to_string(), + "smart".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "weak_list".to_string(), + "office".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "white".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.3, + ); // Weak + network.add_edge( + "smart".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.25, + ); // Weak + network.add_edge( + "office".to_string(), + "doctor".to_string(), + LinkType::Semantic, + 0.2, + ); // Weak let strong_results = network.activate("strong_list", 1.0); let weak_results = network.activate("weak_list", 1.0); @@ -940,11 +1372,26 @@ fn test_drm_source_monitoring() { let mut network = ActivationNetwork::new(); // Studied word - network.add_edge("study_session".to_string(), "actually_studied".to_string(), LinkType::Temporal, 0.85); + network.add_edge( + "study_session".to_string(), + "actually_studied".to_string(), + LinkType::Temporal, + 0.85, + ); // Critical lure (activated through association, not direct study) - network.add_edge("study_session".to_string(), "related_word".to_string(), LinkType::Temporal, 0.8); - network.add_edge("related_word".to_string(), "critical_lure".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "study_session".to_string(), + "related_word".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "related_word".to_string(), + "critical_lure".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("study_session", 1.0); @@ -963,10 +1410,16 @@ fn test_drm_source_monitoring() { // Both should have activation (source confusion) assert!(studied_activation > 0.0, "Studied word should be activated"); - assert!(lure_activation > 0.0, "Lure should also be activated, creating potential source confusion"); + assert!( + lure_activation > 0.0, + "Lure should also be activated, creating potential source confusion" + ); // The lure should have distance > 1 (indirect) but this is the only way to distinguish - let lure_result = results.iter().find(|r| r.memory_id == "critical_lure").unwrap(); + let lure_result = results + .iter() + .find(|r| r.memory_id == "critical_lure") + .unwrap(); assert!( lure_result.distance > 1, "Lure came through indirect activation (distance {}), but feels like direct memory", @@ -982,31 +1435,117 @@ fn test_drm_list_length_effect() { let mut network = ActivationNetwork::new(); // Short list - network.add_edge("short_list".to_string(), "word1".to_string(), LinkType::Temporal, 0.8); - network.add_edge("short_list".to_string(), "word2".to_string(), LinkType::Temporal, 0.8); - network.add_edge("word1".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word2".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); + network.add_edge( + "short_list".to_string(), + "word1".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "short_list".to_string(), + "word2".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "word1".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word2".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); // Long list - network.add_edge("long_list".to_string(), "word_a".to_string(), LinkType::Temporal, 0.8); - network.add_edge("long_list".to_string(), "word_b".to_string(), LinkType::Temporal, 0.8); - network.add_edge("long_list".to_string(), "word_c".to_string(), LinkType::Temporal, 0.8); - network.add_edge("long_list".to_string(), "word_d".to_string(), LinkType::Temporal, 0.8); - network.add_edge("long_list".to_string(), "word_e".to_string(), LinkType::Temporal, 0.8); - network.add_edge("long_list".to_string(), "word_f".to_string(), LinkType::Temporal, 0.8); - network.add_edge("word_a".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_b".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_c".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_d".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_e".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); - network.add_edge("word_f".to_string(), "lure".to_string(), LinkType::Semantic, 0.7); + network.add_edge( + "long_list".to_string(), + "word_a".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "long_list".to_string(), + "word_b".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "long_list".to_string(), + "word_c".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "long_list".to_string(), + "word_d".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "long_list".to_string(), + "word_e".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "long_list".to_string(), + "word_f".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "word_a".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_b".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_c".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_d".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_e".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "word_f".to_string(), + "lure".to_string(), + LinkType::Semantic, + 0.7, + ); let short_results = network.activate("short_list", 1.0); let long_results = network.activate("long_list", 1.0); // Count total activation paths to lure - let short_lure_count = short_results.iter().filter(|r| r.memory_id == "lure").count(); - let long_lure_count = long_results.iter().filter(|r| r.memory_id == "lure").count(); + let short_lure_count = short_results + .iter() + .filter(|r| r.memory_id == "lure") + .count(); + let long_lure_count = long_results + .iter() + .filter(|r| r.memory_id == "lure") + .count(); assert!( long_lure_count >= short_lure_count, @@ -1029,10 +1568,20 @@ fn test_interference_proactive() { let mut network = ActivationNetwork::new(); // Old learning (List A paired associates) - network.add_edge("cue_word".to_string(), "old_response".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "cue_word".to_string(), + "old_response".to_string(), + LinkType::Semantic, + 0.8, + ); // New learning (List B with same cues) - network.add_edge("cue_word".to_string(), "new_response".to_string(), LinkType::Semantic, 0.5); // Weaker - harder to learn + network.add_edge( + "cue_word".to_string(), + "new_response".to_string(), + LinkType::Semantic, + 0.5, + ); // Weaker - harder to learn let results = network.activate("cue_word", 1.0); @@ -1065,10 +1614,20 @@ fn test_interference_retroactive() { let mut network = ActivationNetwork::new(); // Original learning - network.add_edge("stimulus".to_string(), "original_memory".to_string(), LinkType::Semantic, 0.7); + network.add_edge( + "stimulus".to_string(), + "original_memory".to_string(), + LinkType::Semantic, + 0.7, + ); // Interpolated learning (new, stronger) - network.add_edge("stimulus".to_string(), "new_memory".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "stimulus".to_string(), + "new_memory".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("stimulus", 1.0); @@ -1101,12 +1660,32 @@ fn test_interference_similarity_based() { let mut network = ActivationNetwork::new(); // Similar competing memories - network.add_edge("topic".to_string(), "similar_fact_1".to_string(), LinkType::Semantic, 0.75); - network.add_edge("topic".to_string(), "similar_fact_2".to_string(), LinkType::Semantic, 0.73); - network.add_edge("topic".to_string(), "similar_fact_3".to_string(), LinkType::Semantic, 0.71); + network.add_edge( + "topic".to_string(), + "similar_fact_1".to_string(), + LinkType::Semantic, + 0.75, + ); + network.add_edge( + "topic".to_string(), + "similar_fact_2".to_string(), + LinkType::Semantic, + 0.73, + ); + network.add_edge( + "topic".to_string(), + "similar_fact_3".to_string(), + LinkType::Semantic, + 0.71, + ); // Dissimilar memory (should be easier to distinguish) - network.add_edge("topic".to_string(), "dissimilar_fact".to_string(), LinkType::Semantic, 0.80); + network.add_edge( + "topic".to_string(), + "dissimilar_fact".to_string(), + LinkType::Semantic, + 0.80, + ); let results = network.activate("topic", 1.0); @@ -1160,13 +1739,23 @@ fn test_interference_fan_effect() { // Low fan: concept with few associations let mut low_fan_network = ActivationNetwork::with_config(config.clone()); - low_fan_network.add_edge("low_fan_concept".to_string(), "fact_1".to_string(), LinkType::Semantic, 0.9); - low_fan_network.add_edge("low_fan_concept".to_string(), "fact_2".to_string(), LinkType::Semantic, 0.85); + low_fan_network.add_edge( + "low_fan_concept".to_string(), + "fact_1".to_string(), + LinkType::Semantic, + 0.9, + ); + low_fan_network.add_edge( + "low_fan_concept".to_string(), + "fact_2".to_string(), + LinkType::Semantic, + 0.85, + ); // High fan: concept with many associations let mut high_fan_network = ActivationNetwork::with_config(config); for i in 1..=8 { - let strength = 0.9 - (i as f64 * 0.05); // Decreasing strength due to fan + let strength = 0.9 - (i as f64 * 0.05); // Decreasing strength due to fan high_fan_network.add_edge( "high_fan_concept".to_string(), format!("fact_{}", i), @@ -1179,16 +1768,16 @@ fn test_interference_fan_effect() { let high_results = high_fan_network.activate("high_fan_concept", 1.0); // Average activation for low fan - let low_avg: f64 = low_results.iter().map(|r| r.activation).sum::() - / low_results.len().max(1) as f64; + let low_avg: f64 = + low_results.iter().map(|r| r.activation).sum::() / low_results.len().max(1) as f64; // Average activation for high fan - let high_avg: f64 = high_results.iter().map(|r| r.activation).sum::() - / high_results.len().max(1) as f64; + let high_avg: f64 = + high_results.iter().map(|r| r.activation).sum::() / high_results.len().max(1) as f64; // Low fan should have higher average activation (less interference) assert!( - low_avg >= high_avg * 0.8, // Allow some tolerance + low_avg >= high_avg * 0.8, // Allow some tolerance "Low fan concept should have higher average activation: low={}, high={}", low_avg, high_avg @@ -1203,12 +1792,32 @@ fn test_interference_release_from_pi() { let mut network = ActivationNetwork::new(); // Build up PI with category A items - network.add_edge("trial_1".to_string(), "category_a_item_1".to_string(), LinkType::Temporal, 0.7); - network.add_edge("trial_2".to_string(), "category_a_item_2".to_string(), LinkType::Temporal, 0.6); // PI building - network.add_edge("trial_3".to_string(), "category_a_item_3".to_string(), LinkType::Temporal, 0.5); // More PI + network.add_edge( + "trial_1".to_string(), + "category_a_item_1".to_string(), + LinkType::Temporal, + 0.7, + ); + network.add_edge( + "trial_2".to_string(), + "category_a_item_2".to_string(), + LinkType::Temporal, + 0.6, + ); // PI building + network.add_edge( + "trial_3".to_string(), + "category_a_item_3".to_string(), + LinkType::Temporal, + 0.5, + ); // More PI // Category shift (release from PI) - network.add_edge("trial_4".to_string(), "category_b_item_1".to_string(), LinkType::Temporal, 0.85); // Recovery + network.add_edge( + "trial_4".to_string(), + "category_b_item_1".to_string(), + LinkType::Temporal, + 0.85, + ); // Recovery let trial_3_results = network.activate("trial_3", 1.0); let trial_4_results = network.activate("trial_4", 1.0); diff --git a/tests/e2e/tests/cognitive/spreading_activation_tests.rs b/tests/e2e/tests/cognitive/spreading_activation_tests.rs index 78b5fcb..2f91ffe 100644 --- a/tests/e2e/tests/cognitive/spreading_activation_tests.rs +++ b/tests/e2e/tests/cognitive/spreading_activation_tests.rs @@ -5,10 +5,10 @@ //! //! Based on Collins & Loftus (1975) spreading activation theory. +use std::collections::HashSet; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; -use std::collections::HashSet; // ============================================================================ // MULTI-HOP ASSOCIATION TESTS (6 tests) @@ -41,9 +41,7 @@ fn test_spreading_finds_hidden_chains() { let results = network.activate("rust_async", 1.0); // Should find "green_threads" through the chain - let found_green_threads = results - .iter() - .any(|r| r.memory_id == "green_threads"); + let found_green_threads = results.iter().any(|r| r.memory_id == "green_threads"); assert!( found_green_threads, @@ -71,9 +69,24 @@ fn test_spreading_3_hop_discovery() { let mut network = ActivationNetwork::with_config(config); // Create a 3-hop chain: A -> B -> C -> D - network.add_edge("memory_a".to_string(), "memory_b".to_string(), LinkType::Semantic, 0.9); - network.add_edge("memory_b".to_string(), "memory_c".to_string(), LinkType::Semantic, 0.9); - network.add_edge("memory_c".to_string(), "memory_d".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "memory_a".to_string(), + "memory_b".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "memory_b".to_string(), + "memory_c".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "memory_c".to_string(), + "memory_d".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("memory_a", 1.0); @@ -147,8 +160,18 @@ fn test_spreading_beats_similarity_search() { fn test_spreading_path_tracking() { let mut network = ActivationNetwork::new(); - network.add_edge("start".to_string(), "middle".to_string(), LinkType::Semantic, 0.9); - network.add_edge("middle".to_string(), "end".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "start".to_string(), + "middle".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "middle".to_string(), + "end".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("start", 1.0); @@ -167,10 +190,30 @@ fn test_spreading_convergent_activation() { let mut network = ActivationNetwork::new(); // Create convergent paths: A -> B -> D and A -> C -> D - network.add_edge("source".to_string(), "path1".to_string(), LinkType::Semantic, 0.8); - network.add_edge("source".to_string(), "path2".to_string(), LinkType::Semantic, 0.8); - network.add_edge("path1".to_string(), "target".to_string(), LinkType::Semantic, 0.8); - network.add_edge("path2".to_string(), "target".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "source".to_string(), + "path1".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "source".to_string(), + "path2".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "path1".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "path2".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.8, + ); let results = network.activate("source", 1.0); @@ -244,13 +287,35 @@ fn test_activation_decay_per_hop() { let results = network.activate("a", 1.0); - let b_activation = results.iter().find(|r| r.memory_id == "b").map(|r| r.activation).unwrap_or(0.0); - let c_activation = results.iter().find(|r| r.memory_id == "c").map(|r| r.activation).unwrap_or(0.0); - let d_activation = results.iter().find(|r| r.memory_id == "d").map(|r| r.activation).unwrap_or(0.0); + let b_activation = results + .iter() + .find(|r| r.memory_id == "b") + .map(|r| r.activation) + .unwrap_or(0.0); + let c_activation = results + .iter() + .find(|r| r.memory_id == "c") + .map(|r| r.activation) + .unwrap_or(0.0); + let d_activation = results + .iter() + .find(|r| r.memory_id == "d") + .map(|r| r.activation) + .unwrap_or(0.0); // Each hop should reduce activation by decay factor (0.7) - assert!(b_activation > c_activation, "Activation should decay: b ({}) > c ({})", b_activation, c_activation); - assert!(c_activation > d_activation, "Activation should decay: c ({}) > d ({})", c_activation, d_activation); + assert!( + b_activation > c_activation, + "Activation should decay: b ({}) > c ({})", + b_activation, + c_activation + ); + assert!( + c_activation > d_activation, + "Activation should decay: c ({}) > d ({})", + c_activation, + d_activation + ); // Verify approximate decay rate (allowing for floating point) let ratio_bc = c_activation / b_activation; @@ -289,8 +354,16 @@ fn test_activation_decay_factor_configurable() { let high_results = high_network.activate("a", 1.0); let low_results = low_network.activate("a", 1.0); - let high_c = high_results.iter().find(|r| r.memory_id == "c").map(|r| r.activation).unwrap_or(0.0); - let low_c = low_results.iter().find(|r| r.memory_id == "c").map(|r| r.activation).unwrap_or(0.0); + let high_c = high_results + .iter() + .find(|r| r.memory_id == "c") + .map(|r| r.activation) + .unwrap_or(0.0); + let low_c = low_results + .iter() + .find(|r| r.memory_id == "c") + .map(|r| r.activation) + .unwrap_or(0.0); assert!( high_c > low_c, @@ -320,10 +393,8 @@ fn test_activation_distance_law() { let results = network.activate("n0", 1.0); // Collect activations by distance - let mut activations_by_distance: Vec<(u32, f64)> = results - .iter() - .map(|r| (r.distance, r.activation)) - .collect(); + let mut activations_by_distance: Vec<(u32, f64)> = + results.iter().map(|r| (r.distance, r.activation)).collect(); activations_by_distance.sort_by_key(|(d, _)| *d); // Verify monotonic decrease with distance @@ -559,9 +630,21 @@ fn test_link_type_weights() { let results = network.activate("event", 1.0); // Verify different activations based on edge strength - let semantic_act = results.iter().find(|r| r.memory_id == "semantic_link").map(|r| r.activation).unwrap_or(0.0); - let temporal_act = results.iter().find(|r| r.memory_id == "temporal_link").map(|r| r.activation).unwrap_or(0.0); - let causal_act = results.iter().find(|r| r.memory_id == "causal_link").map(|r| r.activation).unwrap_or(0.0); + let semantic_act = results + .iter() + .find(|r| r.memory_id == "semantic_link") + .map(|r| r.activation) + .unwrap_or(0.0); + let temporal_act = results + .iter() + .find(|r| r.memory_id == "temporal_link") + .map(|r| r.activation) + .unwrap_or(0.0); + let causal_act = results + .iter() + .find(|r| r.memory_id == "causal_link") + .map(|r| r.activation) + .unwrap_or(0.0); // Semantic (0.9) > Causal (0.7) > Temporal (0.5) assert!( @@ -617,10 +700,30 @@ fn test_network_builds_from_semantic_similarity() { // These would typically be built from embedding similarity // Rust async ecosystem - network.add_edge("async_rust".to_string(), "tokio".to_string(), LinkType::Semantic, 0.9); - network.add_edge("async_rust".to_string(), "async_await".to_string(), LinkType::Semantic, 0.95); - network.add_edge("tokio".to_string(), "runtime".to_string(), LinkType::Semantic, 0.8); - network.add_edge("tokio".to_string(), "spawn".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "async_rust".to_string(), + "tokio".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "async_rust".to_string(), + "async_await".to_string(), + LinkType::Semantic, + 0.95, + ); + network.add_edge( + "tokio".to_string(), + "runtime".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "tokio".to_string(), + "spawn".to_string(), + LinkType::Semantic, + 0.85, + ); assert_eq!(network.node_count(), 5); assert_eq!(network.edge_count(), 4); @@ -642,9 +745,24 @@ fn test_network_builds_from_temporal_proximity() { // Events that happened close in time // Morning standup sequence - network.add_edge("standup".to_string(), "jira_update".to_string(), LinkType::Temporal, 0.9); - network.add_edge("jira_update".to_string(), "code_review".to_string(), LinkType::Temporal, 0.85); - network.add_edge("code_review".to_string(), "merge_pr".to_string(), LinkType::Temporal, 0.8); + network.add_edge( + "standup".to_string(), + "jira_update".to_string(), + LinkType::Temporal, + 0.9, + ); + network.add_edge( + "jira_update".to_string(), + "code_review".to_string(), + LinkType::Temporal, + 0.85, + ); + network.add_edge( + "code_review".to_string(), + "merge_pr".to_string(), + LinkType::Temporal, + 0.8, + ); // Verify temporal chain let results = network.activate("standup", 1.0); @@ -748,6 +866,13 @@ fn test_network_batch_construction() { let distance_1: Vec<_> = results.iter().filter(|r| r.distance == 1).collect(); let distance_2: Vec<_> = results.iter().filter(|r| r.distance == 2).collect(); - assert_eq!(distance_1.len(), 3, "Should have 3 nodes at distance 1 (cargo, ownership, traits)"); - assert!(distance_2.len() >= 4, "Should have at least 4 nodes at distance 2"); + assert_eq!( + distance_1.len(), + 3, + "Should have 3 nodes at distance 1 (cargo, ownership, traits)" + ); + assert!( + distance_2.len() >= 4, + "Should have at least 4 nodes at distance 2" + ); } diff --git a/tests/e2e/tests/extreme/adversarial_tests.rs b/tests/e2e/tests/extreme/adversarial_tests.rs index 2fcc042..c179d65 100644 --- a/tests/e2e/tests/extreme/adversarial_tests.rs +++ b/tests/e2e/tests/extreme/adversarial_tests.rs @@ -11,12 +11,12 @@ //! //! Based on security testing principles and fuzzing methodologies +use chrono::Utc; +use vestige_core::neuroscience::hippocampal_index::HippocampalIndex; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; use vestige_core::neuroscience::synaptic_tagging::SynapticTaggingSystem; -use vestige_core::neuroscience::hippocampal_index::HippocampalIndex; -use chrono::Utc; // ============================================================================ // MALFORMED INPUT HANDLING (2 tests) @@ -30,8 +30,18 @@ fn test_adversarial_empty_inputs() { let mut network = ActivationNetwork::new(); // Empty string node IDs - network.add_edge("".to_string(), "target".to_string(), LinkType::Semantic, 0.5); - network.add_edge("source".to_string(), "".to_string(), LinkType::Semantic, 0.5); + network.add_edge( + "".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.5, + ); + network.add_edge( + "source".to_string(), + "".to_string(), + LinkType::Semantic, + 0.5, + ); network.add_edge("".to_string(), "".to_string(), LinkType::Semantic, 0.5); // Should handle gracefully @@ -40,8 +50,18 @@ fn test_adversarial_empty_inputs() { let _ = results.len(); // Whitespace-only IDs - network.add_edge(" ".to_string(), "normal".to_string(), LinkType::Semantic, 0.6); - network.add_edge("\t\n".to_string(), "normal".to_string(), LinkType::Temporal, 0.5); + network.add_edge( + " ".to_string(), + "normal".to_string(), + LinkType::Semantic, + 0.6, + ); + network.add_edge( + "\t\n".to_string(), + "normal".to_string(), + LinkType::Temporal, + 0.5, + ); let whitespace_results = network.activate(" ", 1.0); let _ = whitespace_results.len(); @@ -65,16 +85,24 @@ fn test_adversarial_extremely_long_inputs() { let long_id_1: String = "a".repeat(10000); let long_id_2: String = "b".repeat(10000); - network.add_edge(long_id_1.clone(), long_id_2.clone(), LinkType::Semantic, 0.8); + network.add_edge( + long_id_1.clone(), + long_id_2.clone(), + LinkType::Semantic, + 0.8, + ); // Should handle long IDs let results = network.activate(&long_id_1, 1.0); assert_eq!(results.len(), 1, "Should find connection to long_id_2"); - assert_eq!(results[0].memory_id, long_id_2, "Result should have correct long ID"); + assert_eq!( + results[0].memory_id, long_id_2, + "Result should have correct long ID" + ); // Test with hippocampal index let index = HippocampalIndex::new(); - let very_long_content = "word ".repeat(50000); // ~300KB of text + let very_long_content = "word ".repeat(50000); // ~300KB of text let result = index.index_memory( "long_content_memory", @@ -100,18 +128,18 @@ fn test_adversarial_unicode_handling() { // Various Unicode edge cases let unicode_ids = vec![ - "简体中文", // Chinese - "日本語テキスト", // Japanese - "한국어", // Korean - "مرحبا", // Arabic (RTL) - "שלום", // Hebrew (RTL) - "🦀🔥💯", // Emojis - "Ã̲̊", // Combining characters - "\u{200B}", // Zero-width space - "\u{FEFF}", // BOM - "a\u{0308}", // 'a' with combining umlaut - "🏳️‍🌈", // Emoji sequence with ZWJ - "\u{202E}reversed\u{202C}", // RTL override + "简体中文", // Chinese + "日本語テキスト", // Japanese + "한국어", // Korean + "مرحبا", // Arabic (RTL) + "שלום", // Hebrew (RTL) + "🦀🔥💯", // Emojis + "Ã̲̊", // Combining characters + "\u{200B}", // Zero-width space + "\u{FEFF}", // BOM + "a\u{0308}", // 'a' with combining umlaut + "🏳️‍🌈", // Emoji sequence with ZWJ + "\u{202E}reversed\u{202C}", // RTL override ]; for (i, id) in unicode_ids.iter().enumerate() { @@ -153,13 +181,13 @@ fn test_adversarial_control_characters() { // IDs with embedded control characters let control_ids = vec![ - "before\0after", // Null byte - "line1\nline2", // Newline - "tab\there", // Tab - "return\rhere", // Carriage return - "bell\x07ring", // Bell - "escape\x1B[31m", // ANSI escape - "backspace\x08x", // Backspace + "before\0after", // Null byte + "line1\nline2", // Newline + "tab\there", // Tab + "return\rhere", // Carriage return + "bell\x07ring", // Bell + "escape\x1B[31m", // ANSI escape + "backspace\x08x", // Backspace ]; for (i, id) in control_ids.iter().enumerate() { @@ -227,9 +255,11 @@ fn test_adversarial_weight_boundaries() { let results = network.activate("hub", 1.0); // Higher weights should produce higher activation - let mut activations: Vec<(&str, f64)> = weight_cases.iter() + let mut activations: Vec<(&str, f64)> = weight_cases + .iter() .filter_map(|(name, _)| { - results.iter() + results + .iter() .find(|r| r.memory_id == format!("weight_{}", name)) .map(|r| (*name, r.activation)) }) @@ -249,7 +279,8 @@ fn test_adversarial_weight_boundaries() { } // Zero weight edges might not propagate activation at all - let zero_activation = results.iter() + let zero_activation = results + .iter() .find(|r| r.memory_id == "weight_zero") .map(|r| r.activation); @@ -307,10 +338,7 @@ fn test_adversarial_config_boundaries() { zero_hops_net.add_edge("a".to_string(), "b".to_string(), LinkType::Semantic, 0.9); let zero_results = zero_hops_net.activate("a", 1.0); - assert!( - zero_results.is_empty(), - "Zero max_hops should find nothing" - ); + assert!(zero_results.is_empty(), "Zero max_hops should find nothing"); } // ============================================================================ @@ -332,9 +360,24 @@ fn test_adversarial_cyclic_graphs() { let mut no_cycle_net = ActivationNetwork::with_config(no_cycle_config); // Create a simple cycle: A -> B -> C -> A - no_cycle_net.add_edge("cycle_a".to_string(), "cycle_b".to_string(), LinkType::Semantic, 0.9); - no_cycle_net.add_edge("cycle_b".to_string(), "cycle_c".to_string(), LinkType::Semantic, 0.9); - no_cycle_net.add_edge("cycle_c".to_string(), "cycle_a".to_string(), LinkType::Semantic, 0.9); + no_cycle_net.add_edge( + "cycle_a".to_string(), + "cycle_b".to_string(), + LinkType::Semantic, + 0.9, + ); + no_cycle_net.add_edge( + "cycle_b".to_string(), + "cycle_c".to_string(), + LinkType::Semantic, + 0.9, + ); + no_cycle_net.add_edge( + "cycle_c".to_string(), + "cycle_a".to_string(), + LinkType::Semantic, + 0.9, + ); let start = std::time::Instant::now(); let results = no_cycle_net.activate("cycle_a", 1.0); @@ -387,10 +430,20 @@ fn test_adversarial_self_loops() { let mut network = ActivationNetwork::new(); // Create self-loop - network.add_edge("self_loop".to_string(), "self_loop".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "self_loop".to_string(), + "self_loop".to_string(), + LinkType::Semantic, + 0.9, + ); // Also connect to other nodes - network.add_edge("self_loop".to_string(), "other".to_string(), LinkType::Semantic, 0.7); + network.add_edge( + "self_loop".to_string(), + "other".to_string(), + LinkType::Semantic, + 0.7, + ); let start = std::time::Instant::now(); let results = network.activate("self_loop", 1.0); @@ -423,7 +476,12 @@ fn test_adversarial_special_numeric_values() { // We're testing that the system doesn't crash // Normal edge for baseline - network.add_edge("normal".to_string(), "target".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "normal".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.8, + ); // Test activation with edge case values // (The implementation should clamp or validate these) @@ -457,5 +515,8 @@ fn test_adversarial_special_numeric_values() { // Edge should still exist and be valid let assoc = network.get_associations("normal"); - assert!(!assoc.is_empty(), "Edge should still exist after negative reinforce attempt"); + assert!( + !assoc.is_empty(), + "Edge should still exist after negative reinforce attempt" + ); } diff --git a/tests/e2e/tests/extreme/chaos_tests.rs b/tests/e2e/tests/extreme/chaos_tests.rs index 86f1dd6..5811f6a 100644 --- a/tests/e2e/tests/extreme/chaos_tests.rs +++ b/tests/e2e/tests/extreme/chaos_tests.rs @@ -13,15 +13,13 @@ //! Based on Chaos Engineering principles (Netflix, 2011) use chrono::{Duration, Utc}; +use vestige_core::neuroscience::hippocampal_index::{HippocampalIndex, IndexQuery}; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; use vestige_core::neuroscience::synaptic_tagging::{ CaptureWindow, ImportanceEvent, SynapticTaggingConfig, SynapticTaggingSystem, }; -use vestige_core::neuroscience::hippocampal_index::{ - HippocampalIndex, IndexQuery, -}; // ============================================================================ // RANDOM OPERATION SEQUENCE TESTS (2 tests) @@ -68,11 +66,7 @@ fn test_chaos_random_operation_sequence() { // Interleave reinforcement if i >= 7 { - network2.reinforce_edge( - &format!("node_{}", i - 7), - &format!("node_{}", i % 50), - 0.1, - ); + network2.reinforce_edge(&format!("node_{}", i - 7), &format!("node_{}", i % 50), 0.1); } } @@ -135,7 +129,10 @@ fn test_chaos_add_remove_cycles() { // Verify system still works let results = network.activate(&format!("stable_{}", cycle % 20), 1.0); - assert!(!results.is_empty(), "System should remain functional during chaos"); + assert!( + !results.is_empty(), + "System should remain functional during chaos" + ); } // Final activation should still work @@ -229,7 +226,12 @@ fn test_chaos_continuous_growth_under_load() { let mut network = ActivationNetwork::new(); // Initial seed - network.add_edge("root".to_string(), "child_0".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "root".to_string(), + "child_0".to_string(), + LinkType::Semantic, + 0.8, + ); // Continuously grow while querying for iteration in 0..500 { @@ -270,10 +272,7 @@ fn test_chaos_continuous_growth_under_load() { ); let final_results = network.activate("root", 1.0); - assert!( - !final_results.is_empty(), - "Final activation should succeed" - ); + assert!(!final_results.is_empty(), "Final activation should succeed"); } // ============================================================================ @@ -286,8 +285,8 @@ fn test_chaos_continuous_growth_under_load() { #[test] fn test_chaos_deep_chain_handling() { let config = ActivationConfig { - decay_factor: 0.95, // High to allow deep traversal - max_hops: 100, // Allow deep exploration + decay_factor: 0.95, // High to allow deep traversal + max_hops: 100, // Allow deep exploration min_threshold: 0.001, // Low threshold allow_cycles: false, }; @@ -299,7 +298,7 @@ fn test_chaos_deep_chain_handling() { format!("deep_{}", i), format!("deep_{}", i + 1), LinkType::Semantic, - 0.99, // Very strong links + 0.99, // Very strong links ); } @@ -389,21 +388,21 @@ fn test_chaos_high_fanout_handling() { /// Validates that the capture window handles edge cases correctly. #[test] fn test_chaos_capture_window_edge_cases() { - let window = CaptureWindow::new(9.0, 2.0); // 9 hours back, 2 forward + let window = CaptureWindow::new(9.0, 2.0); // 9 hours back, 2 forward let event_time = Utc::now(); // Test exact boundary conditions let test_cases = vec![ // (hours offset, expected in window) - (0.0, true), // Exactly at event - (8.99, true), // Just inside back window - (9.0, true), // At back boundary - (9.01, false), // Just outside back window - (-1.99, true), // Just inside forward window - (-2.0, true), // At forward boundary - (-2.01, false), // Just outside forward window - (100.0, false), // Way outside - (-100.0, false), // Way outside forward + (0.0, true), // Exactly at event + (8.99, true), // Just inside back window + (9.0, true), // At back boundary + (9.01, false), // Just outside back window + (-1.99, true), // Just inside forward window + (-2.0, true), // At forward boundary + (-2.01, false), // Just outside forward window + (100.0, false), // Way outside + (-100.0, false), // Way outside forward ]; for (hours_offset, expected) in test_cases { @@ -441,7 +440,7 @@ fn test_chaos_ancient_memories() { let mut stc = SynapticTaggingSystem::with_config(config); // Tag memories at various ages - stc.tag_memory("very_old"); // Will be tagged "now" for testing + stc.tag_memory("very_old"); // Will be tagged "now" for testing stc.tag_memory("old"); stc.tag_memory("recent"); @@ -478,11 +477,17 @@ fn test_chaos_isolated_subsystem_failures() { // Query non-existent node should return empty, not crash let results = network.activate("nonexistent", 1.0); - assert!(results.is_empty(), "Non-existent node should return empty results"); + assert!( + results.is_empty(), + "Non-existent node should return empty results" + ); // System should still work after "failed" query let valid_results = network.activate("a", 1.0); - assert!(!valid_results.is_empty(), "System should work after handling missing node"); + assert!( + !valid_results.is_empty(), + "System should work after handling missing node" + ); // Test 2: STC with edge case inputs let mut stc = SynapticTaggingSystem::new(); diff --git a/tests/e2e/tests/extreme/mathematical_tests.rs b/tests/e2e/tests/extreme/mathematical_tests.rs index 7a9aadc..e2d7f8c 100644 --- a/tests/e2e/tests/extreme/mathematical_tests.rs +++ b/tests/e2e/tests/extreme/mathematical_tests.rs @@ -9,14 +9,14 @@ //! //! Based on mathematical foundations of memory systems and neuroscience -use vestige_core::neuroscience::spreading_activation::{ - ActivationConfig, ActivationNetwork, LinkType, -}; +use chrono::{Duration, Utc}; +use std::collections::HashMap; use vestige_core::neuroscience::hippocampal_index::{ BarcodeGenerator, HippocampalIndex, INDEX_EMBEDDING_DIM, }; -use chrono::{Duration, Utc}; -use std::collections::HashMap; +use vestige_core::neuroscience::spreading_activation::{ + ActivationConfig, ActivationNetwork, LinkType, +}; // ============================================================================ // EXPONENTIAL DECAY VALIDATION (1 test) @@ -43,7 +43,7 @@ fn test_math_exponential_decay_law() { format!("node_{}", i), format!("node_{}", i + 1), LinkType::Semantic, - 1.0, // Unit weight to isolate decay effect + 1.0, // Unit weight to isolate decay effect ); } @@ -218,10 +218,10 @@ fn test_math_activation_bounds() { // Total activation should be bounded // (for a tree with decay d, total <= 1 / (1 - d) for geometric series) let total_activation: f64 = results.iter().map(|r| r.activation).sum(); - let theoretical_max = 1.0 / (1.0 - 0.8); // = 5.0 for infinite series + let theoretical_max = 1.0 / (1.0 - 0.8); // = 5.0 for infinite series assert!( - total_activation < theoretical_max * 3.0, // Allow margin for fan-out and multi-source + total_activation < theoretical_max * 3.0, // Allow margin for fan-out and multi-source "Total activation should be bounded: {} < {}", total_activation, theoretical_max * 3.0 @@ -276,7 +276,8 @@ fn test_math_barcode_statistics() { // Test 3: Content fingerprints should be mostly unique // (with 10000 samples, collision probability is low for good hash) - let unique_fingerprints: std::collections::HashSet = fingerprints.iter().copied().collect(); + let unique_fingerprints: std::collections::HashSet = + fingerprints.iter().copied().collect(); let uniqueness_ratio = unique_fingerprints.len() as f64 / num_barcodes as f64; assert!( @@ -322,9 +323,7 @@ fn test_math_embedding_dimensions() { let now = Utc::now(); // Create full-size embedding (384 dimensions) - let full_embedding: Vec = (0..384) - .map(|i| (i as f32 / 384.0).sin()) - .collect(); + let full_embedding: Vec = (0..384).map(|i| (i as f32 / 384.0).sin()).collect(); // Index memory with embedding let result = index.index_memory( @@ -340,8 +339,7 @@ fn test_math_embedding_dimensions() { // Verify index stats show correct dimensions let stats = index.stats(); assert_eq!( - stats.index_dimensions, - INDEX_EMBEDDING_DIM, + stats.index_dimensions, INDEX_EMBEDDING_DIM, "Index should use compressed embedding dimension ({})", INDEX_EMBEDDING_DIM ); diff --git a/tests/e2e/tests/extreme/proof_of_superiority.rs b/tests/e2e/tests/extreme/proof_of_superiority.rs index 7875a7e..a63acc1 100644 --- a/tests/e2e/tests/extreme/proof_of_superiority.rs +++ b/tests/e2e/tests/extreme/proof_of_superiority.rs @@ -10,6 +10,10 @@ //! Each test demonstrates a capability that traditional systems cannot match. use chrono::{Duration, Utc}; +use std::collections::{HashMap, HashSet}; +use vestige_core::neuroscience::hippocampal_index::{ + HippocampalIndex, INDEX_EMBEDDING_DIM, IndexQuery, +}; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; @@ -17,10 +21,6 @@ use vestige_core::neuroscience::synaptic_tagging::{ CaptureWindow, ImportanceEvent, ImportanceEventType, SynapticTaggingConfig, SynapticTaggingSystem, }; -use vestige_core::neuroscience::hippocampal_index::{ - HippocampalIndex, IndexQuery, INDEX_EMBEDDING_DIM, -}; -use std::collections::{HashMap, HashSet}; // ============================================================================ // RETROACTIVE IMPORTANCE - UNIQUE TO VESTIGE (1 test) @@ -43,7 +43,7 @@ fn test_proof_retroactive_importance_unique() { min_tag_strength: 0.2, max_cluster_size: 100, enable_clustering: true, - auto_decay: false, // Disable for test stability + auto_decay: false, // Disable for test stability cleanup_interval_hours: 24.0, }; @@ -75,7 +75,7 @@ fn test_proof_retroactive_importance_unique() { event_type: ImportanceEventType::EmotionalContent, memory_id: Some("bob_departure".to_string()), timestamp: Utc::now(), - strength: 1.0, // Maximum importance + strength: 1.0, // Maximum importance context: Some("BREAKING: Bob is leaving the company!".to_string()), }; @@ -90,7 +90,8 @@ fn test_proof_retroactive_importance_unique() { ); // 2. Earlier Bob-related memories should be captured - let captured_ids: HashSet<_> = capture_result.captured_memories + let captured_ids: HashSet<_> = capture_result + .captured_memories .iter() .map(|c| c.memory_id.as_str()) .collect(); @@ -170,20 +171,51 @@ fn test_proof_multi_hop_beats_similarity() { let mut network = ActivationNetwork::with_config(config); // Create the knowledge chain (domain knowledge graph) - network.add_edge("memory_leaks".to_string(), "reference_counting".to_string(), LinkType::Causal, 0.9); - network.add_edge("reference_counting".to_string(), "arc_weak".to_string(), LinkType::Semantic, 0.85); - network.add_edge("arc_weak".to_string(), "cyclic_references".to_string(), LinkType::Semantic, 0.9); - network.add_edge("cyclic_references".to_string(), "solution_weak_refs".to_string(), LinkType::Semantic, 0.95); + network.add_edge( + "memory_leaks".to_string(), + "reference_counting".to_string(), + LinkType::Causal, + 0.9, + ); + network.add_edge( + "reference_counting".to_string(), + "arc_weak".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "arc_weak".to_string(), + "cyclic_references".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "cyclic_references".to_string(), + "solution_weak_refs".to_string(), + LinkType::Semantic, + 0.95, + ); // Also add some direct but less relevant connections - network.add_edge("memory_leaks".to_string(), "valgrind".to_string(), LinkType::Semantic, 0.7); - network.add_edge("memory_leaks".to_string(), "profiling".to_string(), LinkType::Semantic, 0.6); + network.add_edge( + "memory_leaks".to_string(), + "valgrind".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "memory_leaks".to_string(), + "profiling".to_string(), + LinkType::Semantic, + 0.6, + ); // === SPREADING ACTIVATION SEARCH === let spreading_results = network.activate("memory_leaks", 1.0); // Collect what spreading activation found - let spreading_found: HashSet<_> = spreading_results.iter() + let spreading_found: HashSet<_> = spreading_results + .iter() .map(|r| r.memory_id.as_str()) .collect(); @@ -198,7 +230,9 @@ fn test_proof_multi_hop_beats_similarity() { impl MockSimilaritySearch { fn search(&self, query: &str, top_k: usize) -> Vec<(&str, f64)> { let query_emb = self.embeddings.get(query).unwrap(); - let mut results: Vec<_> = self.embeddings.iter() + let mut results: Vec<_> = self + .embeddings + .iter() .filter(|(k, _)| k.as_str() != query) .map(|(k, emb)| { let sim = cosine_sim(query_emb, emb); @@ -223,17 +257,27 @@ fn test_proof_multi_hop_beats_similarity() { } // Create mock embeddings where memory_leaks and cyclic_references are ORTHOGONAL - let mut mock = MockSimilaritySearch { embeddings: HashMap::new() }; - mock.embeddings.insert("memory_leaks".to_string(), vec![1.0, 0.0, 0.0, 0.0]); - mock.embeddings.insert("reference_counting".to_string(), vec![0.7, 0.7, 0.0, 0.0]); - mock.embeddings.insert("arc_weak".to_string(), vec![0.0, 0.7, 0.7, 0.0]); - mock.embeddings.insert("cyclic_references".to_string(), vec![0.0, 0.0, 0.0, 1.0]); // ORTHOGONAL! - mock.embeddings.insert("solution_weak_refs".to_string(), vec![0.0, 0.0, 0.2, 0.9]); - mock.embeddings.insert("valgrind".to_string(), vec![0.8, 0.2, 0.0, 0.0]); // Similar - mock.embeddings.insert("profiling".to_string(), vec![0.6, 0.4, 0.0, 0.0]); // Similar + let mut mock = MockSimilaritySearch { + embeddings: HashMap::new(), + }; + mock.embeddings + .insert("memory_leaks".to_string(), vec![1.0, 0.0, 0.0, 0.0]); + mock.embeddings + .insert("reference_counting".to_string(), vec![0.7, 0.7, 0.0, 0.0]); + mock.embeddings + .insert("arc_weak".to_string(), vec![0.0, 0.7, 0.7, 0.0]); + mock.embeddings + .insert("cyclic_references".to_string(), vec![0.0, 0.0, 0.0, 1.0]); // ORTHOGONAL! + mock.embeddings + .insert("solution_weak_refs".to_string(), vec![0.0, 0.0, 0.2, 0.9]); + mock.embeddings + .insert("valgrind".to_string(), vec![0.8, 0.2, 0.0, 0.0]); // Similar + mock.embeddings + .insert("profiling".to_string(), vec![0.6, 0.4, 0.0, 0.0]); // Similar let similarity_results = mock.search("memory_leaks", 10); - let similarity_found: HashSet<_> = similarity_results.iter() + let similarity_found: HashSet<_> = similarity_results + .iter() .filter(|(_, sim)| *sim > 0.3) .map(|(id, _)| *id) .collect(); @@ -257,13 +301,16 @@ fn test_proof_multi_hop_beats_similarity() { ); // Verify the discovery path - let solution_result = spreading_results.iter() + let solution_result = spreading_results + .iter() .find(|r| r.memory_id == "solution_weak_refs") .expect("Should find solution"); assert_eq!(solution_result.distance, 4, "Solution is 4 hops away"); assert!( - solution_result.path.contains(&"cyclic_references".to_string()), + solution_result + .path + .contains(&"cyclic_references".to_string()), "Path should include cyclic_references" ); } @@ -291,8 +338,12 @@ fn test_proof_hippocampal_indexing_efficiency() { let _ = index.index_memory( &format!("memory_{}", i), - &format!("This is memory number {} with content about topic {} and subtopic {}", - i, i % 50, i % 10), + &format!( + "This is memory number {} with content about topic {} and subtopic {}", + i, + i % 50, + i % 10 + ), "fact", now, Some(embedding), @@ -356,7 +407,7 @@ fn test_proof_hippocampal_indexing_efficiency() { ); // 5. Memory efficiency - let memory_per_full = 384 * 4; // 384 floats * 4 bytes + let memory_per_full = 384 * 4; // 384 floats * 4 bytes let memory_per_index = INDEX_EMBEDDING_DIM * 4; let savings_per_memory = memory_per_full - memory_per_index; let total_savings = savings_per_memory * NUM_MEMORIES; @@ -389,10 +440,10 @@ fn test_proof_temporal_capture_accuracy() { // Memories encoded BEFORE the important event can be captured let backward_tests = vec![ - (Duration::hours(1), true, 1.0), // 1h before - should be captured with high prob - (Duration::hours(4), true, 0.9), // 4h before - should be captured - (Duration::hours(8), true, 0.5), // 8h before - edge of window - (Duration::hours(9), true, 0.0), // 9h before - at boundary + (Duration::hours(1), true, 1.0), // 1h before - should be captured with high prob + (Duration::hours(4), true, 0.9), // 4h before - should be captured + (Duration::hours(8), true, 0.5), // 8h before - edge of window + (Duration::hours(9), true, 0.0), // 9h before - at boundary (Duration::hours(10), false, 0.0), // 10h before - outside window ]; @@ -401,7 +452,8 @@ fn test_proof_temporal_capture_accuracy() { let in_window = window.is_in_window(memory_time, event_time); assert_eq!( - in_window, *should_be_in_window, + in_window, + *should_be_in_window, "PROOF: Memory {}h before event: in_window={}, expected={}", offset.num_hours(), in_window, @@ -421,10 +473,10 @@ fn test_proof_temporal_capture_accuracy() { // Brief period for memories encoded shortly after let forward_tests = vec![ - (Duration::minutes(30), true), // 30min after - in window - (Duration::hours(1), true), // 1h after - in window - (Duration::hours(2), true), // 2h after - at boundary - (Duration::hours(3), false), // 3h after - outside + (Duration::minutes(30), true), // 30min after - in window + (Duration::hours(1), true), // 1h after - in window + (Duration::hours(2), true), // 2h after - at boundary + (Duration::hours(3), false), // 3h after - outside ]; for (offset, should_be_in_window) in &forward_tests { @@ -432,7 +484,8 @@ fn test_proof_temporal_capture_accuracy() { let in_window = window.is_in_window(memory_time, event_time); assert_eq!( - in_window, *should_be_in_window, + in_window, + *should_be_in_window, "PROOF: Memory {}min after event: in_window={}, expected={}", offset.num_minutes(), in_window, @@ -472,7 +525,10 @@ fn test_proof_comprehensive_capability_summary() { let result = stc.trigger_prp(event); let has_retroactive = result.has_captures(); - assert!(has_retroactive, "Capability 1: Retroactive importance - PROVEN"); + assert!( + has_retroactive, + "Capability 1: Retroactive importance - PROVEN" + ); // === CAPABILITY 2: Multi-Hop Discovery === // Traditional: NO (1-hop only) | Vestige: YES (configurable depth) @@ -492,25 +548,36 @@ fn test_proof_comprehensive_capability_summary() { let results = network.activate("a", 1.0); let max_distance = results.iter().map(|r| r.distance).max().unwrap_or(0); - assert!(max_distance >= 4, "Capability 2: Multi-hop discovery (4+ hops) - PROVEN"); + assert!( + max_distance >= 4, + "Capability 2: Multi-hop discovery (4+ hops) - PROVEN" + ); // === CAPABILITY 3: Compressed Hippocampal Index === // Traditional: Full embeddings | Vestige: Compressed index let compression = 384.0 / INDEX_EMBEDDING_DIM as f64; - assert!(compression >= 2.0, "Capability 3: Hippocampal compression ({:.1}x) - PROVEN", compression); + assert!( + compression >= 2.0, + "Capability 3: Hippocampal compression ({:.1}x) - PROVEN", + compression + ); // === CAPABILITY 4: Asymmetric Temporal Windows === // Traditional: NO temporal reasoning | Vestige: Biologically-grounded windows let window = CaptureWindow::new(9.0, 2.0); let asymmetric = 9.0 / 2.0; - assert!(asymmetric > 4.0, "Capability 4: Asymmetric capture windows ({}:1) - PROVEN", asymmetric); + assert!( + asymmetric > 4.0, + "Capability 4: Asymmetric capture windows ({}:1) - PROVEN", + asymmetric + ); // === CAPABILITY 5: Path Tracking === // Traditional: Returns items only | Vestige: Returns full association paths - let path_result = &results[results.len() - 1]; // Furthest result + let path_result = &results[results.len() - 1]; // Furthest result let has_path = !path_result.path.is_empty(); assert!(has_path, "Capability 5: Association path tracking - PROVEN"); @@ -518,10 +585,30 @@ fn test_proof_comprehensive_capability_summary() { // Traditional: Single similarity metric | Vestige: Multiple link types let mut typed_network = ActivationNetwork::new(); - typed_network.add_edge("event".to_string(), "cause".to_string(), LinkType::Causal, 0.9); - typed_network.add_edge("event".to_string(), "time".to_string(), LinkType::Temporal, 0.9); - typed_network.add_edge("event".to_string(), "concept".to_string(), LinkType::Semantic, 0.9); - typed_network.add_edge("event".to_string(), "location".to_string(), LinkType::Spatial, 0.9); + typed_network.add_edge( + "event".to_string(), + "cause".to_string(), + LinkType::Causal, + 0.9, + ); + typed_network.add_edge( + "event".to_string(), + "time".to_string(), + LinkType::Temporal, + 0.9, + ); + typed_network.add_edge( + "event".to_string(), + "concept".to_string(), + LinkType::Semantic, + 0.9, + ); + typed_network.add_edge( + "event".to_string(), + "location".to_string(), + LinkType::Spatial, + 0.9, + ); let typed_results = typed_network.activate("event", 1.0); let link_types: HashSet<_> = typed_results.iter().map(|r| r.link_type).collect(); diff --git a/tests/e2e/tests/extreme/research_validation_tests.rs b/tests/e2e/tests/extreme/research_validation_tests.rs index 2fe7716..11006c9 100644 --- a/tests/e2e/tests/extreme/research_validation_tests.rs +++ b/tests/e2e/tests/extreme/research_validation_tests.rs @@ -10,6 +10,10 @@ //! Each test cites the specific research findings being validated. use chrono::{Duration, Utc}; +use std::collections::HashSet; +use vestige_core::neuroscience::hippocampal_index::{ + HippocampalIndex, HippocampalIndexConfig, IndexQuery, +}; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; @@ -17,10 +21,6 @@ use vestige_core::neuroscience::synaptic_tagging::{ CaptureWindow, ImportanceEvent, ImportanceEventType, SynapticTaggingConfig, SynapticTaggingSystem, }; -use vestige_core::neuroscience::hippocampal_index::{ - HippocampalIndex, HippocampalIndexConfig, IndexQuery, -}; -use std::collections::HashSet; // ============================================================================ // COLLINS & LOFTUS (1975) SPREADING ACTIVATION VALIDATION (1 test) @@ -39,7 +39,7 @@ use std::collections::HashSet; #[test] fn test_research_collins_loftus_spreading_activation() { let config = ActivationConfig { - decay_factor: 0.75, // Semantic distance decay + decay_factor: 0.75, // Semantic distance decay max_hops: 4, min_threshold: 0.05, allow_cycles: false, @@ -48,29 +48,91 @@ fn test_research_collins_loftus_spreading_activation() { // Recreate classic semantic network from the paper // "Fire truck" example: fire_truck -> red -> roses, fire_truck -> vehicle - network.add_edge("fire_truck".to_string(), "red".to_string(), LinkType::Semantic, 0.9); - network.add_edge("fire_truck".to_string(), "vehicle".to_string(), LinkType::Semantic, 0.85); - network.add_edge("fire_truck".to_string(), "fire".to_string(), LinkType::Semantic, 0.9); - network.add_edge("red".to_string(), "roses".to_string(), LinkType::Semantic, 0.7); - network.add_edge("red".to_string(), "cherries".to_string(), LinkType::Semantic, 0.65); - network.add_edge("red".to_string(), "apples".to_string(), LinkType::Semantic, 0.7); - network.add_edge("vehicle".to_string(), "car".to_string(), LinkType::Semantic, 0.8); - network.add_edge("vehicle".to_string(), "truck".to_string(), LinkType::Semantic, 0.85); - network.add_edge("fire".to_string(), "flames".to_string(), LinkType::Semantic, 0.9); - network.add_edge("fire".to_string(), "heat".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "fire_truck".to_string(), + "red".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "fire_truck".to_string(), + "vehicle".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "fire_truck".to_string(), + "fire".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "red".to_string(), + "roses".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "red".to_string(), + "cherries".to_string(), + LinkType::Semantic, + 0.65, + ); + network.add_edge( + "red".to_string(), + "apples".to_string(), + LinkType::Semantic, + 0.7, + ); + network.add_edge( + "vehicle".to_string(), + "car".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "vehicle".to_string(), + "truck".to_string(), + LinkType::Semantic, + 0.85, + ); + network.add_edge( + "fire".to_string(), + "flames".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "fire".to_string(), + "heat".to_string(), + LinkType::Semantic, + 0.8, + ); // Add convergent paths (multiple routes to same concept) - network.add_edge("apples".to_string(), "fruit".to_string(), LinkType::Semantic, 0.9); - network.add_edge("cherries".to_string(), "fruit".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "apples".to_string(), + "fruit".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "cherries".to_string(), + "fruit".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("fire_truck", 1.0); // Validation 1: Direct connections (distance 1) have highest activation - let red_activation = results.iter() + let red_activation = results + .iter() .find(|r| r.memory_id == "red") .map(|r| r.activation) .unwrap_or(0.0); - let roses_activation = results.iter() + let roses_activation = results + .iter() .find(|r| r.memory_id == "roses") .map(|r| r.activation) .unwrap_or(0.0); @@ -83,11 +145,13 @@ fn test_research_collins_loftus_spreading_activation() { ); // Validation 2: Activation decreases with semantic distance - let distance_1: Vec = results.iter() + let distance_1: Vec = results + .iter() .filter(|r| r.distance == 1) .map(|r| r.activation) .collect(); - let distance_2: Vec = results.iter() + let distance_2: Vec = results + .iter() .filter(|r| r.distance == 2) .map(|r| r.activation) .collect(); @@ -107,7 +171,10 @@ fn test_research_collins_loftus_spreading_activation() { assert!(reachable.contains("red"), "Should reach 'red'"); assert!(reachable.contains("vehicle"), "Should reach 'vehicle'"); assert!(reachable.contains("fire"), "Should reach 'fire'"); - assert!(reachable.contains("roses"), "Should reach 'roses' through 'red'"); + assert!( + reachable.contains("roses"), + "Should reach 'roses' through 'red'" + ); // Validation 4: Path information is preserved let roses_result = results.iter().find(|r| r.memory_id == "roses").unwrap(); @@ -135,7 +202,7 @@ fn test_research_collins_loftus_spreading_activation() { #[test] fn test_research_frey_morris_synaptic_tagging() { let config = SynapticTaggingConfig { - capture_window: CaptureWindow::new(9.0, 2.0), // Hours: 9 back, 2 forward + capture_window: CaptureWindow::new(9.0, 2.0), // Hours: 9 back, 2 forward prp_threshold: 0.7, tag_lifetime_hours: 12.0, min_tag_strength: 0.3, @@ -148,7 +215,7 @@ fn test_research_frey_morris_synaptic_tagging() { let mut stc = SynapticTaggingSystem::with_config(config); // Finding 1: Weak stimulation creates tags - stc.tag_memory_with_strength("weak_stim_1", 0.4); // Above min (0.3), weak + stc.tag_memory_with_strength("weak_stim_1", 0.4); // Above min (0.3), weak stc.tag_memory_with_strength("weak_stim_2", 0.5); let stats_after_weak = stc.stats(); @@ -164,7 +231,7 @@ fn test_research_frey_morris_synaptic_tagging() { event_type: ImportanceEventType::EmotionalContent, memory_id: Some("strong_trigger".to_string()), timestamp: Utc::now(), - strength: 0.95, // Above threshold (0.7) + strength: 0.95, // Above threshold (0.7) context: Some("Strong emotional event triggers PRP".to_string()), }; @@ -245,21 +312,26 @@ fn test_research_teyler_rudy_hippocampal_indexing() { .map(|i| ((i as f32 / 100.0) * std::f32::consts::PI).sin()) .collect(); - let barcode = index.index_memory( - "episodic_memory_1", - "Detailed episodic memory content with rich context", - "episodic", - now, - Some(full_embedding.clone()), - ).expect("Should create barcode"); + let barcode = index + .index_memory( + "episodic_memory_1", + "Detailed episodic memory content with rich context", + "episodic", + now, + Some(full_embedding.clone()), + ) + .expect("Should create barcode"); // Barcode should be a valid identifier (u64 ID) // First barcode may have id=0, which is valid - assert!(barcode.creation_hash > 0 || barcode.content_fingerprint > 0, - "T&R Finding 1: Barcode should have valid fingerprints"); + assert!( + barcode.creation_hash > 0 || barcode.content_fingerprint > 0, + "T&R Finding 1: Barcode should have valid fingerprints" + ); // Finding 2: Index points to content (content pointers) - let memory_index = index.get_index("episodic_memory_1") + let memory_index = index + .get_index("episodic_memory_1") .expect("Should retrieve") .expect("Should exist"); @@ -348,7 +420,7 @@ fn test_research_ebbinghaus_forgetting_curve() { let forgetting_curve = |t: f64| -> f64 { // Ebbinghaus formula: R = e^(-t/S) where S is stability - let stability = 2.0; // Memory stability parameter + let stability = 2.0; // Memory stability parameter (-t / stability).exp() }; @@ -368,7 +440,10 @@ fn test_research_ebbinghaus_forgetting_curve() { // Collect activations by "age" let mut age_activations: Vec<(u32, f64)> = Vec::new(); for t in 0..10 { - if let Some(result) = results.iter().find(|r| r.memory_id == format!("memory_age_{}", t)) { + if let Some(result) = results + .iter() + .find(|r| r.memory_id == format!("memory_age_{}", t)) + { age_activations.push((t, result.activation)); } } @@ -387,7 +462,8 @@ fn test_research_ebbinghaus_forgetting_curve() { // Check that differences decrease over time if age_activations.len() >= 3 { let diff_early = age_activations[0].1 - age_activations[1].1; - let diff_late = age_activations[age_activations.len() - 2].1 - age_activations[age_activations.len() - 1].1; + let diff_late = age_activations[age_activations.len() - 2].1 + - age_activations[age_activations.len() - 1].1; // Early differences should be larger (rapid initial forgetting) // But we need to account for near-zero values at the end @@ -403,8 +479,18 @@ fn test_research_ebbinghaus_forgetting_curve() { // Finding 3: Test overlearning (reinforcement) let mut overlearned_network = ActivationNetwork::new(); - overlearned_network.add_edge("study".to_string(), "normal_learning".to_string(), LinkType::Semantic, 0.5); - overlearned_network.add_edge("study".to_string(), "overlearned".to_string(), LinkType::Semantic, 0.5); + overlearned_network.add_edge( + "study".to_string(), + "normal_learning".to_string(), + LinkType::Semantic, + 0.5, + ); + overlearned_network.add_edge( + "study".to_string(), + "overlearned".to_string(), + LinkType::Semantic, + 0.5, + ); // Simulate overlearning with multiple reinforcements for _ in 0..5 { @@ -413,11 +499,13 @@ fn test_research_ebbinghaus_forgetting_curve() { let study_results = overlearned_network.activate("study", 1.0); - let normal_act = study_results.iter() + let normal_act = study_results + .iter() .find(|r| r.memory_id == "normal_learning") .map(|r| r.activation) .unwrap_or(0.0); - let overlearned_act = study_results.iter() + let overlearned_act = study_results + .iter() .find(|r| r.memory_id == "overlearned") .map(|r| r.activation) .unwrap_or(0.0); @@ -447,7 +535,7 @@ fn test_research_ebbinghaus_forgetting_curve() { #[test] fn test_research_fsrs6_properties() { // FSRS-6 default weights - const W20: f64 = 0.1542; // Forgetting curve exponent + const W20: f64 = 0.1542; // Forgetting curve exponent // FSRS-6 retrievability formula fn fsrs6_retrievability(stability: f64, elapsed_days: f64, w20: f64) -> f64 { @@ -455,7 +543,9 @@ fn test_research_fsrs6_properties() { return 1.0; } let factor = 0.9_f64.powf(-1.0 / w20) - 1.0; - (1.0 + factor * elapsed_days / stability).powf(-w20).clamp(0.0, 1.0) + (1.0 + factor * elapsed_days / stability) + .powf(-w20) + .clamp(0.0, 1.0) } // Property 1: R = 0.9 when t = S (by design) diff --git a/tests/e2e/tests/journeys/consolidation_workflow.rs b/tests/e2e/tests/journeys/consolidation_workflow.rs index 6577c89..633c5a3 100644 --- a/tests/e2e/tests/journeys/consolidation_workflow.rs +++ b/tests/e2e/tests/journeys/consolidation_workflow.rs @@ -15,8 +15,8 @@ use chrono::{Duration, Utc}; use vestige_core::{ advanced::dreams::{ - ActivityTracker, ConnectionGraph, ConnectionReason, ConsolidationScheduler, - DreamConfig, DreamMemory, MemoryDreamer, + ActivityTracker, ConnectionGraph, ConnectionReason, ConsolidationScheduler, DreamConfig, + DreamMemory, MemoryDreamer, }, consolidation::SleepConsolidation, }; @@ -82,10 +82,7 @@ fn test_consolidation_detects_idle_periods() { // Initially should be idle (no activity) let stats = scheduler.get_activity_stats(); - assert!( - stats.is_idle, - "Fresh scheduler should be idle" - ); + assert!(stats.is_idle, "Fresh scheduler should be idle"); // Record activity - should no longer be idle scheduler.record_activity(); @@ -93,10 +90,7 @@ fn test_consolidation_detects_idle_periods() { scheduler.record_activity(); let active_stats = scheduler.get_activity_stats(); - assert!( - !active_stats.is_idle, - "Should not be idle after activity" - ); + assert!(!active_stats.is_idle, "Should not be idle after activity"); assert_eq!( active_stats.total_events, 3, "Should track 3 activity events" @@ -176,9 +170,24 @@ fn test_connections_form_between_related_memories() { let mut graph = ConnectionGraph::new(); // Add connections simulating discovered relationships - graph.add_connection("rust_async", "tokio_runtime", 0.9, ConnectionReason::Semantic); - graph.add_connection("tokio_runtime", "green_threads", 0.8, ConnectionReason::Semantic); - graph.add_connection("rust_async", "futures_crate", 0.85, ConnectionReason::SharedConcepts); + graph.add_connection( + "rust_async", + "tokio_runtime", + 0.9, + ConnectionReason::Semantic, + ); + graph.add_connection( + "tokio_runtime", + "green_threads", + 0.8, + ConnectionReason::Semantic, + ); + graph.add_connection( + "rust_async", + "futures_crate", + 0.85, + ConnectionReason::SharedConcepts, + ); // Verify graph structure let stats = graph.get_stats(); @@ -329,9 +338,18 @@ fn test_pruning_removes_weak_memories() { // Verify the config accessor works let config = consolidation.config(); - assert!(!config.enable_pruning, "Default should have pruning disabled"); - assert!(config.pruning_threshold > 0.0, "Should have a threshold configured"); - assert!(config.pruning_min_age_days > 0, "Should have a min age configured"); + assert!( + !config.enable_pruning, + "Default should have pruning disabled" + ); + assert!( + config.pruning_threshold > 0.0, + "Should have a threshold configured" + ); + assert!( + config.pruning_min_age_days > 0, + "Should have a min age configured" + ); } // ============================================================================ @@ -419,22 +437,13 @@ fn test_retention_calculation() { // Full retrieval, max storage let r2 = consolidation.calculate_retention(10.0, 1.0); - assert!( - (r2 - 1.0).abs() < 0.01, - "Max everything should be ~1.0" - ); + assert!((r2 - 1.0).abs() < 0.01, "Max everything should be ~1.0"); // Low retrieval, max storage let r3 = consolidation.calculate_retention(10.0, 0.0); - assert!( - (r3 - 0.3).abs() < 0.01, - "Low retrieval should cap at ~0.3" - ); + assert!((r3 - 0.3).abs() < 0.01, "Low retrieval should cap at ~0.3"); // Both low let r4 = consolidation.calculate_retention(0.0, 0.0); - assert!( - r4 < 0.1, - "Both low should mean low retention" - ); + assert!(r4 < 0.1, "Both low should mean low retention"); } diff --git a/tests/e2e/tests/journeys/import_export.rs b/tests/e2e/tests/journeys/import_export.rs index fbea1ba..91847ff 100644 --- a/tests/e2e/tests/journeys/import_export.rs +++ b/tests/e2e/tests/journeys/import_export.rs @@ -13,9 +13,9 @@ //! 5. User merges memories from multiple sources use chrono::{DateTime, Duration, Utc}; -use vestige_core::memory::IngestInput; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use vestige_core::memory::IngestInput; // ============================================================================ // EXPORT/IMPORT FORMAT @@ -183,7 +183,10 @@ fn test_export_serializes_memories_to_json() { assert!(json.contains("\"metadata\""), "Should contain metadata"); // Verify content is present - assert!(json.contains("Rust ownership"), "Should contain memory content"); + assert!( + json.contains("Rust ownership"), + "Should contain memory content" + ); assert!(json.contains("rust"), "Should contain tags"); // Verify FSRS state @@ -219,12 +222,21 @@ fn test_import_deserializes_json_to_memories() { // Verify memories let mem1 = &imported.memories[0]; - assert!(mem1.content.contains("ownership"), "Content should be preserved"); - assert!(mem1.tags.contains(&"rust".to_string()), "Tags should be preserved"); + assert!( + mem1.content.contains("ownership"), + "Content should be preserved" + ); + assert!( + mem1.tags.contains(&"rust".to_string()), + "Tags should be preserved" + ); assert!(mem1.stability > 0.0, "Stability should be preserved"); // Verify metadata - assert_eq!(imported.metadata.get("project"), Some(&"vestige".to_string())); + assert_eq!( + imported.metadata.get("project"), + Some(&"vestige".to_string()) + ); } // ============================================================================ @@ -268,12 +280,24 @@ fn test_roundtrip_preserves_all_data() { assert_eq!(imported.content, original.content, "Content should match"); assert_eq!(imported.node_type, original.node_type, "Type should match"); assert_eq!(imported.tags, original.tags, "Tags should match"); - assert_eq!(imported.stability, original.stability, "Stability should match"); - assert_eq!(imported.difficulty, original.difficulty, "Difficulty should match"); + assert_eq!( + imported.stability, original.stability, + "Stability should match" + ); + assert_eq!( + imported.difficulty, original.difficulty, + "Difficulty should match" + ); assert_eq!(imported.reps, original.reps, "Reps should match"); assert_eq!(imported.lapses, original.lapses, "Lapses should match"); - assert_eq!(imported.sentiment_score, original.sentiment_score, "Sentiment score should match"); - assert_eq!(imported.sentiment_magnitude, original.sentiment_magnitude, "Sentiment magnitude should match"); + assert_eq!( + imported.sentiment_score, original.sentiment_score, + "Sentiment score should match" + ); + assert_eq!( + imported.sentiment_magnitude, original.sentiment_magnitude, + "Sentiment magnitude should match" + ); assert_eq!(imported.source, original.source, "Source should match"); } @@ -290,11 +314,13 @@ fn test_roundtrip_preserves_all_data() { #[test] fn test_selective_export_by_tags() { // Create memories with different tags - let memories = [ExportedMemory::new("Rust ownership", "concept", vec!["rust", "memory"]), + let memories = [ + ExportedMemory::new("Rust ownership", "concept", vec!["rust", "memory"]), ExportedMemory::new("Python generators", "concept", vec!["python", "generators"]), ExportedMemory::new("Rust borrowing", "concept", vec!["rust", "borrowing"]), ExportedMemory::new("JavaScript async", "concept", vec!["javascript", "async"]), - ExportedMemory::new("Rust async", "concept", vec!["rust", "async"])]; + ExportedMemory::new("Rust async", "concept", vec!["rust", "async"]), + ]; // Filter by "rust" tag let rust_memories: Vec<_> = memories @@ -307,12 +333,14 @@ fn test_selective_export_by_tags() { // Filter by multiple tags (rust AND async) let rust_async_memories: Vec<_> = memories .iter() - .filter(|m| { - m.tags.contains(&"rust".to_string()) && m.tags.contains(&"async".to_string()) - }) + .filter(|m| m.tags.contains(&"rust".to_string()) && m.tags.contains(&"async".to_string())) .collect(); - assert_eq!(rust_async_memories.len(), 1, "Should filter to 1 Rust async memory"); + assert_eq!( + rust_async_memories.len(), + 1, + "Should filter to 1 Rust async memory" + ); assert!(rust_async_memories[0].content.contains("Rust async")); // Export filtered @@ -338,8 +366,14 @@ fn test_selective_export_by_tags() { fn test_import_merges_with_existing_data() { // Simulate existing memories let existing: HashMap = [ - ("1".to_string(), ExportedMemory::new("Rust ownership memory safety", "concept", vec!["rust"])), - ("2".to_string(), ExportedMemory::new("Rust borrowing rules explained", "concept", vec!["rust"])), + ( + "1".to_string(), + ExportedMemory::new("Rust ownership memory safety", "concept", vec!["rust"]), + ), + ( + "2".to_string(), + ExportedMemory::new("Rust borrowing rules explained", "concept", vec!["rust"]), + ), ] .into_iter() .collect(); @@ -427,7 +461,10 @@ fn test_empty_bundle_handling() { // Serialize empty bundle let json = bundle.to_json().unwrap(); - assert!(json.contains("\"memories\": []"), "Should have empty memories array"); + assert!( + json.contains("\"memories\": []"), + "Should have empty memories array" + ); // Deserialize and verify let imported = ExportBundle::from_json(&json).unwrap(); diff --git a/tests/e2e/tests/journeys/ingest_recall_review.rs b/tests/e2e/tests/journeys/ingest_recall_review.rs index fb463b1..cecb5b8 100644 --- a/tests/e2e/tests/journeys/ingest_recall_review.rs +++ b/tests/e2e/tests/journeys/ingest_recall_review.rs @@ -12,9 +12,9 @@ //! 5. User benefits from improved recall over time use vestige_core::{ + consolidation::SleepConsolidation, fsrs::{FSRSScheduler, LearningState, Rating}, memory::{IngestInput, RecallInput, SearchMode}, - consolidation::SleepConsolidation, }; // ============================================================================ @@ -139,7 +139,10 @@ fn test_review_strengthens_memory_with_fsrs() { let result = scheduler.review(&initial_state, Rating::Good, 0.0, None); // Stability should be set from initial parameters - assert!(result.state.stability > 0.0, "Stability should be positive after review"); + assert!( + result.state.stability > 0.0, + "Stability should be positive after review" + ); // Reps should increase assert_eq!(result.state.reps, 1, "Reps should increase after review"); @@ -160,7 +163,10 @@ fn test_review_strengthens_memory_with_fsrs() { again_result.interval <= second_result.interval, "Again rating should reduce interval" ); - assert_eq!(again_result.state.lapses, 1, "Lapses should increase on Again"); + assert_eq!( + again_result.state.lapses, 1, + "Lapses should increase on Again" + ); } // ============================================================================ @@ -184,7 +190,11 @@ fn test_memory_lifecycle_follows_expected_pattern() { // Simulate 10 successful reviews for i in 0..10 { - let elapsed = if i == 0 { 0.0 } else { intervals.last().copied().unwrap_or(1) as f64 }; + let elapsed = if i == 0 { + 0.0 + } else { + intervals.last().copied().unwrap_or(1) as f64 + }; let result = scheduler.review(&state, Rating::Good, elapsed, None); intervals.push(result.interval); state = result.state; @@ -192,7 +202,10 @@ fn test_memory_lifecycle_follows_expected_pattern() { // Verify lifecycle progression assert!(state.reps >= 10, "Should have at least 10 reps"); - assert_eq!(state.lapses, 0, "Should have no lapses with all Good ratings"); + assert_eq!( + state.lapses, 0, + "Should have no lapses with all Good ratings" + ); // Verify interval growth (early intervals may be similar, but should eventually grow) let early_avg: f64 = intervals[..3].iter().map(|&i| i as f64).sum::() / 3.0; @@ -260,10 +273,7 @@ fn test_sentiment_affects_memory_consolidation() { // Test promotion boost let boosted = consolidation.promotion_boost(5.0); - assert!( - boosted > 5.0, - "Promotion should increase storage strength" - ); + assert!(boosted > 5.0, "Promotion should increase storage strength"); assert!( boosted <= 10.0, "Promotion should cap at max storage strength" diff --git a/tests/e2e/tests/journeys/intentions_workflow.rs b/tests/e2e/tests/journeys/intentions_workflow.rs index a9b2b8a..f0530ed 100644 --- a/tests/e2e/tests/journeys/intentions_workflow.rs +++ b/tests/e2e/tests/journeys/intentions_workflow.rs @@ -13,8 +13,8 @@ //! 5. User benefits from context-aware assistance use vestige_core::advanced::intent::{ - ActionType, DetectedIntent, IntentDetector, LearningLevel, MaintenanceType, - OptimizationType, UserAction, + ActionType, DetectedIntent, IntentDetector, LearningLevel, MaintenanceType, OptimizationType, + UserAction, }; // ============================================================================ @@ -89,7 +89,10 @@ fn test_debugging_intent_detection() { // Check intent properties match &result.primary_intent { - DetectedIntent::Debugging { suspected_area, symptoms } => { + DetectedIntent::Debugging { + suspected_area, + symptoms, + } => { assert!(!suspected_area.is_empty(), "Should identify suspected area"); // Symptoms may or may not be captured depending on action order } @@ -129,10 +132,7 @@ fn test_learning_intent_detection() { _ => { // Learning actions should typically detect learning intent // But other intents may score higher in some cases - assert!( - result.confidence > 0.0, - "Should detect some intent" - ); + assert!(result.confidence > 0.0, "Should detect some intent"); } } @@ -169,7 +169,9 @@ fn test_refactoring_intent_detection() { assert!(!target.is_empty(), "Should identify refactoring target"); assert!(!goal.is_empty(), "Should identify refactoring goal"); } - DetectedIntent::NewFeature { related_components, .. } => { + DetectedIntent::NewFeature { + related_components, .. + } => { // Multiple edits could also suggest new feature assert!( related_components.len() >= 0, diff --git a/tests/e2e/tests/journeys/spreading_activation.rs b/tests/e2e/tests/journeys/spreading_activation.rs index d8117a5..7ac345c 100644 --- a/tests/e2e/tests/journeys/spreading_activation.rs +++ b/tests/e2e/tests/journeys/spreading_activation.rs @@ -12,10 +12,10 @@ //! 4. Activation spreads to related memories via association links //! 5. User discovers hidden connections they didn't explicitly search for +use std::collections::HashSet; use vestige_core::neuroscience::spreading_activation::{ ActivationConfig, ActivationNetwork, LinkType, }; -use std::collections::HashSet; // ============================================================================ // HELPER FUNCTIONS @@ -26,17 +26,62 @@ fn create_coding_network() -> ActivationNetwork { let mut network = ActivationNetwork::new(); // Rust ecosystem - network.add_edge("rust".to_string(), "ownership".to_string(), LinkType::Semantic, 0.95); - network.add_edge("rust".to_string(), "borrowing".to_string(), LinkType::Semantic, 0.9); - network.add_edge("rust".to_string(), "cargo".to_string(), LinkType::PartOf, 0.85); - network.add_edge("ownership".to_string(), "memory_safety".to_string(), LinkType::Causal, 0.9); - network.add_edge("borrowing".to_string(), "lifetimes".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "rust".to_string(), + "ownership".to_string(), + LinkType::Semantic, + 0.95, + ); + network.add_edge( + "rust".to_string(), + "borrowing".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "rust".to_string(), + "cargo".to_string(), + LinkType::PartOf, + 0.85, + ); + network.add_edge( + "ownership".to_string(), + "memory_safety".to_string(), + LinkType::Causal, + 0.9, + ); + network.add_edge( + "borrowing".to_string(), + "lifetimes".to_string(), + LinkType::Semantic, + 0.85, + ); // Async ecosystem - network.add_edge("rust".to_string(), "async_rust".to_string(), LinkType::Semantic, 0.8); - network.add_edge("async_rust".to_string(), "tokio".to_string(), LinkType::Semantic, 0.9); - network.add_edge("tokio".to_string(), "runtime".to_string(), LinkType::PartOf, 0.85); - network.add_edge("async_rust".to_string(), "futures".to_string(), LinkType::Semantic, 0.85); + network.add_edge( + "rust".to_string(), + "async_rust".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "async_rust".to_string(), + "tokio".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "tokio".to_string(), + "runtime".to_string(), + LinkType::PartOf, + 0.85, + ); + network.add_edge( + "async_rust".to_string(), + "futures".to_string(), + LinkType::Semantic, + 0.85, + ); network } @@ -52,10 +97,30 @@ fn create_chain_network() -> ActivationNetwork { let mut network = ActivationNetwork::with_config(config); // Create a chain: A -> B -> C -> D -> E - network.add_edge("node_a".to_string(), "node_b".to_string(), LinkType::Semantic, 0.9); - network.add_edge("node_b".to_string(), "node_c".to_string(), LinkType::Semantic, 0.9); - network.add_edge("node_c".to_string(), "node_d".to_string(), LinkType::Semantic, 0.9); - network.add_edge("node_d".to_string(), "node_e".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "node_a".to_string(), + "node_b".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "node_b".to_string(), + "node_c".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "node_c".to_string(), + "node_d".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "node_d".to_string(), + "node_e".to_string(), + LinkType::Semantic, + 0.9, + ); network } @@ -81,7 +146,10 @@ fn test_spreading_finds_hidden_chains() { // Should find all nodes in the chain let found_ids: HashSet<_> = results.iter().map(|r| r.memory_id.as_str()).collect(); - assert!(found_ids.contains("node_b"), "Should find direct neighbor node_b"); + assert!( + found_ids.contains("node_b"), + "Should find direct neighbor node_b" + ); assert!(found_ids.contains("node_c"), "Should find 2-hop node_c"); assert!(found_ids.contains("node_d"), "Should find 3-hop node_d"); assert!(found_ids.contains("node_e"), "Should find 4-hop node_e"); @@ -127,9 +195,21 @@ fn test_activation_decays_with_distance() { let results = network.activate("a", 1.0); - let act_b = results.iter().find(|r| r.memory_id == "b").map(|r| r.activation).unwrap_or(0.0); - let act_c = results.iter().find(|r| r.memory_id == "c").map(|r| r.activation).unwrap_or(0.0); - let act_d = results.iter().find(|r| r.memory_id == "d").map(|r| r.activation).unwrap_or(0.0); + let act_b = results + .iter() + .find(|r| r.memory_id == "b") + .map(|r| r.activation) + .unwrap_or(0.0); + let act_c = results + .iter() + .find(|r| r.memory_id == "c") + .map(|r| r.activation) + .unwrap_or(0.0); + let act_d = results + .iter() + .find(|r| r.memory_id == "d") + .map(|r| r.activation) + .unwrap_or(0.0); // Verify monotonic decrease assert!(act_b > act_c, "b ({:.3}) > c ({:.3})", act_b, act_c); @@ -159,7 +239,12 @@ fn test_edge_reinforcement_hebbian() { let mut network = ActivationNetwork::new(); // Add edge with moderate strength - network.add_edge("concept_a".to_string(), "concept_b".to_string(), LinkType::Semantic, 0.5); + network.add_edge( + "concept_a".to_string(), + "concept_b".to_string(), + LinkType::Semantic, + 0.5, + ); // Get initial associations let initial = network.get_associations("concept_a"); @@ -169,7 +254,10 @@ fn test_edge_reinforcement_hebbian() { .map(|a| a.association_strength) .unwrap_or(0.0); - assert!((initial_strength - 0.5).abs() < 0.01, "Initial should be 0.5"); + assert!( + (initial_strength - 0.5).abs() < 0.01, + "Initial should be 0.5" + ); // Reinforce the connection network.reinforce_edge("concept_a", "concept_b", 0.2); @@ -270,10 +358,30 @@ fn test_different_link_types_affect_activation() { let mut network = ActivationNetwork::new(); // Add edges with different link types - network.add_edge("event".to_string(), "semantic_rel".to_string(), LinkType::Semantic, 0.9); - network.add_edge("event".to_string(), "temporal_rel".to_string(), LinkType::Temporal, 0.8); - network.add_edge("event".to_string(), "causal_rel".to_string(), LinkType::Causal, 0.85); - network.add_edge("event".to_string(), "part_of_rel".to_string(), LinkType::PartOf, 0.7); + network.add_edge( + "event".to_string(), + "semantic_rel".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "event".to_string(), + "temporal_rel".to_string(), + LinkType::Temporal, + 0.8, + ); + network.add_edge( + "event".to_string(), + "causal_rel".to_string(), + LinkType::Causal, + 0.85, + ); + network.add_edge( + "event".to_string(), + "part_of_rel".to_string(), + LinkType::PartOf, + 0.7, + ); let results = network.activate("event", 1.0); @@ -285,10 +393,22 @@ fn test_different_link_types_affect_activation() { assert!(found.contains("part_of_rel")); // Verify link types are preserved - let semantic = results.iter().find(|r| r.memory_id == "semantic_rel").unwrap(); - let temporal = results.iter().find(|r| r.memory_id == "temporal_rel").unwrap(); - let causal = results.iter().find(|r| r.memory_id == "causal_rel").unwrap(); - let part_of = results.iter().find(|r| r.memory_id == "part_of_rel").unwrap(); + let semantic = results + .iter() + .find(|r| r.memory_id == "semantic_rel") + .unwrap(); + let temporal = results + .iter() + .find(|r| r.memory_id == "temporal_rel") + .unwrap(); + let causal = results + .iter() + .find(|r| r.memory_id == "causal_rel") + .unwrap(); + let part_of = results + .iter() + .find(|r| r.memory_id == "part_of_rel") + .unwrap(); assert_eq!(semantic.link_type, LinkType::Semantic); assert_eq!(temporal.link_type, LinkType::Temporal); @@ -339,9 +459,9 @@ fn test_max_hops_limit() { #[test] fn test_minimum_threshold() { let config = ActivationConfig { - decay_factor: 0.5, // 50% decay per hop - max_hops: 10, // High limit - min_threshold: 0.2, // But high threshold + decay_factor: 0.5, // 50% decay per hop + max_hops: 10, // High limit + min_threshold: 0.2, // But high threshold allow_cycles: false, }; let mut network = ActivationNetwork::with_config(config); @@ -370,8 +490,18 @@ fn test_minimum_threshold() { fn test_path_tracking() { let mut network = ActivationNetwork::new(); - network.add_edge("start".to_string(), "middle".to_string(), LinkType::Semantic, 0.9); - network.add_edge("middle".to_string(), "end".to_string(), LinkType::Semantic, 0.9); + network.add_edge( + "start".to_string(), + "middle".to_string(), + LinkType::Semantic, + 0.9, + ); + network.add_edge( + "middle".to_string(), + "end".to_string(), + LinkType::Semantic, + 0.9, + ); let results = network.activate("start", 1.0); @@ -390,10 +520,30 @@ fn test_convergent_paths() { let mut network = ActivationNetwork::new(); // Create convergent paths: source -> a -> target and source -> b -> target - network.add_edge("source".to_string(), "path_a".to_string(), LinkType::Semantic, 0.8); - network.add_edge("source".to_string(), "path_b".to_string(), LinkType::Semantic, 0.8); - network.add_edge("path_a".to_string(), "target".to_string(), LinkType::Semantic, 0.8); - network.add_edge("path_b".to_string(), "target".to_string(), LinkType::Semantic, 0.8); + network.add_edge( + "source".to_string(), + "path_a".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "source".to_string(), + "path_b".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "path_a".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.8, + ); + network.add_edge( + "path_b".to_string(), + "target".to_string(), + LinkType::Semantic, + 0.8, + ); let results = network.activate("source", 1.0); diff --git a/tests/e2e/tests/mcp/protocol_tests.rs b/tests/e2e/tests/mcp/protocol_tests.rs index 20bed76..f3a247f 100644 --- a/tests/e2e/tests/mcp/protocol_tests.rs +++ b/tests/e2e/tests/mcp/protocol_tests.rs @@ -25,9 +25,18 @@ fn test_jsonrpc_request_required_fields() { "params": {} }); - assert_eq!(valid_request["jsonrpc"], "2.0", "jsonrpc version must be 2.0"); - assert!(valid_request["method"].is_string(), "method must be a string"); - assert!(valid_request["id"].is_number(), "id should be present for requests"); + assert_eq!( + valid_request["jsonrpc"], "2.0", + "jsonrpc version must be 2.0" + ); + assert!( + valid_request["method"].is_string(), + "method must be a string" + ); + assert!( + valid_request["id"].is_number(), + "id should be present for requests" + ); } /// Test that JSON-RPC notifications have no id field. @@ -40,7 +49,10 @@ fn test_jsonrpc_notification_has_no_id() { "method": "notifications/initialized" }); - assert!(notification.get("id").is_none(), "Notifications must not have an id field"); + assert!( + notification.get("id").is_none(), + "Notifications must not have an id field" + ); assert_eq!(notification["method"], "notifications/initialized"); } @@ -66,8 +78,14 @@ fn test_jsonrpc_success_response_format() { }); assert_eq!(success_response["jsonrpc"], "2.0"); - assert!(success_response["result"].is_object(), "Success response must have result"); - assert!(success_response.get("error").is_none(), "Success response must not have error"); + assert!( + success_response["result"].is_object(), + "Success response must have result" + ); + assert!( + success_response.get("error").is_none(), + "Success response must not have error" + ); } /// Test JSON-RPC response format for errors. @@ -89,10 +107,22 @@ fn test_jsonrpc_error_response_format() { }); assert_eq!(error_response["jsonrpc"], "2.0"); - assert!(error_response["error"].is_object(), "Error response must have error object"); - assert!(error_response["error"]["code"].is_number(), "Error must have code"); - assert!(error_response["error"]["message"].is_string(), "Error must have message"); - assert!(error_response.get("result").is_none(), "Error response must not have result"); + assert!( + error_response["error"].is_object(), + "Error response must have error object" + ); + assert!( + error_response["error"]["code"].is_number(), + "Error must have code" + ); + assert!( + error_response["error"]["message"].is_string(), + "Error must have message" + ); + assert!( + error_response.get("result").is_none(), + "Error response must not have result" + ); } // ============================================================================ @@ -119,8 +149,12 @@ fn test_standard_jsonrpc_error_codes() { for (code, message) in error_codes { // All standard codes are in the reserved range - assert!((-32700..=-32600).contains(&code), - "Standard error code {} ({}) must be in reserved range", code, message); + assert!( + (-32700..=-32600).contains(&code), + "Standard error code {} ({}) must be in reserved range", + code, + message + ); } } @@ -142,8 +176,12 @@ fn test_mcp_specific_error_codes() { for (code, name) in mcp_error_codes { // MCP-specific codes are in the server error range - assert!((-32099..=-32000).contains(&code), - "MCP error code {} ({}) must be in server error range", code, name); + assert!( + (-32099..=-32000).contains(&code), + "MCP error code {} ({}) must be in server error range", + code, + name + ); } } @@ -177,11 +215,20 @@ fn test_mcp_initialize_request_format() { }); let params = &init_request["params"]; - assert!(params["protocolVersion"].is_string(), "protocolVersion required"); + assert!( + params["protocolVersion"].is_string(), + "protocolVersion required" + ); assert!(params["capabilities"].is_object(), "capabilities required"); assert!(params["clientInfo"].is_object(), "clientInfo required"); - assert!(params["clientInfo"]["name"].is_string(), "clientInfo.name required"); - assert!(params["clientInfo"]["version"].is_string(), "clientInfo.version required"); + assert!( + params["clientInfo"]["name"].is_string(), + "clientInfo.name required" + ); + assert!( + params["clientInfo"]["version"].is_string(), + "clientInfo.version required" + ); } /// Test MCP initialize response format. @@ -206,11 +253,26 @@ fn test_mcp_initialize_response_format() { "instructions": "Vestige is your long-term memory system." }); - assert!(init_response["protocolVersion"].is_string(), "protocolVersion required"); - assert!(init_response["serverInfo"].is_object(), "serverInfo required"); - assert!(init_response["serverInfo"]["name"].is_string(), "serverInfo.name required"); - assert!(init_response["serverInfo"]["version"].is_string(), "serverInfo.version required"); - assert!(init_response["capabilities"].is_object(), "capabilities required"); + assert!( + init_response["protocolVersion"].is_string(), + "protocolVersion required" + ); + assert!( + init_response["serverInfo"].is_object(), + "serverInfo required" + ); + assert!( + init_response["serverInfo"]["name"].is_string(), + "serverInfo.name required" + ); + assert!( + init_response["serverInfo"]["version"].is_string(), + "serverInfo.version required" + ); + assert!( + init_response["capabilities"].is_object(), + "capabilities required" + ); } /// Test that requests before initialization are rejected. @@ -229,8 +291,10 @@ fn test_server_rejects_requests_before_initialize() { } }); - assert_eq!(pre_init_error["error"]["code"], -32003, - "Pre-initialization requests should return ServerNotInitialized error"); + assert_eq!( + pre_init_error["error"]["code"], -32003, + "Pre-initialization requests should return ServerNotInitialized error" + ); } // ============================================================================ @@ -277,9 +341,14 @@ fn test_tools_list_response_format() { for tool in tools { assert!(tool["name"].is_string(), "Tool must have name"); - assert!(tool["inputSchema"].is_object(), "Tool must have inputSchema"); - assert_eq!(tool["inputSchema"]["type"], "object", - "inputSchema must be an object type"); + assert!( + tool["inputSchema"].is_object(), + "Tool must have inputSchema" + ); + assert_eq!( + tool["inputSchema"]["type"], "object", + "inputSchema must be an object type" + ); } } @@ -306,7 +375,10 @@ fn test_tools_call_request_format() { let params = &tools_call_request["params"]; assert!(params["name"].is_string(), "Tool name required"); - assert!(params["arguments"].is_object(), "Arguments should be an object"); + assert!( + params["arguments"].is_object(), + "Arguments should be an object" + ); } /// Test tools/call response format. @@ -328,8 +400,14 @@ fn test_tools_call_response_format() { let content = tools_call_response["content"].as_array().unwrap(); assert!(!content.is_empty(), "Content array should not be empty"); - assert!(content[0]["type"].is_string(), "Content item must have type"); - assert!(content[0]["text"].is_string(), "Text content must have text field"); + assert!( + content[0]["type"].is_string(), + "Content item must have type" + ); + assert!( + content[0]["text"].is_string(), + "Text content must have text field" + ); } // ============================================================================ @@ -407,6 +485,8 @@ fn test_resources_read_response_format() { assert!(!contents.is_empty(), "Contents should not be empty"); assert!(contents[0]["uri"].is_string(), "Content must have uri"); // Must have either text or blob - assert!(contents[0]["text"].is_string() || contents[0]["blob"].is_string(), - "Content must have text or blob"); + assert!( + contents[0]["text"].is_string() || contents[0]["blob"].is_string(), + "Content must have text or blob" + ); } diff --git a/tests/e2e/tests/mcp/tool_tests.rs b/tests/e2e/tests/mcp/tool_tests.rs index 4eaaa17..cbc43b5 100644 --- a/tests/e2e/tests/mcp/tool_tests.rs +++ b/tests/e2e/tests/mcp/tool_tests.rs @@ -3,7 +3,7 @@ //! Comprehensive tests for all MCP tools provided by Vestige. //! Tests cover input validation, execution, and response formats. -use serde_json::{json, Value}; +use serde_json::{Value, json}; // ============================================================================ // HELPER FUNCTIONS @@ -11,7 +11,10 @@ use serde_json::{json, Value}; /// Validate a tool call response structure fn validate_tool_response(response: &Value) { - assert!(response["content"].is_array(), "Response must have content array"); + assert!( + response["content"].is_array(), + "Response must have content array" + ); let content = response["content"].as_array().unwrap(); assert!(!content.is_empty(), "Content array must not be empty"); assert!(content[0]["type"].is_string(), "Content must have type"); @@ -74,7 +77,10 @@ fn test_ingest_tool_rejects_empty_content() { "isError": true }); - assert_eq!(expected_error["isError"], true, "Empty content should be an error"); + assert_eq!( + expected_error["isError"], true, + "Empty content should be an error" + ); } /// Test ingest tool with all optional fields. @@ -193,7 +199,10 @@ fn test_semantic_search_valid() { validate_tool_response(&expected_response); let parsed = parse_response_text(&expected_response); - assert_eq!(parsed["method"], "semantic", "Should indicate semantic search"); + assert_eq!( + parsed["method"], "semantic", + "Should indicate semantic search" + ); } /// Test semantic search handles embedding not ready. @@ -209,7 +218,10 @@ fn test_semantic_search_embedding_not_ready() { }); let parsed = parse_response_text(&expected_response); - assert!(parsed["error"].is_string(), "Should explain embedding not ready"); + assert!( + parsed["error"].is_string(), + "Should explain embedding not ready" + ); assert!(parsed["hint"].is_string(), "Should provide hint"); } @@ -337,7 +349,10 @@ fn test_mark_reviewed_with_rating() { let parsed = parse_response_text(&expected_response); assert_eq!(parsed["success"], true, "Review should succeed"); - assert!(parsed["nextReview"].is_string(), "Should return next review date"); + assert!( + parsed["nextReview"].is_string(), + "Should return next review date" + ); } /// Test mark_reviewed with invalid rating. @@ -382,8 +397,14 @@ fn test_get_stats() { validate_tool_response(&expected_response); let parsed = parse_response_text(&expected_response); - assert!(parsed["totalNodes"].is_number(), "Should return total nodes"); - assert!(parsed["averageRetention"].is_number(), "Should return average retention"); + assert!( + parsed["totalNodes"].is_number(), + "Should return total nodes" + ); + assert!( + parsed["averageRetention"].is_number(), + "Should return average retention" + ); } /// Test health_check returns health status. @@ -431,7 +452,10 @@ fn test_set_intention_basic() { let parsed = parse_response_text(&expected_response); assert_eq!(parsed["success"], true, "Should succeed"); - assert!(parsed["intentionId"].is_string(), "Should return intention ID"); + assert!( + parsed["intentionId"].is_string(), + "Should return intention ID" + ); assert_eq!(parsed["priority"], 3, "High priority should be 3"); } @@ -477,8 +501,14 @@ fn test_check_intentions_with_context() { }); let parsed = parse_response_text(&expected_response); - assert!(parsed["triggered"].is_array(), "Should return triggered intentions"); - assert!(parsed["pending"].is_array(), "Should return pending intentions"); + assert!( + parsed["triggered"].is_array(), + "Should return triggered intentions" + ); + assert!( + parsed["pending"].is_array(), + "Should return pending intentions" + ); } /// Test complete_intention marks as fulfilled. @@ -523,7 +553,10 @@ fn test_list_intentions_with_filter() { }); let parsed = parse_response_text(&expected_response); - assert!(parsed["intentions"].is_array(), "Should return intentions array"); + assert!( + parsed["intentions"].is_array(), + "Should return intentions array" + ); assert_eq!(parsed["status"], "active", "Should echo status filter"); } @@ -553,9 +586,18 @@ fn test_tool_schemas_are_valid_json_schema() { "required": ["content"] }); - assert_eq!(ingest_schema["type"], "object", "Schema must be object type"); - assert!(ingest_schema["properties"].is_object(), "Must have properties"); - assert!(ingest_schema["required"].is_array(), "Must specify required fields"); + assert_eq!( + ingest_schema["type"], "object", + "Schema must be object type" + ); + assert!( + ingest_schema["properties"].is_object(), + "Must have properties" + ); + assert!( + ingest_schema["required"].is_array(), + "Must specify required fields" + ); } /// Test all tools have required inputSchema fields. @@ -575,7 +617,10 @@ fn test_all_tools_have_schema() { ]; for (tool_name, required_fields) in tool_definitions { - assert!(!required_fields.is_empty(), - "Tool {} should have at least one required field", tool_name); + assert!( + !required_fields.is_empty(), + "Tool {} should have at least one required field", + tool_name + ); } }