stellavault 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,59 +1,69 @@
1
1
  # Stellavault
2
2
 
3
+ [![CI](https://github.com/Evanciel/stellavault/actions/workflows/ci.yml/badge.svg)](https://github.com/Evanciel/stellavault/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/stellavault)](https://www.npmjs.com/package/stellavault) [![tests](https://img.shields.io/badge/tests-177%20passing-brightgreen)]()
4
+
3
5
  > **Drop anything. It compiles itself into knowledge.** Claude remembers everything you know.
4
6
 
5
- Self-compiling knowledge base with 3D neural graph, AI-powered search, and spaced repetition — available as a **desktop app**, **CLI**, **Obsidian plugin**, and **MCP server**. Your vault files are never modified.
7
+ Self-compiling knowledge base with a full-featured editor, 3D neural graph, AI-powered search, and spaced repetition — available as a **desktop app**, **CLI**, **Obsidian plugin**, and **MCP server**. Your vault files are never modified.
6
8
 
7
9
  <p align="center">
8
10
  <img src="images/screenshots/graph-main-2.png" alt="3D Knowledge Graph" width="800" />
9
11
  <br><em>Your vault as a neural network. Local-first, no cloud required.</em>
10
12
  </p>
11
13
 
12
- ## Three Ways to Use Stellavault
13
-
14
- ### 1. Desktop App (Recommended)
15
-
16
- Download and run — no terminal needed.
14
+ ## Install
17
15
 
18
- | Platform | Download | Size |
19
- |----------|----------|------|
20
- | **Windows x64** | [Stellavault-win32-x64-0.1.0.zip](https://github.com/Evanciel/stellavault/releases/download/desktop-v0.1.0/Stellavault-win32-x64-0.1.0.zip) | 116 MB |
21
- | **Linux x64** | [Stellavault-linux-x64-0.1.0.zip](https://github.com/Evanciel/stellavault/releases/download/desktop-v0.1.0/Stellavault-linux-x64-0.1.0.zip) | 107 MB |
22
- | macOS | Coming soon (requires Apple code signing) | — |
16
+ ### Desktop App (Recommended one click)
23
17
 
24
- **What you get:**
25
- - Full markdown editor with WYSIWYG toolbar
26
- - File tree sidebar with search filter
27
- - `[[wikilink]]` autocomplete as you type
28
- - Multi-tab editing with Ctrl+S save
29
- - 3D knowledge graph panel
30
- - AI panel — semantic search, vault stats, re-index
31
- - Backlinks panel — see who links to your note
32
- - Quick Switcher (Ctrl+P) and Command Palette (Ctrl+Shift+P)
33
- - Dark/light theme
18
+ <table>
19
+ <tr>
20
+ <td align="center"><a href="https://github.com/Evanciel/stellavault/releases/download/desktop-v0.1.0/Stellavault-win32-x64-0.1.0.zip"><br/><b>⬇ Download for Windows</b><br/><sub>x64 · 116 MB · ZIP</sub></a></td>
21
+ <td align="center"><a href="https://github.com/Evanciel/stellavault/releases/download/desktop-v0.1.0/Stellavault-linux-x64-0.1.0.zip"><br/><b>⬇ Download for Linux</b><br/><sub>x64 · 107 MB · ZIP</sub></a></td>
22
+ <td align="center"><br/><b>macOS</b><br/><sub>Coming soon</sub></td>
23
+ </tr>
24
+ </table>
34
25
 
35
- ### 2. CLI + Web Graph
26
+ > Download → Unzip → Run `stellavault.exe` (Windows) or `stellavault` (Linux) → Pick your notes folder → Done.
36
27
 
37
- For developers and power users.
28
+ ### CLI (for developers)
38
29
 
39
30
  ```bash
40
31
  npm install -g stellavault # or: npx stellavault
41
- stellavault init # Interactive setup wizard
32
+ stellavault init # Interactive setup wizard (3 min)
42
33
  stellavault graph # Launch 3D graph in browser
43
34
  ```
44
35
 
45
- > **Prerequisites**: Node.js 20+. Run `stellavault doctor` to diagnose setup issues.
46
-
47
- ### 3. Obsidian Plugin
36
+ > Requires Node.js 20+. Run `stellavault doctor` to diagnose issues.
48
37
 
49
- Use Stellavault intelligence inside Obsidian.
38
+ ### Obsidian Plugin
50
39
 
51
- 1. Download from [stellavault-obsidian releases](https://github.com/Evanciel/stellavault-obsidian/releases/latest)
52
- 2. Place `main.js`, `manifest.json`, `styles.css` in `.obsidian/plugins/stellavault/`
40
+ 1. Download `main.js` + `manifest.json` + `styles.css` from [stellavault-obsidian releases](https://github.com/Evanciel/stellavault-obsidian/releases/latest)
41
+ 2. Place in `.obsidian/plugins/stellavault/`
53
42
  3. Enable in Settings → Community plugins
54
- 4. Start the API server: `npx stellavault graph` in your vault folder
43
+ 4. Start API: `npx stellavault graph` in your vault folder
44
+
45
+ ---
55
46
 
56
- **Features:** Semantic search modal, memory decay sidebar, learning path suggestions, auto-indexing on file changes.
47
+ ## Editor
48
+
49
+ Full-featured markdown editor — on par with Obsidian.
50
+
51
+ | Feature | Status |
52
+ |---------|--------|
53
+ | Bold, Italic, Underline, Strikethrough | ✅ |
54
+ | Headings 1–6 | ✅ |
55
+ | Bullet, Numbered, Task lists (nested checkboxes) | ✅ |
56
+ | Tables (create, resize columns, add/remove rows & cols) | ✅ |
57
+ | Code blocks with syntax highlighting (40+ languages) | ✅ |
58
+ | Images (URL, clipboard paste, drag & drop) | ✅ |
59
+ | KaTeX math rendering (`$E=mc^2$` inline, `$$...$$` display) | ✅ |
60
+ | `/Slash commands` (12 block types, fuzzy search) | ✅ |
61
+ | `[[Wikilink]]` autocomplete | ✅ |
62
+ | Split view (vertical + horizontal, Ctrl+\\) | ✅ |
63
+ | Text alignment (left / center / right) | ✅ |
64
+ | Highlight, Superscript, Subscript | ✅ |
65
+ | Smart typography (curly quotes, em/en dashes) | ✅ |
66
+ | Horizontal rules | ✅ |
57
67
 
58
68
  ---
59
69
 
@@ -65,9 +75,9 @@ Capture ──→ Organize ──→ Distill ──→ Express
65
75
  Drop anything → auto-extract → raw/ → compile → _wiki/ → draft
66
76
  ```
67
77
 
68
- Inspired by [Karpathy's self-compiling knowledge](https://karpathy.ai/) architecture. Every input flows through the same four-stage pipeline.
78
+ Inspired by Karpathy's self-compiling knowledge architecture.
69
79
 
70
- ### Ingest Anything (14 formats)
80
+ ### Ingest 14 Formats
71
81
 
72
82
  | Input | How |
73
83
  |-------|-----|
@@ -82,201 +92,182 @@ Inspired by [Karpathy's self-compiling knowledge](https://karpathy.ai/) architec
82
92
  ### Express: Get Knowledge Out
83
93
 
84
94
  ```bash
85
- stellavault draft "AI" # Rule-based scaffold (free)
86
- stellavault draft "AI" --ai # Claude API writes full draft
87
- stellavault draft "AI" --format report # Formal report
88
- stellavault draft --format instagram # Social media format
95
+ stellavault draft "AI" --format blog # Blog post from your vault
96
+ stellavault draft "AI" --format outline # Structured outline
97
+ stellavault draft "AI" --ai # Claude API enhanced ($0.03)
89
98
  ```
90
99
 
91
- ## MCP Integration (21 Tools)
100
+ Or use the **Express tab** in the desktop app — enter a topic, pick a format, and generate a draft grounded in your vault. Save to `_drafts/` and edit inline.
101
+
102
+ ---
103
+
104
+ ## Intelligence (What Makes Stellavault Unique)
105
+
106
+ These features do **not exist** in Obsidian — even with plugins.
107
+
108
+ | Feature | Command / Desktop | Description |
109
+ |---------|-------------------|-------------|
110
+ | **Memory Decay** | `stellavault decay` / Memory tab | FSRS-based — shows which real notes you are forgetting |
111
+ | **Knowledge Gaps** | `stellavault gaps` | Detects weak connections between topic clusters |
112
+ | **Contradictions** | `stellavault contradictions` | Finds conflicting statements across your vault |
113
+ | **Duplicates** | `stellavault duplicates` | Near-identical notes with similarity score |
114
+ | **Health Check** | `stellavault lint` | Aggregated vault health score (0–100) |
115
+ | **Learning Path** | `stellavault learn` | AI-personalized review recommendations |
116
+ | **Daily Brief** | Desktop app home screen | Push-type: top decaying notes + stats on app open |
117
+ | **Auto-Tagging** | Automatic on ingest | Content-based keyword extraction + category rules |
118
+ | **Self-Compiling** | `stellavault compile` | raw/ → _wiki/ with extracted concepts + backlinks |
119
+
120
+ ---
92
121
 
93
- Connect Stellavault to Claude Code or Claude Desktop:
122
+ ## MCP Integration (21 Tools)
94
123
 
95
124
  ```bash
96
125
  claude mcp add stellavault -- stellavault serve
97
126
  ```
98
127
 
99
- Claude can now search, ask, draft, lint, and analyze your vault directly.
128
+ Claude can search, ask, draft, lint, and analyze your vault directly.
100
129
 
101
130
  | Tool | What it does |
102
131
  |------|-------------|
103
- | `search` | Hybrid BM25 + vector + RRF search |
104
- | `ask` | Q&A with vault-grounded answers |
132
+ | `search` | Hybrid BM25 + vector + RRF |
133
+ | `ask` | Vault-grounded Q&A |
105
134
  | `generate-draft` | AI drafts from your knowledge |
106
135
  | `get-decay-status` | Memory decay report (FSRS) |
107
136
  | `detect-gaps` | Knowledge gap analysis |
108
- | `get-learning-path` | Personalized review recommendations |
109
137
  | `create-knowledge-node` | AI creates wiki-quality notes |
110
- | `federated-search` | P2P search across connected vaults |
111
- | + 13 more | Documents, topics, decisions, snapshots, export |
112
-
113
- ## Intelligence
138
+ | `federated-search` | P2P search across vaults |
139
+ | + 14 more | Documents, topics, decisions, snapshots, export |
114
140
 
115
- | Feature | Command |
116
- |---------|---------|
117
- | Memory Decay | `stellavault decay` — what you're forgetting (FSRS) |
118
- | Gap Detection | `stellavault gaps` — weak connections between topics |
119
- | Contradictions | `stellavault contradictions` — conflicting statements |
120
- | Duplicates | `stellavault duplicates` — redundant notes |
121
- | Learning Path | `stellavault learn` — AI review recommendations |
122
- | Health Check | `stellavault lint` — overall knowledge score |
123
- | Daily Brief | `stellavault brief` — morning knowledge briefing |
124
- | Weekly Digest | `stellavault digest --visual` — Mermaid chart report |
125
-
126
- ## Self-Evolving Memory
141
+ ---
127
142
 
128
- ```
129
- Session → session-save → daily-log → flush → wiki
130
- ↑ ↓
131
- └──── Claude reads wiki via MCP (21 tools) ←─┘
132
- ```
143
+ ## 3D Visualization
133
144
 
134
- Every conversation makes your knowledge base smarter. Set up [Claude Code hooks](docs/hooks-setup.md) for full automation.
145
+ - Neural graph with cluster coloring (React Three Fiber)
146
+ - Constellation view (MST star patterns)
147
+ - Heatmap overlay + Timeline slider + Decay overlay
148
+ - Multiverse view — your vault as a universe in a P2P network
149
+ - Dark/Light theme
135
150
 
136
- ## Zettelkasten Workflow
151
+ ---
137
152
 
138
- Three-stage flow: **fleeting literature → permanent** (Luhmann + Karpathy).
153
+ ## Try It Now (Demo Vault)
139
154
 
140
155
  ```bash
141
- stellavault fleeting "raw idea" # raw/
142
- stellavault ingest report.pdf # auto-extract → raw/
143
- stellavault compile # raw/ → _wiki/ (concepts + backlinks)
144
- stellavault promote note.md --to permanent # Upgrade stage
145
- stellavault autopilot # Full cycle: inbox → compile → lint
156
+ npx stellavault index --vault ./examples/demo-vault # Index 10 sample notes
157
+ npx stellavault search "vector database" # Semantic search
158
+ npx stellavault graph # 3D graph visualization
146
159
  ```
147
160
 
148
- Auto-assigned Luhmann index codes, frontmatter-first scanning, configurable folders.
161
+ The demo vault includes interconnected notes about Vector Databases, Knowledge Graphs, Spaced Repetition, RAG, MCP, and more — perfect for exploring all features instantly.
149
162
 
150
- ## P2P Federation (Multiverse)
163
+ ---
151
164
 
152
- Your vault is a universe. Connect with others through P2P federation.
165
+ ## Getting Started Guide
153
166
 
154
- - **Hyperswarm P2P** — NAT-traversal, no central server
155
- - **Embeddings only** — original text never leaves your machine
156
- - **Differential privacy** — mathematical privacy guarantees
167
+ ### Desktop App
157
168
 
158
- In the desktop app or web UI, click the **Federation badge** in the header to join/leave the Stella Network.
169
+ 1. **Download** Unzip Run
170
+ 2. First launch asks you to pick your notes folder
171
+ 3. Your notes appear in the sidebar — click to open
172
+ 4. Press `Ctrl+P` for quick file switching
173
+ 5. Click ✦ in the title bar for AI panel (semantic search, stats, draft)
174
+ 6. Click ◉ for 3D graph
159
175
 
160
- ## Tech Stack
176
+ ### CLI
161
177
 
162
- | Layer | Tech |
163
- |-------|------|
164
- | Desktop | Electron + React + TipTap + Zustand |
165
- | Runtime | Node.js 20+ (ESM, TypeScript) |
166
- | Vector Store | SQLite-vec (local, zero config) |
167
- | Embedding | MiniLM-L12-v2 (local, 50+ languages) |
168
- | Search | BM25 + Cosine + RRF Fusion |
169
- | File Parsing | unpdf, mammoth, officeparser, SheetJS |
170
- | Memory | FSRS (Free Spaced Repetition Scheduler) |
171
- | 3D | React Three Fiber + Three.js |
172
- | AI | MCP (Model Context Protocol) + Anthropic SDK |
173
- | P2P | Hyperswarm (optional) |
174
-
175
- ## Full Feature List
176
-
177
- | Category | Features |
178
- |----------|----------|
179
- | **Desktop** | File tree sidebar, multi-tab editor, [[wikilink]] autocomplete, Quick Switcher, Command Palette, 3D graph panel, AI panel, backlinks, dark/light theme |
180
- | **Capture** | 14 formats (PDF/DOCX/PPTX/XLSX/JSON/CSV/XML/HTML/YAML/RTF/YouTube/URL/text), batch folders, drag & drop, voice capture, Quick Capture |
181
- | **Organize** | Zettelkasten 3-stage, auto index codes, wikilink auto-connect, configurable folders |
182
- | **Distill** | compile (raw→wiki), lint (health score), gaps, contradictions, duplicates |
183
- | **Express** | draft (blog/report/outline/instagram/thread/script), blueprint, --ai mode |
184
- | **Memory** | FSRS decay, session-save, flush, compounding loop, ADR templates |
185
- | **Search** | hybrid (BM25+vector+RRF), multilingual 50+, ask Q&A, quotes mode |
186
- | **Visualize** | 3D graph, heatmap, timeline, constellation view, decay overlay, multiverse |
187
- | **AI** | 21 MCP tools, Claude Code hooks, Anthropic SDK |
188
- | **Federation** | Hyperswarm P2P, embedding-only sharing, differential privacy |
189
- | **CLI** | 40+ commands, `sv` alias, `stellavault doctor` diagnostics |
178
+ ```bash
179
+ npm install -g stellavault
180
+ stellavault init # Setup wizard
181
+ stellavault search "machine learning" # Semantic search
182
+ stellavault ingest paper.pdf # Add knowledge
183
+ stellavault graph # 3D graph in browser
184
+ stellavault brief # Morning briefing
185
+ stellavault decay # What are you forgetting?
186
+ ```
190
187
 
191
- ## Getting Started Guide
188
+ ### Keyboard Shortcuts (Desktop)
192
189
 
193
- ### Desktop App (easiest)
190
+ | Shortcut | Action |
191
+ |----------|--------|
192
+ | `Ctrl+P` | Quick Switcher (fuzzy file search) |
193
+ | `Ctrl+Shift+P` | Command Palette (all actions) |
194
+ | `Ctrl+S` | Save current note |
195
+ | `Ctrl+\` | Toggle split view |
196
+ | `Ctrl+B` | Bold |
197
+ | `Ctrl+I` | Italic |
198
+ | `Ctrl+U` | Underline |
199
+ | `Ctrl+E` | Inline code |
200
+ | `/` | Slash commands (at start of line) |
201
+ | `[[` | Wikilink autocomplete |
194
202
 
195
- 1. **Download** from [Releases](https://github.com/Evanciel/stellavault/releases/latest)
196
- 2. **Unzip** to any folder
197
- 3. **Run** `stellavault.exe` (Windows) — first launch asks you to pick your notes folder
198
- 4. **Explore** — your notes appear in the sidebar, click to open in the editor
199
- 5. **Search** — press `Ctrl+P` to quick-switch between notes, or open the AI panel (✦ button) for semantic search
203
+ ### Quick Reference
200
204
 
201
- ### CLI (for developers)
205
+ | Action | Desktop | CLI |
206
+ |--------|---------|-----|
207
+ | Search notes | Ctrl+P or AI panel | `stellavault search "query"` |
208
+ | Add a note | + Note button or drag & drop | `stellavault ingest "text"` |
209
+ | See 3D graph | ◉ button | `stellavault graph` |
210
+ | Memory decay | AI panel → Memory | `stellavault decay` |
211
+ | Generate draft | AI panel → Draft | `stellavault draft "topic"` |
212
+ | Health check | AI panel → Stats | `stellavault lint` |
202
213
 
203
- ```bash
204
- # Step 1: Install
205
- npm install -g stellavault
214
+ ---
206
215
 
207
- # Step 2: Setup (interactive wizard)
208
- stellavault init
209
- # → Asks for vault path → indexes all .md files → tests search
216
+ ## Performance
210
217
 
211
- # Step 3: Daily use
212
- stellavault search "machine learning" # Find notes
213
- stellavault ingest paper.pdf # Add new knowledge
214
- stellavault graph # Open 3D graph in browser
215
- stellavault brief # Morning briefing
216
- stellavault decay # What are you forgetting?
218
+ Tested on synthetic vaults — all operations under 1 second for typical use cases:
217
219
 
218
- # Step 4: Connect to Claude
219
- claude mcp add stellavault -- stellavault serve
220
- # Claude can now read your vault via MCP
221
- ```
220
+ | Operation | 100 docs | 500 docs | 1000 docs |
221
+ |-----------|----------|----------|-----------|
222
+ | Store init | 15ms | 15ms | 16ms |
223
+ | Bulk upsert | 12ms | 102ms | ~200ms |
224
+ | Search (BM25) | <1ms | <1ms | <1ms |
225
+ | Get all docs | <1ms | 2ms | ~4ms |
226
+ | 124K dot products | — | 36ms | — |
222
227
 
223
- ### Obsidian Plugin
228
+ Run your own benchmarks:
224
229
 
225
230
  ```bash
226
- # Step 1: Start the API server (keep running)
227
- npx stellavault graph
231
+ node tests/stress.mjs 500 # Test with 500 synthetic documents
232
+ ```
228
233
 
229
- # Step 2: Install plugin
230
- # Download main.js + manifest.json + styles.css from:
231
- # https://github.com/Evanciel/stellavault-obsidian/releases/latest
232
- # Place in: <vault>/.obsidian/plugins/stellavault/
234
+ Key optimizations:
235
+ - Pre-normalized vectors: cosine similarity single dot product
236
+ - Batched embedding loading (500/batch, prevents RAM overflow)
237
+ - Upper-triangle graph building (50% fewer comparisons)
238
+ - O(n) K-Means centroid updates with typed arrays
233
239
 
234
- # Step 3: Enable in Settings → Community Plugins → Stellavault
240
+ ---
235
241
 
236
- # Step 4: Use
237
- # - Click brain icon (🧠) for semantic search
238
- # - Cmd+Shift+D for memory decay panel
239
- # - Cmd+Shift+L for learning path suggestions
240
- ```
242
+ ## Tech Stack
241
243
 
242
- ### Quick Reference
244
+ | Layer | Tech |
245
+ |-------|------|
246
+ | Desktop | Electron + React + TipTap (15 extensions) + Zustand |
247
+ | Runtime | Node.js 20+ (ESM, TypeScript) |
248
+ | Vector Store | SQLite-vec (local, zero config) |
249
+ | Embedding | MiniLM-L12-v2 (local, 50+ languages, batch processing) |
250
+ | Search | BM25 + Cosine + RRF Fusion |
251
+ | Math | KaTeX (inline + display) |
252
+ | Code | lowlight / highlight.js (40+ languages) |
253
+ | 3D | React Three Fiber + Three.js |
254
+ | AI | MCP (21 tools) + Anthropic SDK |
255
+ | P2P | Hyperswarm (optional, differential privacy) |
256
+ | CI | GitHub Actions (Node 20 + 22) |
243
257
 
244
- | Action | Desktop | CLI | Obsidian |
245
- |--------|---------|-----|----------|
246
- | Search notes | Ctrl+P or AI panel | `stellavault search "query"` | 🧠 icon |
247
- | Add a note | + Note button | `stellavault ingest "text"` | Normal editing |
248
- | See 3D graph | ◉ button | `stellavault graph` | N/A |
249
- | Check memory decay | AI panel → Memory | `stellavault decay` | Decay sidebar |
250
- | Find duplicates | AI panel → Stats | `stellavault duplicates` | N/A |
251
- | Generate draft | N/A (v0.2) | `stellavault draft "topic"` | N/A |
252
- | Connect to Claude | N/A (v0.2) | `claude mcp add stellavault` | N/A |
253
-
254
- ### Configuration
255
-
256
- All settings live in `~/.stellavault.json`:
257
-
258
- ```json
259
- {
260
- "vaultPath": "/path/to/your/notes",
261
- "dbPath": "~/.stellavault/index.db",
262
- "embedding": { "model": "local", "localModel": "all-MiniLM-L6-v2" },
263
- "mcp": { "mode": "stdio", "port": 3333 }
264
- }
265
- ```
258
+ ---
266
259
 
267
- Run `stellavault doctor` anytime to check your setup.
260
+ ## Security
268
261
 
269
- ### Keyboard Shortcuts (Desktop)
262
+ - **Local-first** no data leaves your machine unless you use `--ai`
263
+ - **Vault files never modified** — indexes into SQLite, originals untouched
264
+ - **Electron sandbox enabled** — renderer runs with reduced OS privileges
265
+ - **IPC path validation** — all file operations stay inside vault root
266
+ - **API auth token** — per-session random token for mutating endpoints
267
+ - **SSRF protection** — private IPs blocked on URL ingest
268
+ - **E2E encryption** — AES-256-GCM for cloud sync
270
269
 
271
- | Shortcut | Action |
272
- |----------|--------|
273
- | `Ctrl+P` | Quick Switcher (fuzzy file search) |
274
- | `Ctrl+Shift+P` | Command Palette (all actions) |
275
- | `Ctrl+S` | Save current note |
276
- | `Ctrl+B` | Toggle bold |
277
- | `Ctrl+I` | Toggle italic |
278
- | `Ctrl+E` | Toggle inline code |
279
- | `[[` | Wikilink autocomplete |
270
+ See [SECURITY.md](SECURITY.md) for full details.
280
271
 
281
272
  ## Troubleshooting
282
273
 
@@ -285,14 +276,10 @@ stellavault doctor # Check config, vault, DB, model, Node version
285
276
  ```
286
277
 
287
278
  Common issues:
288
- - **"Command not found"** → Reinstall: `npm i -g stellavault@latest`
289
- - **"API server not found"** → Start the server: `npx stellavault graph`
290
- - **Empty graph** → Run `stellavault index` to re-index your vault
291
- - **Slow first run** → The AI model downloads ~30MB on first use (one time only)
292
-
293
- ## Security
294
-
295
- Local-first — no data leaves your machine unless you explicitly use `--ai` (Anthropic API). Vault files are never modified. See [SECURITY.md](SECURITY.md).
279
+ - **"Command not found"** → `npm i -g stellavault@latest`
280
+ - **"API server not found"** → `npx stellavault graph`
281
+ - **Empty graph** → `stellavault index`
282
+ - **Slow first run** → AI model downloads ~30MB once
296
283
 
297
284
  ## License
298
285
 
@@ -300,7 +287,7 @@ MIT — full source code available for audit.
300
287
 
301
288
  ## Links
302
289
 
303
- - **[Download Desktop App](https://github.com/Evanciel/stellavault/releases/latest)**
290
+ - **[Download Desktop App](https://github.com/Evanciel/stellavault/releases/tag/desktop-v0.1.0)**
304
291
  - [Landing Page](https://evanciel.github.io/stellavault/)
305
292
  - [Obsidian Plugin](https://github.com/Evanciel/stellavault-obsidian)
306
293
  - [npm](https://www.npmjs.com/package/stellavault)
@@ -1 +1 @@
1
- import{c as q,g as K}from"./index-DdorzFNd.js";function L(d,m){for(var w=0;w<m.length;w++){const f=m[w];if(typeof f!="string"&&!Array.isArray(f)){for(const a in f)if(a!=="default"&&!(a in d)){const j=Object.getOwnPropertyDescriptor(f,a);j&&Object.defineProperty(d,a,j.get?j:{enumerable:!0,get:()=>f[a]})}}}return Object.freeze(Object.defineProperty(d,Symbol.toStringTag,{value:"Module"}))}var F={},T;function Q(){return T||(T=1,(function(){function d(t){var e=0;return function(){return e<t.length?{done:!1,value:t[e++]}:{done:!0}}}var m=typeof Object.defineProperties=="function"?Object.defineProperty:function(t,e,o){return t==Array.prototype||t==Object.prototype||(t[e]=o.value),t};function w(t){t=[typeof globalThis=="object"&&globalThis,t,typeof window=="object"&&window,typeof self=="object"&&self,typeof q=="object"&&q];for(var e=0;e<t.length;++e){var o=t[e];if(o&&o.Math==Math)return o}throw Error("Cannot find global object")}var f=w(this);function a(t,e){if(e)t:{var o=f;t=t.split(".");for(var i=0;i<t.length-1;i++){var s=t[i];if(!(s in o))break t;o=o[s]}t=t[t.length-1],i=o[t],e=e(i),e!=i&&e!=null&&m(o,t,{configurable:!0,writable:!0,value:e})}}a("Symbol",function(t){function e(l){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new o(i+(l||"")+"_"+s++,l)}function o(l,n){this.g=l,m(this,"description",{configurable:!0,writable:!0,value:n})}if(t)return t;o.prototype.toString=function(){return this.g};var i="jscomp_symbol_"+(1e9*Math.random()>>>0)+"_",s=0;return e}),a("Symbol.iterator",function(t){if(t)return t;t=Symbol("Symbol.iterator");for(var e="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),o=0;o<e.length;o++){var i=f[e[o]];typeof i=="function"&&typeof i.prototype[t]!="function"&&m(i.prototype,t,{configurable:!0,writable:!0,value:function(){return j(d(this))}})}return t});function j(t){return t={next:t},t[Symbol.iterator]=function(){return this},t}function A(t){var e=typeof Symbol<"u"&&Symbol.iterator&&t[Symbol.iterator];return e?e.call(t):{next:d(t)}}function E(){this.i=!1,this.g=null,this.o=void 0,this.j=1,this.m=0,this.h=null}function S(t){if(t.i)throw new TypeError("Generator is already running");t.i=!0}E.prototype.l=function(t){this.o=t};function _(t,e){t.h={F:e,G:!0},t.j=t.m}E.prototype.return=function(t){this.h={return:t},this.j=this.m};function U(t){this.g=new E,this.h=t}function H(t,e){S(t.g);var o=t.g.g;return o?C(t,"return"in o?o.return:function(i){return{value:i,done:!0}},e,t.g.return):(t.g.return(e),b(t))}function C(t,e,o,i){try{var s=e.call(t.g.g,o);if(!(s instanceof Object))throw new TypeError("Iterator result "+s+" is not an object");if(!s.done)return t.g.i=!1,s;var l=s.value}catch(n){return t.g.g=null,_(t.g,n),b(t)}return t.g.g=null,i.call(t.g,l),b(t)}function b(t){for(;t.g.j;)try{var e=t.h(t.g);if(e)return t.g.i=!1,{value:e.value,done:!1}}catch(o){t.g.o=void 0,_(t.g,o)}if(t.g.i=!1,t.g.h){if(e=t.g.h,t.g.h=null,e.G)throw e.F;return{value:e.return,done:!0}}return{value:void 0,done:!0}}function I(t){this.next=function(e){return S(t.g),t.g.g?e=C(t,t.g.g.next,e,t.g.l):(t.g.l(e),e=b(t)),e},this.throw=function(e){return S(t.g),t.g.g?e=C(t,t.g.g.throw,e,t.g.l):(_(t.g,e),e=b(t)),e},this.return=function(e){return H(t,e)},this[Symbol.iterator]=function(){return this}}function G(t){function e(i){return t.next(i)}function o(i){return t.throw(i)}return new Promise(function(i,s){function l(n){n.done?i(n.value):Promise.resolve(n.value).then(e,o).then(l,s)}l(t.next())})}a("Promise",function(t){function e(n){this.h=0,this.i=void 0,this.g=[],this.o=!1;var r=this.j();try{n(r.resolve,r.reject)}catch(u){r.reject(u)}}function o(){this.g=null}function i(n){return n instanceof e?n:new e(function(r){r(n)})}if(t)return t;o.prototype.h=function(n){if(this.g==null){this.g=[];var r=this;this.i(function(){r.l()})}this.g.push(n)};var s=f.setTimeout;o.prototype.i=function(n){s(n,0)},o.prototype.l=function(){for(;this.g&&this.g.length;){var n=this.g;this.g=[];for(var r=0;r<n.length;++r){var u=n[r];n[r]=null;try{u()}catch(c){this.j(c)}}}this.g=null},o.prototype.j=function(n){this.i(function(){throw n})},e.prototype.j=function(){function n(c){return function(h){u||(u=!0,c.call(r,h))}}var r=this,u=!1;return{resolve:n(this.A),reject:n(this.l)}},e.prototype.A=function(n){if(n===this)this.l(new TypeError("A Promise cannot resolve to itself"));else if(n instanceof e)this.C(n);else{t:switch(typeof n){case"object":var r=n!=null;break t;case"function":r=!0;break t;default:r=!1}r?this.v(n):this.m(n)}},e.prototype.v=function(n){var r=void 0;try{r=n.then}catch(u){this.l(u);return}typeof r=="function"?this.D(r,n):this.m(n)},e.prototype.l=function(n){this.u(2,n)},e.prototype.m=function(n){this.u(1,n)},e.prototype.u=function(n,r){if(this.h!=0)throw Error("Cannot settle("+n+", "+r+"): Promise already settled in state"+this.h);this.h=n,this.i=r,this.h===2&&this.B(),this.H()},e.prototype.B=function(){var n=this;s(function(){if(n.I()){var r=f.console;typeof r<"u"&&r.error(n.i)}},1)},e.prototype.I=function(){if(this.o)return!1;var n=f.CustomEvent,r=f.Event,u=f.dispatchEvent;return typeof u>"u"?!0:(typeof n=="function"?n=new n("unhandledrejection",{cancelable:!0}):typeof r=="function"?n=new r("unhandledrejection",{cancelable:!0}):(n=f.document.createEvent("CustomEvent"),n.initCustomEvent("unhandledrejection",!1,!0,n)),n.promise=this,n.reason=this.i,u(n))},e.prototype.H=function(){if(this.g!=null){for(var n=0;n<this.g.length;++n)l.h(this.g[n]);this.g=null}};var l=new o;return e.prototype.C=function(n){var r=this.j();n.s(r.resolve,r.reject)},e.prototype.D=function(n,r){var u=this.j();try{n.call(r,u.resolve,u.reject)}catch(c){u.reject(c)}},e.prototype.then=function(n,r){function u(v,y){return typeof v=="function"?function(k){try{c(v(k))}catch(D){h(D)}}:y}var c,h,M=new e(function(v,y){c=v,h=y});return this.s(u(n,c),u(r,h)),M},e.prototype.catch=function(n){return this.then(void 0,n)},e.prototype.s=function(n,r){function u(){switch(c.h){case 1:n(c.i);break;case 2:r(c.i);break;default:throw Error("Unexpected state: "+c.h)}}var c=this;this.g==null?l.h(u):this.g.push(u),this.o=!0},e.resolve=i,e.reject=function(n){return new e(function(r,u){u(n)})},e.race=function(n){return new e(function(r,u){for(var c=A(n),h=c.next();!h.done;h=c.next())i(h.value).s(r,u)})},e.all=function(n){var r=A(n),u=r.next();return u.done?i([]):new e(function(c,h){function M(k){return function(D){v[k]=D,y--,y==0&&c(v)}}var v=[],y=0;do v.push(void 0),y++,i(u.value).s(M(v.length-1),h),u=r.next();while(!u.done)})},e});var N=typeof Object.assign=="function"?Object.assign:function(t,e){for(var o=1;o<arguments.length;o++){var i=arguments[o];if(i)for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(t[s]=i[s])}return t};a("Object.assign",function(t){return t||N});var z=this||self,R={facingMode:"user",width:640,height:480};function O(t,e){this.video=t,this.i=0,this.h=Object.assign(Object.assign({},R),e)}O.prototype.stop=function(){var t=this,e,o,i,s;return G(new I(new U(function(l){if(t.g){for(e=t.g.getTracks(),o=A(e),i=o.next();!i.done;i=o.next())s=i.value,s.stop();t.g=void 0}l.j=0})))},O.prototype.start=function(){var t=this,e;return G(new I(new U(function(o){return navigator.mediaDevices&&navigator.mediaDevices.getUserMedia||alert("No navigator.mediaDevices.getUserMedia exists."),e=t.h,o.return(navigator.mediaDevices.getUserMedia({video:{facingMode:e.facingMode,width:e.width,height:e.height}}).then(function(i){$(t,i)}).catch(function(i){var s="Failed to acquire camera feed: "+i;throw console.error(s),alert(s),i}))})))};function P(t){window.requestAnimationFrame(function(){J(t)})}function $(t,e){t.g=e,t.video.srcObject=e,t.video.onloadedmetadata=function(){t.video.play(),P(t)}}function J(t){var e=null;t.video.paused||t.video.currentTime===t.i||(t.i=t.video.currentTime,e=t.h.onFrame()),e?e.then(function(){P(t)}):P(t)}var x=["Camera"],g=z;x[0]in g||typeof g.execScript>"u"||g.execScript("var "+x[0]);for(var p;x.length&&(p=x.shift());)x.length||O===void 0?g[p]&&g[p]!==Object.prototype[p]?g=g[p]:g=g[p]={}:g[p]=O}).call(F)),F}var B=Q();const V=K(B),X=L({__proto__:null,default:V},[B]);export{X as c};
1
+ import{c as q,g as K}from"./index-4LS6c1x8.js";function L(d,m){for(var w=0;w<m.length;w++){const f=m[w];if(typeof f!="string"&&!Array.isArray(f)){for(const a in f)if(a!=="default"&&!(a in d)){const j=Object.getOwnPropertyDescriptor(f,a);j&&Object.defineProperty(d,a,j.get?j:{enumerable:!0,get:()=>f[a]})}}}return Object.freeze(Object.defineProperty(d,Symbol.toStringTag,{value:"Module"}))}var F={},T;function Q(){return T||(T=1,(function(){function d(t){var e=0;return function(){return e<t.length?{done:!1,value:t[e++]}:{done:!0}}}var m=typeof Object.defineProperties=="function"?Object.defineProperty:function(t,e,o){return t==Array.prototype||t==Object.prototype||(t[e]=o.value),t};function w(t){t=[typeof globalThis=="object"&&globalThis,t,typeof window=="object"&&window,typeof self=="object"&&self,typeof q=="object"&&q];for(var e=0;e<t.length;++e){var o=t[e];if(o&&o.Math==Math)return o}throw Error("Cannot find global object")}var f=w(this);function a(t,e){if(e)t:{var o=f;t=t.split(".");for(var i=0;i<t.length-1;i++){var s=t[i];if(!(s in o))break t;o=o[s]}t=t[t.length-1],i=o[t],e=e(i),e!=i&&e!=null&&m(o,t,{configurable:!0,writable:!0,value:e})}}a("Symbol",function(t){function e(l){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new o(i+(l||"")+"_"+s++,l)}function o(l,n){this.g=l,m(this,"description",{configurable:!0,writable:!0,value:n})}if(t)return t;o.prototype.toString=function(){return this.g};var i="jscomp_symbol_"+(1e9*Math.random()>>>0)+"_",s=0;return e}),a("Symbol.iterator",function(t){if(t)return t;t=Symbol("Symbol.iterator");for(var e="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),o=0;o<e.length;o++){var i=f[e[o]];typeof i=="function"&&typeof i.prototype[t]!="function"&&m(i.prototype,t,{configurable:!0,writable:!0,value:function(){return j(d(this))}})}return t});function j(t){return t={next:t},t[Symbol.iterator]=function(){return this},t}function A(t){var e=typeof Symbol<"u"&&Symbol.iterator&&t[Symbol.iterator];return e?e.call(t):{next:d(t)}}function E(){this.i=!1,this.g=null,this.o=void 0,this.j=1,this.m=0,this.h=null}function S(t){if(t.i)throw new TypeError("Generator is already running");t.i=!0}E.prototype.l=function(t){this.o=t};function _(t,e){t.h={F:e,G:!0},t.j=t.m}E.prototype.return=function(t){this.h={return:t},this.j=this.m};function U(t){this.g=new E,this.h=t}function H(t,e){S(t.g);var o=t.g.g;return o?C(t,"return"in o?o.return:function(i){return{value:i,done:!0}},e,t.g.return):(t.g.return(e),b(t))}function C(t,e,o,i){try{var s=e.call(t.g.g,o);if(!(s instanceof Object))throw new TypeError("Iterator result "+s+" is not an object");if(!s.done)return t.g.i=!1,s;var l=s.value}catch(n){return t.g.g=null,_(t.g,n),b(t)}return t.g.g=null,i.call(t.g,l),b(t)}function b(t){for(;t.g.j;)try{var e=t.h(t.g);if(e)return t.g.i=!1,{value:e.value,done:!1}}catch(o){t.g.o=void 0,_(t.g,o)}if(t.g.i=!1,t.g.h){if(e=t.g.h,t.g.h=null,e.G)throw e.F;return{value:e.return,done:!0}}return{value:void 0,done:!0}}function I(t){this.next=function(e){return S(t.g),t.g.g?e=C(t,t.g.g.next,e,t.g.l):(t.g.l(e),e=b(t)),e},this.throw=function(e){return S(t.g),t.g.g?e=C(t,t.g.g.throw,e,t.g.l):(_(t.g,e),e=b(t)),e},this.return=function(e){return H(t,e)},this[Symbol.iterator]=function(){return this}}function G(t){function e(i){return t.next(i)}function o(i){return t.throw(i)}return new Promise(function(i,s){function l(n){n.done?i(n.value):Promise.resolve(n.value).then(e,o).then(l,s)}l(t.next())})}a("Promise",function(t){function e(n){this.h=0,this.i=void 0,this.g=[],this.o=!1;var r=this.j();try{n(r.resolve,r.reject)}catch(u){r.reject(u)}}function o(){this.g=null}function i(n){return n instanceof e?n:new e(function(r){r(n)})}if(t)return t;o.prototype.h=function(n){if(this.g==null){this.g=[];var r=this;this.i(function(){r.l()})}this.g.push(n)};var s=f.setTimeout;o.prototype.i=function(n){s(n,0)},o.prototype.l=function(){for(;this.g&&this.g.length;){var n=this.g;this.g=[];for(var r=0;r<n.length;++r){var u=n[r];n[r]=null;try{u()}catch(c){this.j(c)}}}this.g=null},o.prototype.j=function(n){this.i(function(){throw n})},e.prototype.j=function(){function n(c){return function(h){u||(u=!0,c.call(r,h))}}var r=this,u=!1;return{resolve:n(this.A),reject:n(this.l)}},e.prototype.A=function(n){if(n===this)this.l(new TypeError("A Promise cannot resolve to itself"));else if(n instanceof e)this.C(n);else{t:switch(typeof n){case"object":var r=n!=null;break t;case"function":r=!0;break t;default:r=!1}r?this.v(n):this.m(n)}},e.prototype.v=function(n){var r=void 0;try{r=n.then}catch(u){this.l(u);return}typeof r=="function"?this.D(r,n):this.m(n)},e.prototype.l=function(n){this.u(2,n)},e.prototype.m=function(n){this.u(1,n)},e.prototype.u=function(n,r){if(this.h!=0)throw Error("Cannot settle("+n+", "+r+"): Promise already settled in state"+this.h);this.h=n,this.i=r,this.h===2&&this.B(),this.H()},e.prototype.B=function(){var n=this;s(function(){if(n.I()){var r=f.console;typeof r<"u"&&r.error(n.i)}},1)},e.prototype.I=function(){if(this.o)return!1;var n=f.CustomEvent,r=f.Event,u=f.dispatchEvent;return typeof u>"u"?!0:(typeof n=="function"?n=new n("unhandledrejection",{cancelable:!0}):typeof r=="function"?n=new r("unhandledrejection",{cancelable:!0}):(n=f.document.createEvent("CustomEvent"),n.initCustomEvent("unhandledrejection",!1,!0,n)),n.promise=this,n.reason=this.i,u(n))},e.prototype.H=function(){if(this.g!=null){for(var n=0;n<this.g.length;++n)l.h(this.g[n]);this.g=null}};var l=new o;return e.prototype.C=function(n){var r=this.j();n.s(r.resolve,r.reject)},e.prototype.D=function(n,r){var u=this.j();try{n.call(r,u.resolve,u.reject)}catch(c){u.reject(c)}},e.prototype.then=function(n,r){function u(v,y){return typeof v=="function"?function(k){try{c(v(k))}catch(D){h(D)}}:y}var c,h,M=new e(function(v,y){c=v,h=y});return this.s(u(n,c),u(r,h)),M},e.prototype.catch=function(n){return this.then(void 0,n)},e.prototype.s=function(n,r){function u(){switch(c.h){case 1:n(c.i);break;case 2:r(c.i);break;default:throw Error("Unexpected state: "+c.h)}}var c=this;this.g==null?l.h(u):this.g.push(u),this.o=!0},e.resolve=i,e.reject=function(n){return new e(function(r,u){u(n)})},e.race=function(n){return new e(function(r,u){for(var c=A(n),h=c.next();!h.done;h=c.next())i(h.value).s(r,u)})},e.all=function(n){var r=A(n),u=r.next();return u.done?i([]):new e(function(c,h){function M(k){return function(D){v[k]=D,y--,y==0&&c(v)}}var v=[],y=0;do v.push(void 0),y++,i(u.value).s(M(v.length-1),h),u=r.next();while(!u.done)})},e});var N=typeof Object.assign=="function"?Object.assign:function(t,e){for(var o=1;o<arguments.length;o++){var i=arguments[o];if(i)for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(t[s]=i[s])}return t};a("Object.assign",function(t){return t||N});var z=this||self,R={facingMode:"user",width:640,height:480};function O(t,e){this.video=t,this.i=0,this.h=Object.assign(Object.assign({},R),e)}O.prototype.stop=function(){var t=this,e,o,i,s;return G(new I(new U(function(l){if(t.g){for(e=t.g.getTracks(),o=A(e),i=o.next();!i.done;i=o.next())s=i.value,s.stop();t.g=void 0}l.j=0})))},O.prototype.start=function(){var t=this,e;return G(new I(new U(function(o){return navigator.mediaDevices&&navigator.mediaDevices.getUserMedia||alert("No navigator.mediaDevices.getUserMedia exists."),e=t.h,o.return(navigator.mediaDevices.getUserMedia({video:{facingMode:e.facingMode,width:e.width,height:e.height}}).then(function(i){$(t,i)}).catch(function(i){var s="Failed to acquire camera feed: "+i;throw console.error(s),alert(s),i}))})))};function P(t){window.requestAnimationFrame(function(){J(t)})}function $(t,e){t.g=e,t.video.srcObject=e,t.video.onloadedmetadata=function(){t.video.play(),P(t)}}function J(t){var e=null;t.video.paused||t.video.currentTime===t.i||(t.i=t.video.currentTime,e=t.h.onFrame()),e?e.then(function(){P(t)}):P(t)}var x=["Camera"],g=z;x[0]in g||typeof g.execScript>"u"||g.execScript("var "+x[0]);for(var p;x.length&&(p=x.shift());)x.length||O===void 0?g[p]&&g[p]!==Object.prototype[p]?g=g[p]:g=g[p]={}:g[p]=O}).call(F)),F}var B=Q();const V=K(B),X=L({__proto__:null,default:V},[B]);export{X as c};