enigma-memory 0.1.17 → 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 +85 -27
- package/apps/cli/bin/enigma-desktop.mjs +140 -0
- package/apps/cli/bin/enigma-terminal.mjs +78 -0
- package/apps/cli/bin/enigma.mjs +4979 -3263
- 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/SIMULATION.md +14 -9
- package/deploy/docker-compose.local-production-simulation.yml +54 -12
- package/docs/benchmark-attestation-network.md +487 -487
- package/docs/benchmark-reproducibility.md +289 -289
- package/docs/blockchain-only-mechanisms.md +400 -400
- package/docs/browser-extension-install.md +8 -6
- package/docs/client-connectors.md +16 -12
- package/docs/demo-proof-network.md +275 -275
- package/docs/developer-ecosystem.md +15 -13
- package/docs/developer-proof-quickstart.md +325 -325
- package/docs/enigma-memory-ready-conformance.md +378 -376
- package/docs/install-anywhere.md +64 -30
- package/docs/installers-and-desktop.md +8 -7
- package/docs/memory-benchmarks.md +1 -1
- package/docs/memory-drive-health-model.md +690 -690
- package/docs/novelty-invention-candidates.md +161 -161
- package/docs/proof-network-build-notes.md +240 -240
- package/docs/proof-network-claim-boundaries.md +320 -318
- package/docs/proof-network.md +339 -339
- package/docs/sdk-api.md +324 -324
- package/docs/solana-proof-rail.md +453 -453
- 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 +410 -278
- 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 +249 -2
- 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 +2498 -1185
- 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 +436 -7
- 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 +1150 -125
- 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 +292 -274
- package/scripts/build-hosted-customer-lifecycle.mjs +493 -476
- package/scripts/build-hosted-probe-worker.mjs +19 -4
- package/scripts/build-installer-assets.mjs +409 -389
- 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 +4 -1
- package/scripts/build-proof-network-packet.mjs +213 -213
- package/scripts/check.mjs +25 -4
- package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
- package/scripts/install-enigma-local.mjs +18 -5
- package/scripts/release-audit.mjs +74 -115
- package/scripts/release-provenance.mjs +12 -2
- package/scripts/run-backend-readiness-smoke.mjs +112 -10
- package/scripts/run-standard-memory-benchmarks.mjs +1354 -1352
- package/scripts/scan-secrets.mjs +178 -0
- package/scripts/simulate-production-env.mjs +71 -10
- 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
|
@@ -1,1185 +1,2498 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
throw invalidParams(
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (!isPlainObject(args)) throw invalidParams('
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
{
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
return
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
return {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
return {
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
:
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
}
|
|
1
|
+
import { createHmac, randomBytes } from 'node:crypto';
|
|
2
|
+
import { access, readFile } from 'node:fs/promises';
|
|
3
|
+
import { ENIGMA_VERSION } from '../../core/src/version.mjs';
|
|
4
|
+
import { createInterface } from 'node:readline';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import {
|
|
7
|
+
createVault,
|
|
8
|
+
remember,
|
|
9
|
+
recall,
|
|
10
|
+
deleteMemory,
|
|
11
|
+
exportBundle,
|
|
12
|
+
importBundle,
|
|
13
|
+
rotateContentKey,
|
|
14
|
+
sealContentKeyEpoch,
|
|
15
|
+
resetVaultContentKeys,
|
|
16
|
+
SimulatedEnclaveProvider,
|
|
17
|
+
AttestationVerifier,
|
|
18
|
+
createPoseidonCommitment,
|
|
19
|
+
verifyPoseidonCommitment,
|
|
20
|
+
} from '../../vault/src/index.js';
|
|
21
|
+
import {
|
|
22
|
+
readJsonFileWithRevision,
|
|
23
|
+
withBundleFileLock,
|
|
24
|
+
writeJsonFileAtomic,
|
|
25
|
+
} from '../../vault/src/persistence.js';
|
|
26
|
+
import { createPassport, compileContextPack } from '../../passport/src/index.js';
|
|
27
|
+
import { verifyBundle } from '../../../apps/verifier/bin/enigma-verify.mjs';
|
|
28
|
+
import { aggregateUsageEvents, createUsageEvent } from '../../metering/src/index.js';
|
|
29
|
+
import {
|
|
30
|
+
createConsumerGpuCapacityProfile,
|
|
31
|
+
createOperatorServiceQuote,
|
|
32
|
+
createPermissionlessMemoryJob,
|
|
33
|
+
createServiceSettlementReceipt,
|
|
34
|
+
createSettlementBatch,
|
|
35
|
+
verifyServiceSettlementReceipt,
|
|
36
|
+
} from '../../settlement/src/index.js';
|
|
37
|
+
import {
|
|
38
|
+
assertImmuneIngressPublicSafe,
|
|
39
|
+
createImmuneIngressReport,
|
|
40
|
+
} from '../../importers/src/index.js';
|
|
41
|
+
import {
|
|
42
|
+
enigma_cluster_memories as routeClusterMemories,
|
|
43
|
+
enigma_graph_query as routeGraphQuery,
|
|
44
|
+
enigma_swarm_register_agent as routeSwarmRegisterAgent,
|
|
45
|
+
enigma_swarm_sync as routeSwarmSync,
|
|
46
|
+
} from '../../connectors/swarm-router.mjs';
|
|
47
|
+
import {
|
|
48
|
+
DEFAULT_DESKTOP_ORIGIN,
|
|
49
|
+
PRIVATE_SESSION_RESOURCE_URI,
|
|
50
|
+
createPrivateSessionHttpUrl,
|
|
51
|
+
createPrivateSessionProtocolUrl,
|
|
52
|
+
validateLoopbackDesktopOrigin,
|
|
53
|
+
validatePrivateHandoffIntent,
|
|
54
|
+
validatePrivateHandoffModel,
|
|
55
|
+
} from './private-handoff.js';
|
|
56
|
+
import { assertRemoteToolPolicyCoverage, remoteToolPolicy, requiredScopesForMcpPayload } from './remote-policy.js';
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
const defaultEnclave = new SimulatedEnclaveProvider({ simulationLabel: 'enigma_mcp_runtime' });
|
|
60
|
+
|
|
61
|
+
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
62
|
+
const JSONRPC_VERSION = '2.0';
|
|
63
|
+
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
64
|
+
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: ENIGMA_VERSION });
|
|
65
|
+
const UNLOCKED_VAULT_CACHE_LIMIT = 8;
|
|
66
|
+
const unlockedVaultCache = new Map();
|
|
67
|
+
const cacheAuthenticationKey = randomBytes(32);
|
|
68
|
+
let configuredCheckpointProvider = null;
|
|
69
|
+
let configuredInferenceRuntime = null;
|
|
70
|
+
let configuredX402Client = null;
|
|
71
|
+
const REMOTE_SECURE_VAULT = Symbol('enigma.remote_secure_vault');
|
|
72
|
+
|
|
73
|
+
function enigmaDesktopOrigin() {
|
|
74
|
+
return validateLoopbackDesktopOrigin(process.env.ENIGMA_DESKTOP_URL || DEFAULT_DESKTOP_ORIGIN);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function privateSessionUrl(input = {}) {
|
|
78
|
+
return process.env.ENIGMA_DESKTOP_URL
|
|
79
|
+
? createPrivateSessionHttpUrl(input, enigmaDesktopOrigin())
|
|
80
|
+
: createPrivateSessionProtocolUrl(input);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function rejectSensitiveHandoffIntent(intent) {
|
|
84
|
+
try {
|
|
85
|
+
validatePrivateHandoffIntent(intent);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
throw invalidParams(error.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function configureVaultCheckpointProvider(provider = null) {
|
|
92
|
+
if (provider !== null && (typeof provider?.load !== 'function' || typeof provider?.advance !== 'function')) {
|
|
93
|
+
throw new TypeError('checkpoint provider requires load and advance functions');
|
|
94
|
+
}
|
|
95
|
+
configuredCheckpointProvider = provider;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function configureMcpInferenceRuntime(runtime = null) {
|
|
99
|
+
const hasChat = typeof runtime?.chat?.complete === 'function';
|
|
100
|
+
const hasImages = typeof runtime?.images?.generate === 'function';
|
|
101
|
+
if (runtime !== null && !hasChat && !hasImages) {
|
|
102
|
+
throw new TypeError('MCP inference runtime requires chat.complete() or images.generate()');
|
|
103
|
+
}
|
|
104
|
+
configuredInferenceRuntime = runtime;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function configureMcpX402Client(client = null) {
|
|
108
|
+
if (client !== null && typeof client !== 'function') throw new TypeError('MCP x402 client must be a function');
|
|
109
|
+
configuredX402Client = client;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function credentialCacheTag(credentials) {
|
|
113
|
+
return createHmac('sha256', cacheAuthenticationKey)
|
|
114
|
+
.update(credentials.passphrase ?? (credentials.insecureDevMode ? 'insecure-dev' : 'missing'))
|
|
115
|
+
.digest('hex');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function zeroizeCachedVault(entry) {
|
|
119
|
+
const vault = entry?.vault;
|
|
120
|
+
if (!vault) return;
|
|
121
|
+
for (const epoch of vault.keyEpochs?.values?.() ?? []) epoch.key?.fill?.(0);
|
|
122
|
+
vault.addressKey?.fill?.(0);
|
|
123
|
+
for (const record of vault.memories?.values?.() ?? []) {
|
|
124
|
+
if (Object.prototype.hasOwnProperty.call(record, 'plaintext')) delete record.plaintext;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function invalidateCachedVault(path) {
|
|
129
|
+
const key = resolve(String(path));
|
|
130
|
+
const prior = unlockedVaultCache.get(key);
|
|
131
|
+
unlockedVaultCache.delete(key);
|
|
132
|
+
zeroizeCachedVault(prior);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function cacheUnlockedVault(path, entry) {
|
|
136
|
+
const key = resolve(String(path));
|
|
137
|
+
const prior = unlockedVaultCache.get(key);
|
|
138
|
+
if (prior && prior.vault !== entry.vault) zeroizeCachedVault(prior);
|
|
139
|
+
unlockedVaultCache.delete(key);
|
|
140
|
+
unlockedVaultCache.set(key, entry);
|
|
141
|
+
while (unlockedVaultCache.size > UNLOCKED_VAULT_CACHE_LIMIT) {
|
|
142
|
+
const oldestKey = unlockedVaultCache.keys().next().value;
|
|
143
|
+
const oldest = unlockedVaultCache.get(oldestKey);
|
|
144
|
+
unlockedVaultCache.delete(oldestKey);
|
|
145
|
+
zeroizeCachedVault(oldest);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export function clearUnlockedVaultCache() {
|
|
149
|
+
for (const entry of unlockedVaultCache.values()) zeroizeCachedVault(entry);
|
|
150
|
+
unlockedVaultCache.clear();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
process.once('exit', () => {
|
|
154
|
+
clearUnlockedVaultCache();
|
|
155
|
+
cacheAuthenticationKey.fill(0);
|
|
156
|
+
});
|
|
157
|
+
const JSON_RPC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
158
|
+
const JSON_RPC_ERROR = Object.freeze({
|
|
159
|
+
INVALID_REQUEST: -32600,
|
|
160
|
+
METHOD_NOT_FOUND: -32601,
|
|
161
|
+
INVALID_PARAMS: -32602,
|
|
162
|
+
INTERNAL_ERROR: -32603,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
class JsonRpcProtocolError extends Error {
|
|
166
|
+
constructor(code, message, data = undefined) {
|
|
167
|
+
super(message);
|
|
168
|
+
this.name = 'JsonRpcProtocolError';
|
|
169
|
+
this.code = code;
|
|
170
|
+
this.data = data;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function invalidParams(message = 'Invalid params', data = undefined) {
|
|
175
|
+
return new JsonRpcProtocolError(JSON_RPC_ERROR.INVALID_PARAMS, message, data);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function isJsonRpcProtocolError(error) {
|
|
179
|
+
return error instanceof JsonRpcProtocolError;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function isPlainObject(value) {
|
|
183
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isValidJsonRpcId(id) {
|
|
187
|
+
return id === null
|
|
188
|
+
|| (typeof id === 'string' && JSON_RPC_ID_PATTERN.test(id))
|
|
189
|
+
|| (typeof id === 'number' && Number.isSafeInteger(id));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function ensureParamsObject(params, method) {
|
|
193
|
+
if (params === undefined) return {};
|
|
194
|
+
if (!isPlainObject(params)) throw invalidParams(`${method} params must be an object.`);
|
|
195
|
+
return params;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function rejectAdditionalProperties(object, allowed, context) {
|
|
199
|
+
for (const key of Object.keys(object)) {
|
|
200
|
+
if (!allowed.has(key)) throw invalidParams(`${context} contains unsupported properties.`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function requireString(object, key, context) {
|
|
205
|
+
if (typeof object[key] !== 'string') throw invalidParams(`${context} requires ${key} as a string.`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function optionalString(object, key, context) {
|
|
209
|
+
if (object[key] !== undefined && typeof object[key] !== 'string') {
|
|
210
|
+
throw invalidParams(`${context} ${key} must be a string.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function optionalPlainObject(object, key, context) {
|
|
215
|
+
if (object[key] !== undefined && !isPlainObject(object[key])) {
|
|
216
|
+
throw invalidParams(`${context} ${key} must be an object.`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function optionalStringArray(object, key, context) {
|
|
221
|
+
if (object[key] === undefined) return;
|
|
222
|
+
if (!Array.isArray(object[key]) || object[key].some((item) => typeof item !== 'string')) {
|
|
223
|
+
throw invalidParams(`${context} ${key} must be an array of strings.`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function optionalLimit(object, key, context) {
|
|
228
|
+
if (object[key] === undefined) return;
|
|
229
|
+
if (!Number.isInteger(object[key]) || object[key] < 1 || object[key] > 50) {
|
|
230
|
+
throw invalidParams(`${context} ${key} must be an integer from 1 through 50.`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function optionalBoolean(object, key, context) {
|
|
235
|
+
if (object[key] !== undefined && typeof object[key] !== 'boolean') {
|
|
236
|
+
throw invalidParams(`${context} ${key} must be a boolean.`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function optionalNonNegativeNumber(object, key, context) {
|
|
241
|
+
if (object[key] === undefined) return;
|
|
242
|
+
if (typeof object[key] !== 'number' || !Number.isFinite(object[key]) || object[key] < 0) {
|
|
243
|
+
throw invalidParams(`${context} ${key} must be a non-negative number.`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function requireNumber(object, key, context) {
|
|
248
|
+
if (typeof object[key] !== 'number' || !Number.isFinite(object[key])) {
|
|
249
|
+
throw invalidParams(`${context} requires ${key} as a finite number.`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function optionalObjectArray(object, key, context) {
|
|
254
|
+
if (object[key] === undefined) return;
|
|
255
|
+
if (!Array.isArray(object[key]) || object[key].some((item) => !isPlainObject(item))) {
|
|
256
|
+
throw invalidParams(`${context} ${key} must be an array of objects.`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function optionalIntegerRange(object, key, context, minimum, maximum) {
|
|
261
|
+
if (object[key] === undefined) return;
|
|
262
|
+
if (!Number.isInteger(object[key]) || object[key] < minimum || object[key] > maximum) {
|
|
263
|
+
throw invalidParams(`${context} ${key} must be an integer from ${minimum} through ${maximum}.`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function optionalPermissionMask(object, key, context) {
|
|
268
|
+
const value = object[key];
|
|
269
|
+
if (value === undefined) return;
|
|
270
|
+
const validNumber = Number.isInteger(value) && value >= 0 && value <= 63;
|
|
271
|
+
const validString = typeof value === 'string';
|
|
272
|
+
const validArray = Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
273
|
+
if (!validNumber && !validString && !validArray) {
|
|
274
|
+
throw invalidParams(`${context} ${key} must be a permission bitmask, string, or array of strings.`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function maximumStringLength(object, key, context, maximum) {
|
|
279
|
+
if (typeof object[key] === 'string' && object[key].length > maximum) {
|
|
280
|
+
throw invalidParams(`${context} ${key} exceeds ${maximum} characters.`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function validateCompletionMessages(messages, context) {
|
|
285
|
+
if (!Array.isArray(messages) || messages.length < 1 || messages.length > 128) {
|
|
286
|
+
throw invalidParams(`${context} messages must contain one through 128 messages.`);
|
|
287
|
+
}
|
|
288
|
+
for (const [index, message] of messages.entries()) {
|
|
289
|
+
if (!isPlainObject(message)) throw invalidParams(`${context} messages[${index}] must be an object.`);
|
|
290
|
+
rejectAdditionalProperties(message, new Set(['role', 'content']), `${context} messages[${index}]`);
|
|
291
|
+
requireString(message, 'role', `${context} messages[${index}]`);
|
|
292
|
+
requireString(message, 'content', `${context} messages[${index}]`);
|
|
293
|
+
if (!['system', 'user', 'assistant', 'tool'].includes(message.role)) {
|
|
294
|
+
throw invalidParams(`${context} messages[${index}].role is invalid.`);
|
|
295
|
+
}
|
|
296
|
+
if (message.content.length > 100_000) throw invalidParams(`${context} messages[${index}].content exceeds 100000 characters.`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function validateToolArguments(name, args) {
|
|
301
|
+
if (!isPlainObject(args)) throw invalidParams('tools/call arguments must be an object.');
|
|
302
|
+
switch (name) {
|
|
303
|
+
case 'enigma_private_handoff_health':
|
|
304
|
+
case 'enigma_routing_contract':
|
|
305
|
+
rejectAdditionalProperties(args, new Set(), name);
|
|
306
|
+
return args;
|
|
307
|
+
case 'enigma_complete':
|
|
308
|
+
rejectAdditionalProperties(args, new Set(['messages', 'model', 'privacy_mode', 'temperature', 'max_tokens', 'reasoning_effort', 'web_search', 'require_private_route']), name);
|
|
309
|
+
validateCompletionMessages(args.messages, name);
|
|
310
|
+
optionalString(args, 'model', name);
|
|
311
|
+
maximumStringLength(args, 'model', name, 160);
|
|
312
|
+
optionalString(args, 'privacy_mode', name);
|
|
313
|
+
if (args.privacy_mode !== undefined && !['off', 'smart', 'full'].includes(args.privacy_mode)) throw invalidParams(`${name} privacy_mode must be off, smart, or full.`);
|
|
314
|
+
optionalNonNegativeNumber(args, 'temperature', name);
|
|
315
|
+
if (args.temperature !== undefined && args.temperature > 2) throw invalidParams(`${name} temperature must not exceed 2.`);
|
|
316
|
+
optionalIntegerRange(args, 'max_tokens', name, 1, 131072);
|
|
317
|
+
optionalString(args, 'reasoning_effort', name);
|
|
318
|
+
if (args.reasoning_effort !== undefined && !['none', 'low', 'medium', 'high'].includes(args.reasoning_effort)) throw invalidParams(`${name} reasoning_effort is invalid.`);
|
|
319
|
+
optionalBoolean(args, 'web_search', name);
|
|
320
|
+
optionalBoolean(args, 'require_private_route', name);
|
|
321
|
+
return args;
|
|
322
|
+
case 'enigma_generate_image':
|
|
323
|
+
rejectAdditionalProperties(args, new Set(['prompt', 'model', 'negative_prompt', 'width', 'height', 'steps', 'cfg_scale', 'variants', 'format', 'seed']), name);
|
|
324
|
+
requireString(args, 'prompt', name);
|
|
325
|
+
requireString(args, 'model', name);
|
|
326
|
+
optionalString(args, 'negative_prompt', name);
|
|
327
|
+
maximumStringLength(args, 'prompt', name, 16000);
|
|
328
|
+
maximumStringLength(args, 'model', name, 160);
|
|
329
|
+
maximumStringLength(args, 'negative_prompt', name, 8000);
|
|
330
|
+
optionalIntegerRange(args, 'width', name, 256, 2048);
|
|
331
|
+
optionalIntegerRange(args, 'height', name, 256, 2048);
|
|
332
|
+
optionalIntegerRange(args, 'steps', name, 1, 100);
|
|
333
|
+
optionalNonNegativeNumber(args, 'cfg_scale', name);
|
|
334
|
+
if (args.cfg_scale !== undefined && (args.cfg_scale < 1 || args.cfg_scale > 30)) throw invalidParams(`${name} cfg_scale must be from 1 through 30.`);
|
|
335
|
+
optionalIntegerRange(args, 'variants', name, 1, 4);
|
|
336
|
+
optionalString(args, 'format', name);
|
|
337
|
+
if (args.format !== undefined && !['png', 'jpeg', 'webp'].includes(args.format)) throw invalidParams(`${name} format must be png, jpeg, or webp.`);
|
|
338
|
+
optionalIntegerRange(args, 'seed', name, 0, 2147483647);
|
|
339
|
+
return args;
|
|
340
|
+
case 'enigma_x402_execute':
|
|
341
|
+
rejectAdditionalProperties(args, new Set(['url', 'method', 'headers', 'body', 'max_response_bytes']), name);
|
|
342
|
+
requireString(args, 'url', name);
|
|
343
|
+
maximumStringLength(args, 'url', name, 4096);
|
|
344
|
+
optionalString(args, 'method', name);
|
|
345
|
+
if (args.method !== undefined && !['GET', 'POST'].includes(args.method)) throw invalidParams(`${name} method must be GET or POST.`);
|
|
346
|
+
optionalPlainObject(args, 'headers', name);
|
|
347
|
+
for (const [header, value] of Object.entries(args.headers || {})) {
|
|
348
|
+
if (!['accept', 'content-type', 'idempotency-key'].includes(header.toLowerCase()) || typeof value !== 'string' || value.length > 4096) {
|
|
349
|
+
throw invalidParams(`${name} contains a forbidden or invalid request header.`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (args.body !== undefined && typeof args.body !== 'string' && !isPlainObject(args.body)) throw invalidParams(`${name} body must be a string or object.`);
|
|
353
|
+
optionalIntegerRange(args, 'max_response_bytes', name, 1024, 1048576);
|
|
354
|
+
return args;
|
|
355
|
+
case 'enigma_start_private_session':
|
|
356
|
+
rejectAdditionalProperties(args, new Set(['intent', 'model']), name);
|
|
357
|
+
optionalString(args, 'intent', name);
|
|
358
|
+
optionalString(args, 'model', name);
|
|
359
|
+
rejectSensitiveHandoffIntent(args.intent);
|
|
360
|
+
try { validatePrivateHandoffModel(args.model); } catch (error) { throw invalidParams(error.message); }
|
|
361
|
+
return args;
|
|
362
|
+
case 'enigma_init':
|
|
363
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'tenant_id', 'subject_id', 'actor_id', 'policy_id', 'insecureDevMode']), name);
|
|
364
|
+
optionalString(args, 'bundlePath', name);
|
|
365
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
366
|
+
optionalString(args, 'tenant_id', name);
|
|
367
|
+
optionalString(args, 'subject_id', name);
|
|
368
|
+
optionalString(args, 'actor_id', name);
|
|
369
|
+
optionalString(args, 'policy_id', name);
|
|
370
|
+
return args;
|
|
371
|
+
case 'enigma_remember':
|
|
372
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'text', 'purpose', 'tags', 'metadata', 'insecureDevMode']), name);
|
|
373
|
+
optionalString(args, 'bundlePath', name);
|
|
374
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
375
|
+
requireString(args, 'text', name);
|
|
376
|
+
optionalString(args, 'purpose', name);
|
|
377
|
+
optionalStringArray(args, 'tags', name);
|
|
378
|
+
optionalPlainObject(args, 'metadata', name);
|
|
379
|
+
return args;
|
|
380
|
+
case 'enigma_search':
|
|
381
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'query', 'memory_addr', 'purpose', 'limit', 'insecureDevMode', 'allowOldEpochReads']), name);
|
|
382
|
+
optionalString(args, 'bundlePath', name);
|
|
383
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
384
|
+
optionalBoolean(args, 'allowOldEpochReads', name);
|
|
385
|
+
optionalString(args, 'query', name);
|
|
386
|
+
optionalString(args, 'memory_addr', name);
|
|
387
|
+
optionalString(args, 'purpose', name);
|
|
388
|
+
optionalLimit(args, 'limit', name);
|
|
389
|
+
return args;
|
|
390
|
+
case 'enigma_context_pack':
|
|
391
|
+
rejectAdditionalProperties(args, new Set([
|
|
392
|
+
'bundlePath',
|
|
393
|
+
'query',
|
|
394
|
+
'purpose',
|
|
395
|
+
'limit',
|
|
396
|
+
'memory_addresses',
|
|
397
|
+
'optimize',
|
|
398
|
+
'max_estimated_tokens',
|
|
399
|
+
'price_per_million_tokens',
|
|
400
|
+
'currency',
|
|
401
|
+
'insecureDevMode',
|
|
402
|
+
'allowOldEpochReads',
|
|
403
|
+
]), name);
|
|
404
|
+
optionalString(args, 'bundlePath', name);
|
|
405
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
406
|
+
optionalBoolean(args, 'allowOldEpochReads', name);
|
|
407
|
+
optionalString(args, 'query', name);
|
|
408
|
+
optionalString(args, 'purpose', name);
|
|
409
|
+
optionalLimit(args, 'limit', name);
|
|
410
|
+
optionalStringArray(args, 'memory_addresses', name);
|
|
411
|
+
optionalBoolean(args, 'optimize', name);
|
|
412
|
+
optionalNonNegativeNumber(args, 'max_estimated_tokens', name);
|
|
413
|
+
optionalNonNegativeNumber(args, 'price_per_million_tokens', name);
|
|
414
|
+
optionalString(args, 'currency', name);
|
|
415
|
+
return args;
|
|
416
|
+
case 'enigma_delete':
|
|
417
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'memory_addr', 'reason', 'insecureDevMode']), name);
|
|
418
|
+
optionalString(args, 'bundlePath', name);
|
|
419
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
420
|
+
requireString(args, 'memory_addr', name);
|
|
421
|
+
optionalString(args, 'reason', name);
|
|
422
|
+
return args;
|
|
423
|
+
case 'enigma_vault_rotate':
|
|
424
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'key_id', 'insecureDevMode']), name);
|
|
425
|
+
optionalString(args, 'bundlePath', name);
|
|
426
|
+
optionalString(args, 'key_id', name);
|
|
427
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
428
|
+
return args;
|
|
429
|
+
case 'enigma_vault_seal':
|
|
430
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'epoch', 'insecureDevMode']), name);
|
|
431
|
+
optionalString(args, 'bundlePath', name);
|
|
432
|
+
optionalIntegerRange(args, 'epoch', name, 1, Number.MAX_SAFE_INTEGER);
|
|
433
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
434
|
+
return args;
|
|
435
|
+
case 'enigma_vault_reset':
|
|
436
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'key_id', 'insecureDevMode']), name);
|
|
437
|
+
optionalString(args, 'bundlePath', name);
|
|
438
|
+
optionalString(args, 'key_id', name);
|
|
439
|
+
optionalBoolean(args, 'insecureDevMode', name);
|
|
440
|
+
return args;
|
|
441
|
+
case 'enigma_verify_receipts':
|
|
442
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'bundle']), name);
|
|
443
|
+
optionalString(args, 'bundlePath', name);
|
|
444
|
+
optionalPlainObject(args, 'bundle', name);
|
|
445
|
+
return args;
|
|
446
|
+
case 'enigma_swarm_register_agent':
|
|
447
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'agent_id', 'swarm_id', 'namespace', 'permission_mask']), name);
|
|
448
|
+
optionalString(args, 'bundlePath', name);
|
|
449
|
+
requireString(args, 'agent_id', name);
|
|
450
|
+
optionalString(args, 'swarm_id', name);
|
|
451
|
+
optionalString(args, 'namespace', name);
|
|
452
|
+
optionalPermissionMask(args, 'permission_mask', name);
|
|
453
|
+
return args;
|
|
454
|
+
case 'enigma_graph_query':
|
|
455
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'agent_id', 'swarm_id', 'namespace', 'start', 'entity_id', 'query', 'max_depth', 'limit', 'direction']), name);
|
|
456
|
+
optionalString(args, 'bundlePath', name);
|
|
457
|
+
requireString(args, 'agent_id', name);
|
|
458
|
+
optionalString(args, 'swarm_id', name);
|
|
459
|
+
optionalString(args, 'namespace', name);
|
|
460
|
+
optionalString(args, 'start', name);
|
|
461
|
+
optionalString(args, 'entity_id', name);
|
|
462
|
+
optionalString(args, 'query', name);
|
|
463
|
+
optionalIntegerRange(args, 'max_depth', name, 0, 12);
|
|
464
|
+
optionalIntegerRange(args, 'limit', name, 1, 500);
|
|
465
|
+
optionalString(args, 'direction', name);
|
|
466
|
+
return args;
|
|
467
|
+
case 'enigma_cluster_memories':
|
|
468
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'agent_id', 'swarm_id', 'namespace', 'threshold', 'max_clusters']), name);
|
|
469
|
+
optionalString(args, 'bundlePath', name);
|
|
470
|
+
requireString(args, 'agent_id', name);
|
|
471
|
+
optionalString(args, 'swarm_id', name);
|
|
472
|
+
optionalString(args, 'namespace', name);
|
|
473
|
+
optionalNonNegativeNumber(args, 'threshold', name);
|
|
474
|
+
if (args.threshold !== undefined && args.threshold > 1) throw invalidParams(`${name} threshold must not exceed 1.`);
|
|
475
|
+
optionalIntegerRange(args, 'max_clusters', name, 1, 100);
|
|
476
|
+
return args;
|
|
477
|
+
case 'enigma_swarm_sync':
|
|
478
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'agent_id', 'swarm_id', 'namespace', 'snapshot', 'apply', 'include_content', 'allow_content']), name);
|
|
479
|
+
optionalString(args, 'bundlePath', name);
|
|
480
|
+
requireString(args, 'agent_id', name);
|
|
481
|
+
optionalString(args, 'swarm_id', name);
|
|
482
|
+
optionalString(args, 'namespace', name);
|
|
483
|
+
optionalPlainObject(args, 'snapshot', name);
|
|
484
|
+
optionalBoolean(args, 'apply', name);
|
|
485
|
+
optionalBoolean(args, 'include_content', name);
|
|
486
|
+
optionalBoolean(args, 'allow_content', name);
|
|
487
|
+
return args;
|
|
488
|
+
case 'enigma_immune_ingress':
|
|
489
|
+
rejectAdditionalProperties(args, new Set(['candidate', 'candidates', 'generated_at', 'now']), name);
|
|
490
|
+
optionalPlainObject(args, 'candidate', name);
|
|
491
|
+
optionalObjectArray(args, 'candidates', name);
|
|
492
|
+
optionalString(args, 'generated_at', name);
|
|
493
|
+
optionalString(args, 'now', name);
|
|
494
|
+
if (args.candidate === undefined && args.candidates === undefined) throw invalidParams(`${name} requires candidate or candidates.`);
|
|
495
|
+
return args;
|
|
496
|
+
case 'enigma_meter_usage':
|
|
497
|
+
rejectAdditionalProperties(args, new Set([
|
|
498
|
+
'events',
|
|
499
|
+
'tenant_id',
|
|
500
|
+
'meter_id',
|
|
501
|
+
'provider',
|
|
502
|
+
'model',
|
|
503
|
+
'operation',
|
|
504
|
+
'timestamp',
|
|
505
|
+
'generated_at',
|
|
506
|
+
'prompt_tokens',
|
|
507
|
+
'completion_tokens',
|
|
508
|
+
'memory_baseline_tokens',
|
|
509
|
+
'memory_optimized_tokens',
|
|
510
|
+
'currency',
|
|
511
|
+
'input_price_per_million_tokens',
|
|
512
|
+
'output_price_per_million_tokens',
|
|
513
|
+
'price_per_million_tokens',
|
|
514
|
+
]), name);
|
|
515
|
+
optionalObjectArray(args, 'events', name);
|
|
516
|
+
optionalString(args, 'tenant_id', name);
|
|
517
|
+
optionalString(args, 'meter_id', name);
|
|
518
|
+
optionalString(args, 'provider', name);
|
|
519
|
+
optionalString(args, 'model', name);
|
|
520
|
+
optionalString(args, 'operation', name);
|
|
521
|
+
optionalString(args, 'timestamp', name);
|
|
522
|
+
optionalString(args, 'generated_at', name);
|
|
523
|
+
optionalString(args, 'currency', name);
|
|
524
|
+
optionalNonNegativeNumber(args, 'prompt_tokens', name);
|
|
525
|
+
optionalNonNegativeNumber(args, 'completion_tokens', name);
|
|
526
|
+
optionalNonNegativeNumber(args, 'memory_baseline_tokens', name);
|
|
527
|
+
optionalNonNegativeNumber(args, 'memory_optimized_tokens', name);
|
|
528
|
+
optionalNonNegativeNumber(args, 'input_price_per_million_tokens', name);
|
|
529
|
+
optionalNonNegativeNumber(args, 'output_price_per_million_tokens', name);
|
|
530
|
+
optionalNonNegativeNumber(args, 'price_per_million_tokens', name);
|
|
531
|
+
return args;
|
|
532
|
+
case 'enigma_settlement_job':
|
|
533
|
+
rejectAdditionalProperties(args, new Set(['tenant_id', 'job_type', 'memory_commitment_root', 'policy_hash', 'usage_event_hash', 'requested_at', 'expires_at', 'max_price_amount', 'payment_asset']), name);
|
|
534
|
+
requireString(args, 'tenant_id', name);
|
|
535
|
+
requireString(args, 'job_type', name);
|
|
536
|
+
requireString(args, 'memory_commitment_root', name);
|
|
537
|
+
requireString(args, 'policy_hash', name);
|
|
538
|
+
requireString(args, 'usage_event_hash', name);
|
|
539
|
+
optionalString(args, 'requested_at', name);
|
|
540
|
+
requireString(args, 'expires_at', name);
|
|
541
|
+
requireNumber(args, 'max_price_amount', name);
|
|
542
|
+
optionalString(args, 'payment_asset', name);
|
|
543
|
+
return args;
|
|
544
|
+
case 'enigma_settlement_capacity':
|
|
545
|
+
rejectAdditionalProperties(args, new Set(['operator_id', 'accelerator_class', 'hardware_ref', 'region', 'model_family', 'model_refs', 'observed_at', 'expires_at', 'vram_gb', 'max_context_window_tokens', 'available_context_tokens_per_minute', 'p95_latency_ms', 'price_per_million_context_tokens', 'asset', 'capacity_ref', 'terms_ref']), name);
|
|
546
|
+
requireString(args, 'operator_id', name);
|
|
547
|
+
requireString(args, 'accelerator_class', name);
|
|
548
|
+
requireString(args, 'hardware_ref', name);
|
|
549
|
+
requireString(args, 'region', name);
|
|
550
|
+
requireString(args, 'model_family', name);
|
|
551
|
+
optionalStringArray(args, 'model_refs', name);
|
|
552
|
+
if (!Array.isArray(args.model_refs)) throw invalidParams(`${name} requires model_refs as an array.`);
|
|
553
|
+
optionalString(args, 'observed_at', name);
|
|
554
|
+
requireString(args, 'expires_at', name);
|
|
555
|
+
requireNumber(args, 'vram_gb', name);
|
|
556
|
+
requireNumber(args, 'max_context_window_tokens', name);
|
|
557
|
+
requireNumber(args, 'available_context_tokens_per_minute', name);
|
|
558
|
+
requireNumber(args, 'p95_latency_ms', name);
|
|
559
|
+
requireNumber(args, 'price_per_million_context_tokens', name);
|
|
560
|
+
optionalString(args, 'asset', name);
|
|
561
|
+
requireString(args, 'capacity_ref', name);
|
|
562
|
+
requireString(args, 'terms_ref', name);
|
|
563
|
+
return args;
|
|
564
|
+
case 'enigma_settlement_quote':
|
|
565
|
+
rejectAdditionalProperties(args, new Set(['job', 'operator_id', 'service_kind', 'quoted_at', 'expires_at', 'price_amount', 'asset', 'capacity_ref', 'capacity_profile', 'terms_ref']), name);
|
|
566
|
+
optionalPlainObject(args, 'job', name);
|
|
567
|
+
optionalPlainObject(args, 'capacity_profile', name);
|
|
568
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
569
|
+
requireString(args, 'operator_id', name);
|
|
570
|
+
requireString(args, 'service_kind', name);
|
|
571
|
+
optionalString(args, 'quoted_at', name);
|
|
572
|
+
requireString(args, 'expires_at', name);
|
|
573
|
+
requireNumber(args, 'price_amount', name);
|
|
574
|
+
optionalString(args, 'asset', name);
|
|
575
|
+
if (args.capacity_profile === undefined) requireString(args, 'capacity_ref', name);
|
|
576
|
+
requireString(args, 'terms_ref', name);
|
|
577
|
+
return args;
|
|
578
|
+
case 'enigma_settlement_receipt':
|
|
579
|
+
rejectAdditionalProperties(args, new Set(['job', 'quote', 'completed_at', 'settled_amount', 'settlement_ref', 'service_receipt_ref']), name);
|
|
580
|
+
optionalPlainObject(args, 'job', name);
|
|
581
|
+
optionalPlainObject(args, 'quote', name);
|
|
582
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
583
|
+
if (args.quote === undefined) throw invalidParams(`${name} requires quote as an object.`);
|
|
584
|
+
optionalString(args, 'completed_at', name);
|
|
585
|
+
requireNumber(args, 'settled_amount', name);
|
|
586
|
+
requireString(args, 'settlement_ref', name);
|
|
587
|
+
requireString(args, 'service_receipt_ref', name);
|
|
588
|
+
return args;
|
|
589
|
+
case 'enigma_settlement_verify':
|
|
590
|
+
rejectAdditionalProperties(args, new Set(['job', 'quote', 'receipt']), name);
|
|
591
|
+
optionalPlainObject(args, 'job', name);
|
|
592
|
+
optionalPlainObject(args, 'quote', name);
|
|
593
|
+
optionalPlainObject(args, 'receipt', name);
|
|
594
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
595
|
+
if (args.quote === undefined) throw invalidParams(`${name} requires quote as an object.`);
|
|
596
|
+
if (args.receipt === undefined) throw invalidParams(`${name} requires receipt as an object.`);
|
|
597
|
+
return args;
|
|
598
|
+
case 'enigma_settlement_batch':
|
|
599
|
+
rejectAdditionalProperties(args, new Set(['receipts', 'asset', 'batch_ref', 'generated_at']), name);
|
|
600
|
+
optionalObjectArray(args, 'receipts', name);
|
|
601
|
+
if (args.receipts === undefined) throw invalidParams(`${name} requires receipts as an array.`);
|
|
602
|
+
optionalString(args, 'asset', name);
|
|
603
|
+
requireString(args, 'batch_ref', name);
|
|
604
|
+
optionalString(args, 'generated_at', name);
|
|
605
|
+
return args;
|
|
606
|
+
case 'enigma_vault_create_record':
|
|
607
|
+
rejectAdditionalProperties(args, new Set(['plaintext', 'metadata']), name);
|
|
608
|
+
requireString(args, 'plaintext', name);
|
|
609
|
+
optionalPlainObject(args, 'metadata', name);
|
|
610
|
+
return args;
|
|
611
|
+
case 'enigma_vault_zeroize_record':
|
|
612
|
+
rejectAdditionalProperties(args, new Set(['recordId']), name);
|
|
613
|
+
requireString(args, 'recordId', name);
|
|
614
|
+
return args;
|
|
615
|
+
case 'enigma_verify_erasure_attestation':
|
|
616
|
+
rejectAdditionalProperties(args, new Set(['attestation', 'allowSimulated', 'expectedPcr']), name);
|
|
617
|
+
optionalPlainObject(args, 'attestation', name);
|
|
618
|
+
optionalBoolean(args, 'allowSimulated', name);
|
|
619
|
+
optionalString(args, 'expectedPcr', name);
|
|
620
|
+
if (!args.attestation) throw invalidParams(`${name} requires attestation object.`);
|
|
621
|
+
return args;
|
|
622
|
+
case 'enigma_nullifier_record_tombstone':
|
|
623
|
+
rejectAdditionalProperties(args, new Set(['commitment', 'nullifierHash', 'ownerPubkey']), name);
|
|
624
|
+
requireString(args, 'commitment', name);
|
|
625
|
+
requireString(args, 'nullifierHash', name);
|
|
626
|
+
requireString(args, 'ownerPubkey', name);
|
|
627
|
+
return args;
|
|
628
|
+
default:
|
|
629
|
+
throw invalidParams('Unknown tool.');
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
function validatePromptArguments(args) {
|
|
634
|
+
if (args === undefined) return undefined;
|
|
635
|
+
if (!isPlainObject(args)) throw invalidParams('prompts/get arguments must be an object.');
|
|
636
|
+
rejectAdditionalProperties(args, new Set(['question', 'purpose']), 'prompts/get arguments');
|
|
637
|
+
optionalString(args, 'question', 'prompts/get arguments');
|
|
638
|
+
optionalString(args, 'purpose', 'prompts/get arguments');
|
|
639
|
+
return args;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function remoteToolDescriptors() {
|
|
643
|
+
assertRemoteToolPolicyCoverage(toolDescriptors);
|
|
644
|
+
return toolDescriptors.map((descriptor) => {
|
|
645
|
+
const policy = remoteToolPolicy(descriptor.name);
|
|
646
|
+
const forbidden = new Set(policy.clientForbiddenFields);
|
|
647
|
+
const schema = descriptor.inputSchema;
|
|
648
|
+
if (!schema?.properties || forbidden.size === 0) return descriptor;
|
|
649
|
+
const properties = Object.fromEntries(Object.entries(schema.properties).filter(([name]) => !forbidden.has(name)));
|
|
650
|
+
const required = Array.isArray(schema.required) ? schema.required.filter((name) => !forbidden.has(name)) : undefined;
|
|
651
|
+
return {
|
|
652
|
+
...descriptor,
|
|
653
|
+
inputSchema: {
|
|
654
|
+
...schema,
|
|
655
|
+
properties,
|
|
656
|
+
...(required === undefined ? {} : { required }),
|
|
657
|
+
},
|
|
658
|
+
};
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function assertNestedTenantBinding(value, tenantId, { required = false } = {}) {
|
|
663
|
+
let found = 0;
|
|
664
|
+
function visit(candidate) {
|
|
665
|
+
if (Array.isArray(candidate)) {
|
|
666
|
+
candidate.forEach(visit);
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (!isPlainObject(candidate)) return;
|
|
670
|
+
for (const [key, child] of Object.entries(candidate)) {
|
|
671
|
+
if (key === 'tenant_id' || key === 'tenantId') {
|
|
672
|
+
found += 1;
|
|
673
|
+
if (child !== tenantId) throw invalidParams('Remote MCP settlement or metering input belongs to a different tenant.');
|
|
674
|
+
}
|
|
675
|
+
visit(child);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
visit(value);
|
|
679
|
+
if (required && found === 0) throw invalidParams('Remote MCP input does not contain the server-bound tenant.');
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
async function bindRemoteToolArguments(name, args, context) {
|
|
683
|
+
if (context.transport !== 'streamable-http') return args;
|
|
684
|
+
if (!isPlainObject(args)) throw invalidParams('tools/call arguments must be an object.');
|
|
685
|
+
const policy = remoteToolPolicy(name);
|
|
686
|
+
if (!policy) throw invalidParams('Remote MCP policy is missing for this tool.');
|
|
687
|
+
const forbidden = Object.keys(args).find((key) => policy.clientForbiddenFields.includes(key));
|
|
688
|
+
if (forbidden) throw invalidParams(`Remote MCP does not accept client-controlled ${forbidden}.`);
|
|
689
|
+
const requiresBinding = policy.vaultBinding !== 'none' || policy.tenantBinding !== 'none';
|
|
690
|
+
let binding = null;
|
|
691
|
+
if (requiresBinding) {
|
|
692
|
+
if (typeof context.resolveVaultContext !== 'function') throw new Error('remote tenant and vault resolver is not configured');
|
|
693
|
+
binding = await context.resolveVaultContext(context.principal);
|
|
694
|
+
if (!isPlainObject(binding) || typeof binding.tenant_id !== 'string' || !binding.tenant_id) {
|
|
695
|
+
throw new Error('remote tenant and vault resolver returned an invalid binding');
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
let bound = { ...args };
|
|
699
|
+
if (policy.vaultBinding !== 'none') {
|
|
700
|
+
if (typeof binding.bundlePath !== 'string' || !binding.bundlePath) throw new Error('remote vault resolver returned no bundle path');
|
|
701
|
+
bound.bundlePath = binding.bundlePath;
|
|
702
|
+
if (name === 'enigma_init') {
|
|
703
|
+
bound = {
|
|
704
|
+
...bound,
|
|
705
|
+
tenant_id: binding.tenant_id,
|
|
706
|
+
subject_id: String(binding.subject_id || ''),
|
|
707
|
+
actor_id: String(binding.actor_id || ''),
|
|
708
|
+
policy_id: String(binding.policy_id || ''),
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
if (name === 'enigma_search' || name === 'enigma_context_pack') bound.allowOldEpochReads = false;
|
|
712
|
+
Object.defineProperty(bound, REMOTE_SECURE_VAULT, { value: true, enumerable: true });
|
|
713
|
+
}
|
|
714
|
+
if (policy.tenantBinding === 'inject') {
|
|
715
|
+
if (name === 'enigma_meter_usage' && Array.isArray(bound.events)) {
|
|
716
|
+
assertNestedTenantBinding(bound.events, binding.tenant_id, { required: true });
|
|
717
|
+
}
|
|
718
|
+
bound.tenant_id = binding.tenant_id;
|
|
719
|
+
} else if (policy.tenantBinding === 'validate_nested') {
|
|
720
|
+
assertNestedTenantBinding(bound, binding.tenant_id, { required: true });
|
|
721
|
+
}
|
|
722
|
+
return validateToolArguments(name, bound);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
async function bindRemoteResourceInput(params, normalizedUri, context) {
|
|
726
|
+
if (context.transport !== 'streamable-http' || normalizedUri !== PASSPORT_SUMMARY_RESOURCE_URI) return inputWithBundlePath(params);
|
|
727
|
+
const forbiddenFields = new Set(['bundlePath', 'bundle_path', 'insecureDevMode', 'insecure_dev_mode']);
|
|
728
|
+
const parsed = new URL(String(params.uri));
|
|
729
|
+
const forbiddenQuery = [...parsed.searchParams.keys()].find((key) => forbiddenFields.has(key));
|
|
730
|
+
const forbiddenProperty = Object.keys(params).find((key) => forbiddenFields.has(key));
|
|
731
|
+
if (forbiddenQuery || forbiddenProperty) throw invalidParams(`Remote MCP does not accept client-controlled ${forbiddenQuery || forbiddenProperty}.`);
|
|
732
|
+
if (typeof context.resolveVaultContext !== 'function') throw new Error('remote vault resolver is not configured');
|
|
733
|
+
const binding = await context.resolveVaultContext(context.principal);
|
|
734
|
+
if (!isPlainObject(binding) || typeof binding.bundlePath !== 'string' || !binding.bundlePath) {
|
|
735
|
+
throw new Error('remote vault resolver returned an invalid binding');
|
|
736
|
+
}
|
|
737
|
+
const bound = { uri: params.uri, bundlePath: binding.bundlePath };
|
|
738
|
+
Object.defineProperty(bound, REMOTE_SECURE_VAULT, { value: true, enumerable: true });
|
|
739
|
+
return bound;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
function sanitizeRemoteCustodyOutput(value, context) {
|
|
743
|
+
if (context.transport !== 'streamable-http' || !value || typeof value !== 'object' || Buffer.isBuffer(value) || value instanceof Uint8Array) return value;
|
|
744
|
+
if (Array.isArray(value)) return value.map((item) => sanitizeRemoteCustodyOutput(item, context));
|
|
745
|
+
const sanitized = {};
|
|
746
|
+
for (const [key, item] of Object.entries(value)) {
|
|
747
|
+
if (key === 'bundlePath' || key === 'bundle_path') continue;
|
|
748
|
+
sanitized[key] = sanitizeRemoteCustodyOutput(item, context);
|
|
749
|
+
}
|
|
750
|
+
return sanitized;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function sanitizeOperationalError(error) {
|
|
754
|
+
return {
|
|
755
|
+
ok: false,
|
|
756
|
+
error: 'Tool execution failed.',
|
|
757
|
+
error_name: typeof error?.name === 'string' ? error.name : 'Error',
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function mcpImmuneIngressCandidates(input) {
|
|
762
|
+
if (!isPlainObject(input)) return input;
|
|
763
|
+
if (Object.prototype.hasOwnProperty.call(input, 'candidates')) return input.candidates;
|
|
764
|
+
if (Object.prototype.hasOwnProperty.call(input, 'candidate')) return input.candidate;
|
|
765
|
+
if (Object.prototype.hasOwnProperty.call(input, 'memory_candidates')) return input.memory_candidates;
|
|
766
|
+
if (Object.prototype.hasOwnProperty.call(input, 'memoryCandidates')) return input.memoryCandidates;
|
|
767
|
+
return input;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function mcpImmuneIngressOptions(input, options = {}) {
|
|
771
|
+
return {
|
|
772
|
+
...options,
|
|
773
|
+
now: options.now ?? input?.now ?? input?.generated_at ?? input?.generatedAt,
|
|
774
|
+
source_type: options.source_type ?? options.sourceType ?? 'mcp_candidate_ingress',
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
export function createMcpImmuneIngressReport(input = {}, options = {}) {
|
|
779
|
+
return createImmuneIngressReport(mcpImmuneIngressCandidates(input), mcpImmuneIngressOptions(input, options));
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
export function assertMcpImmuneIngressPublicSafe(input = {}, options = {}) {
|
|
783
|
+
return assertImmuneIngressPublicSafe(mcpImmuneIngressCandidates(input), mcpImmuneIngressOptions(input, options));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
export const toolDescriptors = [
|
|
788
|
+
{
|
|
789
|
+
name: 'enigma_private_handoff_health',
|
|
790
|
+
description: 'Check whether the local Enigma private workspace is reachable. This diagnostic never accepts or returns a user prompt.',
|
|
791
|
+
inputSchema: {
|
|
792
|
+
type: 'object',
|
|
793
|
+
properties: {},
|
|
794
|
+
additionalProperties: false,
|
|
795
|
+
},
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
name: 'enigma_routing_contract',
|
|
799
|
+
description: 'Explain when an MCP host must use an Enigma private-session handoff instead of relaying prompt text through host-visible tool arguments.',
|
|
800
|
+
inputSchema: {
|
|
801
|
+
type: 'object',
|
|
802
|
+
properties: {},
|
|
803
|
+
additionalProperties: false,
|
|
804
|
+
},
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
name: 'enigma_start_private_session',
|
|
808
|
+
description: 'Open the Enigma private workspace for sensitive prompts. Pass only a non-sensitive intent label; the actual prompt must be typed inside Enigma and never placed in this tool call.',
|
|
809
|
+
inputSchema: {
|
|
810
|
+
type: 'object',
|
|
811
|
+
properties: {
|
|
812
|
+
intent: {
|
|
813
|
+
type: 'string',
|
|
814
|
+
maxLength: 160,
|
|
815
|
+
description: 'Optional non-sensitive handoff label such as "private legal question". Never include the actual private prompt.',
|
|
816
|
+
},
|
|
817
|
+
model: {
|
|
818
|
+
type: 'string',
|
|
819
|
+
maxLength: 160,
|
|
820
|
+
description: 'Optional configured Enigma model route to preselect.',
|
|
821
|
+
},
|
|
822
|
+
},
|
|
823
|
+
additionalProperties: false,
|
|
824
|
+
},
|
|
825
|
+
_meta: {
|
|
826
|
+
'openai/outputTemplate': PRIVATE_SESSION_RESOURCE_URI,
|
|
827
|
+
'ui/resourceUri': PRIVATE_SESSION_RESOURCE_URI,
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
name: 'enigma_complete',
|
|
832
|
+
description: 'Run a direct Enigma completion with Smart Privacy and explicit route disclosure. MCP tool arguments are visible to the MCP host; use enigma_start_private_session when the prompt must remain outside host chat.',
|
|
833
|
+
inputSchema: {
|
|
834
|
+
type: 'object',
|
|
835
|
+
properties: {
|
|
836
|
+
messages: {
|
|
837
|
+
type: 'array',
|
|
838
|
+
minItems: 1,
|
|
839
|
+
maxItems: 128,
|
|
840
|
+
items: {
|
|
841
|
+
type: 'object',
|
|
842
|
+
properties: {
|
|
843
|
+
role: { type: 'string', enum: ['system', 'user', 'assistant', 'tool'] },
|
|
844
|
+
content: { type: 'string', maxLength: 100000 },
|
|
845
|
+
},
|
|
846
|
+
required: ['role', 'content'],
|
|
847
|
+
additionalProperties: false,
|
|
848
|
+
},
|
|
849
|
+
},
|
|
850
|
+
model: { type: 'string', default: 'enigma-auto' },
|
|
851
|
+
privacy_mode: { type: 'string', enum: ['off', 'smart', 'full'], default: 'smart' },
|
|
852
|
+
temperature: { type: 'number', minimum: 0, maximum: 2 },
|
|
853
|
+
max_tokens: { type: 'integer', minimum: 1, maximum: 131072 },
|
|
854
|
+
reasoning_effort: { type: 'string', enum: ['none', 'low', 'medium', 'high'] },
|
|
855
|
+
web_search: { type: 'boolean', default: false },
|
|
856
|
+
require_private_route: { type: 'boolean', default: false },
|
|
857
|
+
},
|
|
858
|
+
required: ['messages'],
|
|
859
|
+
additionalProperties: false,
|
|
860
|
+
},
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
name: 'enigma_generate_image',
|
|
864
|
+
description: 'Generate image assets through a configured Enigma image route. The prompt is sent only to that configured route and is not retained in the MCP receipt.',
|
|
865
|
+
inputSchema: {
|
|
866
|
+
type: 'object',
|
|
867
|
+
properties: {
|
|
868
|
+
prompt: { type: 'string', maxLength: 16000 },
|
|
869
|
+
model: { type: 'string', maxLength: 160 },
|
|
870
|
+
negative_prompt: { type: 'string', maxLength: 8000 },
|
|
871
|
+
width: { type: 'integer', minimum: 256, maximum: 2048, default: 1024 },
|
|
872
|
+
height: { type: 'integer', minimum: 256, maximum: 2048, default: 1024 },
|
|
873
|
+
steps: { type: 'integer', minimum: 1, maximum: 100, default: 30 },
|
|
874
|
+
cfg_scale: { type: 'number', minimum: 1, maximum: 30, default: 7.5 },
|
|
875
|
+
variants: { type: 'integer', minimum: 1, maximum: 4, default: 1 },
|
|
876
|
+
format: { type: 'string', enum: ['png', 'jpeg', 'webp'], default: 'webp' },
|
|
877
|
+
seed: { type: 'integer', minimum: 0, maximum: 2147483647 },
|
|
878
|
+
},
|
|
879
|
+
required: ['prompt', 'model'],
|
|
880
|
+
additionalProperties: false,
|
|
881
|
+
},
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
name: 'enigma_x402_execute',
|
|
885
|
+
description: 'Execute an x402 v2 paid HTTP request using the configured real wallet signer, strict recipient/network/asset allowlists, and an atomic-unit budget. This moves funds; inspect the server offer before calling.',
|
|
886
|
+
inputSchema: {
|
|
887
|
+
type: 'object',
|
|
888
|
+
properties: {
|
|
889
|
+
url: { type: 'string', maxLength: 4096 },
|
|
890
|
+
method: { type: 'string', enum: ['GET', 'POST'], default: 'GET' },
|
|
891
|
+
headers: {
|
|
892
|
+
type: 'object',
|
|
893
|
+
description: 'Only Accept, Content-Type, and Idempotency-Key are allowed.',
|
|
894
|
+
additionalProperties: { type: 'string', maxLength: 4096 },
|
|
895
|
+
},
|
|
896
|
+
body: { anyOf: [{ type: 'string' }, { type: 'object' }] },
|
|
897
|
+
max_response_bytes: { type: 'integer', minimum: 1024, maximum: 1048576, default: 262144 },
|
|
898
|
+
},
|
|
899
|
+
required: ['url'],
|
|
900
|
+
additionalProperties: false,
|
|
901
|
+
},
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
name: 'enigma_init',
|
|
905
|
+
description: 'Create a local Enigma vault bundle when one does not already exist.',
|
|
906
|
+
inputSchema: {
|
|
907
|
+
type: 'object',
|
|
908
|
+
properties: {
|
|
909
|
+
bundlePath: { type: 'string' },
|
|
910
|
+
tenant_id: { type: 'string' },
|
|
911
|
+
subject_id: { type: 'string' },
|
|
912
|
+
actor_id: { type: 'string' },
|
|
913
|
+
policy_id: { type: 'string' },
|
|
914
|
+
insecureDevMode: { type: 'boolean', description: 'Explicitly allow a plaintext disposable development bundle when no server passphrase is configured.' },
|
|
915
|
+
},
|
|
916
|
+
additionalProperties: false,
|
|
917
|
+
},
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
name: 'enigma_remember',
|
|
921
|
+
description: 'Store a memory in the local Enigma vault and emit a receipt without using provider-native memory as canonical state.',
|
|
922
|
+
inputSchema: {
|
|
923
|
+
type: 'object',
|
|
924
|
+
properties: {
|
|
925
|
+
bundlePath: { type: 'string' },
|
|
926
|
+
text: { type: 'string' },
|
|
927
|
+
purpose: { type: 'string' },
|
|
928
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
929
|
+
metadata: { type: 'object' },
|
|
930
|
+
insecureDevMode: { type: 'boolean' },
|
|
931
|
+
},
|
|
932
|
+
required: ['text'],
|
|
933
|
+
additionalProperties: false,
|
|
934
|
+
},
|
|
935
|
+
},
|
|
936
|
+
{
|
|
937
|
+
name: 'enigma_search',
|
|
938
|
+
description: 'Search active local Enigma memories by query, or recall one memory by address when memory_addr is supplied.',
|
|
939
|
+
inputSchema: {
|
|
940
|
+
type: 'object',
|
|
941
|
+
properties: {
|
|
942
|
+
bundlePath: { type: 'string' },
|
|
943
|
+
query: { type: 'string' },
|
|
944
|
+
memory_addr: { type: 'string' },
|
|
945
|
+
purpose: { type: 'string' },
|
|
946
|
+
limit: { type: 'integer', minimum: 1, maximum: 50 },
|
|
947
|
+
insecureDevMode: { type: 'boolean' },
|
|
948
|
+
allowOldEpochReads: { type: 'boolean' },
|
|
949
|
+
},
|
|
950
|
+
additionalProperties: false,
|
|
951
|
+
},
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
name: 'enigma_context_pack',
|
|
955
|
+
description: 'Compile an MCP-safe context pack from active local memories and emit retrieval/injection receipts.',
|
|
956
|
+
inputSchema: {
|
|
957
|
+
type: 'object',
|
|
958
|
+
properties: {
|
|
959
|
+
bundlePath: { type: 'string' },
|
|
960
|
+
query: { type: 'string' },
|
|
961
|
+
purpose: { type: 'string' },
|
|
962
|
+
limit: { type: 'integer', minimum: 1, maximum: 50 },
|
|
963
|
+
memory_addresses: { type: 'array', items: { type: 'string' } },
|
|
964
|
+
optimize: { type: 'boolean' },
|
|
965
|
+
max_estimated_tokens: { type: 'number', minimum: 0 },
|
|
966
|
+
price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
967
|
+
currency: { type: 'string' },
|
|
968
|
+
insecureDevMode: { type: 'boolean' },
|
|
969
|
+
allowOldEpochReads: { type: 'boolean' },
|
|
970
|
+
},
|
|
971
|
+
additionalProperties: false,
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: 'enigma_delete',
|
|
976
|
+
description: 'Tombstone an Enigma memory so it is not served in future context packs.',
|
|
977
|
+
inputSchema: {
|
|
978
|
+
type: 'object',
|
|
979
|
+
properties: {
|
|
980
|
+
bundlePath: { type: 'string' },
|
|
981
|
+
memory_addr: { type: 'string' },
|
|
982
|
+
reason: { type: 'string' },
|
|
983
|
+
insecureDevMode: { type: 'boolean' },
|
|
984
|
+
},
|
|
985
|
+
required: ['memory_addr'],
|
|
986
|
+
additionalProperties: false,
|
|
987
|
+
},
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
name: 'enigma_vault_rotate',
|
|
991
|
+
description: 'Rotate to a new content-key epoch while honestly retaining prior keys for authorized historical reads.',
|
|
992
|
+
inputSchema: {
|
|
993
|
+
type: 'object',
|
|
994
|
+
properties: {
|
|
995
|
+
bundlePath: { type: 'string' },
|
|
996
|
+
key_id: { type: 'string' },
|
|
997
|
+
insecureDevMode: { type: 'boolean' },
|
|
998
|
+
},
|
|
999
|
+
additionalProperties: false,
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
name: 'enigma_vault_seal',
|
|
1004
|
+
description: 'Seal a content-key epoch against future writes while retaining its key for policy-authorized reads.',
|
|
1005
|
+
inputSchema: {
|
|
1006
|
+
type: 'object',
|
|
1007
|
+
properties: {
|
|
1008
|
+
bundlePath: { type: 'string' },
|
|
1009
|
+
epoch: { type: 'integer', minimum: 1 },
|
|
1010
|
+
insecureDevMode: { type: 'boolean' },
|
|
1011
|
+
},
|
|
1012
|
+
additionalProperties: false,
|
|
1013
|
+
},
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: 'enigma_vault_reset',
|
|
1017
|
+
description: 'Perform a software content-key reset, remove local records, and emit signed evidence without claiming physical-media, backup, or external-copy erasure.',
|
|
1018
|
+
inputSchema: {
|
|
1019
|
+
type: 'object',
|
|
1020
|
+
properties: {
|
|
1021
|
+
bundlePath: { type: 'string' },
|
|
1022
|
+
key_id: { type: 'string' },
|
|
1023
|
+
insecureDevMode: { type: 'boolean' },
|
|
1024
|
+
},
|
|
1025
|
+
additionalProperties: false,
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
name: 'enigma_verify_receipts',
|
|
1030
|
+
description: 'Verify receipts/checkpoints in a local or exported Enigma bundle and return a machine-readable verdict.',
|
|
1031
|
+
inputSchema: {
|
|
1032
|
+
type: 'object',
|
|
1033
|
+
properties: {
|
|
1034
|
+
bundlePath: { type: 'string' },
|
|
1035
|
+
bundle: { type: 'object' },
|
|
1036
|
+
},
|
|
1037
|
+
additionalProperties: false,
|
|
1038
|
+
},
|
|
1039
|
+
},
|
|
1040
|
+
{
|
|
1041
|
+
name: 'enigma_swarm_register_agent',
|
|
1042
|
+
description: 'Register an agent in a local swarm domain with a namespace fence and explicit permission mask.',
|
|
1043
|
+
inputSchema: {
|
|
1044
|
+
type: 'object',
|
|
1045
|
+
properties: {
|
|
1046
|
+
bundlePath: { type: 'string' },
|
|
1047
|
+
agent_id: { type: 'string' },
|
|
1048
|
+
swarm_id: { type: 'string' },
|
|
1049
|
+
namespace: { type: 'string' },
|
|
1050
|
+
permission_mask: {
|
|
1051
|
+
oneOf: [
|
|
1052
|
+
{ type: 'integer', minimum: 0, maximum: 63 },
|
|
1053
|
+
{ type: 'string' },
|
|
1054
|
+
{ type: 'array', items: { type: 'string' } },
|
|
1055
|
+
],
|
|
1056
|
+
},
|
|
1057
|
+
},
|
|
1058
|
+
required: ['agent_id'],
|
|
1059
|
+
additionalProperties: false,
|
|
1060
|
+
},
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
name: 'enigma_graph_query',
|
|
1064
|
+
description: 'Traverse the namespace-fenced local memory entity graph, including cross-atom associative links.',
|
|
1065
|
+
inputSchema: {
|
|
1066
|
+
type: 'object',
|
|
1067
|
+
properties: {
|
|
1068
|
+
bundlePath: { type: 'string' },
|
|
1069
|
+
agent_id: { type: 'string' },
|
|
1070
|
+
swarm_id: { type: 'string' },
|
|
1071
|
+
namespace: { type: 'string' },
|
|
1072
|
+
start: { type: 'string' },
|
|
1073
|
+
entity_id: { type: 'string' },
|
|
1074
|
+
query: { type: 'string' },
|
|
1075
|
+
max_depth: { type: 'integer', minimum: 0, maximum: 12 },
|
|
1076
|
+
limit: { type: 'integer', minimum: 1, maximum: 500 },
|
|
1077
|
+
direction: { type: 'string' },
|
|
1078
|
+
},
|
|
1079
|
+
required: ['agent_id'],
|
|
1080
|
+
additionalProperties: false,
|
|
1081
|
+
},
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
name: 'enigma_cluster_memories',
|
|
1085
|
+
description: 'Group active namespace-fenced memories by semantic proximity and return committed centroid fingerprints.',
|
|
1086
|
+
inputSchema: {
|
|
1087
|
+
type: 'object',
|
|
1088
|
+
properties: {
|
|
1089
|
+
bundlePath: { type: 'string' },
|
|
1090
|
+
agent_id: { type: 'string' },
|
|
1091
|
+
swarm_id: { type: 'string' },
|
|
1092
|
+
namespace: { type: 'string' },
|
|
1093
|
+
threshold: { type: 'number', minimum: 0, maximum: 1 },
|
|
1094
|
+
max_clusters: { type: 'integer', minimum: 1, maximum: 100 },
|
|
1095
|
+
},
|
|
1096
|
+
required: ['agent_id'],
|
|
1097
|
+
additionalProperties: false,
|
|
1098
|
+
},
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
name: 'enigma_swarm_sync',
|
|
1102
|
+
description: 'Create or validate an opt-in local gossip simulation using Merkle diffs; no network transmission occurs and raw content is excluded by default.',
|
|
1103
|
+
inputSchema: {
|
|
1104
|
+
type: 'object',
|
|
1105
|
+
properties: {
|
|
1106
|
+
bundlePath: { type: 'string' },
|
|
1107
|
+
agent_id: { type: 'string' },
|
|
1108
|
+
swarm_id: { type: 'string' },
|
|
1109
|
+
namespace: { type: 'string' },
|
|
1110
|
+
snapshot: { type: 'object' },
|
|
1111
|
+
apply: { type: 'boolean' },
|
|
1112
|
+
include_content: { type: 'boolean' },
|
|
1113
|
+
allow_content: { type: 'boolean' },
|
|
1114
|
+
},
|
|
1115
|
+
required: ['agent_id'],
|
|
1116
|
+
additionalProperties: false,
|
|
1117
|
+
},
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
name: 'enigma_immune_ingress',
|
|
1121
|
+
description: 'Scan MCP-supplied memory candidate objects and return a public-safe immune quarantine report with opaque refs only.',
|
|
1122
|
+
inputSchema: {
|
|
1123
|
+
type: 'object',
|
|
1124
|
+
properties: {
|
|
1125
|
+
candidate: { type: 'object' },
|
|
1126
|
+
candidates: { type: 'array', items: { type: 'object' } },
|
|
1127
|
+
generated_at: { type: 'string' },
|
|
1128
|
+
now: { type: 'string' },
|
|
1129
|
+
},
|
|
1130
|
+
additionalProperties: false,
|
|
1131
|
+
},
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
name: 'enigma_meter_usage',
|
|
1135
|
+
description: 'Create content-minimized memory usage events or aggregate supplied usage events without raw prompts or provider responses.',
|
|
1136
|
+
inputSchema: {
|
|
1137
|
+
type: 'object',
|
|
1138
|
+
properties: {
|
|
1139
|
+
events: { type: 'array', items: { type: 'object' } },
|
|
1140
|
+
tenant_id: { type: 'string' },
|
|
1141
|
+
meter_id: { type: 'string' },
|
|
1142
|
+
provider: { type: 'string' },
|
|
1143
|
+
model: { type: 'string' },
|
|
1144
|
+
operation: { type: 'string' },
|
|
1145
|
+
timestamp: { type: 'string' },
|
|
1146
|
+
generated_at: { type: 'string' },
|
|
1147
|
+
prompt_tokens: { type: 'number', minimum: 0 },
|
|
1148
|
+
completion_tokens: { type: 'number', minimum: 0 },
|
|
1149
|
+
memory_baseline_tokens: { type: 'number', minimum: 0 },
|
|
1150
|
+
memory_optimized_tokens: { type: 'number', minimum: 0 },
|
|
1151
|
+
currency: { type: 'string' },
|
|
1152
|
+
input_price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
1153
|
+
output_price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
1154
|
+
price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
1155
|
+
},
|
|
1156
|
+
additionalProperties: false,
|
|
1157
|
+
},
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
name: 'enigma_settlement_job',
|
|
1161
|
+
description: 'Create a permissionless hash-only memory service job for settlement rails.',
|
|
1162
|
+
inputSchema: {
|
|
1163
|
+
type: 'object',
|
|
1164
|
+
properties: {
|
|
1165
|
+
tenant_id: { type: 'string' },
|
|
1166
|
+
job_type: { type: 'string' },
|
|
1167
|
+
memory_commitment_root: { type: 'string' },
|
|
1168
|
+
policy_hash: { type: 'string' },
|
|
1169
|
+
usage_event_hash: { type: 'string' },
|
|
1170
|
+
requested_at: { type: 'string' },
|
|
1171
|
+
expires_at: { type: 'string' },
|
|
1172
|
+
max_price_amount: { type: 'number' },
|
|
1173
|
+
payment_asset: { type: 'string' },
|
|
1174
|
+
},
|
|
1175
|
+
required: ['tenant_id', 'job_type', 'memory_commitment_root', 'policy_hash', 'usage_event_hash', 'expires_at', 'max_price_amount'],
|
|
1176
|
+
additionalProperties: false,
|
|
1177
|
+
},
|
|
1178
|
+
},
|
|
1179
|
+
{
|
|
1180
|
+
name: 'enigma_settlement_capacity',
|
|
1181
|
+
description: 'Create a consumer/workstation GPU memory-optimizer capacity profile for permissionless discovery and settlement without raw-memory decentralization claims.',
|
|
1182
|
+
inputSchema: {
|
|
1183
|
+
type: 'object',
|
|
1184
|
+
properties: {
|
|
1185
|
+
operator_id: { type: 'string' },
|
|
1186
|
+
accelerator_class: { type: 'string' },
|
|
1187
|
+
hardware_ref: { type: 'string' },
|
|
1188
|
+
region: { type: 'string' },
|
|
1189
|
+
model_family: { type: 'string' },
|
|
1190
|
+
model_refs: { type: 'array', items: { type: 'string' } },
|
|
1191
|
+
observed_at: { type: 'string' },
|
|
1192
|
+
expires_at: { type: 'string' },
|
|
1193
|
+
vram_gb: { type: 'number' },
|
|
1194
|
+
max_context_window_tokens: { type: 'number' },
|
|
1195
|
+
available_context_tokens_per_minute: { type: 'number' },
|
|
1196
|
+
p95_latency_ms: { type: 'number' },
|
|
1197
|
+
price_per_million_context_tokens: { type: 'number' },
|
|
1198
|
+
asset: { type: 'string' },
|
|
1199
|
+
capacity_ref: { type: 'string' },
|
|
1200
|
+
terms_ref: { type: 'string' },
|
|
1201
|
+
},
|
|
1202
|
+
required: ['operator_id', 'accelerator_class', 'hardware_ref', 'region', 'model_family', 'model_refs', 'expires_at', 'vram_gb', 'max_context_window_tokens', 'available_context_tokens_per_minute', 'p95_latency_ms', 'price_per_million_context_tokens', 'capacity_ref', 'terms_ref'],
|
|
1203
|
+
additionalProperties: false,
|
|
1204
|
+
},
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
name: 'enigma_settlement_quote',
|
|
1208
|
+
description: 'Create an operator quote for a permissionless memory service job.',
|
|
1209
|
+
inputSchema: {
|
|
1210
|
+
type: 'object',
|
|
1211
|
+
properties: {
|
|
1212
|
+
job: { type: 'object' },
|
|
1213
|
+
operator_id: { type: 'string' },
|
|
1214
|
+
service_kind: { type: 'string' },
|
|
1215
|
+
quoted_at: { type: 'string' },
|
|
1216
|
+
expires_at: { type: 'string' },
|
|
1217
|
+
price_amount: { type: 'number' },
|
|
1218
|
+
asset: { type: 'string' },
|
|
1219
|
+
capacity_ref: { type: 'string' },
|
|
1220
|
+
capacity_profile: { type: 'object' },
|
|
1221
|
+
terms_ref: { type: 'string' },
|
|
1222
|
+
},
|
|
1223
|
+
required: ['job', 'operator_id', 'service_kind', 'expires_at', 'price_amount', 'terms_ref'],
|
|
1224
|
+
additionalProperties: false,
|
|
1225
|
+
},
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
name: 'enigma_settlement_receipt',
|
|
1229
|
+
description: 'Create a service settlement receipt linking job, quote, usage hash, memory root, policy hash, service receipt, and settlement ref.',
|
|
1230
|
+
inputSchema: {
|
|
1231
|
+
type: 'object',
|
|
1232
|
+
properties: {
|
|
1233
|
+
job: { type: 'object' },
|
|
1234
|
+
quote: { type: 'object' },
|
|
1235
|
+
completed_at: { type: 'string' },
|
|
1236
|
+
settled_amount: { type: 'number' },
|
|
1237
|
+
settlement_ref: { type: 'string' },
|
|
1238
|
+
service_receipt_ref: { type: 'string' },
|
|
1239
|
+
},
|
|
1240
|
+
required: ['job', 'quote', 'settled_amount', 'settlement_ref', 'service_receipt_ref'],
|
|
1241
|
+
additionalProperties: false,
|
|
1242
|
+
},
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
name: 'enigma_settlement_verify',
|
|
1246
|
+
description: 'Verify a service settlement receipt against its job and quote.',
|
|
1247
|
+
inputSchema: {
|
|
1248
|
+
type: 'object',
|
|
1249
|
+
properties: {
|
|
1250
|
+
job: { type: 'object' },
|
|
1251
|
+
quote: { type: 'object' },
|
|
1252
|
+
receipt: { type: 'object' },
|
|
1253
|
+
},
|
|
1254
|
+
required: ['job', 'quote', 'receipt'],
|
|
1255
|
+
additionalProperties: false,
|
|
1256
|
+
},
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
name: 'enigma_settlement_batch',
|
|
1260
|
+
description: 'Aggregate service settlement receipts into a hash-only settlement batch without investment or provider-invoice claims.',
|
|
1261
|
+
inputSchema: {
|
|
1262
|
+
type: 'object',
|
|
1263
|
+
properties: {
|
|
1264
|
+
receipts: { type: 'array', items: { type: 'object' } },
|
|
1265
|
+
asset: { type: 'string' },
|
|
1266
|
+
batch_ref: { type: 'string' },
|
|
1267
|
+
generated_at: { type: 'string' },
|
|
1268
|
+
},
|
|
1269
|
+
required: ['receipts', 'batch_ref'],
|
|
1270
|
+
additionalProperties: false,
|
|
1271
|
+
},
|
|
1272
|
+
},
|
|
1273
|
+
// NOTE: enigma_verify_erasure_attestation is intentionally NOT exposed as an MCP
|
|
1274
|
+
// tool. The hardware path pins only the chain root and trusts the leaf public key
|
|
1275
|
+
// without verifying leaf/intermediate signatures, and the TPM path allowlists a
|
|
1276
|
+
// forgeable issuer string — an attacker could obtain valid:true with their own
|
|
1277
|
+
// key. The exported function remains for internal/direct use until real chain +
|
|
1278
|
+
// quote validation lands.
|
|
1279
|
+
{
|
|
1280
|
+
name: 'enigma_nullifier_record_tombstone',
|
|
1281
|
+
description: 'Build an owner-signed Solana record_revocation instruction for a registered Enigma commitment. Returns complete ordered account metas and instruction data; the owner must sign. Records protocol-level revocation/non-use only — not physical deletion of plaintext, backups, or external copies.',
|
|
1282
|
+
inputSchema: {
|
|
1283
|
+
type: 'object',
|
|
1284
|
+
properties: {
|
|
1285
|
+
commitment: { type: 'string', pattern: '^(0x)?[0-9a-fA-F]{64}$' },
|
|
1286
|
+
nullifierHash: { type: 'string', pattern: '^(0x)?[0-9a-fA-F]{64}$' },
|
|
1287
|
+
ownerPubkey: { type: 'string', description: 'Base58 Solana public key of the commitment owner (required signer)' },
|
|
1288
|
+
},
|
|
1289
|
+
required: ['commitment', 'nullifierHash', 'ownerPubkey'],
|
|
1290
|
+
additionalProperties: false,
|
|
1291
|
+
},
|
|
1292
|
+
},
|
|
1293
|
+
];
|
|
1294
|
+
|
|
1295
|
+
const PASSPORT_SUMMARY_RESOURCE_URI = 'enigma://passport/summary';
|
|
1296
|
+
const PRIVATE_SESSION_HANDOFF_RESOURCE_URI = PRIVATE_SESSION_RESOURCE_URI;
|
|
1297
|
+
const STANDARD_MEMORY_PROMPT_NAME = 'enigma_standard_memory_prompt';
|
|
1298
|
+
|
|
1299
|
+
export const resourceDescriptors = [
|
|
1300
|
+
{
|
|
1301
|
+
uri: PASSPORT_SUMMARY_RESOURCE_URI,
|
|
1302
|
+
name: 'Enigma Passport Summary',
|
|
1303
|
+
description: 'MCP-safe Passport and Vault metadata for the local Enigma bundle. Raw memory plaintext is never exposed.',
|
|
1304
|
+
mimeType: 'application/json',
|
|
1305
|
+
},
|
|
1306
|
+
{
|
|
1307
|
+
uri: PRIVATE_SESSION_HANDOFF_RESOURCE_URI,
|
|
1308
|
+
name: 'Enigma Private Session Handoff',
|
|
1309
|
+
description: 'Enigma-branded MCP App handoff. The host sees only non-sensitive handoff metadata; the actual prompt is typed in the local Enigma workspace.',
|
|
1310
|
+
mimeType: 'text/html;profile=mcp-app',
|
|
1311
|
+
},
|
|
1312
|
+
];
|
|
1313
|
+
|
|
1314
|
+
export const promptDescriptors = [
|
|
1315
|
+
{
|
|
1316
|
+
name: STANDARD_MEMORY_PROMPT_NAME,
|
|
1317
|
+
description: 'Standard Enigma memory prompt for provider-neutral, receipt-aware user-specific answers.',
|
|
1318
|
+
arguments: [
|
|
1319
|
+
{
|
|
1320
|
+
name: 'question',
|
|
1321
|
+
description: 'Optional user question the assistant is preparing to answer.',
|
|
1322
|
+
required: false,
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
name: 'purpose',
|
|
1326
|
+
description: 'Optional retrieval purpose to pass when requesting Enigma context.',
|
|
1327
|
+
required: false,
|
|
1328
|
+
},
|
|
1329
|
+
],
|
|
1330
|
+
},
|
|
1331
|
+
];
|
|
1332
|
+
|
|
1333
|
+
function bundlePath(input = {}) {
|
|
1334
|
+
const raw = input.bundlePath ?? input.bundle_path ?? input.bundle ?? process.env.ENIGMA_BUNDLE ?? DEFAULT_BUNDLE;
|
|
1335
|
+
return resolve(String(raw));
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
function bundlePassphrase(input = {}) {
|
|
1339
|
+
const value = input.passphrase ?? input.passPhrase ?? process.env.ENIGMA_PASSPHRASE ?? undefined;
|
|
1340
|
+
if (value !== undefined && String(value).trim().length === 0) throw new Error('ENIGMA_PASSPHRASE is empty');
|
|
1341
|
+
return value === undefined ? undefined : String(value);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function bundleInsecureDevMode(input = {}) {
|
|
1345
|
+
if (input[REMOTE_SECURE_VAULT] === true) return false;
|
|
1346
|
+
return input.insecureDevMode === true
|
|
1347
|
+
|| input.insecure_dev_mode === true
|
|
1348
|
+
|| ['1', 'true'].includes(String(process.env.ENIGMA_INSECURE_DEV_MODE ?? '').toLowerCase());
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
function bundleCredentials(input = {}) {
|
|
1352
|
+
const passphrase = bundlePassphrase(input);
|
|
1353
|
+
const insecureDevMode = bundleInsecureDevMode(input);
|
|
1354
|
+
if (passphrase === undefined && !insecureDevMode) {
|
|
1355
|
+
throw new Error('Persistent MCP vault access requires ENIGMA_PASSPHRASE unless ENIGMA_INSECURE_DEV_MODE=1 is explicitly enabled.');
|
|
1356
|
+
}
|
|
1357
|
+
return {
|
|
1358
|
+
passphrase,
|
|
1359
|
+
insecureDevMode,
|
|
1360
|
+
allowOldEpochReads: input.allowOldEpochReads ?? input.allow_old_epoch_reads,
|
|
1361
|
+
checkpointProvider: input.checkpointProvider ?? configuredCheckpointProvider,
|
|
1362
|
+
requireExternalCheckpoint: input.requireExternalCheckpoint === true
|
|
1363
|
+
|| process.env.ENIGMA_REQUIRE_EXTERNAL_CHECKPOINT === '1',
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
async function readJson(path) {
|
|
1368
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
async function fileExists(path) {
|
|
1372
|
+
try {
|
|
1373
|
+
await access(path);
|
|
1374
|
+
return true;
|
|
1375
|
+
} catch (error) {
|
|
1376
|
+
if (error?.code === 'ENOENT') return false;
|
|
1377
|
+
throw error;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
async function loadState(path, input = {}) {
|
|
1382
|
+
const credentials = bundleCredentials(input);
|
|
1383
|
+
const loaded = await readJsonFileWithRevision(path, credentials);
|
|
1384
|
+
const cacheKey = resolve(String(path));
|
|
1385
|
+
const authTag = credentialCacheTag(credentials);
|
|
1386
|
+
const cached = unlockedVaultCache.get(cacheKey);
|
|
1387
|
+
const policyMatches = credentials.allowOldEpochReads === undefined
|
|
1388
|
+
|| cached?.vault?.allowOldEpochReads === credentials.allowOldEpochReads;
|
|
1389
|
+
if (cached?.revision === loaded.revision && cached.authTag === authTag && policyMatches) {
|
|
1390
|
+
unlockedVaultCache.delete(cacheKey);
|
|
1391
|
+
unlockedVaultCache.set(cacheKey, cached);
|
|
1392
|
+
return { ...cached, stored: loaded.value, revision: loaded.revision };
|
|
1393
|
+
}
|
|
1394
|
+
if (cached) invalidateCachedVault(cacheKey);
|
|
1395
|
+
const imported = importBundle({
|
|
1396
|
+
bundle: loaded.value,
|
|
1397
|
+
...credentials,
|
|
1398
|
+
strict: true,
|
|
1399
|
+
recordImport: false,
|
|
1400
|
+
});
|
|
1401
|
+
const vault = imported.vault;
|
|
1402
|
+
const state = {
|
|
1403
|
+
stored: loaded.value,
|
|
1404
|
+
revision: loaded.revision,
|
|
1405
|
+
vault,
|
|
1406
|
+
passport: createPassport({ vault }),
|
|
1407
|
+
verified: imported.verified,
|
|
1408
|
+
authTag,
|
|
1409
|
+
};
|
|
1410
|
+
cacheUnlockedVault(cacheKey, state);
|
|
1411
|
+
return state;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
async function persistState(path, vault, input = {}) {
|
|
1415
|
+
if (input.lockHeld !== true) {
|
|
1416
|
+
return withBundleFileLock(path, async () => {
|
|
1417
|
+
const expectedRevision = Object.prototype.hasOwnProperty.call(input, 'expectedRevision')
|
|
1418
|
+
? input.expectedRevision
|
|
1419
|
+
: (await fileExists(path) ? (await readJsonFileWithRevision(path, bundleCredentials(input))).revision : null);
|
|
1420
|
+
return persistState(path, vault, { ...input, lockHeld: true, expectedRevision });
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
const credentials = bundleCredentials(input);
|
|
1424
|
+
const exported = exportBundle({ vault, passphrase: credentials.passphrase, includePlaintext: false });
|
|
1425
|
+
const bundle = exported.bundle ?? exported;
|
|
1426
|
+
const persisted = await writeJsonFileAtomic(path, bundle, {
|
|
1427
|
+
...(Object.prototype.hasOwnProperty.call(input, 'expectedRevision')
|
|
1428
|
+
? { expectedRevision: input.expectedRevision }
|
|
1429
|
+
: {}),
|
|
1430
|
+
checkpointProvider: credentials.checkpointProvider,
|
|
1431
|
+
requireExternalCheckpoint: credentials.requireExternalCheckpoint,
|
|
1432
|
+
});
|
|
1433
|
+
const state = {
|
|
1434
|
+
stored: bundle,
|
|
1435
|
+
revision: persisted.revision,
|
|
1436
|
+
vault,
|
|
1437
|
+
passport: createPassport({ vault }),
|
|
1438
|
+
verified: true,
|
|
1439
|
+
authTag: credentialCacheTag(credentials),
|
|
1440
|
+
};
|
|
1441
|
+
cacheUnlockedVault(path, state);
|
|
1442
|
+
Object.defineProperty(bundle, '__revision', { value: persisted.revision, enumerable: false });
|
|
1443
|
+
return bundle;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
async function withVaultTransaction(path, input, operation) {
|
|
1447
|
+
return withBundleFileLock(path, async () => {
|
|
1448
|
+
const state = await loadState(path, input);
|
|
1449
|
+
try {
|
|
1450
|
+
const result = await operation(state);
|
|
1451
|
+
const bundle = await persistState(path, state.vault, {
|
|
1452
|
+
...input,
|
|
1453
|
+
lockHeld: true,
|
|
1454
|
+
expectedRevision: state.revision,
|
|
1455
|
+
});
|
|
1456
|
+
return { ...state, revision: bundle.__revision, result, bundle };
|
|
1457
|
+
} catch (error) {
|
|
1458
|
+
invalidateCachedVault(path);
|
|
1459
|
+
throw error;
|
|
1460
|
+
}
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
function bundleSummary(path, bundle, created) {
|
|
1465
|
+
return {
|
|
1466
|
+
ok: true,
|
|
1467
|
+
created,
|
|
1468
|
+
bundlePath: path,
|
|
1469
|
+
schema: bundle.schema,
|
|
1470
|
+
vault_id: bundle.vault?.vault_id,
|
|
1471
|
+
tenant_id: bundle.vault?.tenant_id,
|
|
1472
|
+
subject_id: bundle.vault?.subject_id,
|
|
1473
|
+
active_count: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses.length : 0,
|
|
1474
|
+
receipt_count: Array.isArray(bundle.receipts) ? bundle.receipts.length : 0,
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
function normalizeResourceUri(uri) {
|
|
1479
|
+
try {
|
|
1480
|
+
const parsed = new URL(String(uri));
|
|
1481
|
+
return parsed.protocol === 'enigma:' ? `enigma://${parsed.hostname}${parsed.pathname}` : String(uri);
|
|
1482
|
+
} catch {
|
|
1483
|
+
return String(uri);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
function inputWithBundlePath(params = {}) {
|
|
1488
|
+
const uri = String(params?.uri ?? PASSPORT_SUMMARY_RESOURCE_URI);
|
|
1489
|
+
const args = params?.arguments && typeof params.arguments === 'object' && !Array.isArray(params.arguments)
|
|
1490
|
+
? params.arguments
|
|
1491
|
+
: {};
|
|
1492
|
+
let requestedPath = params?.bundlePath ?? params?.bundle_path ?? args.bundlePath ?? args.bundle_path;
|
|
1493
|
+
try {
|
|
1494
|
+
const parsed = new URL(uri);
|
|
1495
|
+
requestedPath ??= parsed.searchParams.get('bundlePath') ?? parsed.searchParams.get('bundle_path') ?? undefined;
|
|
1496
|
+
} catch {
|
|
1497
|
+
// Invalid or relative resource identifiers are rejected by the resource handler.
|
|
1498
|
+
}
|
|
1499
|
+
return {
|
|
1500
|
+
uri,
|
|
1501
|
+
...(requestedPath === undefined ? {} : { bundlePath: requestedPath }),
|
|
1502
|
+
...(params.insecureDevMode === true ? { insecureDevMode: true } : {}),
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
function passportFromBundle(bundle) {
|
|
1507
|
+
const vault = {
|
|
1508
|
+
...bundle.vault,
|
|
1509
|
+
active_memory_addresses: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses : [],
|
|
1510
|
+
tombstones: Array.isArray(bundle.tombstones) ? bundle.tombstones : [],
|
|
1511
|
+
};
|
|
1512
|
+
return createPassport({
|
|
1513
|
+
vault,
|
|
1514
|
+
passport_id: `passport:${vault.vault_id ?? 'local-vault'}`,
|
|
1515
|
+
now: vault.updated_at ?? vault.created_at ?? bundle.exported_at,
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
function passportSummary(path, bundle) {
|
|
1520
|
+
if (bundle.schema !== 'enigma.vault_bundle.v1') throw new Error(`Unsupported Enigma bundle schema: ${bundle.schema ?? '<missing>'}`);
|
|
1521
|
+
const passport = passportFromBundle(bundle);
|
|
1522
|
+
return {
|
|
1523
|
+
ok: true,
|
|
1524
|
+
schema: 'enigma.mcp.passport_summary.v1',
|
|
1525
|
+
bundlePath: path,
|
|
1526
|
+
bundle_schema: bundle.schema,
|
|
1527
|
+
exported_at: bundle.exported_at,
|
|
1528
|
+
passport: {
|
|
1529
|
+
schema: passport.schema,
|
|
1530
|
+
passport_id: passport.passport_id,
|
|
1531
|
+
owner: passport.owner,
|
|
1532
|
+
created_at: passport.created_at,
|
|
1533
|
+
updated_at: passport.updated_at,
|
|
1534
|
+
vault: passport.vault,
|
|
1535
|
+
policies: passport.policies,
|
|
1536
|
+
checkpoints: passport.checkpoints,
|
|
1537
|
+
active_memory_addresses: passport.active_memory_addresses,
|
|
1538
|
+
tombstone_addresses: passport.tombstone_addresses,
|
|
1539
|
+
},
|
|
1540
|
+
vault: {
|
|
1541
|
+
schema: bundle.vault?.schema,
|
|
1542
|
+
vault_id: bundle.vault?.vault_id,
|
|
1543
|
+
tenant_id: bundle.vault?.tenant_id,
|
|
1544
|
+
subject_id: bundle.vault?.subject_id,
|
|
1545
|
+
actor_id: bundle.vault?.actor_id,
|
|
1546
|
+
policy_id: bundle.vault?.policy_id,
|
|
1547
|
+
created_at: bundle.vault?.created_at,
|
|
1548
|
+
updated_at: bundle.vault?.updated_at,
|
|
1549
|
+
encryption: bundle.vault?.encryption,
|
|
1550
|
+
key_id: bundle.vault?.key_id,
|
|
1551
|
+
active_set_root: bundle.vault?.active_set_root,
|
|
1552
|
+
receipt_log_root: bundle.vault?.receipt_log_root,
|
|
1553
|
+
sequence: bundle.vault?.sequence,
|
|
1554
|
+
},
|
|
1555
|
+
counts: {
|
|
1556
|
+
active_memory_addresses: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses.length : 0,
|
|
1557
|
+
tombstones: Array.isArray(bundle.tombstones) ? bundle.tombstones.length : 0,
|
|
1558
|
+
memory_objects: Array.isArray(bundle.memory_objects) ? bundle.memory_objects.length : 0,
|
|
1559
|
+
events: Array.isArray(bundle.events) ? bundle.events.length : 0,
|
|
1560
|
+
receipts: Array.isArray(bundle.receipts) ? bundle.receipts.length : 0,
|
|
1561
|
+
},
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
export async function enigma_passport_summary_resource(input = {}) {
|
|
1566
|
+
const options = input && typeof input === 'object' ? input : {};
|
|
1567
|
+
const uri = options.uri ?? PASSPORT_SUMMARY_RESOURCE_URI;
|
|
1568
|
+
if (normalizeResourceUri(uri) !== PASSPORT_SUMMARY_RESOURCE_URI) {
|
|
1569
|
+
throw new Error(`Unknown Enigma resource: ${uri ?? '<missing>'}`);
|
|
1570
|
+
}
|
|
1571
|
+
const path = bundlePath(options);
|
|
1572
|
+
const { stored: bundle } = await loadState(path, options);
|
|
1573
|
+
return {
|
|
1574
|
+
contents: [
|
|
1575
|
+
{
|
|
1576
|
+
uri: String(uri),
|
|
1577
|
+
mimeType: 'application/json',
|
|
1578
|
+
text: JSON.stringify(passportSummary(path, bundle)),
|
|
1579
|
+
},
|
|
1580
|
+
],
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
|
|
1585
|
+
function privateSessionWidgetHtml() {
|
|
1586
|
+
const url = privateSessionUrl();
|
|
1587
|
+
return `<!doctype html>
|
|
1588
|
+
<html lang="en">
|
|
1589
|
+
<head>
|
|
1590
|
+
<meta charset="utf-8">
|
|
1591
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1592
|
+
<title>Enigma private session</title>
|
|
1593
|
+
<style>
|
|
1594
|
+
:root{color-scheme:dark;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#0a0908;color:#f4f2ef}
|
|
1595
|
+
*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;background:radial-gradient(circle at 84% 0,rgba(255,122,26,.15),transparent 24rem),#0a0908}
|
|
1596
|
+
main{width:min(620px,100%);padding:30px;border:1px solid rgba(255,255,255,.14);border-radius:18px;background:rgba(20,17,14,.92);box-shadow:inset 0 1px rgba(255,255,255,.07),0 24px 64px rgba(0,0,0,.45)}
|
|
1597
|
+
.eyebrow{font:600 11px ui-monospace,monospace;letter-spacing:.18em;color:#ff8b3d}.mark{display:inline-block;width:8px;height:8px;margin-right:8px;border-radius:50%;background:#ff7a1a}
|
|
1598
|
+
h1{max-width:14ch;margin:14px 0 10px;font-size:clamp(30px,7vw,52px);line-height:.98;letter-spacing:-.05em}p{max-width:58ch;color:#b9b6b1;font-size:14px;line-height:1.6}
|
|
1599
|
+
a{display:inline-flex;margin-top:20px;padding:11px 15px;border-radius:9px;background:#ff7a1a;color:#1a0b02;font:700 11px ui-monospace,monospace;text-decoration:none;text-transform:uppercase}
|
|
1600
|
+
section{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:26px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.12)}
|
|
1601
|
+
section div{padding:14px;background:#100e0c}small{display:block;color:#7d7a76;font:10px/1.45 ui-monospace,monospace}strong{display:block;margin-bottom:4px;font-size:12px}
|
|
1602
|
+
@media(max-width:520px){section{grid-template-columns:1fr}}
|
|
1603
|
+
</style>
|
|
1604
|
+
</head>
|
|
1605
|
+
<body>
|
|
1606
|
+
<main>
|
|
1607
|
+
<span class="eyebrow"><span class="mark"></span>ENIGMA / PRIVATE HANDOFF</span>
|
|
1608
|
+
<h1>Type the private prompt inside Enigma.</h1>
|
|
1609
|
+
<p>The actual prompt stays out of the MCP host chat. When you send it, the selected provider adapter receives the prepared request; Anchor Guard may mask supported patterns but is not semantic secrecy.</p>
|
|
1610
|
+
<a href="${url}" target="_blank" rel="noreferrer">Open private workspace</a>
|
|
1611
|
+
<section>
|
|
1612
|
+
<div><strong>MCP host</strong><small>Handoff fact, route label, non-sensitive intent. No workspace prompt.</small></div>
|
|
1613
|
+
<div><strong>Enigma workspace</strong><small>In-memory transcript and local context orchestration.</small></div>
|
|
1614
|
+
<div><strong>Configured provider</strong><small>Receives adapter input, optionally pattern-redacted by Anchor Guard.</small></div>
|
|
1615
|
+
</section>
|
|
1616
|
+
</main>
|
|
1617
|
+
</body>
|
|
1618
|
+
</html>`;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
function enigma_private_session_resource(input = {}) {
|
|
1622
|
+
const uri = input.uri ?? PRIVATE_SESSION_HANDOFF_RESOURCE_URI;
|
|
1623
|
+
if (String(uri) !== PRIVATE_SESSION_HANDOFF_RESOURCE_URI) {
|
|
1624
|
+
throw new Error(`Unknown Enigma resource: ${uri ?? '<missing>'}`);
|
|
1625
|
+
}
|
|
1626
|
+
return {
|
|
1627
|
+
contents: [{
|
|
1628
|
+
uri: PRIVATE_SESSION_HANDOFF_RESOURCE_URI,
|
|
1629
|
+
mimeType: 'text/html;profile=mcp-app',
|
|
1630
|
+
text: privateSessionWidgetHtml(),
|
|
1631
|
+
}],
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
export async function enigma_private_handoff_health(input = {}) {
|
|
1636
|
+
validateToolArguments('enigma_private_handoff_health', input);
|
|
1637
|
+
const origin = enigmaDesktopOrigin();
|
|
1638
|
+
const startedAt = Date.now();
|
|
1639
|
+
const protocolUrl = createPrivateSessionProtocolUrl();
|
|
1640
|
+
try {
|
|
1641
|
+
const response = await fetch(`${origin}/api/health`, {
|
|
1642
|
+
method: 'GET',
|
|
1643
|
+
headers: { Accept: 'application/json' },
|
|
1644
|
+
redirect: 'error',
|
|
1645
|
+
signal: AbortSignal.timeout(1_500),
|
|
1646
|
+
});
|
|
1647
|
+
const body = await response.json();
|
|
1648
|
+
const reachable = response.ok
|
|
1649
|
+
&& body?.ok === true
|
|
1650
|
+
&& body?.schema === 'enigma.desktop.health.v1'
|
|
1651
|
+
&& body?.service === 'enigma-desktop'
|
|
1652
|
+
&& typeof body?.instanceId === 'string';
|
|
1653
|
+
return {
|
|
1654
|
+
schema: 'enigma.private_handoff_health.v1',
|
|
1655
|
+
reachable,
|
|
1656
|
+
origin,
|
|
1657
|
+
latencyMs: Date.now() - startedAt,
|
|
1658
|
+
desktop: reachable ? body : null,
|
|
1659
|
+
protocolUrl,
|
|
1660
|
+
directProbeConfigured: Boolean(process.env.ENIGMA_DESKTOP_URL),
|
|
1661
|
+
privateSessionResource: PRIVATE_SESSION_HANDOFF_RESOURCE_URI,
|
|
1662
|
+
...(reachable ? {} : { reason: 'invalid_enigma_health_schema' }),
|
|
1663
|
+
};
|
|
1664
|
+
} catch {
|
|
1665
|
+
return {
|
|
1666
|
+
schema: 'enigma.private_handoff_health.v1',
|
|
1667
|
+
reachable: false,
|
|
1668
|
+
origin,
|
|
1669
|
+
latencyMs: Date.now() - startedAt,
|
|
1670
|
+
desktop: null,
|
|
1671
|
+
protocolUrl,
|
|
1672
|
+
directProbeConfigured: Boolean(process.env.ENIGMA_DESKTOP_URL),
|
|
1673
|
+
privateSessionResource: PRIVATE_SESSION_HANDOFF_RESOURCE_URI,
|
|
1674
|
+
action: 'Launch the Enigma desktop app through the enigma:// protocol. Set ENIGMA_DESKTOP_URL only for a known CLI host.',
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
export function enigma_routing_contract(input = {}) {
|
|
1680
|
+
validateToolArguments('enigma_routing_contract', input);
|
|
1681
|
+
return {
|
|
1682
|
+
schema: 'enigma.private_routing_contract.v1',
|
|
1683
|
+
decision: {
|
|
1684
|
+
sensitiveOrPrivate: 'Call enigma_start_private_session with a non-sensitive intent label only.',
|
|
1685
|
+
alreadyHostVisible: 'Use normal Enigma memory tools only when the user accepts that the host can inspect the supplied text.',
|
|
1686
|
+
actualPrivatePrompt: 'The user types it inside Enigma to keep it out of the MCP host chat; the configured provider still receives prepared adapter input.',
|
|
1687
|
+
},
|
|
1688
|
+
hostVisible: [
|
|
1689
|
+
'Messages typed into the host chat.',
|
|
1690
|
+
'The fact that an Enigma private session was requested.',
|
|
1691
|
+
'Non-sensitive intent and model labels passed to the handoff tool.',
|
|
1692
|
+
'Any text explicitly passed to ordinary MCP tool arguments.',
|
|
1693
|
+
],
|
|
1694
|
+
keptOutOfMcpHost: [
|
|
1695
|
+
'The prompt typed after the Enigma workspace opens.',
|
|
1696
|
+
'The in-memory workspace transcript until refresh or explicit clearing.',
|
|
1697
|
+
'The provider response rendered inside the workspace.',
|
|
1698
|
+
],
|
|
1699
|
+
providerVisible: [
|
|
1700
|
+
'The prompt and retrieved context prepared for the selected adapter.',
|
|
1701
|
+
'Anchor Guard can mask documented patterns but does not detect arbitrary sensitive prose.',
|
|
1702
|
+
],
|
|
1703
|
+
claims: {
|
|
1704
|
+
hostChatInvisible: false,
|
|
1705
|
+
privateHandoffAvailable: true,
|
|
1706
|
+
promptRelayIsPrivateFromHost: false,
|
|
1707
|
+
workspacePromptReturnedToMcpHost: false,
|
|
1708
|
+
configuredProviderReceivesAdapterInput: true,
|
|
1709
|
+
configuredProviderInvisible: false,
|
|
1710
|
+
},
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
export function enigma_start_private_session(input = {}) {
|
|
1715
|
+
input = validateToolArguments('enigma_start_private_session', input);
|
|
1716
|
+
const intent = input.intent?.trim() || 'private question';
|
|
1717
|
+
const model = input.model?.trim() || null;
|
|
1718
|
+
return {
|
|
1719
|
+
schema: 'enigma.private_session_handoff.v1',
|
|
1720
|
+
url: privateSessionUrl({ intent, ...(model ? { model } : {}) }),
|
|
1721
|
+
intent,
|
|
1722
|
+
model,
|
|
1723
|
+
resourceUri: PRIVATE_SESSION_HANDOFF_RESOURCE_URI,
|
|
1724
|
+
embedEnabled: true,
|
|
1725
|
+
hostBoundary: 'The workspace keeps the prompt out of the MCP host chat. The configured provider receives Enigma-prepared adapter input.',
|
|
1726
|
+
providerBoundary: 'Anchor Guard may mask email, wallet, IPv4, formatted phone, and base58 patterns. It does not make arbitrary sensitive prose invisible to the configured provider.',
|
|
1727
|
+
instructionsForHost: [
|
|
1728
|
+
'Do not ask the user to paste the sensitive prompt into the host chat.',
|
|
1729
|
+
'Do not place the sensitive prompt in an MCP tool argument.',
|
|
1730
|
+
'Open the Enigma private session and let the user type there.',
|
|
1731
|
+
],
|
|
1732
|
+
instructionsForUser: [
|
|
1733
|
+
'Open the Enigma private workspace.',
|
|
1734
|
+
'Choose a configured route if needed.',
|
|
1735
|
+
'Type the actual private prompt inside Enigma.',
|
|
1736
|
+
'The configured provider receives the prepared adapter input when you send.',
|
|
1737
|
+
],
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
export function enigma_standard_memory_prompt(input = {}) {
|
|
1741
|
+
const args = input?.arguments && typeof input.arguments === 'object' && !Array.isArray(input.arguments)
|
|
1742
|
+
? input.arguments
|
|
1743
|
+
: (input && typeof input === 'object' ? input : {});
|
|
1744
|
+
const question = typeof args.question === 'string' && args.question.trim() ? args.question.trim() : 'the user-specific question';
|
|
1745
|
+
const purpose = typeof args.purpose === 'string' && args.purpose.trim() ? args.purpose.trim() : 'answer_user_specific_question';
|
|
1746
|
+
return {
|
|
1747
|
+
description: 'Use Enigma as the canonical memory and proof layer before making user-specific claims.',
|
|
1748
|
+
messages: [
|
|
1749
|
+
{
|
|
1750
|
+
role: 'user',
|
|
1751
|
+
content: {
|
|
1752
|
+
type: 'text',
|
|
1753
|
+
text: [
|
|
1754
|
+
'Before answering user-specific questions, request relevant context through Enigma instead of relying on provider-native memory.',
|
|
1755
|
+
`Use the Enigma MCP tools with purpose "${purpose}" to retrieve a context pack or search result for: ${question}`,
|
|
1756
|
+
'Treat provider-native memory as a cache only; Enigma receipts and active Vault state are the source of truth.',
|
|
1757
|
+
'Be honest: if Enigma has no relevant context, receipts, or permission for a claim, say you do not know or need more context rather than guessing.',
|
|
1758
|
+
'Do not put raw memory plaintext into receipts, relay records, witness artifacts, SIEM events, or public proof artifacts.',
|
|
1759
|
+
].join('\n'),
|
|
1760
|
+
},
|
|
1761
|
+
},
|
|
1762
|
+
],
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
function requireInferenceRuntime(capability) {
|
|
1767
|
+
if (!configuredInferenceRuntime || typeof configuredInferenceRuntime[capability] !== 'object') {
|
|
1768
|
+
throw new Error(`Enigma ${capability} inference runtime is not configured`);
|
|
1769
|
+
}
|
|
1770
|
+
return configuredInferenceRuntime;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
export async function enigma_complete(input = {}) {
|
|
1774
|
+
input = validateToolArguments('enigma_complete', input);
|
|
1775
|
+
const runtime = requireInferenceRuntime('chat');
|
|
1776
|
+
return runtime.chat.complete({
|
|
1777
|
+
messages: input.messages,
|
|
1778
|
+
model: input.model || 'enigma-auto',
|
|
1779
|
+
privacyMode: input.privacy_mode || 'smart',
|
|
1780
|
+
temperature: input.temperature,
|
|
1781
|
+
maxTokens: input.max_tokens,
|
|
1782
|
+
reasoningEffort: input.reasoning_effort,
|
|
1783
|
+
webSearch: input.web_search === true,
|
|
1784
|
+
requirePrivateRoute: input.require_private_route === true,
|
|
1785
|
+
stream: false,
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
export async function enigma_generate_image(input = {}) {
|
|
1790
|
+
input = validateToolArguments('enigma_generate_image', input);
|
|
1791
|
+
const runtime = requireInferenceRuntime('images');
|
|
1792
|
+
return runtime.images.generate({
|
|
1793
|
+
prompt: input.prompt,
|
|
1794
|
+
model: input.model,
|
|
1795
|
+
negativePrompt: input.negative_prompt,
|
|
1796
|
+
width: input.width,
|
|
1797
|
+
height: input.height,
|
|
1798
|
+
steps: input.steps,
|
|
1799
|
+
cfgScale: input.cfg_scale,
|
|
1800
|
+
variants: input.variants,
|
|
1801
|
+
format: input.format,
|
|
1802
|
+
seed: input.seed,
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
export async function enigma_x402_execute(input = {}) {
|
|
1807
|
+
input = validateToolArguments('enigma_x402_execute', input);
|
|
1808
|
+
if (!configuredX402Client) throw new Error('Enigma x402 execution client is not configured');
|
|
1809
|
+
const headers = { ...(input.headers || {}) };
|
|
1810
|
+
const body = input.body === undefined
|
|
1811
|
+
? undefined
|
|
1812
|
+
: typeof input.body === 'string'
|
|
1813
|
+
? input.body
|
|
1814
|
+
: JSON.stringify(input.body);
|
|
1815
|
+
if (body !== undefined && !Object.keys(headers).some((name) => name.toLowerCase() === 'content-type')) {
|
|
1816
|
+
headers['Content-Type'] = 'application/json';
|
|
1817
|
+
}
|
|
1818
|
+
const execution = await configuredX402Client(input.url, { method: input.method || 'GET', headers, body });
|
|
1819
|
+
const maximum = input.max_response_bytes || 262144;
|
|
1820
|
+
const declared = Number(execution.response.headers.get('content-length'));
|
|
1821
|
+
if (Number.isFinite(declared) && declared > maximum) {
|
|
1822
|
+
await execution.response.body?.cancel?.();
|
|
1823
|
+
throw new Error('x402 resource response exceeds the configured limit');
|
|
1824
|
+
}
|
|
1825
|
+
const bytes = Buffer.from(await execution.response.arrayBuffer());
|
|
1826
|
+
if (bytes.length > maximum) throw new Error('x402 resource response exceeds the configured limit');
|
|
1827
|
+
const contentType = execution.response.headers.get('content-type') || 'application/octet-stream';
|
|
1828
|
+
let responseBody = bytes.toString('utf8');
|
|
1829
|
+
if (contentType.includes('application/json')) {
|
|
1830
|
+
try { responseBody = JSON.parse(responseBody); } catch { throw new Error('x402 resource returned invalid JSON'); }
|
|
1831
|
+
}
|
|
1832
|
+
return {
|
|
1833
|
+
schema: 'enigma.x402_execution.v1',
|
|
1834
|
+
status: execution.response.status,
|
|
1835
|
+
contentType,
|
|
1836
|
+
body: responseBody,
|
|
1837
|
+
settlement: execution.settlement,
|
|
1838
|
+
paymentRequired: execution.paymentRequired,
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
export async function enigma_init(input = {}) {
|
|
1843
|
+
input = validateToolArguments('enigma_init', input);
|
|
1844
|
+
const path = bundlePath(input);
|
|
1845
|
+
const credentials = bundleCredentials(input);
|
|
1846
|
+
return withBundleFileLock(path, async () => {
|
|
1847
|
+
if (await fileExists(path)) {
|
|
1848
|
+
const state = await loadState(path, input);
|
|
1849
|
+
return bundleSummary(path, state.stored, false);
|
|
1850
|
+
}
|
|
1851
|
+
const vault = createVault({
|
|
1852
|
+
tenant_id: input.tenant_id,
|
|
1853
|
+
subject_id: input.subject_id,
|
|
1854
|
+
actor_id: input.actor_id,
|
|
1855
|
+
policy_id: input.policy_id,
|
|
1856
|
+
passphrase: credentials.passphrase,
|
|
1857
|
+
});
|
|
1858
|
+
const bundle = await persistState(path, vault, { ...input, lockHeld: true, expectedRevision: null });
|
|
1859
|
+
return bundleSummary(path, bundle, true);
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
export async function enigma_remember(input = {}) {
|
|
1864
|
+
input = validateToolArguments('enigma_remember', input);
|
|
1865
|
+
const path = bundlePath(input);
|
|
1866
|
+
const { result } = await withVaultTransaction(path, input, ({ vault, passport }) => remember({
|
|
1867
|
+
vault,
|
|
1868
|
+
passport,
|
|
1869
|
+
text: input.text,
|
|
1870
|
+
purpose: input.purpose ?? 'mcp_memory',
|
|
1871
|
+
purpose_tags: Array.isArray(input.tags) ? input.tags : [],
|
|
1872
|
+
metadata: input.metadata ?? {},
|
|
1873
|
+
}));
|
|
1874
|
+
return { ok: true, memory_addr: result.memory_addr, receipt_id: result.receipt?.receipt_id };
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
export async function enigma_search(input = {}) {
|
|
1878
|
+
input = validateToolArguments('enigma_search', input);
|
|
1879
|
+
const path = bundlePath(input);
|
|
1880
|
+
const { result } = await withVaultTransaction(path, input, ({ vault, passport }) => {
|
|
1881
|
+
if (input.memory_addr) {
|
|
1882
|
+
return recall({ vault, passport, memory_addr: input.memory_addr, purpose: input.purpose ?? 'mcp_search' });
|
|
1883
|
+
}
|
|
1884
|
+
const pack = compileContextPack({
|
|
1885
|
+
vault,
|
|
1886
|
+
passport,
|
|
1887
|
+
query: input.query ?? '',
|
|
1888
|
+
purpose: input.purpose ?? 'mcp_search',
|
|
1889
|
+
limit: Number(input.limit ?? 8),
|
|
1890
|
+
});
|
|
1891
|
+
return { memories: pack.memories ?? [], receipts: pack.retrieval_receipts ?? pack.receipts ?? [] };
|
|
1892
|
+
});
|
|
1893
|
+
return result;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
export async function enigma_context_pack(input = {}) {
|
|
1897
|
+
input = validateToolArguments('enigma_context_pack', input);
|
|
1898
|
+
const path = bundlePath(input);
|
|
1899
|
+
const { result } = await withVaultTransaction(path, input, ({ vault, passport }) => compileContextPack({
|
|
1900
|
+
vault,
|
|
1901
|
+
passport,
|
|
1902
|
+
query: input.query ?? '',
|
|
1903
|
+
purpose: input.purpose ?? 'mcp_context_pack',
|
|
1904
|
+
optimize: input.optimize,
|
|
1905
|
+
max_estimated_tokens: input.max_estimated_tokens,
|
|
1906
|
+
price_per_million_tokens: input.price_per_million_tokens,
|
|
1907
|
+
currency: input.currency,
|
|
1908
|
+
limit: Number(input.limit ?? 8),
|
|
1909
|
+
memory_addresses: input.memory_addresses,
|
|
1910
|
+
}));
|
|
1911
|
+
return result;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
export async function enigma_delete(input = {}) {
|
|
1915
|
+
input = validateToolArguments('enigma_delete', input);
|
|
1916
|
+
const path = bundlePath(input);
|
|
1917
|
+
const { result } = await withVaultTransaction(path, input, ({ vault, passport }) => deleteMemory({
|
|
1918
|
+
vault,
|
|
1919
|
+
passport,
|
|
1920
|
+
memory_addr: input.memory_addr,
|
|
1921
|
+
reason: input.reason ?? 'mcp_delete',
|
|
1922
|
+
}));
|
|
1923
|
+
return { ok: true, memory_addr: result.memory_addr, receipt_id: result.receipt?.receipt_id };
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
export async function enigma_vault_rotate(input = {}) {
|
|
1927
|
+
input = validateToolArguments('enigma_vault_rotate', input);
|
|
1928
|
+
const path = bundlePath(input);
|
|
1929
|
+
const { result } = await withVaultTransaction(path, input, ({ vault }) => rotateContentKey({
|
|
1930
|
+
vault,
|
|
1931
|
+
key_id: input.key_id,
|
|
1932
|
+
}));
|
|
1933
|
+
return { ok: true, operation: 'key_rotate', ...result };
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
export async function enigma_vault_seal(input = {}) {
|
|
1937
|
+
input = validateToolArguments('enigma_vault_seal', input);
|
|
1938
|
+
const path = bundlePath(input);
|
|
1939
|
+
const { result } = await withVaultTransaction(path, input, ({ vault }) => sealContentKeyEpoch({
|
|
1940
|
+
vault,
|
|
1941
|
+
epoch: input.epoch,
|
|
1942
|
+
}));
|
|
1943
|
+
return { ok: true, operation: 'key_seal', ...result };
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
export async function enigma_vault_reset(input = {}) {
|
|
1947
|
+
input = validateToolArguments('enigma_vault_reset', input);
|
|
1948
|
+
const path = bundlePath(input);
|
|
1949
|
+
const { result } = await withVaultTransaction(path, input, ({ vault }) => resetVaultContentKeys({
|
|
1950
|
+
vault,
|
|
1951
|
+
key_id: input.key_id,
|
|
1952
|
+
}));
|
|
1953
|
+
return { ok: true, operation: 'key_reset', ...result };
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
export async function enigma_verify_receipts(input = {}) {
|
|
1957
|
+
input = validateToolArguments('enigma_verify_receipts', input);
|
|
1958
|
+
if (input.bundle) return verifyBundle(input.bundle);
|
|
1959
|
+
const path = bundlePath(input);
|
|
1960
|
+
bundleCredentials(input);
|
|
1961
|
+
const stored = await readJson(path);
|
|
1962
|
+
const report = verifyBundle(stored);
|
|
1963
|
+
if (!report.ok) return report;
|
|
1964
|
+
await loadState(path, input);
|
|
1965
|
+
return report;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
async function activeSwarmAtoms(input) {
|
|
1969
|
+
const path = bundlePath(input);
|
|
1970
|
+
if (!(await fileExists(path))) return [];
|
|
1971
|
+
const { result } = await withVaultTransaction(path, input, ({ vault, passport }) => {
|
|
1972
|
+
const atoms = [];
|
|
1973
|
+
for (const memoryAddr of [...vault.activeAddresses].sort()) {
|
|
1974
|
+
const recalled = recall({
|
|
1975
|
+
vault,
|
|
1976
|
+
passport,
|
|
1977
|
+
memory_addr: memoryAddr,
|
|
1978
|
+
purpose: 'mcp_swarm_context',
|
|
1979
|
+
});
|
|
1980
|
+
const { content_ciphertext: ignoredCiphertext, ...memory } = recalled.memory;
|
|
1981
|
+
atoms.push({ ...memory, content: recalled.content });
|
|
1982
|
+
}
|
|
1983
|
+
return atoms;
|
|
1984
|
+
});
|
|
1985
|
+
return result;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
export async function enigma_swarm_register_agent(input = {}) {
|
|
1989
|
+
input = validateToolArguments('enigma_swarm_register_agent', input);
|
|
1990
|
+
return routeSwarmRegisterAgent(input);
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
export async function enigma_graph_query(input = {}) {
|
|
1994
|
+
input = validateToolArguments('enigma_graph_query', input);
|
|
1995
|
+
return routeGraphQuery({ ...input, atoms: await activeSwarmAtoms(input) });
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
export async function enigma_cluster_memories(input = {}) {
|
|
1999
|
+
input = validateToolArguments('enigma_cluster_memories', input);
|
|
2000
|
+
return routeClusterMemories({ ...input, atoms: await activeSwarmAtoms(input) });
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
export async function enigma_swarm_sync(input = {}) {
|
|
2004
|
+
input = validateToolArguments('enigma_swarm_sync', input);
|
|
2005
|
+
return routeSwarmSync({ ...input, atoms: await activeSwarmAtoms(input) });
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
export async function enigma_immune_ingress(input = {}) {
|
|
2009
|
+
input = validateToolArguments('enigma_immune_ingress', input);
|
|
2010
|
+
return createMcpImmuneIngressReport(input);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
export async function enigma_meter_usage(input = {}) {
|
|
2014
|
+
input = validateToolArguments('enigma_meter_usage', input);
|
|
2015
|
+
if (Array.isArray(input.events)) {
|
|
2016
|
+
return aggregateUsageEvents({
|
|
2017
|
+
events: input.events,
|
|
2018
|
+
tenant_id: input.tenant_id,
|
|
2019
|
+
meter_id: input.meter_id,
|
|
2020
|
+
generated_at: input.generated_at,
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
return createUsageEvent({
|
|
2024
|
+
tenant_id: input.tenant_id,
|
|
2025
|
+
meter_id: input.meter_id,
|
|
2026
|
+
provider: input.provider,
|
|
2027
|
+
model: input.model,
|
|
2028
|
+
operation: input.operation,
|
|
2029
|
+
timestamp: input.timestamp,
|
|
2030
|
+
prompt_tokens: input.prompt_tokens,
|
|
2031
|
+
completion_tokens: input.completion_tokens,
|
|
2032
|
+
memory_baseline_tokens: input.memory_baseline_tokens,
|
|
2033
|
+
memory_optimized_tokens: input.memory_optimized_tokens,
|
|
2034
|
+
pricing: {
|
|
2035
|
+
currency: input.currency,
|
|
2036
|
+
input_price_per_million_tokens: input.input_price_per_million_tokens ?? input.price_per_million_tokens,
|
|
2037
|
+
output_price_per_million_tokens: input.output_price_per_million_tokens ?? input.price_per_million_tokens,
|
|
2038
|
+
},
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
export async function enigma_settlement_job(input = {}) {
|
|
2043
|
+
input = validateToolArguments('enigma_settlement_job', input);
|
|
2044
|
+
return createPermissionlessMemoryJob(input);
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
export async function enigma_settlement_capacity(input = {}) {
|
|
2048
|
+
input = validateToolArguments('enigma_settlement_capacity', input);
|
|
2049
|
+
return createConsumerGpuCapacityProfile(input);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
export async function enigma_settlement_quote(input = {}) {
|
|
2053
|
+
input = validateToolArguments('enigma_settlement_quote', input);
|
|
2054
|
+
return createOperatorServiceQuote(input);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
export async function enigma_settlement_receipt(input = {}) {
|
|
2058
|
+
input = validateToolArguments('enigma_settlement_receipt', input);
|
|
2059
|
+
return createServiceSettlementReceipt(input);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
export async function enigma_settlement_verify(input = {}) {
|
|
2063
|
+
input = validateToolArguments('enigma_settlement_verify', input);
|
|
2064
|
+
return verifyServiceSettlementReceipt(input);
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
export async function enigma_settlement_batch(input = {}) {
|
|
2068
|
+
input = validateToolArguments('enigma_settlement_batch', input);
|
|
2069
|
+
return createSettlementBatch(input);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
export async function enigma_vault_create_record(input = {}) {
|
|
2074
|
+
input = validateToolArguments('enigma_vault_create_record', input);
|
|
2075
|
+
return defaultEnclave.createRecord(input.plaintext, input.metadata || {});
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
export async function enigma_vault_zeroize_record(input = {}) {
|
|
2079
|
+
input = validateToolArguments('enigma_vault_zeroize_record', input);
|
|
2080
|
+
return defaultEnclave.zeroizeRecord(input.recordId);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
export async function enigma_verify_erasure_attestation(input = {}) {
|
|
2084
|
+
input = validateToolArguments('enigma_verify_erasure_attestation', input);
|
|
2085
|
+
return AttestationVerifier.verify(input.attestation, {
|
|
2086
|
+
// Simulated attestations are developer-mode only: must be explicitly enabled.
|
|
2087
|
+
allowSimulated: input.allowSimulated ?? false,
|
|
2088
|
+
allowlistedSimulatedKeyPem: defaultEnclave.publicKeyPem,
|
|
2089
|
+
expectedPcr: input.expectedPcr,
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
export async function enigma_nullifier_record_tombstone(input = {}) {
|
|
2094
|
+
input = validateToolArguments('enigma_nullifier_record_tombstone', input);
|
|
2095
|
+
const { PublicKey } = await import('@solana/web3.js');
|
|
2096
|
+
|
|
2097
|
+
const programId = 'E18KZR1Jq8fG3FFACpoHsE21ME3t1ftKPEwXL7cFWkoZ';
|
|
2098
|
+
const programKey = new PublicKey(programId);
|
|
2099
|
+
// Strict 32-byte hex validation — no padding, no truncation, no silent mutation.
|
|
2100
|
+
const HEX32_RE = /^(0x)?[0-9a-fA-F]{64}$/;
|
|
2101
|
+
if (!HEX32_RE.test(input.commitment)) {
|
|
2102
|
+
throw new Error('enigma_nullifier_record_tombstone: commitment must be exactly 32 bytes of hex (64 hex chars, optional 0x prefix)');
|
|
2103
|
+
}
|
|
2104
|
+
if (!HEX32_RE.test(input.nullifierHash)) {
|
|
2105
|
+
throw new Error('enigma_nullifier_record_tombstone: nullifierHash must be exactly 32 bytes of hex (64 hex chars, optional 0x prefix)');
|
|
2106
|
+
}
|
|
2107
|
+
const commitmentClean = input.commitment.replace(/^0x/, '');
|
|
2108
|
+
const nullifierClean = input.nullifierHash.replace(/^0x/, '');
|
|
2109
|
+
|
|
2110
|
+
const commitmentBytes = Buffer.from(commitmentClean, 'hex');
|
|
2111
|
+
const nullifierBytes = Buffer.from(nullifierClean, 'hex');
|
|
2112
|
+
if (commitmentBytes.length !== 32 || nullifierBytes.length !== 32) {
|
|
2113
|
+
throw new Error('enigma_nullifier_record_tombstone: decoded values must be exactly 32 bytes');
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
// Owner is the required Signer; the tombstone PDA is derived from owner + commitment.
|
|
2117
|
+
let ownerKey;
|
|
2118
|
+
try {
|
|
2119
|
+
ownerKey = new PublicKey(input.ownerPubkey);
|
|
2120
|
+
} catch {
|
|
2121
|
+
throw new Error('enigma_nullifier_record_tombstone: ownerPubkey must be a valid base58 public key');
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
const [commitmentPda, commitmentBump] = PublicKey.findProgramAddressSync(
|
|
2125
|
+
[Buffer.from('commitment'), ownerKey.toBuffer(), commitmentBytes],
|
|
2126
|
+
programKey,
|
|
2127
|
+
);
|
|
2128
|
+
const [tombstonePda, tombstoneBump] = PublicKey.findProgramAddressSync(
|
|
2129
|
+
[Buffer.from('tombstone'), ownerKey.toBuffer(), commitmentBytes],
|
|
2130
|
+
programKey,
|
|
2131
|
+
);
|
|
2132
|
+
const [registryPda, registryBump] = PublicKey.findProgramAddressSync(
|
|
2133
|
+
[Buffer.from('nullifier_registry')],
|
|
2134
|
+
programKey,
|
|
2135
|
+
);
|
|
2136
|
+
|
|
2137
|
+
// Anchor discriminator for global:record_revocation (owner-signed revocation record;
|
|
2138
|
+
// no PCR/attestation framing — physical deletion is out of scope).
|
|
2139
|
+
const discriminator = Buffer.from([108, 45, 14, 21, 217, 230, 163, 121]);
|
|
2140
|
+
const instructionData = Buffer.concat([
|
|
2141
|
+
discriminator,
|
|
2142
|
+
commitmentBytes,
|
|
2143
|
+
nullifierBytes,
|
|
2144
|
+
]);
|
|
2145
|
+
|
|
2146
|
+
// Ordered account metas matching RecordRevocation (commitment_record, tombstone,
|
|
2147
|
+
// registry, owner, system). The commitment must be registered first — revocation
|
|
2148
|
+
// flips its is_nullified flag on-chain.
|
|
2149
|
+
const accounts = [
|
|
2150
|
+
{ pubkey: commitmentPda.toBase58(), isSigner: false, isWritable: true, role: 'commitment_record', bump: commitmentBump },
|
|
2151
|
+
{ pubkey: tombstonePda.toBase58(), isSigner: false, isWritable: true, role: 'tombstone', bump: tombstoneBump },
|
|
2152
|
+
{ pubkey: registryPda.toBase58(), isSigner: false, isWritable: true, role: 'registry', bump: registryBump },
|
|
2153
|
+
{ pubkey: ownerKey.toBase58(), isSigner: true, isWritable: true, role: 'owner' },
|
|
2154
|
+
{ pubkey: '11111111111111111111111111111111', isSigner: false, isWritable: false, role: 'system_program' },
|
|
2155
|
+
];
|
|
2156
|
+
|
|
2157
|
+
return {
|
|
2158
|
+
programId,
|
|
2159
|
+
instruction: 'record_revocation',
|
|
2160
|
+
discriminator: Array.from(discriminator),
|
|
2161
|
+
accounts,
|
|
2162
|
+
instructionDataHex: instructionData.toString('hex'),
|
|
2163
|
+
commitment: input.commitment,
|
|
2164
|
+
nullifierHash: input.nullifierHash,
|
|
2165
|
+
ownerPubkey: ownerKey.toBase58(),
|
|
2166
|
+
requiresOwnerSignature: true,
|
|
2167
|
+
requiresRegisteredCommitment: true,
|
|
2168
|
+
timestamp: new Date().toISOString(),
|
|
2169
|
+
broadcastReady: true,
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
// enigma_verify_erasure_attestation deliberately excluded from RPC handlers (see
|
|
2175
|
+
// toolDescriptors note above): hardware attestation verification is not yet safe.
|
|
2176
|
+
export const handlers = Object.freeze({
|
|
2177
|
+
enigma_private_handoff_health,
|
|
2178
|
+
enigma_routing_contract,
|
|
2179
|
+
enigma_start_private_session,
|
|
2180
|
+
enigma_complete,
|
|
2181
|
+
enigma_generate_image,
|
|
2182
|
+
enigma_x402_execute,
|
|
2183
|
+
enigma_init,
|
|
2184
|
+
enigma_remember,
|
|
2185
|
+
enigma_search,
|
|
2186
|
+
enigma_context_pack,
|
|
2187
|
+
enigma_delete,
|
|
2188
|
+
enigma_vault_rotate,
|
|
2189
|
+
enigma_vault_seal,
|
|
2190
|
+
enigma_vault_reset,
|
|
2191
|
+
enigma_verify_receipts,
|
|
2192
|
+
enigma_swarm_register_agent,
|
|
2193
|
+
enigma_graph_query,
|
|
2194
|
+
enigma_cluster_memories,
|
|
2195
|
+
enigma_swarm_sync,
|
|
2196
|
+
enigma_immune_ingress,
|
|
2197
|
+
enigma_meter_usage,
|
|
2198
|
+
enigma_settlement_job,
|
|
2199
|
+
enigma_settlement_capacity,
|
|
2200
|
+
enigma_settlement_quote,
|
|
2201
|
+
enigma_settlement_receipt,
|
|
2202
|
+
enigma_settlement_verify,
|
|
2203
|
+
enigma_settlement_batch,
|
|
2204
|
+
enigma_vault_create_record,
|
|
2205
|
+
enigma_vault_zeroize_record,
|
|
2206
|
+
enigma_nullifier_record_tombstone,
|
|
2207
|
+
});
|
|
2208
|
+
|
|
2209
|
+
function jsonRpcResult(id, result) {
|
|
2210
|
+
return { jsonrpc: JSONRPC_VERSION, id, result };
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
function jsonRpcError(id, code, message, data = undefined) {
|
|
2214
|
+
const error = data === undefined ? { code, message } : { code, message, data };
|
|
2215
|
+
return { jsonrpc: JSONRPC_VERSION, id, error };
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
function isRequestObject(request) {
|
|
2219
|
+
return request !== null && typeof request === 'object' && !Array.isArray(request);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
function hasJsonRpcId(request) {
|
|
2223
|
+
return Object.prototype.hasOwnProperty.call(request, 'id');
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
function toolArguments(name, params) {
|
|
2227
|
+
const args = params.arguments ?? {};
|
|
2228
|
+
return validateToolArguments(name, args);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
function toolHandler(name) {
|
|
2232
|
+
return Object.prototype.hasOwnProperty.call(handlers, name) ? handlers[name] : undefined;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
function toolCallContent(result, toolName) {
|
|
2236
|
+
const verificationFailed = (toolName === 'enigma_verify_receipts' || toolName === 'enigma_settlement_verify') && result && typeof result === 'object' && result.ok === false;
|
|
2237
|
+
if (toolName === 'enigma_generate_image' && result && typeof result === 'object') {
|
|
2238
|
+
const content = [];
|
|
2239
|
+
const assets = (result.assets || []).map((asset, index) => {
|
|
2240
|
+
const mimeType = `image/${asset.format === 'jpg' ? 'jpeg' : asset.format || 'webp'}`;
|
|
2241
|
+
if (typeof asset.base64 === 'string') {
|
|
2242
|
+
content.push({ type: 'image', data: asset.base64, mimeType });
|
|
2243
|
+
return { index, format: asset.format, inline: true };
|
|
2244
|
+
}
|
|
2245
|
+
if (typeof asset.url === 'string' && asset.url.startsWith('data:')) {
|
|
2246
|
+
const match = /^data:([^;,]+);base64,(.+)$/s.exec(asset.url);
|
|
2247
|
+
if (match) {
|
|
2248
|
+
content.push({ type: 'image', data: match[2], mimeType: match[1] });
|
|
2249
|
+
return { index, format: asset.format, inline: true };
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
content.push({ type: 'text', text: `Generated image ${index + 1}: ${asset.url}` });
|
|
2253
|
+
return { index, format: asset.format, url: asset.url };
|
|
2254
|
+
});
|
|
2255
|
+
const structuredContent = { ...result, assets };
|
|
2256
|
+
content.unshift({ type: 'text', text: JSON.stringify(structuredContent) });
|
|
2257
|
+
return { content, structuredContent, isError: false };
|
|
2258
|
+
}
|
|
2259
|
+
return {
|
|
2260
|
+
content: [{ type: 'text', text: JSON.stringify(result ?? null) }],
|
|
2261
|
+
structuredContent: result ?? null,
|
|
2262
|
+
isError: verificationFailed,
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
function toolCallError(error) {
|
|
2267
|
+
const result = sanitizeOperationalError(error);
|
|
2268
|
+
return {
|
|
2269
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
2270
|
+
structuredContent: result,
|
|
2271
|
+
isError: true,
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
function validateInitializeParams(params) {
|
|
2276
|
+
const input = ensureParamsObject(params, 'initialize');
|
|
2277
|
+
rejectAdditionalProperties(input, new Set(['protocolVersion', 'capabilities', 'clientInfo']), 'initialize params');
|
|
2278
|
+
optionalString(input, 'protocolVersion', 'initialize params');
|
|
2279
|
+
optionalPlainObject(input, 'capabilities', 'initialize params');
|
|
2280
|
+
optionalPlainObject(input, 'clientInfo', 'initialize params');
|
|
2281
|
+
if (input.protocolVersion !== undefined && input.protocolVersion !== MCP_PROTOCOL_VERSION) {
|
|
2282
|
+
throw invalidParams('Unsupported MCP protocol version.', { supportedProtocolVersions: [MCP_PROTOCOL_VERSION] });
|
|
2283
|
+
}
|
|
2284
|
+
return input;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
function validateNoParams(params, method) {
|
|
2288
|
+
const input = ensureParamsObject(params, method);
|
|
2289
|
+
rejectAdditionalProperties(input, new Set(), `${method} params`);
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
async function handleSingleJsonRpcRequest(request, context = {}) {
|
|
2293
|
+
if (!isRequestObject(request)) return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
2294
|
+
|
|
2295
|
+
const notification = !hasJsonRpcId(request);
|
|
2296
|
+
const id = notification ? null : request.id;
|
|
2297
|
+
if (!notification && !isValidJsonRpcId(id)) {
|
|
2298
|
+
return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
2299
|
+
}
|
|
2300
|
+
if (request.jsonrpc !== JSONRPC_VERSION || typeof request.method !== 'string') {
|
|
2301
|
+
return jsonRpcError(id, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
2302
|
+
}
|
|
2303
|
+
if (context.transport === 'streamable-http') {
|
|
2304
|
+
const requiredScopes = requiredScopesForMcpPayload(request);
|
|
2305
|
+
if (!context.principal || !Array.isArray(context.principal.scopes) || requiredScopes.some((scope) => !context.principal.scopes.includes(scope))) {
|
|
2306
|
+
return notification ? undefined : jsonRpcError(id, JSON_RPC_ERROR.INVALID_REQUEST, 'Insufficient OAuth scope.', { requiredScopes });
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
try {
|
|
2311
|
+
switch (request.method) {
|
|
2312
|
+
case 'initialize': {
|
|
2313
|
+
validateInitializeParams(request.params);
|
|
2314
|
+
return notification ? undefined : jsonRpcResult(id, {
|
|
2315
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
2316
|
+
capabilities: {
|
|
2317
|
+
tools: { listChanged: false },
|
|
2318
|
+
resources: { listChanged: false },
|
|
2319
|
+
prompts: { listChanged: false },
|
|
2320
|
+
},
|
|
2321
|
+
serverInfo: SERVER_INFO,
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
case 'notifications/initialized':
|
|
2325
|
+
validateNoParams(request.params, 'notifications/initialized');
|
|
2326
|
+
return undefined;
|
|
2327
|
+
case 'ping':
|
|
2328
|
+
validateNoParams(request.params, 'ping');
|
|
2329
|
+
return notification ? undefined : jsonRpcResult(id, {});
|
|
2330
|
+
case 'tools/list':
|
|
2331
|
+
validateNoParams(request.params, 'tools/list');
|
|
2332
|
+
return notification ? undefined : jsonRpcResult(id, { tools: context.transport === 'streamable-http' ? remoteToolDescriptors() : toolDescriptors });
|
|
2333
|
+
case 'resources/list':
|
|
2334
|
+
validateNoParams(request.params, 'resources/list');
|
|
2335
|
+
return notification ? undefined : jsonRpcResult(id, { resources: resourceDescriptors });
|
|
2336
|
+
case 'resources/templates/list':
|
|
2337
|
+
validateNoParams(request.params, 'resources/templates/list');
|
|
2338
|
+
return notification ? undefined : jsonRpcResult(id, { resourceTemplates: [] });
|
|
2339
|
+
case 'resources/read': {
|
|
2340
|
+
const params = ensureParamsObject(request.params, 'resources/read');
|
|
2341
|
+
rejectAdditionalProperties(params, new Set(['uri', 'bundlePath', 'insecureDevMode']), 'resources/read params');
|
|
2342
|
+
requireString(params, 'uri', 'resources/read params');
|
|
2343
|
+
optionalString(params, 'bundlePath', 'resources/read params');
|
|
2344
|
+
optionalBoolean(params, 'insecureDevMode', 'resources/read params');
|
|
2345
|
+
const normalizedUri = normalizeResourceUri(params.uri);
|
|
2346
|
+
let result;
|
|
2347
|
+
if (normalizedUri === PASSPORT_SUMMARY_RESOURCE_URI) {
|
|
2348
|
+
result = await enigma_passport_summary_resource(await bindRemoteResourceInput(params, normalizedUri, context));
|
|
2349
|
+
} else if (normalizedUri === PRIVATE_SESSION_HANDOFF_RESOURCE_URI) {
|
|
2350
|
+
result = enigma_private_session_resource({ uri: normalizedUri });
|
|
2351
|
+
} else {
|
|
2352
|
+
throw invalidParams('Unknown resource.');
|
|
2353
|
+
}
|
|
2354
|
+
if (context.transport === 'streamable-http' && Array.isArray(result?.contents)) {
|
|
2355
|
+
result = {
|
|
2356
|
+
...result,
|
|
2357
|
+
contents: result.contents.map((content) => {
|
|
2358
|
+
if (content?.mimeType !== 'application/json' || typeof content.text !== 'string') return content;
|
|
2359
|
+
try {
|
|
2360
|
+
return { ...content, text: JSON.stringify(sanitizeRemoteCustodyOutput(JSON.parse(content.text), context)) };
|
|
2361
|
+
} catch {
|
|
2362
|
+
return content;
|
|
2363
|
+
}
|
|
2364
|
+
}),
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
return notification ? undefined : jsonRpcResult(id, result);
|
|
2368
|
+
}
|
|
2369
|
+
case 'prompts/list':
|
|
2370
|
+
validateNoParams(request.params, 'prompts/list');
|
|
2371
|
+
return notification ? undefined : jsonRpcResult(id, { prompts: promptDescriptors });
|
|
2372
|
+
case 'prompts/get': {
|
|
2373
|
+
const params = ensureParamsObject(request.params, 'prompts/get');
|
|
2374
|
+
rejectAdditionalProperties(params, new Set(['name', 'arguments']), 'prompts/get params');
|
|
2375
|
+
requireString(params, 'name', 'prompts/get params');
|
|
2376
|
+
if (params.name !== STANDARD_MEMORY_PROMPT_NAME) throw invalidParams('Unknown prompt.');
|
|
2377
|
+
validatePromptArguments(params.arguments);
|
|
2378
|
+
return notification ? undefined : jsonRpcResult(id, enigma_standard_memory_prompt(params));
|
|
2379
|
+
}
|
|
2380
|
+
case 'tools/call': {
|
|
2381
|
+
const params = ensureParamsObject(request.params, 'tools/call');
|
|
2382
|
+
rejectAdditionalProperties(params, new Set(['name', 'arguments']), 'tools/call params');
|
|
2383
|
+
requireString(params, 'name', 'tools/call params');
|
|
2384
|
+
const handler = toolHandler(params.name);
|
|
2385
|
+
if (!handler) throw invalidParams('Unknown tool.');
|
|
2386
|
+
const args = context.transport === 'streamable-http'
|
|
2387
|
+
? await bindRemoteToolArguments(params.name, params.arguments ?? {}, context)
|
|
2388
|
+
: toolArguments(params.name, params);
|
|
2389
|
+
try {
|
|
2390
|
+
const result = sanitizeRemoteCustodyOutput(await handler(args), context);
|
|
2391
|
+
return notification ? undefined : jsonRpcResult(id, toolCallContent(result, params.name));
|
|
2392
|
+
} catch (error) {
|
|
2393
|
+
return notification ? undefined : jsonRpcResult(id, toolCallError(error));
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
default:
|
|
2397
|
+
return notification ? undefined : jsonRpcError(id, JSON_RPC_ERROR.METHOD_NOT_FOUND, 'Method not found');
|
|
2398
|
+
}
|
|
2399
|
+
} catch (error) {
|
|
2400
|
+
if (notification) return undefined;
|
|
2401
|
+
if (isJsonRpcProtocolError(error)) return jsonRpcError(id, error.code, error.message, error.data);
|
|
2402
|
+
return jsonRpcError(id, JSON_RPC_ERROR.INTERNAL_ERROR, 'Internal error', { name: error.name });
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
export async function handleJsonRpcRequest(request, context = {}) {
|
|
2407
|
+
if (!Array.isArray(request)) return handleSingleJsonRpcRequest(request, context);
|
|
2408
|
+
if (request.length === 0) return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
2409
|
+
|
|
2410
|
+
const responses = [];
|
|
2411
|
+
for (const item of request) {
|
|
2412
|
+
const response = await handleSingleJsonRpcRequest(item, context);
|
|
2413
|
+
if (response !== undefined) responses.push(response);
|
|
2414
|
+
}
|
|
2415
|
+
return responses.length === 0 ? undefined : responses;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
function writeJsonLine(output, value) {
|
|
2419
|
+
if (value !== undefined) output.write(`${JSON.stringify(value)}\n`);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
export function startStdioServer(io = {}) {
|
|
2423
|
+
const input = io.input ?? io.stdin ?? process.stdin;
|
|
2424
|
+
const output = io.output ?? io.stdout ?? process.stdout;
|
|
2425
|
+
const errorOutput = io.errorOutput ?? io.stderr ?? process.stderr;
|
|
2426
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
2427
|
+
let queue = Promise.resolve();
|
|
2428
|
+
|
|
2429
|
+
async function processLine(line) {
|
|
2430
|
+
const trimmed = line.trim();
|
|
2431
|
+
if (!trimmed) return;
|
|
2432
|
+
try {
|
|
2433
|
+
writeJsonLine(output, await handleJsonRpcRequest(JSON.parse(trimmed)));
|
|
2434
|
+
} catch (error) {
|
|
2435
|
+
const parseError = error instanceof SyntaxError
|
|
2436
|
+
? jsonRpcError(null, -32700, 'Parse error')
|
|
2437
|
+
: jsonRpcError(null, JSON_RPC_ERROR.INTERNAL_ERROR, 'Internal error', { name: error.name });
|
|
2438
|
+
writeJsonLine(output, parseError);
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
lines.on('line', (line) => {
|
|
2443
|
+
queue = queue.then(() => processLine(line), () => processLine(line));
|
|
2444
|
+
});
|
|
2445
|
+
lines.on('error', (error) => {
|
|
2446
|
+
errorOutput?.write?.(`${error.message}\n`);
|
|
2447
|
+
});
|
|
2448
|
+
|
|
2449
|
+
return {
|
|
2450
|
+
close() {
|
|
2451
|
+
lines.close();
|
|
2452
|
+
},
|
|
2453
|
+
done: new Promise((resolveDone) => {
|
|
2454
|
+
lines.on('close', () => {
|
|
2455
|
+
queue.then(resolveDone, resolveDone);
|
|
2456
|
+
});
|
|
2457
|
+
}),
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
export default {
|
|
2462
|
+
toolDescriptors,
|
|
2463
|
+
resourceDescriptors,
|
|
2464
|
+
promptDescriptors,
|
|
2465
|
+
handlers,
|
|
2466
|
+
enigma_private_handoff_health,
|
|
2467
|
+
enigma_routing_contract,
|
|
2468
|
+
enigma_start_private_session,
|
|
2469
|
+
configureMcpInferenceRuntime,
|
|
2470
|
+
configureMcpX402Client,
|
|
2471
|
+
enigma_complete,
|
|
2472
|
+
enigma_generate_image,
|
|
2473
|
+
enigma_x402_execute,
|
|
2474
|
+
enigma_init,
|
|
2475
|
+
enigma_remember,
|
|
2476
|
+
enigma_search,
|
|
2477
|
+
enigma_context_pack,
|
|
2478
|
+
enigma_delete,
|
|
2479
|
+
enigma_verify_receipts,
|
|
2480
|
+
enigma_swarm_register_agent,
|
|
2481
|
+
enigma_graph_query,
|
|
2482
|
+
enigma_cluster_memories,
|
|
2483
|
+
enigma_swarm_sync,
|
|
2484
|
+
enigma_immune_ingress,
|
|
2485
|
+
enigma_meter_usage,
|
|
2486
|
+
enigma_settlement_job,
|
|
2487
|
+
enigma_settlement_capacity,
|
|
2488
|
+
enigma_settlement_quote,
|
|
2489
|
+
enigma_settlement_receipt,
|
|
2490
|
+
enigma_settlement_verify,
|
|
2491
|
+
enigma_settlement_batch,
|
|
2492
|
+
enigma_passport_summary_resource,
|
|
2493
|
+
enigma_standard_memory_prompt,
|
|
2494
|
+
createMcpImmuneIngressReport,
|
|
2495
|
+
assertMcpImmuneIngressPublicSafe,
|
|
2496
|
+
handleJsonRpcRequest,
|
|
2497
|
+
startStdioServer,
|
|
2498
|
+
};
|