enigma-memory 0.1.18 → 0.1.22
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 +76 -24
- package/apps/cli/bin/enigma-desktop.mjs +140 -0
- package/apps/cli/bin/enigma-terminal.mjs +78 -0
- package/apps/cli/bin/enigma.mjs +1923 -285
- package/apps/desktop/electron-main.cjs +217 -0
- package/apps/desktop/package.json +12 -0
- package/apps/desktop/src/app.js +264 -7
- package/apps/desktop/src/index.html +3514 -1373
- package/apps/desktop/src/launch-electron.mjs +51 -0
- package/apps/desktop/src/server.mjs +2914 -0
- package/apps/desktop/src/styles.css +2972 -260
- package/apps/desktop/src/zk-browser-prove.mjs +53 -0
- package/apps/desktop/src/zk-state.mjs +1789 -0
- package/apps/gateway/bin/enigma-gateway.mjs +102 -5
- package/apps/gateway/src/server.mjs +271 -8
- package/apps/ios/EnigmaCore/Package.swift +12 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
- package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
- package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
- package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
- package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
- package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
- package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
- package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
- package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
- package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
- package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
- package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
- package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
- package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
- package/apps/native-host/README.md +19 -8
- package/apps/native-host/bin/enigma-native-host.mjs +229 -13
- package/apps/relay/bin/enigma-relay.mjs +103 -5
- package/apps/relay/src/federation-runtime.mjs +618 -0
- package/apps/relay/src/server.mjs +310 -9
- package/apps/verifier/bin/enigma-verify.mjs +327 -11
- package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/vk_bytes.json +32 -0
- package/cortex-v3/proving-assets.json +64 -0
- package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
- package/cortex-v3/zk/action-transition-vk.json +119 -0
- package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
- package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
- package/cortex-v3/zk/intent-witness.mjs +365 -0
- package/cortex-v3/zk/intent-witness.test.mjs +485 -0
- package/cortex-v3/zk/proving-assets.mjs +203 -0
- package/cortex-v3/zk/sale-witness.mjs +783 -0
- package/cortex-v3/zk/sale-witness.test.mjs +784 -0
- package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
- package/cortex-v3/zk/settlement-evidence.mjs +722 -0
- package/cortex-v3/zk/setup-intent.mjs +688 -0
- package/cortex-v3/zk/setup-sale.mjs +666 -0
- package/cortex-v3/zk/setup.mjs +594 -0
- package/cortex-v3/zk/witness.mjs +184 -0
- package/cortex-v3/zk/zk-codec.mjs +232 -0
- package/cortex-v3/zk/zk-codec.test.mjs +293 -0
- package/cortex-v3/zk/zk-settle.mjs +370 -0
- package/cortex-v3/zk/zk-tree.mjs +256 -0
- package/cortex-v3/zk/zk-tree.test.mjs +419 -0
- package/deploy/docker-compose.local-production-simulation.yml +36 -0
- package/docs/browser-extension-install.md +8 -6
- package/docs/client-connectors.md +15 -11
- package/docs/developer-ecosystem.md +15 -13
- package/docs/enigma-memory-ready-conformance.md +11 -9
- package/docs/install-anywhere.md +61 -28
- package/docs/installers-and-desktop.md +8 -7
- package/docs/novelty-invention-candidates.md +161 -161
- package/docs/proof-network-claim-boundaries.md +320 -318
- package/examples/01-quickstart-agent/index.mjs +49 -0
- package/examples/01_agent_memory_quickstart.mjs +57 -0
- package/examples/02-multi-agent-swarm/index.mjs +57 -0
- package/examples/02_cross_model_passport.mjs +64 -0
- package/examples/03-langchain-memory/index.mjs +41 -0
- package/examples/03_poseidon_commitment_verification.mjs +71 -0
- package/examples/04-python-trading-agent/trader.py +49 -0
- package/examples/README.md +27 -0
- package/examples/ci/github-actions.yml +7 -2
- package/package.json +142 -11
- package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
- package/packages/connectors/src/index.js +196 -4
- package/packages/connectors/swarm-router.mjs +168 -0
- package/packages/core/src/index.js +248 -1
- package/packages/core/src/version.mjs +7 -0
- package/packages/dev-tools/package.json +19 -0
- package/packages/dev-tools/src/index.js +4 -0
- package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
- package/packages/dev-tools/src/swarm-simulator.js +101 -0
- package/packages/dev-tools/src/vault-inspector.js +114 -0
- package/packages/dev-tools/src/vector-benchmark.js +100 -0
- package/packages/developer-platform/src/access-credentials.js +341 -0
- package/packages/developer-platform/src/http.js +132 -0
- package/packages/developer-platform/src/index.js +4 -0
- package/packages/developer-platform/src/usage-http.js +60 -0
- package/packages/developer-platform/src/usage.js +295 -0
- package/packages/enclave-runtime/attestation.mjs +159 -0
- package/packages/enclave-runtime/index.mjs +47 -0
- package/packages/enclave-runtime/session-manager.mjs +253 -0
- package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
- package/packages/enigma-reflex/package.json +14 -0
- package/packages/enigma-reflex/src/index.js +204 -0
- package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
- package/packages/enigma-reflex/training/requirements.txt +8 -0
- package/packages/enigma-reflex/training/train.py +314 -0
- package/packages/enigma-weave/LICENSE +22 -0
- package/packages/enigma-weave/UPSTREAM.json +21 -0
- package/packages/enigma-weave/package.json +14 -0
- package/packages/enigma-weave/src/index.js +286 -0
- package/packages/hosted-cloud/src/index.js +80 -5
- package/packages/importers/src/index.js +432 -0
- package/packages/inference-runtime/src/browser.js +401 -0
- package/packages/inference-runtime/src/chat.js +265 -0
- package/packages/inference-runtime/src/code.js +407 -0
- package/packages/inference-runtime/src/contracts.js +162 -0
- package/packages/inference-runtime/src/http.js +232 -0
- package/packages/inference-runtime/src/image.js +186 -0
- package/packages/inference-runtime/src/index.js +10 -0
- package/packages/inference-runtime/src/model-router.js +320 -0
- package/packages/inference-runtime/src/platform.js +125 -0
- package/packages/inference-runtime/src/privacy.js +400 -0
- package/packages/inference-runtime/src/video.js +253 -0
- package/packages/mcp-server/README.md +22 -6
- package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
- package/packages/mcp-server/src/index.js +1418 -105
- package/packages/mcp-server/src/oauth.js +561 -0
- package/packages/mcp-server/src/private-handoff.js +84 -0
- package/packages/mcp-server/src/remote-http.js +273 -0
- package/packages/mcp-server/src/remote-policy.js +72 -0
- package/packages/mcp-server/swarm-bridge.mjs +361 -0
- package/packages/mesh/index.d.ts +283 -0
- package/packages/mesh/package.json +23 -0
- package/packages/mesh/src/crypto.js +189 -0
- package/packages/mesh/src/federation-packets.js +353 -0
- package/packages/mesh/src/gossip.js +311 -0
- package/packages/mesh/src/index.js +6 -0
- package/packages/mesh/src/protocol.js +255 -0
- package/packages/mesh/src/router.js +279 -0
- package/packages/mesh/src/transport.js +306 -0
- package/packages/passport/src/index.js +426 -1
- package/packages/private-economy/src/credits-http.js +100 -0
- package/packages/private-economy/src/credits.js +447 -0
- package/packages/private-economy/src/index.js +5 -0
- package/packages/private-economy/src/payments-http.js +120 -0
- package/packages/private-economy/src/payments.js +509 -0
- package/packages/private-economy/src/x402.js +346 -0
- package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
- package/packages/rag/index.d.ts +182 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
- package/packages/rag/package.json +27 -0
- package/packages/rag/src/blinded-search.js +109 -0
- package/packages/rag/src/bm25.js +169 -0
- package/packages/rag/src/embeddings.js +459 -0
- package/packages/rag/src/hybrid.js +76 -0
- package/packages/rag/src/index.js +38 -0
- package/packages/rag/src/reranker.js +61 -0
- package/packages/rag/src/research.js +107 -0
- package/packages/rag/src/vector-store.js +430 -0
- package/packages/rag/src/verify-model-artifacts.mjs +4 -0
- package/packages/sdk/index.d.ts +760 -0
- package/packages/sdk/package.json +33 -0
- package/packages/sdk/python/README.md +24 -0
- package/packages/sdk/python/enigma_sdk.py +250 -0
- package/packages/sdk/python/pyproject.toml +34 -0
- package/packages/sdk/python/requirements.txt +1 -0
- package/packages/sdk/python/setup.py +20 -0
- package/packages/sdk/src/federation/capability-grant.js +389 -0
- package/packages/sdk/src/federation/federation-router.js +360 -0
- package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
- package/packages/sdk/src/federation/index.js +3 -0
- package/packages/sdk/src/index.js +1796 -0
- package/packages/sdk/src/intelligence/contradiction.js +337 -0
- package/packages/sdk/src/intelligence/decision-engine.js +155 -0
- package/packages/sdk/src/intelligence/index.js +4 -0
- package/packages/sdk/src/intelligence/ontology.js +122 -0
- package/packages/sdk/src/intelligence/temporal.js +123 -0
- package/packages/sdk/src/market-client.js +142 -0
- package/packages/sdk/src/mesh-client.js +110 -0
- package/packages/sdk/src/middleware/index.js +3 -0
- package/packages/sdk/src/middleware/langchain.js +159 -0
- package/packages/sdk/src/middleware/llamaindex.js +101 -0
- package/packages/sdk/src/middleware/vercel-ai.js +112 -0
- package/packages/sdk/src/rag-client.js +85 -0
- package/packages/sdk/src/swarm-orchestrator.js +260 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
- package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
- package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
- package/packages/snapcompact/index.d.ts +284 -0
- package/packages/snapcompact/package.json +25 -0
- package/packages/snapcompact/src/index.js +716 -0
- package/packages/storage/PACKAGE_CONTRACT.md +1 -1
- package/packages/terminal-console/animations.mjs +240 -0
- package/packages/terminal-console/auto-anchor.mjs +220 -0
- package/packages/terminal-console/banner.mjs +91 -0
- package/packages/terminal-console/commands.mjs +459 -0
- package/packages/terminal-console/delegation.mjs +152 -0
- package/packages/terminal-console/index.mjs +5 -0
- package/packages/terminal-console/outbox.mjs +143 -0
- package/packages/terminal-console/phantom-bridge.mjs +637 -0
- package/packages/terminal-console/repl.mjs +136 -0
- package/packages/terminal-console/signer-store.mjs +130 -0
- package/packages/terminal-console/solana-rpc.mjs +214 -0
- package/packages/terminal-console/solana-transport.mjs +189 -0
- package/packages/terminal-tui/dashboard.mjs +214 -0
- package/packages/terminal-tui/index.mjs +28 -0
- package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
- package/packages/terminal-tui/telemetry-hud.mjs +137 -0
- package/packages/vault/index.d.ts +449 -0
- package/packages/vault/package.json +27 -0
- package/packages/vault/src/e2ee.mjs +393 -0
- package/packages/vault/src/enclave.js +481 -0
- package/packages/vault/src/erasure.js +207 -0
- package/packages/vault/src/index.js +1018 -155
- package/packages/vault/src/persistence.js +307 -0
- package/packages/vault/src/poseidon.js +354 -0
- package/packages/vault/src/receipt.js +459 -0
- package/scripts/benchmark-optical-context.mjs +166 -0
- package/scripts/bootstrap-enigma.mjs +502 -0
- package/scripts/build-edge-backend-workers.mjs +20 -5
- package/scripts/build-goal-completion-audit.mjs +72 -25
- package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
- package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
- package/scripts/build-hosted-probe-worker.mjs +19 -4
- package/scripts/build-installer-assets.mjs +41 -21
- package/scripts/build-operator-evidence-starter.mjs +59 -1
- package/scripts/build-production-backend-env-kit.mjs +2 -0
- package/scripts/build-production-unblocker.mjs +3 -0
- package/scripts/check.mjs +17 -3
- package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
- package/scripts/install-enigma-local.mjs +18 -5
- package/scripts/release-audit.mjs +65 -109
- package/scripts/release-provenance.mjs +6 -0
- package/scripts/run-backend-readiness-smoke.mjs +112 -10
- package/scripts/scan-secrets.mjs +1 -0
- package/scripts/simulate-production-env.mjs +7 -2
- package/scripts/validate-hosted-backend-live.mjs +112 -1
- package/specs/antibody-pack-v1.schema.json +95 -0
- package/specs/antigen-envelope-v1.schema.json +81 -0
- package/specs/boundary-manifest-v1.schema.json +35 -35
- package/specs/capsule-v1.schema.json +55 -55
- package/specs/claim-boundary-manifest-v1.schema.json +22 -22
- package/specs/claim-ledger-v1.schema.json +291 -0
- package/specs/context-passport-v1.schema.json +59 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -26
- package/specs/evidence-packet-v1.schema.json +177 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
- package/specs/immune-scan-report-v1.schema.json +112 -0
- package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
- package/specs/memory-atom-v1.schema.json +59 -0
- package/specs/memory-event-v1.schema.json +42 -42
- package/specs/passport-v1.schema.json +50 -50
- package/specs/proof-of-non-use-v1.schema.json +65 -0
- package/specs/quarantine-record-v1.schema.json +126 -0
- package/specs/receipt-v1.schema.json +61 -61
- package/specs/state-checkpoint-v1.schema.json +37 -37
- package/specs/trust-bundle-v1.schema.json +56 -56
- package/specs/trust-card-v1.schema.json +119 -0
- package/docs/proof-network-launch-plan.md +0 -421
- package/packages/metering/PACKAGE_CONTRACT.md +0 -20
- package/scripts/build-ai-orchestration-plan.mjs +0 -248
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"clean_up_tokenization_spaces": true,
|
|
3
|
+
"cls_token": "[CLS]",
|
|
4
|
+
"do_basic_tokenize": true,
|
|
5
|
+
"do_lower_case": true,
|
|
6
|
+
"mask_token": "[MASK]",
|
|
7
|
+
"model_max_length": 512,
|
|
8
|
+
"never_split": null,
|
|
9
|
+
"pad_token": "[PAD]",
|
|
10
|
+
"sep_token": "[SEP]",
|
|
11
|
+
"strip_accents": null,
|
|
12
|
+
"tokenize_chinese_chars": true,
|
|
13
|
+
"tokenizer_class": "BertTokenizer",
|
|
14
|
+
"unk_token": "[UNK]"
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@enigma/rag",
|
|
3
|
+
"version": "0.1.22",
|
|
4
|
+
"description": "Enigma ZK-RAG: Client-Side Semantic Vector Search & Blinded Context Retrieval",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"types": "./index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"src/",
|
|
10
|
+
"models/",
|
|
11
|
+
"index.d.ts"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"import": "./src/index.js",
|
|
17
|
+
"default": "./src/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./embeddings": "./src/embeddings.js",
|
|
20
|
+
"./vector-store": "./src/vector-store.js",
|
|
21
|
+
"./blinded-search": "./src/blinded-search.js"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@enigma/core": "workspace:*",
|
|
25
|
+
"@huggingface/transformers": "4.2.0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Enigma ZK-RAG: Blinded Vector Retrieval Engine.
|
|
2
|
+
// Allows an AI agent or client to query a remote vector index without leaking
|
|
3
|
+
// the query embedding coordinates using Inner-Product Preserving Orthogonal Transformations.
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import { EMBEDDING_DIM } from './embeddings.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a deterministic pseudo-random orthogonal matrix Q using Gram-Schmidt orthogonalization.
|
|
9
|
+
* Q has property Q^T * Q = I, which preserves inner products: (Q*u) · (Q*v) = u · v.
|
|
10
|
+
* @param {Buffer|string} secretKey - 32-byte secret key shared between trusted client sessions
|
|
11
|
+
* @param {number} [dim=384] - Vector dimensionality
|
|
12
|
+
* @returns {Float32Array[]} Array of d orthogonal basis vectors
|
|
13
|
+
*/
|
|
14
|
+
export function generateOrthogonalBasis(secretKey, dim = EMBEDDING_DIM) {
|
|
15
|
+
const seed = Buffer.isBuffer(secretKey) ? secretKey : Buffer.from(secretKey, 'utf8');
|
|
16
|
+
const basis = [];
|
|
17
|
+
|
|
18
|
+
// Generate random vectors from seed using HKDF
|
|
19
|
+
for (let i = 0; i < dim; i++) {
|
|
20
|
+
const raw = Buffer.from(crypto.hkdfSync('sha256', seed, Buffer.from(`enigma.basis.v1.${i}`, 'utf8'), Buffer.alloc(0), dim * 4));
|
|
21
|
+
const vec = new Float32Array(dim);
|
|
22
|
+
for (let j = 0; j < dim; j++) {
|
|
23
|
+
const u32 = raw.readInt32LE(j * 4);
|
|
24
|
+
vec[j] = u32 / 2147483648.0; // scale to [-1, 1]
|
|
25
|
+
}
|
|
26
|
+
basis.push(vec);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Gram-Schmidt process
|
|
30
|
+
const ortho = [];
|
|
31
|
+
for (let i = 0; i < dim; i++) {
|
|
32
|
+
const v = new Float32Array(basis[i]);
|
|
33
|
+
for (let j = 0; j < i; j++) {
|
|
34
|
+
const u = ortho[j];
|
|
35
|
+
let dot = 0;
|
|
36
|
+
for (let k = 0; k < dim; k++) dot += basis[i][k] * u[k];
|
|
37
|
+
for (let k = 0; k < dim; k++) v[k] -= dot * u[k];
|
|
38
|
+
}
|
|
39
|
+
// Normalize
|
|
40
|
+
let normSq = 0;
|
|
41
|
+
for (let k = 0; k < dim; k++) normSq += v[k] * v[k];
|
|
42
|
+
const norm = Math.sqrt(normSq);
|
|
43
|
+
if (norm > 1e-12) {
|
|
44
|
+
for (let k = 0; k < dim; k++) v[k] /= norm;
|
|
45
|
+
}
|
|
46
|
+
ortho.push(v);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return ortho;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Transforms a vector through an orthogonal basis matrix: v' = Q * v.
|
|
54
|
+
* @param {Float32Array} vector - Original embedding vector
|
|
55
|
+
* @param {Float32Array[]} basis - Orthogonal basis matrix Q
|
|
56
|
+
* @returns {Float32Array} Transformed vector
|
|
57
|
+
*/
|
|
58
|
+
export function applyOrthogonalTransform(vector, basis) {
|
|
59
|
+
const dim = vector.length;
|
|
60
|
+
const out = new Float32Array(dim);
|
|
61
|
+
for (let i = 0; i < dim; i++) {
|
|
62
|
+
let sum = 0;
|
|
63
|
+
const row = basis[i];
|
|
64
|
+
for (let j = 0; j < dim; j++) {
|
|
65
|
+
sum += row[j] * vector[j];
|
|
66
|
+
}
|
|
67
|
+
out[i] = sum;
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Client: Blinds a query vector with a private random positive scalar alpha and orthogonal rotation.
|
|
74
|
+
* Query: q_blind = alpha * Q * q.
|
|
75
|
+
* The server computes (q_blind · v'_i) = alpha * (q · v_i), which strictly preserves relative similarity ranking.
|
|
76
|
+
* @param {Float32Array} queryVector
|
|
77
|
+
* @param {Float32Array[]} basis
|
|
78
|
+
* @param {number} [alpha] - Optional private scaling factor > 0 (randomized if omitted)
|
|
79
|
+
* @returns {{ blindedVector: Float32Array, alpha: number }}
|
|
80
|
+
*/
|
|
81
|
+
export function blindQueryVector(queryVector, basis, alpha = null) {
|
|
82
|
+
const scale = alpha !== null ? alpha : (1.0 + (crypto.randomBytes(4).readUInt32LE(0) / 4294967295.0) * 4.0);
|
|
83
|
+
const rotated = applyOrthogonalTransform(queryVector, basis);
|
|
84
|
+
const blinded = new Float32Array(rotated.length);
|
|
85
|
+
for (let i = 0; i < rotated.length; i++) {
|
|
86
|
+
blinded[i] = rotated[i] * scale;
|
|
87
|
+
}
|
|
88
|
+
return { blindedVector: blinded, alpha: scale };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Server: Evaluates dot product ranking on blinded vectors without learning the query vector.
|
|
93
|
+
* @param {Float32Array} blindedQuery - Blinded query vector from client
|
|
94
|
+
* @param {Map<string, Float32Array>} transformedDocs - Transformed document vectors (Q * v_i)
|
|
95
|
+
* @param {number} [topK=5]
|
|
96
|
+
* @returns {Array<{ id: string, blindedScore: number }>}
|
|
97
|
+
*/
|
|
98
|
+
export function evaluateBlindedRanking(blindedQuery, transformedDocs, topK = 5) {
|
|
99
|
+
const scores = [];
|
|
100
|
+
for (const [id, docVec] of transformedDocs.entries()) {
|
|
101
|
+
let dot = 0;
|
|
102
|
+
for (let i = 0; i < blindedQuery.length; i++) {
|
|
103
|
+
dot += blindedQuery[i] * docVec[i];
|
|
104
|
+
}
|
|
105
|
+
scores.push({ id, blindedScore: dot });
|
|
106
|
+
}
|
|
107
|
+
scores.sort((a, b) => b.blindedScore - a.blindedScore);
|
|
108
|
+
return scores.slice(0, topK);
|
|
109
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Enigma Hybrid RAG: BM25 Lexical Inverted Index & Scoring.
|
|
2
|
+
// Implements Okapi BM25 ranking for exact keyword matching, technical identifiers,
|
|
3
|
+
// code symbols, and Solana addresses.
|
|
4
|
+
|
|
5
|
+
export class BM25Index {
|
|
6
|
+
/**
|
|
7
|
+
* @param {Object} [options]
|
|
8
|
+
* @param {number} [options.k1=1.2] - Term frequency saturation parameter
|
|
9
|
+
* @param {number} [options.b=0.75] - Document length normalization parameter
|
|
10
|
+
*/
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.k1 = typeof options.k1 === 'number' ? options.k1 : 1.2;
|
|
13
|
+
this.b = typeof options.b === 'number' ? options.b : 0.75;
|
|
14
|
+
|
|
15
|
+
/** @type {Map<string, { id: string, text: string, scope: string, terms: string[], length: number }>} */
|
|
16
|
+
this.docs = new Map();
|
|
17
|
+
/** @type {Map<string, Set<string>>} term -> Set<docId> */
|
|
18
|
+
this.invertedIndex = new Map();
|
|
19
|
+
this.totalDocLength = 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Tokenizes text into normalized lexical terms.
|
|
24
|
+
* Preserves alphanumeric identifiers, hex hashes, and technical terms.
|
|
25
|
+
* @param {string} text
|
|
26
|
+
* @returns {string[]}
|
|
27
|
+
*/
|
|
28
|
+
tokenize(text) {
|
|
29
|
+
if (!text || typeof text !== 'string') return [];
|
|
30
|
+
return text
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.split(/[^a-zA-Z0-9_\-]/)
|
|
33
|
+
.filter(t => t.length >= 2);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Indexes or updates a document in the BM25 index.
|
|
38
|
+
* @param {string} id
|
|
39
|
+
* @param {string} text
|
|
40
|
+
* @param {string} [scope='enigma.global']
|
|
41
|
+
*/
|
|
42
|
+
add(id, text, scope = 'enigma.global') {
|
|
43
|
+
if (this.docs.has(id)) {
|
|
44
|
+
this.remove(id);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const terms = this.tokenize(text);
|
|
48
|
+
const length = terms.length;
|
|
49
|
+
this.docs.set(id, { id, text, scope, terms, length });
|
|
50
|
+
this.totalDocLength += length;
|
|
51
|
+
|
|
52
|
+
const termSet = new Set(terms);
|
|
53
|
+
for (const term of termSet) {
|
|
54
|
+
if (!this.invertedIndex.has(term)) {
|
|
55
|
+
this.invertedIndex.set(term, new Set());
|
|
56
|
+
}
|
|
57
|
+
this.invertedIndex.get(term).add(id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Removes a document from the BM25 index.
|
|
63
|
+
* @param {string} id
|
|
64
|
+
*/
|
|
65
|
+
remove(id) {
|
|
66
|
+
const doc = this.docs.get(id);
|
|
67
|
+
if (!doc) return;
|
|
68
|
+
|
|
69
|
+
this.totalDocLength = Math.max(0, this.totalDocLength - doc.length);
|
|
70
|
+
const termSet = new Set(doc.terms);
|
|
71
|
+
for (const term of termSet) {
|
|
72
|
+
const posting = this.invertedIndex.get(term);
|
|
73
|
+
if (posting) {
|
|
74
|
+
posting.delete(id);
|
|
75
|
+
if (posting.size === 0) this.invertedIndex.delete(term);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this.docs.delete(id);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Clears all indexed documents, inverted index tokens, and document length aggregates.
|
|
83
|
+
*/
|
|
84
|
+
clear() {
|
|
85
|
+
this.docs.clear();
|
|
86
|
+
this.invertedIndex.clear();
|
|
87
|
+
this.totalDocLength = 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Computes Okapi BM25 score for a query against a document.
|
|
92
|
+
* @param {string[]} queryTerms
|
|
93
|
+
* @param {Object} doc
|
|
94
|
+
* @param {number} avgDocLen
|
|
95
|
+
* @param {number} N - Total document count
|
|
96
|
+
* @returns {number}
|
|
97
|
+
*/
|
|
98
|
+
scoreDoc(queryTerms, doc, avgDocLen, N) {
|
|
99
|
+
let score = 0;
|
|
100
|
+
const termFreqs = new Map();
|
|
101
|
+
for (const t of doc.terms) {
|
|
102
|
+
termFreqs.set(t, (termFreqs.get(t) || 0) + 1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const term of queryTerms) {
|
|
106
|
+
const posting = this.invertedIndex.get(term);
|
|
107
|
+
const n_t = posting ? posting.size : 0;
|
|
108
|
+
if (n_t === 0) continue;
|
|
109
|
+
|
|
110
|
+
// Robertson-Spärck Jones IDF
|
|
111
|
+
const idf = Math.log((N - n_t + 0.5) / (n_t + 0.5) + 1.0);
|
|
112
|
+
const f = termFreqs.get(term) || 0;
|
|
113
|
+
if (f === 0) continue;
|
|
114
|
+
|
|
115
|
+
const num = f * (this.k1 + 1);
|
|
116
|
+
const denom = f + this.k1 * (1 - this.b + this.b * (doc.length / (avgDocLen || 1)));
|
|
117
|
+
score += idf * (num / denom);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return score;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Performs BM25 lexical search.
|
|
125
|
+
* @param {string} queryText
|
|
126
|
+
* @param {Object} [options]
|
|
127
|
+
* @param {number} [options.topK=10]
|
|
128
|
+
* @param {string} [options.scope]
|
|
129
|
+
* @returns {Array<{ id: string, text: string, score: number, scope: string }>}
|
|
130
|
+
*/
|
|
131
|
+
search(queryText, options = {}) {
|
|
132
|
+
const queryTerms = this.tokenize(queryText);
|
|
133
|
+
if (queryTerms.length === 0 || this.docs.size === 0) return [];
|
|
134
|
+
|
|
135
|
+
const topK = options.topK || 10;
|
|
136
|
+
const scope = options.scope;
|
|
137
|
+
const N = this.docs.size;
|
|
138
|
+
const avgDocLen = this.totalDocLength / N;
|
|
139
|
+
|
|
140
|
+
// Collect candidate document IDs that match at least one query term
|
|
141
|
+
const candidateIds = new Set();
|
|
142
|
+
for (const term of queryTerms) {
|
|
143
|
+
const posting = this.invertedIndex.get(term);
|
|
144
|
+
if (posting) {
|
|
145
|
+
for (const id of posting) candidateIds.add(id);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const scored = [];
|
|
150
|
+
for (const id of candidateIds) {
|
|
151
|
+
const doc = this.docs.get(id);
|
|
152
|
+
if (!doc) continue;
|
|
153
|
+
if (scope && doc.scope !== scope) continue;
|
|
154
|
+
|
|
155
|
+
const rawScore = this.scoreDoc(queryTerms, doc, avgDocLen, N);
|
|
156
|
+
if (rawScore > 0) {
|
|
157
|
+
scored.push({
|
|
158
|
+
id: doc.id,
|
|
159
|
+
text: doc.text,
|
|
160
|
+
score: rawScore,
|
|
161
|
+
scope: doc.scope,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
scored.sort((a, b) => b.score - a.score);
|
|
167
|
+
return scored.slice(0, topK);
|
|
168
|
+
}
|
|
169
|
+
}
|