@soulcraft/cor 3.0.0-rc.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/LICENSE +16 -0
- package/README.md +328 -0
- package/dist/aggregation/NativeAggregationEngine.d.ts +118 -0
- package/dist/aggregation/NativeAggregationEngine.js +186 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +236 -0
- package/dist/graph/GraphAccelerationAdapter.d.ts +153 -0
- package/dist/graph/GraphAccelerationAdapter.js +326 -0
- package/dist/graph/NativeGraphAdjacencyIndex.d.ts +286 -0
- package/dist/graph/NativeGraphAdjacencyIndex.js +944 -0
- package/dist/hnsw/AdaptiveDiskAnnModeSelector.d.ts +187 -0
- package/dist/hnsw/AdaptiveDiskAnnModeSelector.js +313 -0
- package/dist/hnsw/NativeDiskAnnWrapper.d.ts +489 -0
- package/dist/hnsw/NativeDiskAnnWrapper.js +1456 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +29 -0
- package/dist/legacyLayoutGuard.d.ts +93 -0
- package/dist/legacyLayoutGuard.js +237 -0
- package/dist/license/constants.d.ts +30 -0
- package/dist/license/constants.js +30 -0
- package/dist/license/onlineValidator.d.ts +43 -0
- package/dist/license/onlineValidator.js +225 -0
- package/dist/license/types.d.ts +39 -0
- package/dist/license/types.js +5 -0
- package/dist/license.d.ts +64 -0
- package/dist/license.js +165 -0
- package/dist/migration/MigrationCoordinator.d.ts +171 -0
- package/dist/migration/MigrationCoordinator.js +249 -0
- package/dist/migration/indexEpochGuard.d.ts +163 -0
- package/dist/migration/indexEpochGuard.js +202 -0
- package/dist/native/NativeEmbeddingEngine.d.ts +79 -0
- package/dist/native/NativeEmbeddingEngine.js +318 -0
- package/dist/native/NativeRoaringBitmap32.d.ts +114 -0
- package/dist/native/NativeRoaringBitmap32.js +221 -0
- package/dist/native/ffi.d.ts +20 -0
- package/dist/native/ffi.js +48 -0
- package/dist/native/idMapperTestSupport.d.ts +67 -0
- package/dist/native/idMapperTestSupport.js +112 -0
- package/dist/native/index.d.ts +49 -0
- package/dist/native/index.js +87 -0
- package/dist/native/napi.d.ts +21 -0
- package/dist/native/napi.js +88 -0
- package/dist/native/types.d.ts +1298 -0
- package/dist/native/types.js +16 -0
- package/dist/plugin.d.ts +50 -0
- package/dist/plugin.js +388 -0
- package/dist/providerContracts.d.ts +277 -0
- package/dist/providerContracts.js +38 -0
- package/dist/resource/OsMemoryProbe.d.ts +175 -0
- package/dist/resource/OsMemoryProbe.js +206 -0
- package/dist/resource/ResourceManager.d.ts +491 -0
- package/dist/resource/ResourceManager.js +960 -0
- package/dist/utils/ColumnManifest.d.ts +97 -0
- package/dist/utils/ColumnManifest.js +129 -0
- package/dist/utils/NativeColumnStore.d.ts +284 -0
- package/dist/utils/NativeColumnStore.js +685 -0
- package/dist/utils/NativeMetadataIndex.d.ts +882 -0
- package/dist/utils/NativeMetadataIndex.js +2631 -0
- package/dist/utils/NativeUnifiedCache.d.ts +87 -0
- package/dist/utils/NativeUnifiedCache.js +273 -0
- package/dist/utils/binaryIdMapperFactory.d.ts +59 -0
- package/dist/utils/binaryIdMapperFactory.js +94 -0
- package/dist/utils/collation.d.ts +30 -0
- package/dist/utils/collation.js +40 -0
- package/dist/utils/columnStoreTypes.d.ts +161 -0
- package/dist/utils/columnStoreTypes.js +29 -0
- package/dist/utils/nativeBinaryEntityIdMapper.d.ts +211 -0
- package/dist/utils/nativeBinaryEntityIdMapper.js +381 -0
- package/dist/utils/nativeEntityIdMapper.d.ts +111 -0
- package/dist/utils/nativeEntityIdMapper.js +170 -0
- package/docs/ADR-002-diskann-100-percent-rust.md +294 -0
- package/docs/ADR-003-semantic-time-travel.md +100 -0
- package/docs/aggregation.md +251 -0
- package/docs/comparison.md +162 -0
- package/docs/deployment-limits.md +87 -0
- package/docs/diskann.md +184 -0
- package/docs/migration-3.0.md +396 -0
- package/docs/performance-budget.md +274 -0
- package/docs/performance.md +117 -0
- package/docs/scaling.md +439 -0
- package/docs/snapshot-safety.md +246 -0
- package/docs/u64-id-space.md +214 -0
- package/docs/verification-report.md +670 -0
- package/native/brainy-native.node +0 -0
- package/native/index.d.ts +3916 -0
- package/package.json +92 -0
- package/scripts/migrate-cortex-2x-to-3x.mjs +970 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Soulcraft Cor - Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Soulcraft Labs. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is proprietary and confidential. Unauthorized copying, distribution,
|
|
6
|
+
modification, or use of this software, via any medium, is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
A valid license key is required to use this software. License keys can be purchased
|
|
9
|
+
at https://soulcraft.com/pricing?focus=pro.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
12
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
13
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
14
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
15
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
16
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# @soulcraft/cor
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/soulcraftlabs/brainy/main/brainy.png" alt="Soulcraft" width="180">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@soulcraft/cor"><img src="https://badge.fury.io/js/%40soulcraft%2Fcor.svg" alt="npm version"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/@soulcraft/cor"><img src="https://img.shields.io/npm/dm/@soulcraft/cor.svg" alt="npm downloads"></a>
|
|
10
|
+
<a href="https://soulcraft.com/pricing?focus=cor"><img src="https://img.shields.io/badge/license-commercial-blue.svg" alt="Commercial License"></a>
|
|
11
|
+
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg" alt="TypeScript"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<strong>Native Rust acceleration for <a href="https://www.npmjs.com/package/@soulcraft/brainy">@soulcraft/brainy</a>.</strong>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
Adaptive DiskANN to 1 B+ vectors · Triple-intelligence find() (metadata ∩ graph ∩ vector) · Time-travel reads (<code>db.asOf(g)</code>) · Sub-millisecond vector search at 1 M · 13–18× pgvector index latency on the reference host
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bun add @soulcraft/cor # or: npm install @soulcraft/cor
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**[soulcraft.com/docs](https://soulcraft.com/docs)** · **[Pricing](https://soulcraft.com/pricing?focus=cor)** · **[Benchmarks](https://github.com/soulcraftlabs/cor/blob/main/docs/performance.md)** · **[Comparison](https://github.com/soulcraftlabs/cor/blob/main/docs/comparison.md)**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
Brainy handles your knowledge graph. Cor makes it fast — and scales it from one workspace to a billion vectors on a single machine.
|
|
31
|
+
|
|
32
|
+
When performance matters — at scale, in production, with large embedding models — Cor automatically swaps in compiled Rust implementations for distance calculations, vector index, metadata filtering, graph adjacency, and embeddings. No code changes. No configuration changes. Add the package and it activates.
|
|
33
|
+
|
|
34
|
+
**New in cor 3.0** *(measured numbers on bxl9000 — Ryzen 9 7950X3D / 184 GB / NVMe; reproducible from `scripts/verify-*.mjs`)*:
|
|
35
|
+
|
|
36
|
+
- **Triple-intelligence find()** — Combines metadata filter + graph hop + vector similarity in a single query. **Substrate-composition p50 ≈ 0.230 ms at 1 M** (per-stage measured; this run is on a synthetic corpus, so end-to-end latency **and** recall are being re-validated on real-manifold data (SIFT) — see [docs/comparison.md](docs/comparison.md) honesty note).
|
|
37
|
+
- **Adaptive DiskANN** — 100 % pure-Rust Vamana + PQ. Auto-engages on local storage. **MEASURED: p50 0.85 ms at 1 M** (`mode=auto`).
|
|
38
|
+
- **Time-travel reads** (`db.asOf(g)` / `db.with(...)`) — Pin a generation, read the brain as it existed at that moment. All three shadow-page substrates (UUID↔int + verb endpoints) participate in the pin lifecycle.
|
|
39
|
+
- **Competitive position: 13–18× pgvector index latency** (p50, reference host bxl9000), sub-millisecond p99 at 1 M. Latency, not a blanket "faster" — the recall-matched, real-data library A/B is in progress. See **[docs/comparison.md](https://github.com/soulcraftlabs/cor/blob/main/docs/comparison.md)** for methodology + honesty notes.
|
|
40
|
+
|
|
41
|
+
Architecture: **[docs/diskann.md](https://github.com/soulcraftlabs/cor/blob/main/docs/diskann.md)** · Time-travel contract: **[docs/snapshot-safety.md](https://github.com/soulcraftlabs/cor/blob/main/docs/snapshot-safety.md)** · Performance budget: **[docs/performance-budget.md](https://github.com/soulcraftlabs/cor/blob/main/docs/performance-budget.md)** · Full verification: **[docs/verification-report.md](https://github.com/soulcraftlabs/cor/blob/main/docs/verification-report.md)** · **Upgrading from 2.x?** **[docs/migration-3.0.md](https://github.com/soulcraftlabs/cor/blob/main/docs/migration-3.0.md)**
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
bun add @soulcraft/brainy @soulcraft/cor
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { Brainy, NounType } from '@soulcraft/brainy'
|
|
53
|
+
|
|
54
|
+
const brain = new Brainy({
|
|
55
|
+
storage: { type: 'filesystem', rootDirectory: './data' },
|
|
56
|
+
plugins: ['@soulcraft/cor']
|
|
57
|
+
})
|
|
58
|
+
await brain.init()
|
|
59
|
+
// [brainy] Plugin activated: @soulcraft/cor
|
|
60
|
+
// All native providers registered — same API, Rust speed.
|
|
61
|
+
|
|
62
|
+
await brain.add({ data: 'Native Rust SIMD acceleration', type: NounType.Concept })
|
|
63
|
+
const results = await brain.find({ query: 'fast vector search' })
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Activate your license
|
|
67
|
+
|
|
68
|
+
Free tier activates automatically — no key needed. For Pro/Enterprise:
|
|
69
|
+
|
|
70
|
+
1. Get your activation code from [soulcraft.com/account](https://soulcraft.com/account)
|
|
71
|
+
2. Run in your project directory:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx @soulcraft/cor activate CX-XXXX-XXXX
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This creates a `.soulcraft.json` in your project — commit it to your repository and it works everywhere (dev, staging, prod, Docker, CI).
|
|
78
|
+
|
|
79
|
+
**Other CLI commands:**
|
|
80
|
+
```bash
|
|
81
|
+
npx cor status # show license info
|
|
82
|
+
npx cor deactivate # remove license
|
|
83
|
+
npx cor help # all commands
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
License validation runs **locally in Rust** — no network calls at startup. Get a key at **[soulcraft.com/pricing](https://soulcraft.com/pricing?focus=cor)**.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## What Gets Accelerated
|
|
91
|
+
|
|
92
|
+
Every provider listed here is a drop-in replacement — Brainy's plugin system wires them in automatically based on your license tier.
|
|
93
|
+
|
|
94
|
+
| Subsystem | What Cor Provides |
|
|
95
|
+
|-----------|---------------------|
|
|
96
|
+
| **Adaptive DiskANN** | 100% pure-Rust Vamana α-pruned graph + Product Quantization. Single-machine billion-vector ANN search; MEASURED p50 0.85 ms at 1 M on bxl9000. Auto-engages on local-storage installs |
|
|
97
|
+
| **Triple-intelligence find()** | Composes metadata filter + graph hop + vector ANN in one query. Substrate-composition p50 ≈ 0.230 ms at 1 M (per-stage measured on synthetic; end-to-end SIFT re-validation in progress) |
|
|
98
|
+
| **Time-travel reads** | `db.asOf(g)` / `db.with(...)` — pin a generation, read the brain as it existed at that moment. All 3 substrates participate in the pin lifecycle |
|
|
99
|
+
| **SIMD distance** | Float32 cosine; SQ8 uint8 cosine (81× faster); SQ4 nibble-packed |
|
|
100
|
+
| **Embeddings** | Candle ML runtime — in-process, no Python sidecar, no HTTP roundtrip. CPU and Apple Metal |
|
|
101
|
+
| **Batch embeddings** | Single Rust forward pass for bulk import and reindex |
|
|
102
|
+
| **Metadata index** | Rust LSM-tree query/mutation engine with CRoaring bitmap posting lists. MEASURED 525 K inserts/sec at 100 M |
|
|
103
|
+
| **Graph adjacency** | 4 LSM-trees + verb-endpoints shadow-page store with typed verb tracking |
|
|
104
|
+
| **Entity ID mapper** | Mmap'd UUID ↔ u64 with shadow-page snapshot safety; supports 2 B+ entities |
|
|
105
|
+
| **Vector quantization** | SQ8 (4× memory), SQ4 (8× memory), Product Quantization (16–32×) |
|
|
106
|
+
| **Graph compression** | Delta-varint encoded connection lists |
|
|
107
|
+
| **Roaring bitmaps** | CRoaring bindings — binary-compatible with `roaring-wasm` |
|
|
108
|
+
| **Msgpack** | Native encode/decode |
|
|
109
|
+
| **mmap storage** | Zero-copy SSTable reads via memory-mapped files; shadow-page LSM for snapshot safety |
|
|
110
|
+
| **Aggregation engine** | Incremental updates with Rayon parallel rebuild |
|
|
111
|
+
| **Compaction** | Pin-aware (respects `min_pinned_generation` for time-travel) + graph-aware BFS ordering for disk locality |
|
|
112
|
+
|
|
113
|
+
### Scale envelope at a glance
|
|
114
|
+
|
|
115
|
+
> **MEASURED at 1 M / 10 M / 100 M on bxl9000.** Source files cited in
|
|
116
|
+
> `docs/verification-report.md`. 1 B numbers are projected from SIFT1B
|
|
117
|
+
> trends + 100 M measured + Subramanya et al. (NeurIPS 2019) algorithm
|
|
118
|
+
> latency model.
|
|
119
|
+
|
|
120
|
+
| Vectors | RAM | DiskANN p50 | LSM filter p50 | Graph 2-hop p50 | **Composed find() p50** | Source |
|
|
121
|
+
|--------:|---:|---:|---:|---:|---:|:---|
|
|
122
|
+
| 1 M | 0.5–2 GB | **0.85 ms** | **23.8 µs** | **14.3 µs** | **0.230 ms** | bxl9000, measured |
|
|
123
|
+
| 10 M | 1–5 GB | _running_ | **537 µs** | _running_ | _projected_ | bxl9000, partial |
|
|
124
|
+
| 100 M | 5–20 GB | _projected_ | **5.85 ms** | _projected_ | _projected_ | bxl9000, LSM only |
|
|
125
|
+
| **1 B** | **20–70 GB** | **5–10 ms** (PROJECTED) | _projected_ | _projected_ | _projected_ | SIFT1B reference |
|
|
126
|
+
|
|
127
|
+
All numbers are for the search engine itself. End-to-end query latency adds entity hydration; see **[docs/scaling.md](https://github.com/soulcraftlabs/cor/blob/main/docs/scaling.md#operational-ceiling-at-1-b)** for the honest full-stack story.
|
|
128
|
+
|
|
129
|
+
**Running many brains per box (per-tenant pools, e.g. one brain per user)?** Cor auto-raises its own soft open-file limit on startup and warns you (with the exact fix) if the OS file/mmap limits would bottleneck a pool before RAM. The hard `ulimit -n` + Linux `vm.max_map_count` must be set by your deployment — copy-paste Docker / Compose / Kubernetes / host config in **[docs/deployment-limits.md](https://github.com/soulcraftlabs/cor/blob/main/docs/deployment-limits.md)**.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Performance
|
|
134
|
+
|
|
135
|
+
All numbers **measured** with `vitest bench` on Linux x64.
|
|
136
|
+
|
|
137
|
+
### Distance Calculations — 384-dimensional vectors (all-MiniLM-L6-v2)
|
|
138
|
+
|
|
139
|
+
| Operation | Throughput | Latency | vs full-precision |
|
|
140
|
+
|-----------|----------:|--------:|:-----------------:|
|
|
141
|
+
| `cosineDistance` (float32) | 45,965 ops/s | 21.8 μs | baseline |
|
|
142
|
+
| `cosineDistanceSq8` (quantized) | 3,715,855 ops/s | 0.27 μs | **81×** |
|
|
143
|
+
| `cosineDistanceSq8Batch` (1K vectors) | 2,142 ops/s | 467 μs | **28×** |
|
|
144
|
+
| `cosineDistanceBatch` (float32, 1K) | 77 ops/s | 13.0 ms | — |
|
|
145
|
+
| `quantizeSq8` (encode 384-dim) | 74,020 ops/s | 13.5 μs | — |
|
|
146
|
+
|
|
147
|
+
**Quantize once at index time. Get 81× faster distances at every query.**
|
|
148
|
+
|
|
149
|
+
### Aggregation Engine
|
|
150
|
+
|
|
151
|
+
| Operation | Throughput | Latency |
|
|
152
|
+
|-----------|----------:|--------:|
|
|
153
|
+
| `incrementalUpdate` (1K entities, 3 metrics) | 809 ops/s | 1.2 ms |
|
|
154
|
+
| `rebuildAggregate` (10K entities, 5 groups) | 475 ops/s | 2.1 ms |
|
|
155
|
+
| `rebuildAggregate` (100K entities, Rayon) | 66 ops/s | 15.2 ms |
|
|
156
|
+
| `queryAggregate` (1K groups, sort + paginate) | 986 ops/s | 1.0 ms |
|
|
157
|
+
|
|
158
|
+
### Serialization
|
|
159
|
+
|
|
160
|
+
| Operation | Throughput | Latency |
|
|
161
|
+
|-----------|----------:|--------:|
|
|
162
|
+
| `msgpackEncode` (1K entities) | 235 ops/s | 4.3 ms |
|
|
163
|
+
| `msgpackDecode` (1K entities) | 355 ops/s | 2.8 ms |
|
|
164
|
+
| `RoaringBitmap32.serialize` (10K elements) | 361,258 ops/s | 2.8 μs |
|
|
165
|
+
| `RoaringBitmap32.deserialize` (10K elements) | 548,714 ops/s | 1.8 μs |
|
|
166
|
+
| `encodeConnections` (1K lists) | 913 ops/s | 1.1 ms |
|
|
167
|
+
| `decodeConnections` (1K lists) | 1,078 ops/s | 928 μs |
|
|
168
|
+
|
|
169
|
+
Full breakdown: **[docs/performance.md](https://github.com/soulcraftlabs/cor/blob/main/docs/performance.md)** · Side-by-side comparison: **[docs/comparison.md](https://github.com/soulcraftlabs/cor/blob/main/docs/comparison.md)**
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Free Tier vs Pro
|
|
174
|
+
|
|
175
|
+
| Feature | Free | Pro / Enterprise |
|
|
176
|
+
|---------|:----:|:----------------:|
|
|
177
|
+
| mmap-enhanced filesystem storage | ✓ | ✓ |
|
|
178
|
+
| **Adaptive DiskANN billion-scale index** | — | ✓ |
|
|
179
|
+
| **Triple-intelligence find() composition** | — | ✓ |
|
|
180
|
+
| **Time-travel reads (`db.asOf(g)`)** | — | ✓ |
|
|
181
|
+
| SIMD distance (float32, SQ8, SQ4) | — | ✓ |
|
|
182
|
+
| Vector quantization (SQ8, SQ4, PQ) | — | ✓ |
|
|
183
|
+
| Candle ML embeddings (CPU / Metal) | — | ✓ |
|
|
184
|
+
| Native metadata index (LSM + CRoaring) | — | ✓ |
|
|
185
|
+
| Graph adjacency index (4 LSM-trees + verb endpoints) | — | ✓ |
|
|
186
|
+
| Entity ID mapper (mmap UUID ↔ u64) | — | ✓ |
|
|
187
|
+
| Snapshot-safe shadow-page LSM stores | — | ✓ |
|
|
188
|
+
| CRoaring bitmap bindings | — | ✓ |
|
|
189
|
+
| Native msgpack encode/decode | — | ✓ |
|
|
190
|
+
| Incremental aggregation engine | — | ✓ |
|
|
191
|
+
| Pin-aware + graph-aware compaction | — | ✓ |
|
|
192
|
+
|
|
193
|
+
Free tier activates automatically with no key. Pro/Enterprise require a license key — see [soulcraft.com/pricing](https://soulcraft.com/pricing?focus=cor).
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Verify Activation
|
|
198
|
+
|
|
199
|
+
Check which providers are active after `brain.init()`:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const diag = brain.diagnostics()
|
|
203
|
+
console.log(diag.providers)
|
|
204
|
+
// {
|
|
205
|
+
// distance: { source: 'plugin' },
|
|
206
|
+
// vectorIndex: { source: 'plugin' }, // Adaptive DiskANN
|
|
207
|
+
// embeddings: { source: 'plugin' },
|
|
208
|
+
// metadataIndex: { source: 'plugin' },
|
|
209
|
+
// graphIndex: { source: 'plugin' },
|
|
210
|
+
// ...
|
|
211
|
+
// }
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Require specific providers in production — fail fast if something isn't native:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
brain.requireProviders(['distance', 'vectorIndex', 'embeddings', 'metadataIndex', 'graphIndex'])
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## License & Subscription
|
|
223
|
+
|
|
224
|
+
Cor uses a **subscription license** with offline validation. Your key is an Ed25519-signed JWT verified entirely in Rust at process start — no network call required. A background heartbeat runs once every 24 hours to check subscription status.
|
|
225
|
+
|
|
226
|
+
### Graceful Degradation
|
|
227
|
+
|
|
228
|
+
Cor **never hard-blocks** your process on a lapsed license. If your subscription lapses:
|
|
229
|
+
|
|
230
|
+
1. A warning appears on the next process start
|
|
231
|
+
2. A **14-day grace period** begins
|
|
232
|
+
3. After the grace period, Cor silently degrades to free tier — storage keeps working, compute acceleration pauses
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
[cor] Subscription canceled. Renew at soulcraft.com/account. Grace period: 12 days remaining.
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Renew at any time during the grace period to restore compute acceleration instantly on the next startup.
|
|
239
|
+
|
|
240
|
+
### Key Source
|
|
241
|
+
|
|
242
|
+
Cor reads `.soulcraft.json` from the project root (`process.cwd()`):
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{ "cor": "CX-7F3A-9B2D" }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
On first use, short codes are exchanged for a JWT via `soulcraft.com/api/license/exchange` and cached in memory for the process lifetime. The file itself is never rewritten — each cold start re-exchanges if needed.
|
|
249
|
+
|
|
250
|
+
Run `npx @soulcraft/cor activate CX-XXXX-XXXX` to create this file.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Platform Support
|
|
255
|
+
|
|
256
|
+
Pre-built binaries ship inside the npm package. No compile step needed.
|
|
257
|
+
|
|
258
|
+
| Platform | Architecture | Binary Included |
|
|
259
|
+
|----------|-------------|:---------------:|
|
|
260
|
+
| Linux | x64 (glibc 2.17+) | ✓ |
|
|
261
|
+
| Linux | arm64 (glibc) | ✓ |
|
|
262
|
+
| macOS | arm64 (Apple Silicon) | ✓ |
|
|
263
|
+
| macOS | x64 (Intel) | ✓ |
|
|
264
|
+
| Windows | x64 | ✓ |
|
|
265
|
+
|
|
266
|
+
> **GPU / CUDA acceleration** is available for Enterprise customers. [Contact us](https://soulcraft.com/contact-sales) to discuss your requirements.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Troubleshooting
|
|
271
|
+
|
|
272
|
+
| Symptom | Likely cause | Fix |
|
|
273
|
+
|---------|-------------|-----|
|
|
274
|
+
| `[cor] missing sc_cor_ prefix` | `.soulcraft.json` contains wrong key or non-cor key | Re-run `npx @soulcraft/cor activate CX-XXXX-XXXX` |
|
|
275
|
+
| `[cor] license expired` | Key is past its expiry date | Renew at [soulcraft.com/account](https://soulcraft.com/account) |
|
|
276
|
+
| `[cor] invalid signature` | Key was truncated or corrupted | Re-activate: `npx @soulcraft/cor activate CX-XXXX-XXXX` |
|
|
277
|
+
| `[cor] invalid product: workshop` | Workshop key used for Cor | Keys are product-specific — get a Cor key at [soulcraft.com/account](https://soulcraft.com/account) |
|
|
278
|
+
| `[cor] native module unavailable` | Native binary not found for current platform | Check platform table above |
|
|
279
|
+
| Compute providers inactive, no warning | No key set — free tier is active | Run `npx @soulcraft/cor activate CX-XXXX-XXXX` |
|
|
280
|
+
| `[cor] License lapsed. Compute acceleration disabled.` | Grace period expired | Renew at [soulcraft.com/account](https://soulcraft.com/account) |
|
|
281
|
+
| `[cor] License suspended. Contact support.` | Account suspended | Open a ticket at [soulcraft.com/issues](https://soulcraft.com/issues) |
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Direct Native Access
|
|
286
|
+
|
|
287
|
+
For advanced use cases — custom pipelines, tooling, benchmarks — access the Rust bindings directly without Brainy:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
import { loadNativeModule, isNativeAvailable } from '@soulcraft/cor'
|
|
291
|
+
|
|
292
|
+
if (isNativeAvailable()) {
|
|
293
|
+
const native = loadNativeModule()
|
|
294
|
+
const dist = native.cosineDistance(vectorA, vectorB)
|
|
295
|
+
const encoded = native.msgpackEncode(data)
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Requirements
|
|
302
|
+
|
|
303
|
+
- **Bun 1.0+** (recommended) or **Node.js 22 LTS**
|
|
304
|
+
- `@soulcraft/brainy >= 7.15.4`
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
bun add @soulcraft/brainy @soulcraft/cor # Bun — best performance
|
|
308
|
+
npm install @soulcraft/brainy @soulcraft/cor # Node.js — fully supported
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Learn More
|
|
314
|
+
|
|
315
|
+
- **[Brainy documentation](https://soulcraft.com/docs)** — Full Brainy API reference
|
|
316
|
+
- **[Plugin system](https://github.com/soulcraftlabs/brainy/blob/main/docs/PLUGINS.md)** — How Brainy plugins work
|
|
317
|
+
- **[Performance benchmarks](https://github.com/soulcraftlabs/cor/blob/main/docs/performance.md)** — Full benchmark table with methodology
|
|
318
|
+
- **[Brainy vs Cor comparison](https://github.com/soulcraftlabs/cor/blob/main/docs/comparison.md)** — Side-by-side feature and speed comparison
|
|
319
|
+
- **[soulcraft.com/pricing](https://soulcraft.com/pricing?focus=cor)** — Pro and Enterprise plans
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## License
|
|
324
|
+
|
|
325
|
+
Commercial — [soulcraft.com/pricing](https://soulcraft.com/pricing?focus=cor)
|
|
326
|
+
|
|
327
|
+
Free tier (mmap storage) is available without a license key.
|
|
328
|
+
Pro and Enterprise tiers require a paid subscription.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NativeAggregationEngine — TypeScript wrapper implementing Brainy's AggregationProvider.
|
|
3
|
+
*
|
|
4
|
+
* Delegates all computation to the Rust NativeAggregationEngine:
|
|
5
|
+
* - Incremental updates with BTreeMap precise MIN/MAX
|
|
6
|
+
* - Rayon parallel rebuild across CPU cores
|
|
7
|
+
* - Welford's online stddev/variance
|
|
8
|
+
* - Integer timestamp bucketing (no Date object allocation)
|
|
9
|
+
* - Compiled source filters on rebuild path
|
|
10
|
+
*
|
|
11
|
+
* Architecture:
|
|
12
|
+
* - Rust owns: all metric computation, group key calculation, state management
|
|
13
|
+
* - TS owns: provider interface conformance, Brainy ↔ Rust type translation
|
|
14
|
+
*
|
|
15
|
+
* The wrapper implements Brainy's AggregationProvider interface so it can be
|
|
16
|
+
* registered via `context.registerProvider('aggregation', ...)` and used
|
|
17
|
+
* transparently by AggregationIndex.
|
|
18
|
+
*/
|
|
19
|
+
import type { AggregateDefinition, AggregateGroupState, AggregateQueryParams, AggregateResult, AggregationProvider, GroupByDimension } from '@soulcraft/brainy';
|
|
20
|
+
/**
|
|
21
|
+
* Native Rust-accelerated aggregation provider.
|
|
22
|
+
*
|
|
23
|
+
* Implements AggregationProvider for transparent use by Brainy's AggregationIndex.
|
|
24
|
+
* All metric computation happens in Rust; results are translated back to
|
|
25
|
+
* Brainy's TypeScript types at the FFI boundary.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Registered automatically by cor plugin — no user action needed.
|
|
30
|
+
* // When cor is installed, AggregationIndex uses this provider for:
|
|
31
|
+
* // - 50x faster incremental updates
|
|
32
|
+
* // - 100x faster rebuilds (Rayon parallel)
|
|
33
|
+
* // - Precise MIN/MAX after deletes (BTreeMap, never stale)
|
|
34
|
+
* // - Online stddev/variance (Welford's algorithm)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class NativeAggregationProvider implements AggregationProvider {
|
|
38
|
+
private engine;
|
|
39
|
+
constructor();
|
|
40
|
+
/**
|
|
41
|
+
* Register an aggregate definition with the Rust engine.
|
|
42
|
+
* Compiles the definition for efficient hot-path processing.
|
|
43
|
+
* Called by AggregationIndex.defineAggregate().
|
|
44
|
+
*/
|
|
45
|
+
defineAggregate(def: AggregateDefinition): void;
|
|
46
|
+
/**
|
|
47
|
+
* Remove a registered aggregate definition and its internal state.
|
|
48
|
+
* Called by AggregationIndex.removeAggregate().
|
|
49
|
+
*/
|
|
50
|
+
removeAggregate(name: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Incrementally update aggregation state for an entity change.
|
|
53
|
+
*
|
|
54
|
+
* The entity is passed directly to Rust via NAPI serde-json (no JSON.stringify
|
|
55
|
+
* needed — NAPI converts JS objects to serde_json::Value automatically).
|
|
56
|
+
*
|
|
57
|
+
* Returns the modified group states for Brainy to merge into its state maps.
|
|
58
|
+
*
|
|
59
|
+
* @param name - Aggregate name
|
|
60
|
+
* @param def - Full aggregate definition (for compatibility; Rust uses cached version)
|
|
61
|
+
* @param entity - The entity that changed
|
|
62
|
+
* @param op - Operation type: 'add', 'update', or 'delete'
|
|
63
|
+
* @param prev - Previous entity state (required for 'update' ops)
|
|
64
|
+
* @returns Modified group states
|
|
65
|
+
*/
|
|
66
|
+
incrementalUpdate(name: string, def: AggregateDefinition, entity: Record<string, unknown>, op: 'add' | 'update' | 'delete', prev?: Record<string, unknown>): AggregateGroupState[];
|
|
67
|
+
/**
|
|
68
|
+
* Compute the group key for an entity given GROUP BY dimensions.
|
|
69
|
+
*
|
|
70
|
+
* Uses integer timestamp arithmetic for time-windowed dimensions
|
|
71
|
+
* (no Date object allocation).
|
|
72
|
+
*
|
|
73
|
+
* @param entity - Entity to compute group key for
|
|
74
|
+
* @param groupBy - GROUP BY dimensions
|
|
75
|
+
* @returns Group key object
|
|
76
|
+
*/
|
|
77
|
+
computeGroupKey(entity: Record<string, unknown>, groupBy: GroupByDimension[]): Record<string, string | number>;
|
|
78
|
+
/**
|
|
79
|
+
* Rebuild an entire aggregate from scratch using Rayon parallel iteration.
|
|
80
|
+
*
|
|
81
|
+
* Distributes entities across CPU cores. Each thread accumulates into
|
|
82
|
+
* thread-local state maps, merged at the end using Chan-Golub-LeVeque
|
|
83
|
+
* parallel variance formula for correct Welford's M2 merging.
|
|
84
|
+
*
|
|
85
|
+
* For 100K entities on 8 cores: ~50ms vs ~5s in JS (100x speedup).
|
|
86
|
+
*
|
|
87
|
+
* @param def - Aggregate definition
|
|
88
|
+
* @param entities - All entities to rebuild from
|
|
89
|
+
* @returns Map of serialized group key → group state
|
|
90
|
+
*/
|
|
91
|
+
rebuildAggregate(def: AggregateDefinition, entities: Array<Record<string, unknown>>): Map<string, AggregateGroupState>;
|
|
92
|
+
/**
|
|
93
|
+
* Query aggregate state with filtering, sorting, and pagination.
|
|
94
|
+
*
|
|
95
|
+
* Uses internal Rust state when available, falls back to parsing
|
|
96
|
+
* the provided state map.
|
|
97
|
+
*
|
|
98
|
+
* @param state - State map from Brainy (used as fallback)
|
|
99
|
+
* @param params - Query parameters (where, orderBy, limit, offset)
|
|
100
|
+
* @returns Sorted, filtered, paginated query results
|
|
101
|
+
*/
|
|
102
|
+
queryAggregate(state: Map<string, AggregateGroupState>, params: AggregateQueryParams): AggregateResult[];
|
|
103
|
+
/**
|
|
104
|
+
* Restore previously serialized Rust state.
|
|
105
|
+
* Called during AggregationIndex.init() with persisted state data.
|
|
106
|
+
*/
|
|
107
|
+
restoreState(data: string): void;
|
|
108
|
+
/**
|
|
109
|
+
* Serialize internal Rust state for persistence.
|
|
110
|
+
* Called during AggregationIndex.flush().
|
|
111
|
+
*/
|
|
112
|
+
serializeState(): string;
|
|
113
|
+
/**
|
|
114
|
+
* Get engine statistics: definition count, total groups, etc.
|
|
115
|
+
*/
|
|
116
|
+
getStats(): Record<string, unknown>;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=NativeAggregationEngine.d.ts.map
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NativeAggregationEngine — TypeScript wrapper implementing Brainy's AggregationProvider.
|
|
3
|
+
*
|
|
4
|
+
* Delegates all computation to the Rust NativeAggregationEngine:
|
|
5
|
+
* - Incremental updates with BTreeMap precise MIN/MAX
|
|
6
|
+
* - Rayon parallel rebuild across CPU cores
|
|
7
|
+
* - Welford's online stddev/variance
|
|
8
|
+
* - Integer timestamp bucketing (no Date object allocation)
|
|
9
|
+
* - Compiled source filters on rebuild path
|
|
10
|
+
*
|
|
11
|
+
* Architecture:
|
|
12
|
+
* - Rust owns: all metric computation, group key calculation, state management
|
|
13
|
+
* - TS owns: provider interface conformance, Brainy ↔ Rust type translation
|
|
14
|
+
*
|
|
15
|
+
* The wrapper implements Brainy's AggregationProvider interface so it can be
|
|
16
|
+
* registered via `context.registerProvider('aggregation', ...)` and used
|
|
17
|
+
* transparently by AggregationIndex.
|
|
18
|
+
*/
|
|
19
|
+
import { loadNativeModule } from '../native/index.js';
|
|
20
|
+
/**
|
|
21
|
+
* Native Rust-accelerated aggregation provider.
|
|
22
|
+
*
|
|
23
|
+
* Implements AggregationProvider for transparent use by Brainy's AggregationIndex.
|
|
24
|
+
* All metric computation happens in Rust; results are translated back to
|
|
25
|
+
* Brainy's TypeScript types at the FFI boundary.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Registered automatically by cor plugin — no user action needed.
|
|
30
|
+
* // When cor is installed, AggregationIndex uses this provider for:
|
|
31
|
+
* // - 50x faster incremental updates
|
|
32
|
+
* // - 100x faster rebuilds (Rayon parallel)
|
|
33
|
+
* // - Precise MIN/MAX after deletes (BTreeMap, never stale)
|
|
34
|
+
* // - Online stddev/variance (Welford's algorithm)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class NativeAggregationProvider {
|
|
38
|
+
engine;
|
|
39
|
+
constructor() {
|
|
40
|
+
const native = loadNativeModule();
|
|
41
|
+
this.engine = new native.NativeAggregationEngine();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Register an aggregate definition with the Rust engine.
|
|
45
|
+
* Compiles the definition for efficient hot-path processing.
|
|
46
|
+
* Called by AggregationIndex.defineAggregate().
|
|
47
|
+
*/
|
|
48
|
+
defineAggregate(def) {
|
|
49
|
+
this.engine.defineAggregate(JSON.stringify(def));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Remove a registered aggregate definition and its internal state.
|
|
53
|
+
* Called by AggregationIndex.removeAggregate().
|
|
54
|
+
*/
|
|
55
|
+
removeAggregate(name) {
|
|
56
|
+
this.engine.removeAggregate(name);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Incrementally update aggregation state for an entity change.
|
|
60
|
+
*
|
|
61
|
+
* The entity is passed directly to Rust via NAPI serde-json (no JSON.stringify
|
|
62
|
+
* needed — NAPI converts JS objects to serde_json::Value automatically).
|
|
63
|
+
*
|
|
64
|
+
* Returns the modified group states for Brainy to merge into its state maps.
|
|
65
|
+
*
|
|
66
|
+
* @param name - Aggregate name
|
|
67
|
+
* @param def - Full aggregate definition (for compatibility; Rust uses cached version)
|
|
68
|
+
* @param entity - The entity that changed
|
|
69
|
+
* @param op - Operation type: 'add', 'update', or 'delete'
|
|
70
|
+
* @param prev - Previous entity state (required for 'update' ops)
|
|
71
|
+
* @returns Modified group states
|
|
72
|
+
*/
|
|
73
|
+
incrementalUpdate(name, def, entity, op, prev) {
|
|
74
|
+
// Ensure definition is registered (idempotent if already registered)
|
|
75
|
+
this.engine.defineAggregate(JSON.stringify(def));
|
|
76
|
+
const resultJson = this.engine.incrementalUpdate(name, entity, op, prev);
|
|
77
|
+
const rawGroups = JSON.parse(resultJson);
|
|
78
|
+
return rawGroups.map(normalizeGroupState);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Compute the group key for an entity given GROUP BY dimensions.
|
|
82
|
+
*
|
|
83
|
+
* Uses integer timestamp arithmetic for time-windowed dimensions
|
|
84
|
+
* (no Date object allocation).
|
|
85
|
+
*
|
|
86
|
+
* @param entity - Entity to compute group key for
|
|
87
|
+
* @param groupBy - GROUP BY dimensions
|
|
88
|
+
* @returns Group key object
|
|
89
|
+
*/
|
|
90
|
+
computeGroupKey(entity, groupBy) {
|
|
91
|
+
const resultJson = this.engine.computeGroupKey(entity, JSON.stringify(groupBy));
|
|
92
|
+
return JSON.parse(resultJson);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Rebuild an entire aggregate from scratch using Rayon parallel iteration.
|
|
96
|
+
*
|
|
97
|
+
* Distributes entities across CPU cores. Each thread accumulates into
|
|
98
|
+
* thread-local state maps, merged at the end using Chan-Golub-LeVeque
|
|
99
|
+
* parallel variance formula for correct Welford's M2 merging.
|
|
100
|
+
*
|
|
101
|
+
* For 100K entities on 8 cores: ~50ms vs ~5s in JS (100x speedup).
|
|
102
|
+
*
|
|
103
|
+
* @param def - Aggregate definition
|
|
104
|
+
* @param entities - All entities to rebuild from
|
|
105
|
+
* @returns Map of serialized group key → group state
|
|
106
|
+
*/
|
|
107
|
+
rebuildAggregate(def, entities) {
|
|
108
|
+
const resultJson = this.engine.rebuildAggregate(JSON.stringify(def), JSON.stringify(entities));
|
|
109
|
+
const rawGroups = JSON.parse(resultJson);
|
|
110
|
+
const stateMap = new Map();
|
|
111
|
+
for (const raw of rawGroups) {
|
|
112
|
+
const group = normalizeGroupState(raw);
|
|
113
|
+
const serialized = serializeGroupKey(group.groupKey);
|
|
114
|
+
stateMap.set(serialized, group);
|
|
115
|
+
}
|
|
116
|
+
return stateMap;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Query aggregate state with filtering, sorting, and pagination.
|
|
120
|
+
*
|
|
121
|
+
* Uses internal Rust state when available, falls back to parsing
|
|
122
|
+
* the provided state map.
|
|
123
|
+
*
|
|
124
|
+
* @param state - State map from Brainy (used as fallback)
|
|
125
|
+
* @param params - Query parameters (where, orderBy, limit, offset)
|
|
126
|
+
* @returns Sorted, filtered, paginated query results
|
|
127
|
+
*/
|
|
128
|
+
queryAggregate(state, params) {
|
|
129
|
+
// Serialize state for Rust (convert Map to array)
|
|
130
|
+
const groups = Array.from(state.values());
|
|
131
|
+
const stateJson = JSON.stringify(groups);
|
|
132
|
+
const resultJson = this.engine.queryAggregate(stateJson, JSON.stringify(params));
|
|
133
|
+
return JSON.parse(resultJson);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Restore previously serialized Rust state.
|
|
137
|
+
* Called during AggregationIndex.init() with persisted state data.
|
|
138
|
+
*/
|
|
139
|
+
restoreState(data) {
|
|
140
|
+
this.engine.restoreState(data);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Serialize internal Rust state for persistence.
|
|
144
|
+
* Called during AggregationIndex.flush().
|
|
145
|
+
*/
|
|
146
|
+
serializeState() {
|
|
147
|
+
return this.engine.serializeState();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get engine statistics: definition count, total groups, etc.
|
|
151
|
+
*/
|
|
152
|
+
getStats() {
|
|
153
|
+
return JSON.parse(this.engine.stats);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Normalize raw Rust output to Brainy's AggregateGroupState format.
|
|
158
|
+
* Handles null → Infinity/NegInfinity conversion for min/max.
|
|
159
|
+
*/
|
|
160
|
+
function normalizeGroupState(raw) {
|
|
161
|
+
const metrics = {};
|
|
162
|
+
for (const [name, state] of Object.entries(raw.metrics)) {
|
|
163
|
+
metrics[name] = {
|
|
164
|
+
sum: state.sum,
|
|
165
|
+
count: state.count,
|
|
166
|
+
min: state.min ?? Infinity,
|
|
167
|
+
max: state.max ?? -Infinity,
|
|
168
|
+
m2: state.m2 ?? 0
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
groupKey: raw.groupKey,
|
|
173
|
+
metrics,
|
|
174
|
+
materializedEntityId: raw.materializedEntityId ?? undefined,
|
|
175
|
+
lastUpdated: raw.lastUpdated
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Serialize a group key to a deterministic string.
|
|
180
|
+
* Must match Brainy's `serializeGroupKey()` for state compatibility.
|
|
181
|
+
*/
|
|
182
|
+
function serializeGroupKey(groupKey) {
|
|
183
|
+
const sorted = Object.keys(groupKey).sort();
|
|
184
|
+
return sorted.map(k => `${k}=${groupKey[k]}`).join('|');
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=NativeAggregationEngine.js.map
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cor CLI — license management for @soulcraft/cor
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* activate <code-or-key> Write activation code or JWT to .soulcraft.json
|
|
7
|
+
* status Show current license configuration and validation result
|
|
8
|
+
* deactivate Remove the cor license from .soulcraft.json
|
|
9
|
+
* help Print this help text
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=cli.d.ts.map
|