mirror of
https://github.com/samvallad33/vestige.git
synced 2026-07-24 23:41:01 +02:00
Merge remote-tracking branch 'origin/main' into feat/dashboard-live-max
# Conflicts: # apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css # apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css.br # apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css.gz # apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css # apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css.br # apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css.gz # apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css # apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css.br # apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css.gz # apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css # apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css.br # apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css.gz # apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css # apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css.br # apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css.gz # apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css # apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css.br # apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css.gz # apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css # apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css.br # apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css.gz # apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css # apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css.br # apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css.gz # apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css # apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css.br # apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css.gz # apps/dashboard/build/_app/immutable/assets/7.F0TwMZ5M.css # apps/dashboard/build/_app/immutable/chunks/BLadwbF7.js # apps/dashboard/build/_app/immutable/chunks/C4h_mRt2.js # apps/dashboard/build/_app/immutable/chunks/CqMQEF-F.js # apps/dashboard/build/_app/immutable/chunks/De_e6MzK.js # apps/dashboard/build/_app/immutable/chunks/DzesjbbJ.js # apps/dashboard/build/_app/immutable/nodes/20.DENLzARE.js # apps/dashboard/build/_app/immutable/nodes/22.C719k-1W.js # apps/dashboard/build/_app/immutable/nodes/25.CpxKI_0Q.js # apps/dashboard/build/_app/version.json # apps/dashboard/build/_app/version.json.br # apps/dashboard/build/_app/version.json.gz # apps/dashboard/build/index.html # apps/dashboard/build/index.html.br # apps/dashboard/build/index.html.gz
This commit is contained in:
commit
3200f04de2
279 changed files with 1629 additions and 8218 deletions
64
CHANGELOG.md
64
CHANGELOG.md
|
|
@ -7,6 +7,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed — Auto-consolidation merge: opt-out lever + protected pins honored (#142)
|
||||
|
||||
The background consolidation cycle's auto-dedup pass silently concat-merges
|
||||
near-duplicate memories (cosine ≥ 0.85): it keeps the strongest node, folds the
|
||||
weaker ones in as `[MERGED]` blocks, and **hard-deletes** the originals — with no
|
||||
reflog and no way to turn it off. Two fixes. First, it is now disableable: set
|
||||
`VESTIGE_AUTO_CONSOLIDATE_MERGE=0` (or `false`/`off`/`no`) to suppress it. It
|
||||
remains **on by default** (behavior unchanged), and the `dedup` MCP tool stays
|
||||
available for on-demand, previewable, reversible merges regardless. Second,
|
||||
**protected (pinned) memories are now excluded from this pass** — previously
|
||||
`dedup protect` did nothing here, so a pinned memory could be absorbed or deleted
|
||||
unattended, contradicting the interactive contract that a protected node may only
|
||||
survive a merge, never be absorbed. A protected node is now never an anchor, never
|
||||
a cluster member, and thus never merged into or deleted, whether the lever is on
|
||||
or off.
|
||||
|
||||
## [2.2.1] - 2026-07-02 — "Windows embeddings + backfill safety"
|
||||
|
||||
A focused patch release. Two fixes plus a first-run guide.
|
||||
|
||||
### Fixed — Windows embeddings never initialized (#101)
|
||||
|
||||
The `x86_64-pc-windows-msvc` v2.2.0 binary was built without the `vector-search`
|
||||
feature, so the storage layer's `#[cfg(feature = "vector-search")]` paths compiled
|
||||
out. On Windows this meant new memories got no embedding, semantic search returned
|
||||
nothing, `vestige health` reported "Embedding Service: Not Ready" (0% coverage),
|
||||
and no model download was ever attempted — while v2.1.23 worked on the same machine.
|
||||
The release build now includes `vector-search` on Windows (it compiles cleanly on
|
||||
MSVC because `usearch` is pinned with `features = ["fp16lib"]`). npm and direct
|
||||
downloads are fixed by the same rebuilt release asset. Thanks @Vrakoss for the
|
||||
precise report.
|
||||
|
||||
### Fixed — Retroactive Salience Backfill: bounded promote + opt-out lever (#103)
|
||||
|
||||
The consolidation-pass backfill promoted root-cause memories with an **uncapped**
|
||||
`stability * 1.5` FSRS multiply, and a code comment wrongly claimed it was capped.
|
||||
On a chronically-recurring failure this could inflate a cause's stability without
|
||||
bound, distorting its review schedule. Backfill promotion is now bounded to
|
||||
`MIN(stability * 1.5, stability + 365.0)` (the additive +365-day ceiling the
|
||||
backfill module already computed but never applied), on both the auto-fire and the
|
||||
manual `backfill` tool paths. Auto-fire remains **on by default** (it shipped and
|
||||
was documented in v2.2.0) but is now disableable: set `VESTIGE_BACKFILL_AUTOFIRE=0`
|
||||
(or `false`/`off`/`no`) to turn it off; the manual `backfill` tool + CLI remain
|
||||
available regardless. Thanks @randomnimbus for the report and the initial patch.
|
||||
|
||||
### Added — First-run guide (#83)
|
||||
|
||||
A single `docs/GETTING-STARTED.md` that consolidates install, "what gets saved",
|
||||
how to inspect your memory, and project scoping into one 30-minute first-run path,
|
||||
linked from the README.
|
||||
|
||||
### Credits
|
||||
|
||||
This release was driven by the community:
|
||||
|
||||
- **@Vrakoss** reported the Windows embeddings regression (#101) with a clean,
|
||||
precise repro that pinned the failure immediately.
|
||||
- **@randomnimbus** (Peter Lauzon) reported the backfill safety issue (#103) and
|
||||
contributed the fix — the bounded `promote_memory_backfill` and the
|
||||
`VESTIGE_BACKFILL_AUTOFIRE` lever shipped as they proposed them
|
||||
(co-authored in `f7530af`).
|
||||
|
||||
Thank you both.
|
||||
|
||||
## [2.2.0] - 2026-06-29 — "Retroactive Salience + Tool Consolidation"
|
||||
|
||||
Three independent value streams land together as a coherent release.
|
||||
|
|
|
|||
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -4897,7 +4897,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|||
|
||||
[[package]]
|
||||
name = "vestige-core"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"blake3",
|
||||
|
|
@ -4938,7 +4938,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vestige-mcp"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ exclude = [
|
|||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
edition = "2024"
|
||||
license = "AGPL-3.0-only"
|
||||
repository = "https://github.com/samvallad33/vestige"
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ vestige-mcp --version # prints the installed version
|
|||
vestige stats # prints your memory count (0 on a fresh install)
|
||||
```
|
||||
|
||||
That's the whole install. Per-agent guides (Cursor, VS Code, Windsurf, JetBrains, Xcode, OpenCode, Codex, Claude Desktop) are [here ↓](#-works-with-every-ai-agent).
|
||||
That's the whole install. New here? The [**30-minute first-run guide**](docs/GETTING-STARTED.md) walks you from install to your first backward-reach: what gets saved (and what doesn't), how to inspect your own memory, and how to scope it per project. Per-agent guides (Cursor, VS Code, Windsurf, JetBrains, Xcode, OpenCode, Codex, Claude Desktop) are [here ↓](#-works-with-every-ai-agent).
|
||||
|
||||
Now talk to your agent like it has a memory, because now it does:
|
||||
|
||||
|
|
@ -287,6 +287,7 @@ Registering the server exposes the tools; a short instruction tells the agent *w
|
|||
|
||||
| | |
|
||||
|---|---|
|
||||
| [**Getting Started**](docs/GETTING-STARTED.md) | Your first 30 minutes, start to finish |
|
||||
| [**FAQ**](docs/FAQ.md) | 30+ real questions answered |
|
||||
| [**The Science**](docs/SCIENCE.md) | Every feature, every paper |
|
||||
| [**Storage Modes**](docs/STORAGE.md) | Global · per-project · multi-instance |
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
export const env={}
|
||||
|
|
@ -1 +0,0 @@
|
|||
€export const env={}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.cinema-overlay.svelte-1uwqs3k{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;background:radial-gradient(circle at 50% 40%,#05050f,#010108);display:flex;flex-direction:column}body.cinema-open .graph-stats-pill{display:none}.cinema-canvas.svelte-1uwqs3k{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0}.cinema-top.svelte-1uwqs3k{position:relative;z-index:2;display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:max(.75rem,env(safe-area-inset-top)) 1rem .75rem;flex-wrap:wrap}.cinema-badge.svelte-1uwqs3k{font-size:.65rem;padding:.1rem .45rem;border-radius:999px;border:1px solid rgba(129,140,248,.4);color:var(--color-synapse-glow)}.cinema-badge-gpu.svelte-1uwqs3k{border-color:#14e8c680;color:#14e8c6}.cinema-act.svelte-1uwqs3k{font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--color-dream-glow);opacity:.85}.cinema-plan-card.svelte-1uwqs3k{position:absolute;z-index:3;top:50%;left:50%;transform:translate(-50%,-50%);max-width:520px;padding:1.5rem 1.75rem;border-radius:16px;text-align:center;animation:svelte-1uwqs3k-cinema-plan-in .5s ease both}@keyframes svelte-1uwqs3k-cinema-plan-in{0%{opacity:0;transform:translate(-50%,-46%)}to{opacity:1;transform:translate(-50%,-50%)}}.cinema-plan-kicker.svelte-1uwqs3k{font-size:.65rem;letter-spacing:.18em;text-transform:uppercase;color:var(--color-synapse-glow);margin-bottom:.5rem}.cinema-plan-logline.svelte-1uwqs3k{font-size:clamp(1.05rem,2.2vw,1.4rem);line-height:1.5;color:var(--color-bright);margin:0}.cinema-note.svelte-1uwqs3k{font-size:.78rem;color:var(--color-synapse-glow);opacity:.85;margin:0 0 .6rem;font-style:italic}.cinema-dot.svelte-1uwqs3k{width:8px;height:8px;border-radius:50%;background:var(--color-muted)}.cinema-dot.active.svelte-1uwqs3k{background:#14e8c6;box-shadow:0 0 10px #14e8c6}.cinema-toggle.svelte-1uwqs3k{font-size:.7rem;color:var(--color-dim);display:flex;align-items:center;gap:.3rem;cursor:pointer}.cinema-close.svelte-1uwqs3k{background:transparent;border:1px solid rgba(255,255,255,.15);color:var(--color-text);border-radius:8px;width:32px;height:32px;cursor:pointer}.cinema-caption-wrap.svelte-1uwqs3k{position:relative;z-index:2;margin-top:auto;padding:1rem 1.25rem max(1.25rem,env(safe-area-inset-bottom));max-width:720px}.cinema-chip.svelte-1uwqs3k{display:inline-block;font-size:.65rem;text-transform:uppercase;letter-spacing:.08em;color:var(--color-dream-glow);margin-bottom:.35rem}.cinema-caption.svelte-1uwqs3k{font-size:clamp(1.05rem,2.4vw,1.6rem);line-height:1.45;color:var(--color-bright);text-shadow:0 2px 24px rgba(0,0,0,.9);min-height:2.6em;margin:0 0 .75rem}.cinema-progress.svelte-1uwqs3k{height:3px;background:#ffffff1a;border-radius:3px;overflow:hidden}.cinema-progress-fill.svelte-1uwqs3k{height:100%;background:linear-gradient(90deg,var(--color-synapse),color-mix(in oklch,var(--color-dream),#ff2d55 calc(var(--tension, 0) * 100%)));transition:width .2s linear,background .4s ease}.cinema-beatcount.svelte-1uwqs3k{margin-top:.4rem;display:flex;gap:.75rem;align-items:center}.cinema-replay.svelte-1uwqs3k{background:transparent;border:1px solid rgba(129,140,248,.4);color:var(--color-synapse-glow);border-radius:999px;padding:.15rem .7rem;cursor:pointer;font-size:.75rem}.cinema-dream.svelte-1uwqs3k{color:var(--color-dream-glow);letter-spacing:.08em;animation:svelte-1uwqs3k-cinema-dream-pulse 3s ease-in-out infinite}.cinema-restore.svelte-1uwqs3k{position:absolute;bottom:.6rem;right:.8rem;z-index:95;background:#0a0a1a80;border:1px solid rgba(129,140,248,.25);color:var(--color-muted);border-radius:999px;padding:.2rem .7rem;font-size:.7rem;letter-spacing:.04em;cursor:pointer;opacity:.4;transition:opacity .2s ease}.cinema-restore.svelte-1uwqs3k:hover{opacity:1}@keyframes svelte-1uwqs3k-cinema-dream-pulse{0%,to{opacity:.55}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.cinema-progress-fill.svelte-1uwqs3k{transition:none}}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.sr-only.svelte-q2v96u{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
@keyframes svelte-1jku20k-arc-drift{0%{stroke-dashoffset:0}to{stroke-dashoffset:-32}}.arc-particle{animation-name:svelte-1jku20k-arc-drift;animation-timing-function:linear;animation-iteration-count:infinite}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.dd.svelte-1fd3ybn{position:relative;display:inline-flex;flex-direction:column;gap:.3rem}.dd-label.svelte-1fd3ybn{font-size:.65rem;text-transform:uppercase;letter-spacing:.08em;color:var(--color-muted);padding-left:.15rem}.dd-trigger.svelte-1fd3ybn{display:inline-flex;align-items:center;gap:.5rem;padding:.55rem .7rem .55rem .8rem;min-width:9rem;background:#ffffff08;border:1px solid rgba(99,102,241,.12);border-radius:.75rem;color:var(--color-text);font-size:.8rem;font-family:inherit;cursor:pointer;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:border-color .2s ease,background .2s ease,box-shadow .2s ease}.dd-trigger.svelte-1fd3ybn:hover{border-color:#6366f14d;background:#ffffff0d}.dd-trigger.svelte-1fd3ybn:focus-visible,.dd-trigger.dd-open.svelte-1fd3ybn{outline:none;border-color:#6366f180;box-shadow:0 0 0 3px #6366f11f}.dd-trigger-icon.svelte-1fd3ybn{color:var(--color-synapse-glow);display:inline-flex}.dd-value.svelte-1fd3ybn{flex:1;text-align:left;display:inline-flex;align-items:center;gap:.45rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dd-placeholder.svelte-1fd3ybn{color:var(--color-muted)}.dd-dot.svelte-1fd3ybn{width:.5rem;height:.5rem;border-radius:50%;flex-shrink:0;box-shadow:0 0 6px currentColor}.dd-chevron.svelte-1fd3ybn{color:var(--color-dim);display:inline-flex;transition:transform .25s cubic-bezier(.34,1.56,.64,1)}.dd-chevron-open.svelte-1fd3ybn{transform:rotate(180deg);color:var(--color-synapse-glow)}.dd-menu.svelte-1fd3ybn{position:absolute;top:calc(100% + .4rem);left:0;z-index:60;min-width:100%;max-height:18rem;overflow-y:auto;padding:.35rem;border-radius:.85rem;transform-origin:top center}@media not (prefers-reduced-motion:reduce){.dd-menu.svelte-1fd3ybn{animation:svelte-1fd3ybn-dd-pop .18s cubic-bezier(.34,1.56,.64,1)}@keyframes svelte-1fd3ybn-dd-pop{0%{opacity:0;transform:translateY(-6px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}}.dd-option.svelte-1fd3ybn{width:100%;display:flex;align-items:center;gap:.5rem;padding:.5rem .6rem;border:none;background:transparent;color:var(--color-dim);font-size:.8rem;font-family:inherit;text-align:left;border-radius:.6rem;cursor:pointer;transition:background .12s ease,color .12s ease}.dd-active.svelte-1fd3ybn{background:#6366f124;color:var(--color-text)}.dd-selected.svelte-1fd3ybn{color:var(--color-synapse-glow)}.dd-opt-icon.svelte-1fd3ybn{color:var(--color-dim);display:inline-flex}.dd-active.svelte-1fd3ybn .dd-opt-icon:where(.svelte-1fd3ybn){color:var(--color-synapse-glow)}.dd-opt-label.svelte-1fd3ybn{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dd-badge.svelte-1fd3ybn{font-size:.65rem;font-variant-numeric:tabular-nums;color:var(--color-muted);background:#ffffff0d;padding:.05rem .4rem;border-radius:.4rem}.dd-check.svelte-1fd3ybn{color:var(--color-synapse-glow);display:inline-flex}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.vestige-icon.svelte-1eqehiz{display:inline-block;flex-shrink:0;vertical-align:middle;overflow:visible}@media not (prefers-reduced-motion:reduce){.vestige-icon-draw.svelte-1eqehiz path,.vestige-icon-draw.svelte-1eqehiz circle,.vestige-icon-draw.svelte-1eqehiz rect{stroke-dasharray:64;stroke-dashoffset:64;animation:svelte-1eqehiz-icon-draw .7s cubic-bezier(.65,0,.35,1) forwards}@keyframes svelte-1eqehiz-icon-draw{to{stroke-dashoffset:0}}}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.spine.svelte-8n8iia{position:absolute;left:8%;right:8%;bottom:calc(2.5rem + env(safe-area-inset-bottom,0px));pointer-events:none}.active-label.svelte-8n8iia{text-align:center;margin-bottom:.6rem;font-family:SF Mono,ui-monospace,Menlo,Consolas,monospace;font-size:.72rem;letter-spacing:.08em;color:#cfe9ff;text-shadow:0 0 24px rgba(30,180,255,.35);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.track.svelte-8n8iia{position:relative;height:2px;background:#ffffff12;border-radius:1px}.tick.svelte-8n8iia{position:absolute;top:50%;width:3px;height:10px;transform:translate(-50%,-50%);border-radius:2px;background:#6ef0e6;transition:opacity .2s linear}.tick.hot.svelte-8n8iia{box-shadow:0 0 12px #6ef0e6bf}.tick.backward.svelte-8n8iia{background:#ff4070}.tick.backward.hot.svelte-8n8iia{box-shadow:0 0 12px #ff4070bf}.playhead.svelte-8n8iia{position:absolute;top:50%;width:1.5px;height:16px;transform:translate(-50%,-50%);background:#cfe9ffe6;box-shadow:0 0 10px #1eb4ff80}.verdict.svelte-ssd7yu{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);text-align:center;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;padding:clamp(18px,3vw,40px) clamp(28px,6vw,80px);border-radius:20px;background:radial-gradient(ellipse at center,#05070edb,#05070eb8 60%,#05070e00);pointer-events:none}.k.svelte-ssd7yu{font-size:clamp(13px,1.8vw,18px);color:#9fd0e4;letter-spacing:.16em;text-transform:uppercase}.v.svelte-ssd7yu{font-size:clamp(32px,6.4vw,72px);font-weight:600;margin-top:.12em;line-height:1.05;background:linear-gradient(90deg,#7fe6c0,#6ef0e6,#a6dcff);-webkit-background-clip:text;background-clip:text;color:transparent;filter:drop-shadow(0 0 26px rgba(110,240,220,.45))}.s.svelte-ssd7yu{font-size:clamp(11px,1.5vw,15px);color:#8fb0be;margin-top:.6em;font-family:SF Mono,ui-monospace,Menlo,Consolas,monospace;letter-spacing:.04em}.quarantine.svelte-ssd7yu .k:where(.svelte-ssd7yu){color:#ffb0a6}.quarantine.svelte-ssd7yu .v:where(.svelte-ssd7yu){background:linear-gradient(90deg,#ff6a5e,#ff9d6b,#ffd2a8);filter:drop-shadow(0 0 26px rgba(255,90,70,.45))}.quarantine.svelte-ssd7yu .s:where(.svelte-ssd7yu){color:#d9a49a}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.observatory-canvas.svelte-16248mg{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;display:block;background:#05060a}.fallback.svelte-16248mg{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;text-align:center;padding:0 10%;font-family:SF Mono,ui-monospace,Menlo,Consolas,monospace;pointer-events:auto}.fallback-title.svelte-16248mg{color:#5dcaa5;font-size:.95rem;letter-spacing:.28em;text-shadow:0 0 20px rgba(93,202,165,.4)}.fallback-reason.svelte-16248mg{color:#9fd0e4;font-size:.8rem;letter-spacing:.04em;opacity:.85}.fallback-hint.svelte-16248mg{color:#7c8a97;font-size:.75rem;max-width:34rem;line-height:1.6}.fallback-hint.svelte-16248mg a:where(.svelte-16248mg){color:#cfe9ff;text-decoration:underline;text-underline-offset:3px}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
.header-tile.svelte-162svzm:after{content:"";position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;border-radius:inherit;box-shadow:0 0 18px -2px currentColor;opacity:.35;pointer-events:none}@media not (prefers-reduced-motion:reduce){.header-tile.svelte-162svzm:after{animation:svelte-162svzm-tile-glow 4s ease-in-out infinite}@keyframes svelte-162svzm-tile-glow{0%,to{opacity:.22}50%{opacity:.5}}}.text-balance.svelte-162svzm{text-wrap:balance}.text-pretty.svelte-162svzm{text-wrap:pretty}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
import{h as Q,y as R,z as T,U,aQ as X,Y as L,a as A,f as k,c as f,r as l,X as F,p as Y,j as C,b as D,s as j,g as I,d as G,u as J}from"./CGq8RnJq.js";import"./Bzak7iHL.js";import{s as P}from"./DAau0uzT.js";import{s as K}from"./BbCqB9Us.js";import{i as B}from"./Ccqjq5DS.js";import{s as E}from"./uCQU803Y.js";import{p as m}from"./DV6OI5iy.js";import{I as S}from"./CKbQrCJw.js";function de(t,e,a){Q(()=>{var r=R(()=>e(t,a==null?void 0:a())||{});if(a&&(r!=null&&r.update)){var i=!1,n={};T(()=>{var s=a();U(s),i&&X(n,s)&&(n=s,r.update(s))}),i=!0}if(r!=null&&r.destroy)return()=>r.destroy()})}var V=k('<p class="text-sm text-dim mt-0.5 text-pretty svelte-162svzm"> </p>'),W=k('<div class="flex items-center gap-2 shrink-0 flex-wrap justify-end svelte-162svzm"><!></div>'),Z=k('<header class="flex items-start justify-between gap-4 mb-6 enter svelte-162svzm"><div class="flex items-center gap-3.5 min-w-0 svelte-162svzm"><div><!></div> <div class="min-w-0 svelte-162svzm"><h1 class="text-2xl font-bold text-aurora leading-tight text-balance svelte-162svzm"> </h1> <!></div></div> <!></header>');function fe(t,e){let a=m(e,"accent",3,"synapse");var r=Z(),i=f(r),n=f(i),s=f(n);S(s,{get name(){return e.icon},size:22,draw:!0}),l(n);var x=F(n,2),u=f(x),v=f(u,!0);l(u);var h=F(u,2);{var b=c=>{var d=V(),y=f(d,!0);l(d),L(()=>P(y,e.subtitle)),A(c,d)};B(h,c=>{e.subtitle&&c(b)})}l(x),l(i);var p=F(i,2);{var g=c=>{var d=W(),y=f(d);K(y,()=>e.children),l(d),A(c,d)};B(p,c=>{e.children&&c(g)})}l(r),L(()=>{E(n,1,`header-tile relative flex items-center justify-center w-11 h-11 rounded-xl shrink-0
|
||||
bg-${a()??""}/12 border border-${a()??""}/25 text-${a()??""}-glow`,"svelte-162svzm"),P(v,e.title)}),A(t,r)}var $=k("<span> </span>");function le(t,e){var q;Y(e,!0);let a=m(e,"decimals",3,0),r=m(e,"scale",3,1),i=m(e,"prefix",3,""),n=m(e,"suffix",3,""),s=m(e,"duration",3,900),x=m(e,"class",3,""),u=m(e,"group",3,!0),v=G(0),h=0,b=0,p=0,g=!1;const c=typeof window<"u"&&((q=window.matchMedia)==null?void 0:q.call(window,"(prefers-reduced-motion: reduce)").matches);function d(o){return o===1?1:1-Math.pow(2,-10*o)}function y(o){if(c){j(v,o,!0);return}cancelAnimationFrame(h),b=I(v),p=0;function w(M){p||(p=M);const _=Math.min(1,(M-p)/s());j(v,b+(o-b)*d(_)),_<1?h=requestAnimationFrame(w):j(v,o,!0)}h=requestAnimationFrame(w)}C(()=>{const o=e.value;return g||(g=!0),y(o),()=>cancelAnimationFrame(h)});let H=J(()=>(()=>{const w=(I(v)*r()).toFixed(a());if(!u())return w;const[M,_]=w.split("."),O=M.replace(/\B(?=(\d{3})+(?!\d))/g,",");return _!==void 0?`${O}.${_}`:O})());var z=$(),N=f(z);l(z),L(()=>{E(z,1,`tabular-nums ${x()??""}`),P(N,`${i()??""}${I(H)??""}${n()??""}`)}),A(t,z),D()}const ee=()=>{var t;return typeof window<"u"&&((t=window.matchMedia)==null?void 0:t.call(window,"(prefers-reduced-motion: reduce)").matches)};function me(t,e={}){const{y:a=16,delay:r=0,once:i=!0,threshold:n=.12}=e;if(ee())return t.classList.add("reveal-in"),{};t.classList.add("reveal"),t.style.setProperty("--reveal-y",`${a}px`),r&&t.style.setProperty("--reveal-delay",`${r}ms`);const s=new IntersectionObserver(x=>{for(const u of x)u.isIntersecting?(t.classList.add("reveal-in"),i&&s.unobserve(t)):i||t.classList.remove("reveal-in")},{threshold:n,rootMargin:"0px 0px -8% 0px"});return s.observe(t),{destroy(){s.disconnect()}}}export{le as A,fe as P,de as a,me as r};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
function m(z,a,e,t){const o=1/Math.tan(z/2),y=1/(e-t),n=new Float32Array(16);return n[0]=o/a,n[5]=o,n[10]=t*y,n[11]=-1,n[14]=t*e*y,n}function w(z,a,e){const[t,o,y]=z;let n=t-a[0],f=o-a[1],r=y-a[2],c=Math.hypot(n,f,r)||1;n/=c,f/=c,r/=c;let h=e[1]*r-e[2]*f,s=e[2]*n-e[0]*r,x=e[0]*f-e[1]*n;c=Math.hypot(h,s,x)||1,h/=c,s/=c,x/=c;const i=f*x-r*s,u=r*h-n*x,M=n*s-f*h,l=new Float32Array(16);return l[0]=h,l[1]=i,l[2]=n,l[4]=s,l[5]=u,l[6]=f,l[8]=x,l[9]=M,l[10]=r,l[12]=-(h*t+s*o+x*y),l[13]=-(i*t+u*o+M*y),l[14]=-(n*t+f*o+r*y),l[15]=1,l}function A(z,a){const e=new Float32Array(16);for(let t=0;t<4;t++)for(let o=0;o<4;o++)e[t*4+o]=z[o]*a[t*4]+z[4+o]*a[t*4+1]+z[8+o]*a[t*4+2]+z[12+o]*a[t*4+3];return e}function v(z,a,e,t=.35){const o=z*Math.PI*2,y=[Math.sin(o)*e,e*t,Math.cos(o)*e],n=m(50*Math.PI/180,a,.1,4e3),f=w(y,[0,0,0],[0,1,0]);let r=-y[0],c=-y[1],h=-y[2],s=Math.hypot(r,c,h)||1;r/=s,c/=s,h/=s;let x=c*0-h*1,i=h*0-r*0,u=r*1-c*0;s=Math.hypot(x,i,u)||1,x/=s,i/=s,u/=s;const M=i*h-u*c,l=u*r-x*h,p=x*c-i*r;return{viewProj:A(n,f),right:[x,i,u],up:[M,l,p],eye:y}}export{w as l,A as m,v as o,m as p};
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{i as p,E as t}from"./CGq8RnJq.js";import{B as i}from"./W8qDZJD6.js";function E(r,s,...a){var e=new i(r);p(()=>{const n=s()??null;e.ensure(n,n&&(o=>n(o,...a)))},t)}export{E as s};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{Q as g,R as d,j as c,y as m,S as i,T as b,g as p,U as v,V as y,W as h}from"./CGq8RnJq.js";function x(n=!1){const s=g,e=s.l.u;if(!e)return;let f=()=>v(s.s);if(n){let a=0,t={};const _=y(()=>{let l=!1;const r=s.s;for(const o in r)r[o]!==t[o]&&(t[o]=r[o],l=!0);return l&&a++,a});f=()=>p(_)}e.b.length&&d(()=>{u(s,f),i(e.b)}),c(()=>{const a=m(()=>e.m.map(b));return()=>{for(const t of a)typeof t=="function"&&t()}}),e.a.length&&c(()=>{u(s,f),i(e.a)})}function u(n,s){if(n.l.s)for(const e of n.l.s)p(e);s()}h();export{x as i};
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
var e;typeof window<"u"&&((e=window.__svelte??(window.__svelte={})).v??(e.v=new Set)).add("5");
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{l as s,m as v,h as o,t as c,n as b,o as m,q as h,v as q}from"./CGq8RnJq.js";function _(e,r,l=!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}}(!l||r!==void 0)&&(e.selectedIndex=-1)}function y(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,l=r){var a=new WeakSet,t=!0;s(e,"change",u=>{var f=u?"[selected]":":checked",n;if(e.multiple)n=[].map.call(e.querySelectorAll(f),i);else{var d=e.querySelector(f)??e.querySelector("option:not([disabled])");n=d&&i(d)}l(n),v!==null&&a.add(v)}),o(()=>{var u=r();if(e===document.activeElement){var f=q??v;if(a.has(f))return}if(_(e,u,t),t&&u===void 0){var n=e.querySelector(":checked");n!==null&&(u=i(n),l(u))}e.__value=u,t=!1}),y(e)}function i(e){return"__value"in e?e.__value:e.value}export{p as b};
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{s as e}from"./DJDK-KWF.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -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",MemorySuppressed:"#A33FFF",MemoryUnsuppressed:"#14E8C6",Rac1CascadeSwept:"#6E3FFF",SearchPerformed:"#818CF8",DeepReferenceCompleted:"#C4B5FD",HookVerdictRecorded:"#F59E0B",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};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{i as R,w as A,ai as S,E as b,aj as g,aG as N,ak as w,al as B,G as F,F as E,h as I,z as O,y as Y,aw as _,ad as e}from"./CGq8RnJq.js";import{B as p}from"./W8qDZJD6.js";function G(a,r,n=!1){A&&S();var c=new p(a),i=n?b:0;function s(f,T){if(A){const h=g(a);var t;if(h===N?t=0:h===w?t=!1:t=parseInt(h.substring(1)),f!==t){var u=B();F(u),c.anchor=u,E(!1),c.ensure(f,T),E(!0);return}}c.ensure(f,T)}R(()=>{var f=!1;r((T,t=0)=>{f=!0,s(t,T)}),f||s(!1,null)},i)}function l(a,r){return a===r||(a==null?void 0:a[e])===r}function H(a={},r,n,c){return I(()=>{var i,s;return O(()=>{i=s,s=[],Y(()=>{a!==n(...s)&&(r(a,...s),i&&l(n(...i),a)&&r(null,...i))})}),()=>{_(()=>{s&&l(n(...s),a)&&r(null,...s)})}}),a}export{H as b,G as i};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
import{c,w as g}from"./DAau0uzT.js";const v=200;function $(){const{subscribe:e,set:n,update:t}=g({connected:!1,reconnecting:!1,events:[],lastHeartbeat:null,error:null});let o=null,s=null,d=0;function m(i){const l=i||(window.location.port==="5173"?`ws://${window.location.hostname}:3927/ws`:`ws://${window.location.host}/ws`);if((o==null?void 0:o.readyState)!==WebSocket.OPEN)try{o=new WebSocket(l),o.onopen=()=>{d=0,t(r=>({...r,connected:!0,reconnecting:!1,error:null}))},o.onmessage=r=>{try{const u=JSON.parse(r.data);t(f=>{if(u.type==="Heartbeat")return{...f,lastHeartbeat:u};const w=[u,...f.events].slice(0,v);return{...f,events:w}})}catch(u){console.warn("[vestige] Failed to parse WebSocket message:",u)}},o.onclose=()=>{t(r=>({...r,connected:!1})),p(l)},o.onerror=()=>{t(r=>({...r,error:"WebSocket connection failed"}))}}catch(r){t(u=>({...u,error:String(r)}))}}function p(i){s&&clearTimeout(s),t(r=>({...r,reconnecting:!0}));const l=Math.min(1e3*2**d,3e4);d++,s=setTimeout(()=>m(i),l)}function b(){s&&clearTimeout(s),o==null||o.close(),o=null,n({connected:!1,reconnecting:!1,events:[],lastHeartbeat:null,error:null})}function y(){t(i=>({...i,events:[]}))}function h(i){t(l=>{const r=[i,...l.events].slice(0,v);return{...l,events:r}})}return{subscribe:e,connect:m,disconnect:b,clearEvents:y,injectEvent:h}}const a=$(),S=c(a,e=>e.connected),H=c(a,e=>e.reconnecting),T=c(a,e=>e.events);c(a,e=>e.lastHeartbeat);const M=c(a,e=>{var n,t;return((t=(n=e.lastHeartbeat)==null?void 0:n.data)==null?void 0:t.memory_count)??0}),k=c(a,e=>{var n,t;return((t=(n=e.lastHeartbeat)==null?void 0:n.data)==null?void 0:t.avg_retention)??0}),_=c(a,e=>{var n,t;return((t=(n=e.lastHeartbeat)==null?void 0:n.data)==null?void 0:t.suppressed_count)??0}),W=c(a,e=>{var n,t;return((t=(n=e.lastHeartbeat)==null?void 0:n.data)==null?void 0:t.uptime_secs)??0}),N=c(a,e=>e.events.filter(n=>n.type==="TraceEvent")),P=c(a,e=>{var t;const n=e.events.find(o=>o.type==="TraceEvent");return((t=n==null?void 0:n.data)==null?void 0:t.run_id)??null}),R=c(a,e=>e.events.find(n=>n.type==="TraceEvent")??null),C=c(a,e=>e.events.filter(n=>n.type==="MemoryPrOpened"||n.type==="MemoryPrDecided"));function F(e){if(!Number.isFinite(e)||e<0)return"—";const n=Math.floor(e/86400),t=Math.floor(e%86400/3600),o=Math.floor(e%3600/60),s=Math.floor(e%60);return n>0?t>0?`${n}d ${t}h`:`${n}d`:t>0?o>0?`${t}h ${o}m`:`${t}h`:o>0?s>0?`${o}m ${s}s`:`${o}m`:`${s}s`}export{S as a,P as b,M as c,k as d,T as e,F as f,H as i,R as l,C as m,_ as s,N as t,W as u,a as w};
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
const s="/api";async function t(e,o){const r=await fetch(`${s}${e}`,{headers:{"Content-Type":"application/json"},...o});if(!r.ok)throw new Error(`API ${r.status}: ${r.statusText}`);return r.json()}const n={memories:{list:e=>{const o=e?"?"+new URLSearchParams(e).toString():"";return t(`/memories${o}`)},get:e=>t(`/memories/${e}`),delete:e=>t(`/memories/${e}`,{method:"DELETE"}),promote:e=>t(`/memories/${e}/promote`,{method:"POST"}),demote:e=>t(`/memories/${e}/demote`,{method:"POST"}),suppress:(e,o)=>t(`/memories/${e}/suppress`,{method:"POST",body:o?JSON.stringify({reason:o}):void 0}),unsuppress:e=>t(`/memories/${e}/unsuppress`,{method:"POST"})},search:(e,o=20)=>t(`/search?q=${encodeURIComponent(e)}&limit=${o}`),stats:()=>t("/stats"),health:()=>t("/health"),timeline:(e=7,o=200)=>t(`/timeline?days=${e}&limit=${o}`),graph:e=>{const o=e?"?"+new URLSearchParams(Object.entries(e).filter(([,r])=>r!==void 0).map(([r,i])=>[r,String(i)])).toString():"";return t(`/graph${o}`)},dream:()=>t("/dream",{method:"POST"}),explore:(e,o="associations",r,i=10)=>t("/explore",{method:"POST",body:JSON.stringify({from_id:e,action:o,to_id:r,limit:i})}),predict:()=>t("/predict",{method:"POST"}),importance:e=>t("/importance",{method:"POST",body:JSON.stringify({content:e})}),consolidate:()=>t("/consolidate",{method:"POST"}),retentionDistribution:()=>t("/retention-distribution"),memoryChangelog:(e=100)=>t(`/changelog?limit=${e}`),duplicates:(e=.8,o=20)=>t(`/duplicates?threshold=${e}&limit=${o}`),contradictions:e=>{const o=e?"?"+new URLSearchParams(Object.entries(e).filter(([,r])=>r!==void 0).map(([r,i])=>[r,String(i)])).toString():"";return t(`/contradictions${o}`)},crossProjectPatterns:()=>t("/patterns/cross-project"),memoryAudit:(e,o=100)=>t(`/memories/${encodeURIComponent(e)}/audit?limit=${o}`),intentions:(e="active")=>t(`/intentions?status=${e}`),deepReference:(e,o=20)=>t("/deep_reference",{method:"POST",body:JSON.stringify({query:e,depth:o})}),sanhedrin:{latest:()=>t("/sanhedrin/latest"),telemetry:(e=7)=>t(`/sanhedrin/telemetry?days=${e}`),appeal:(e,o,r,i)=>t("/sanhedrin/appeal",{method:"POST",body:JSON.stringify({reason:e,note:o,claimId:r,receiptId:i})})},traces:{list:(e=50)=>t(`/traces?limit=${e}`),get:e=>t(`/traces/${encodeURIComponent(e)}`),exportUrl:e=>`${s}/traces/${encodeURIComponent(e)}/export`},receipts:{list:(e=50)=>t(`/receipts?limit=${e}`),listForRun:(e,o=50)=>t(`/receipts?run=${encodeURIComponent(e)}&limit=${o}`),get:e=>t(`/receipts/${encodeURIComponent(e)}`)},memoryPrs:{list:(e,o=100)=>{const r=new URLSearchParams;return e&&r.set("status",e),r.set("limit",String(o)),t(`/memory-prs?${r.toString()}`)},get:e=>t(`/memory-prs/${encodeURIComponent(e)}`),act:(e,o)=>t(`/memory-prs/${encodeURIComponent(e)}/${o}`,{method:"POST"}),getMode:()=>t("/memory-prs/mode"),setMode:e=>t("/memory-prs/mode",{method:"POST",body:JSON.stringify({mode:e})})}};export{n as a};
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,134 +0,0 @@
|
|||
var F=Object.defineProperty;var N=(a,e,t)=>e in a?F(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var u=(a,e,t)=>N(a,typeof e!="symbol"?e+"":e,t);import{r as D}from"./BMB5u1EX.js";import{b as G}from"./DY7cP31Q.js";const L=32,U=126,P=63,z=.6,R=1.32,S="...";function O(a){return new Map(a.glyphs.map(e=>[e.unicode,e]))}function A(a){const e=a.codePointAt(0)??P;return e>=L&&e<=U?a:"?"}function C(a,e){if(e===void 0||e<0)return a;if(e===0)return"";const t=Array.from(a,A);return t.length<=e?t.join(""):e<=S.length?".".repeat(e):`${t.slice(0,e-S.length).join("")}${S}`}function k(a,e){return a.split(`
|
||||
`).map(t=>C(t,e))}function V(a,e,t={}){var h;const r=O(e),s=r.get(P),o=e.atlas.width,i=e.atlas.height,n=t.advance??z,c=t.lineHeight??((h=e.metrics)==null?void 0:h.lineHeight)??R,p=t.maxWidthEm===void 0?void 0:Math.max(0,Math.floor(t.maxWidthEm/n)),d=[];let g=0;for(const x of k(a,p)){let f=0;for(const m of Array.from(x)){const _=A(m).codePointAt(0)??P,l=r.get(_)??s;if(l!=null&&l.planeBounds&&l.atlasBounds){const y=l.planeBounds,v=l.atlasBounds,T=v.left/o,w=1-v.top/i,B=(v.right-v.left)/o,M=1-v.bottom/i-w;d.push({x:f+y.left,y:g+y.bottom,w:y.right-y.left,h:y.top-y.bottom,u:T,v:w,uw:B,vh:M})}f+=n}g-=c}return d}async function j(a){var h,x,f;const e=`${G}/msdf/jetbrains-mono.json`,t=`${G}/msdf/jetbrains-mono.png`,r=await fetch(e);if(!r.ok)throw new Error(`MSDF atlas JSON failed: ${r.status} ${e}`);const s=await r.json();if(((h=s.atlas)==null?void 0:h.yOrigin)!=="bottom")throw new Error(`MSDF atlas yOrigin must be bottom, got ${((x=s.atlas)==null?void 0:x.yOrigin)??"missing"}`);const o=await fetch(t);if(!o.ok)throw new Error(`MSDF atlas PNG failed: ${o.status} ${t}`);const i=await o.blob(),n=await createImageBitmap(i),c=a.createTexture({label:"msdf-jetbrains-mono-rgba8unorm",size:[n.width,n.height,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});a.queue.copyExternalImageToTexture({source:n},{texture:c},{width:n.width,height:n.height}),(f=n.close)==null||f.call(n);const p=a.createSampler({label:"msdf-jetbrains-mono-linear-sampler",magFilter:"linear",minFilter:"linear",mipmapFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),d=c.createView({label:"msdf-jetbrains-mono-view"}),g=new Map(s.glyphs.map(m=>[m.unicode,m]));return{...s,glyphMap:g,texture:c,textureView:d,sampler:p,dispose:()=>c.destroy()}}const H=`
|
||||
struct Params {
|
||||
frame: f32,
|
||||
loop_phase: f32,
|
||||
node_count: f32,
|
||||
edge_count: f32,
|
||||
path_count: f32,
|
||||
pulse: f32,
|
||||
viewport_w: f32,
|
||||
viewport_h: f32,
|
||||
brightness: f32,
|
||||
demo_id: f32,
|
||||
time: f32,
|
||||
capture_mode: f32,
|
||||
live_kind: f32,
|
||||
live_frame: f32,
|
||||
live_energy: f32,
|
||||
projection_days: f32,
|
||||
cursor_x: f32,
|
||||
cursor_y: f32,
|
||||
cursor_vx: f32,
|
||||
cursor_vy: f32,
|
||||
};
|
||||
|
||||
struct Glyph {
|
||||
anchor_size: vec4f,
|
||||
quad_offset: vec4f,
|
||||
uv_rect: vec4f,
|
||||
info: vec4f,
|
||||
color: vec4f,
|
||||
};
|
||||
|
||||
struct VSOut {
|
||||
@builtin(position) clip: vec4f,
|
||||
@location(0) uv: vec2f,
|
||||
@location(1) @interpolate(flat) info: vec4f,
|
||||
@location(2) @interpolate(flat) color: vec4f,
|
||||
@location(3) @interpolate(flat) weight: f32,
|
||||
};
|
||||
|
||||
@group(0) @binding(0) var<uniform> params: Params;
|
||||
@group(0) @binding(1) var<storage, read> glyphs: array<Glyph>;
|
||||
@group(0) @binding(2) var atlas_sampler: sampler;
|
||||
@group(0) @binding(3) var atlas_tex: texture_2d<f32>;
|
||||
|
||||
const QUAD = array<vec2f, 6>(
|
||||
vec2f(0.0, 0.0), vec2f(1.0, 0.0), vec2f(1.0, 1.0),
|
||||
vec2f(0.0, 0.0), vec2f(1.0, 1.0), vec2f(0.0, 1.0)
|
||||
);
|
||||
|
||||
fn median3(c: vec3f) -> f32 {
|
||||
return max(min(c.r, c.g), min(max(c.r, c.g), c.b));
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn vs_text(@builtin(vertex_index) vi: u32, @builtin(instance_index) ii: u32) -> VSOut {
|
||||
let glyph = glyphs[ii];
|
||||
let corner = QUAD[vi];
|
||||
let anchor = glyph.anchor_size.xy;
|
||||
let size = glyph.anchor_size.zw;
|
||||
let quad_offset = glyph.quad_offset.xy;
|
||||
let uv_min = glyph.uv_rect.xy;
|
||||
let uv_max = glyph.uv_rect.zw;
|
||||
let aspect = max(0.0001, params.viewport_w / max(1.0, params.viewport_h));
|
||||
let depth = clamp(glyph.info.z, 0.0, 1.0);
|
||||
let cursor_pre = vec2f(params.cursor_x, params.cursor_y);
|
||||
let cursor_delta = cursor_pre - anchor;
|
||||
let d = distance(anchor, cursor_pre);
|
||||
// Wide influence radius so the field reacts when the cursor is anywhere NEAR
|
||||
// the text, not only dead-on (v1 R=0.45 was too tight to feel).
|
||||
let R = 0.75;
|
||||
let cursor_w = exp(-(d * d) / (R * R));
|
||||
// Per-glyph SCALE-UP near the cursor: glyphs the pointer approaches swell toward
|
||||
// you. Scaling the quad around its anchor is the most legible "alive" cue.
|
||||
let grow = 1.0 + cursor_w * 0.55;
|
||||
var pos = anchor + (quad_offset + corner * size) * grow;
|
||||
// Depth → clip z. Trust (depth~1) floats forward (small z), low-trust sinks back.
|
||||
// Cursor lifts a glyph forward, but z MUST stay > 0 or clip.z<0 clips the quad
|
||||
// behind the near plane and the glyph vanishes (v1 bug: cursor made text disappear).
|
||||
var z = mix(0.42, 0.10, depth);
|
||||
z = clamp(z - cursor_w * 0.42, 0.04, 0.6);
|
||||
let lean_dir = select(vec2f(0.0, 0.0), normalize(cursor_delta), length(cursor_delta) > 0.0001);
|
||||
pos = pos + lean_dir * cursor_w * 0.04;
|
||||
pos = pos + vec2f(sin(params.time * 0.6), cos(params.time * 0.5)) * ((1.0 - depth) * 0.006) * params.pulse;
|
||||
// Keep glyphs square in BOTH orientations: normalize by the longer axis.
|
||||
// Landscape (aspect>1): narrow x. Portrait (aspect<1): shrink y instead —
|
||||
// dividing x by aspect<1 would WIDEN x and push text off-screen.
|
||||
pos.x = pos.x / max(aspect, 1.0);
|
||||
pos.y = pos.y * min(aspect, 1.0);
|
||||
let wclip = 1.0 + z;
|
||||
var out: VSOut;
|
||||
out.clip = vec4f(pos, z, wclip);
|
||||
out.uv = vec2f(mix(uv_min.x, uv_max.x, corner.x), mix(uv_max.y, uv_min.y, corner.y));
|
||||
out.info = vec4f(glyph.info.x, glyph.info.y, cursor_w, depth);
|
||||
out.color = glyph.color;
|
||||
out.weight = clamp(glyph.info.w, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_text(in: VSOut) -> @location(0) vec4f {
|
||||
let atlas_px = vec2f(textureDimensions(atlas_tex, 0));
|
||||
let cursor_w = clamp(in.info.z, 0.0, 1.0);
|
||||
let depth = clamp(in.info.w, 0.0, 1.0);
|
||||
let weight = clamp(in.weight, 0.0, 1.0);
|
||||
var uv = in.uv;
|
||||
uv = uv + vec2f(sin(uv.y * 40.0 + params.time * 3.0), cos(uv.x * 40.0 + params.time * 3.0)) * (cursor_w * 0.007);
|
||||
let msdf = textureSample(atlas_tex, atlas_sampler, uv).rgb;
|
||||
let dist = median3(msdf);
|
||||
let uv_width = max(fwidth(uv), vec2f(1.0 / max(atlas_px.x, 1.0), 1.0 / max(atlas_px.y, 1.0)));
|
||||
let texels_per_px = max(length(uv_width * atlas_px), 0.0001);
|
||||
let screen_range = max(0.5, 4.0 / texels_per_px);
|
||||
// Depth-of-field: far/un-hovered glyphs soften, cursor sharpens. Kept GENTLE so
|
||||
// the resting field stays READABLE regardless of the data's depth value.
|
||||
let dof = (1.0 - depth) * (1.0 - cursor_w);
|
||||
let screen_range_dof = screen_range / (1.0 + dof * 0.6);
|
||||
// Weight (FSRS retention) modulates stroke mass WITHIN a readable band: it can
|
||||
// thicken a lot but only thin slightly, so a low-retention record never
|
||||
// disappears (data must be legible even at weight~0 — every route depends on this).
|
||||
let weight_bias = (weight - 0.5) * 0.10 + 0.03;
|
||||
let px_dist = screen_range_dof * (dist - 0.5 + weight_bias);
|
||||
let coverage = clamp(px_dist + 0.5, 0.0, 1.0);
|
||||
let reveal_span = max(1.0, in.info.y);
|
||||
let reveal = clamp((params.frame - in.info.x) / reveal_span, 0.0, 1.0);
|
||||
let alpha = coverage * in.color.a * reveal;
|
||||
if (alpha < 0.001) { discard; }
|
||||
// Glow floor keeps EVERY line clearly lit at rest (even depth~0), depth adds
|
||||
// forward-brightness, cursor pushes near glyphs HARD past the bloom line to flare.
|
||||
let glow = mix(1.15, 1.5, depth) + cursor_w * 1.4;
|
||||
let rgb = in.color.rgb * params.brightness * glow;
|
||||
return vec4f(rgb * alpha, alpha);
|
||||
}
|
||||
`,E=20,q=[...D("#22C7DE"),1];class K{constructor(e){u(this,"engine");u(this,"atlas",null);u(this,"bindLayout",null);u(this,"pipeline",null);u(this,"glyphBuffer",null);u(this,"bindGroup",null);u(this,"glyphCapacity",0);u(this,"glyphCount",0);u(this,"pendingItems",[]);u(this,"runs",[]);u(this,"runDepths",new Map);u(this,"initPromise",null);this.engine=e}async init(){return this.initPromise?this.initPromise:(this.initPromise=this.initInner(),this.initPromise)}async initInner(){const e=this.engine.gpuDevice;!e||!this.engine.paramsBuffer||(this.atlas=await j(e),this.ensurePipeline(e),this.pendingItems.length&&this.uploadItems(this.pendingItems))}setText(e){const t=typeof e=="string"?[{text:e,x:-.62,y:0,size:.075}]:Array.isArray(e)?e:[e];this.pendingItems=t,this.uploadItems(t)}ensurePipeline(e){if(this.pipeline||!this.engine.paramsBuffer)return;const t=e.createShaderModule({label:"msdf-text-wgsl",code:H});this.bindLayout=e.createBindGroupLayout({label:"msdf-text-bind-layout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});const r=e.createPipelineLayout({label:"msdf-text-pipeline-layout",bindGroupLayouts:[this.bindLayout]}),s={color:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}};this.pipeline=e.createRenderPipeline({label:"msdf-text-pipeline",layout:r,vertex:{module:t,entryPoint:"vs_text"},fragment:{module:t,entryPoint:"fs_text",targets:[{format:this.engine.sceneFormat,blend:s}]},primitive:{topology:"triangle-list"}})}uploadItems(e){const t=this.engine.gpuDevice;if(!t||!this.engine.paramsBuffer||!this.atlas)return;this.ensurePipeline(t);const r=[],s=[];let o=0;e.forEach((n,c)=>{const p=n.size??.075,d=V(n.text,this.atlas,{maxWidthEm:n.maxWidthEm}),g=n.color??q,h=d,x=o;let f=Number.POSITIVE_INFINITY,m=Number.NEGATIVE_INFINITY,b=Number.POSITIVE_INFINITY,_=Number.NEGATIVE_INFINITY;for(const l of h){const y=n.x+l.x*p,v=n.x+(l.x+l.w)*p,T=n.y+l.y*p,w=n.y+(l.y+l.h)*p;f=Math.min(f,y),m=Math.max(m,v),b=Math.min(b,T),_=Math.max(_,w),W(r,n,l,g,p,o++)}if(h.length>0){const l=n.id??`msdf-text:${c}`;s.push({id:l,kind:n.kind??"text",text:n.text,x0:f,x1:m,y0:b,y1:_,payload:n,glyphStart:x,glyphCount:o-x}),this.runDepths.set(l,I(n.depth??.5))}}),this.runs=s,this.glyphCount=r.length/E;const i=new Float32Array(r.length||E);i.set(r),this.ensureGlyphBuffer(t,Math.max(1,this.glyphCount)),!(!this.glyphBuffer||!this.bindLayout)&&(t.queue.writeBuffer(this.glyphBuffer,0,i),this.bindGroup=t.createBindGroup({label:"msdf-text-bind-group",layout:this.bindLayout,entries:[{binding:0,resource:{buffer:this.engine.paramsBuffer}},{binding:1,resource:{buffer:this.glyphBuffer}},{binding:2,resource:this.atlas.sampler},{binding:3,resource:this.atlas.textureView}]}))}ensureGlyphBuffer(e,t){var r;this.glyphBuffer&&this.glyphCapacity>=t||((r=this.glyphBuffer)==null||r.destroy(),this.glyphCapacity=Math.max(t,Math.ceil(this.glyphCapacity*1.5),32),this.glyphBuffer=e.createBuffer({label:"msdf-text-glyphs",size:this.glyphCapacity*E*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}))}render(e){!this.pipeline||!this.bindGroup||this.glyphCount<=0||(e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6,this.glyphCount))}pickAt(e,t){const r=Math.max(1e-4,(this.engine.params[6]||1)/Math.max(1,this.engine.params[7]||1)),s=Math.max(r,1),o=Math.min(r,1);for(const i of this.runs){const n=(i.payload.hitPadX??i.payload.hitPad??0)/s,c=(i.payload.hitPadY??i.payload.hitPad??0)*o,p=i.x0/s-n,d=i.x1/s+n,g=i.y0*o-c,h=i.y1*o+c;if(e>=p&&e<=d&&t>=g&&t<=h)return{id:i.id,kind:i.kind,payload:i.payload}}return null}setRunDepth(e,t=.5){const r=this.engine.gpuDevice;if(!(!r||!this.glyphBuffer))for(const s of this.runs){const o=s.id===e?t:s.payload.depth??.5,i=I(o);if(this.runDepths.get(s.id)===i)continue;this.runDepths.set(s.id,i);const n=new Float32Array([i]);for(let c=0;c<s.glyphCount;c+=1){const p=(s.glyphStart+c)*E+14;r.queue.writeBuffer(this.glyphBuffer,p*4,n)}}}dispose(){var e,t;(e=this.glyphBuffer)==null||e.destroy(),this.glyphBuffer=null,(t=this.atlas)==null||t.dispose(),this.atlas=null,this.bindGroup=null,this.pipeline=null}}function W(a,e,t,r,s,o){const i=(e.startFrame??0)+o*2,n=e.revealSpan??18;a.push(e.x,e.y,t.w*s,t.h*s,t.x*s,t.y*s,0,0,t.u,t.v,t.u+t.uw,t.v+t.vh,i,n,I(e.depth??.5),I(e.weight??.5),r[0],r[1],r[2],r[3])}function I(a){return Math.min(1,Math.max(0,Number.isFinite(a)?a:.5))}export{K as T};
|
||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue