enigma-memory 0.1.18 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -24
- package/apps/cli/bin/enigma-desktop.mjs +140 -0
- package/apps/cli/bin/enigma-terminal.mjs +78 -0
- package/apps/cli/bin/enigma.mjs +1923 -285
- package/apps/desktop/electron-main.cjs +217 -0
- package/apps/desktop/package.json +12 -0
- package/apps/desktop/src/app.js +264 -7
- package/apps/desktop/src/index.html +3514 -1373
- package/apps/desktop/src/launch-electron.mjs +51 -0
- package/apps/desktop/src/server.mjs +2914 -0
- package/apps/desktop/src/styles.css +2972 -260
- package/apps/desktop/src/zk-browser-prove.mjs +53 -0
- package/apps/desktop/src/zk-state.mjs +1789 -0
- package/apps/gateway/bin/enigma-gateway.mjs +102 -5
- package/apps/gateway/src/server.mjs +271 -8
- package/apps/ios/EnigmaCore/Package.swift +12 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
- package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
- package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
- package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
- package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
- package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
- package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
- package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
- package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
- package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
- package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
- package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
- package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
- package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
- package/apps/native-host/README.md +19 -8
- package/apps/native-host/bin/enigma-native-host.mjs +229 -13
- package/apps/relay/bin/enigma-relay.mjs +103 -5
- package/apps/relay/src/federation-runtime.mjs +618 -0
- package/apps/relay/src/server.mjs +310 -9
- package/apps/verifier/bin/enigma-verify.mjs +327 -11
- package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/vk_bytes.json +32 -0
- package/cortex-v3/proving-assets.json +64 -0
- package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
- package/cortex-v3/zk/action-transition-vk.json +119 -0
- package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
- package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
- package/cortex-v3/zk/intent-witness.mjs +365 -0
- package/cortex-v3/zk/intent-witness.test.mjs +485 -0
- package/cortex-v3/zk/proving-assets.mjs +203 -0
- package/cortex-v3/zk/sale-witness.mjs +783 -0
- package/cortex-v3/zk/sale-witness.test.mjs +784 -0
- package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
- package/cortex-v3/zk/settlement-evidence.mjs +722 -0
- package/cortex-v3/zk/setup-intent.mjs +688 -0
- package/cortex-v3/zk/setup-sale.mjs +666 -0
- package/cortex-v3/zk/setup.mjs +594 -0
- package/cortex-v3/zk/witness.mjs +184 -0
- package/cortex-v3/zk/zk-codec.mjs +232 -0
- package/cortex-v3/zk/zk-codec.test.mjs +293 -0
- package/cortex-v3/zk/zk-settle.mjs +370 -0
- package/cortex-v3/zk/zk-tree.mjs +256 -0
- package/cortex-v3/zk/zk-tree.test.mjs +419 -0
- package/deploy/docker-compose.local-production-simulation.yml +36 -0
- package/docs/browser-extension-install.md +8 -6
- package/docs/client-connectors.md +15 -11
- package/docs/developer-ecosystem.md +15 -13
- package/docs/enigma-memory-ready-conformance.md +11 -9
- package/docs/install-anywhere.md +61 -28
- package/docs/installers-and-desktop.md +8 -7
- package/docs/novelty-invention-candidates.md +161 -161
- package/docs/proof-network-claim-boundaries.md +320 -318
- package/examples/01-quickstart-agent/index.mjs +49 -0
- package/examples/01_agent_memory_quickstart.mjs +57 -0
- package/examples/02-multi-agent-swarm/index.mjs +57 -0
- package/examples/02_cross_model_passport.mjs +64 -0
- package/examples/03-langchain-memory/index.mjs +41 -0
- package/examples/03_poseidon_commitment_verification.mjs +71 -0
- package/examples/04-python-trading-agent/trader.py +49 -0
- package/examples/README.md +27 -0
- package/examples/ci/github-actions.yml +7 -2
- package/package.json +142 -11
- package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
- package/packages/connectors/src/index.js +196 -4
- package/packages/connectors/swarm-router.mjs +168 -0
- package/packages/core/src/index.js +248 -1
- package/packages/core/src/version.mjs +7 -0
- package/packages/dev-tools/package.json +19 -0
- package/packages/dev-tools/src/index.js +4 -0
- package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
- package/packages/dev-tools/src/swarm-simulator.js +101 -0
- package/packages/dev-tools/src/vault-inspector.js +114 -0
- package/packages/dev-tools/src/vector-benchmark.js +100 -0
- package/packages/developer-platform/src/access-credentials.js +341 -0
- package/packages/developer-platform/src/http.js +132 -0
- package/packages/developer-platform/src/index.js +4 -0
- package/packages/developer-platform/src/usage-http.js +60 -0
- package/packages/developer-platform/src/usage.js +295 -0
- package/packages/enclave-runtime/attestation.mjs +159 -0
- package/packages/enclave-runtime/index.mjs +47 -0
- package/packages/enclave-runtime/session-manager.mjs +253 -0
- package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
- package/packages/enigma-reflex/package.json +14 -0
- package/packages/enigma-reflex/src/index.js +204 -0
- package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
- package/packages/enigma-reflex/training/requirements.txt +8 -0
- package/packages/enigma-reflex/training/train.py +314 -0
- package/packages/enigma-weave/LICENSE +22 -0
- package/packages/enigma-weave/UPSTREAM.json +21 -0
- package/packages/enigma-weave/package.json +14 -0
- package/packages/enigma-weave/src/index.js +286 -0
- package/packages/hosted-cloud/src/index.js +80 -5
- package/packages/importers/src/index.js +432 -0
- package/packages/inference-runtime/src/browser.js +401 -0
- package/packages/inference-runtime/src/chat.js +265 -0
- package/packages/inference-runtime/src/code.js +407 -0
- package/packages/inference-runtime/src/contracts.js +162 -0
- package/packages/inference-runtime/src/http.js +232 -0
- package/packages/inference-runtime/src/image.js +186 -0
- package/packages/inference-runtime/src/index.js +10 -0
- package/packages/inference-runtime/src/model-router.js +320 -0
- package/packages/inference-runtime/src/platform.js +125 -0
- package/packages/inference-runtime/src/privacy.js +400 -0
- package/packages/inference-runtime/src/video.js +253 -0
- package/packages/mcp-server/README.md +22 -6
- package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
- package/packages/mcp-server/src/index.js +1418 -105
- package/packages/mcp-server/src/oauth.js +561 -0
- package/packages/mcp-server/src/private-handoff.js +84 -0
- package/packages/mcp-server/src/remote-http.js +273 -0
- package/packages/mcp-server/src/remote-policy.js +72 -0
- package/packages/mcp-server/swarm-bridge.mjs +361 -0
- package/packages/mesh/index.d.ts +283 -0
- package/packages/mesh/package.json +23 -0
- package/packages/mesh/src/crypto.js +189 -0
- package/packages/mesh/src/federation-packets.js +353 -0
- package/packages/mesh/src/gossip.js +311 -0
- package/packages/mesh/src/index.js +6 -0
- package/packages/mesh/src/protocol.js +255 -0
- package/packages/mesh/src/router.js +279 -0
- package/packages/mesh/src/transport.js +306 -0
- package/packages/passport/src/index.js +426 -1
- package/packages/private-economy/src/credits-http.js +100 -0
- package/packages/private-economy/src/credits.js +447 -0
- package/packages/private-economy/src/index.js +5 -0
- package/packages/private-economy/src/payments-http.js +120 -0
- package/packages/private-economy/src/payments.js +509 -0
- package/packages/private-economy/src/x402.js +346 -0
- package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
- package/packages/rag/index.d.ts +182 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
- package/packages/rag/package.json +27 -0
- package/packages/rag/src/blinded-search.js +109 -0
- package/packages/rag/src/bm25.js +169 -0
- package/packages/rag/src/embeddings.js +459 -0
- package/packages/rag/src/hybrid.js +76 -0
- package/packages/rag/src/index.js +38 -0
- package/packages/rag/src/reranker.js +61 -0
- package/packages/rag/src/research.js +107 -0
- package/packages/rag/src/vector-store.js +430 -0
- package/packages/rag/src/verify-model-artifacts.mjs +4 -0
- package/packages/sdk/index.d.ts +760 -0
- package/packages/sdk/package.json +33 -0
- package/packages/sdk/python/README.md +24 -0
- package/packages/sdk/python/enigma_sdk.py +250 -0
- package/packages/sdk/python/pyproject.toml +34 -0
- package/packages/sdk/python/requirements.txt +1 -0
- package/packages/sdk/python/setup.py +20 -0
- package/packages/sdk/src/federation/capability-grant.js +389 -0
- package/packages/sdk/src/federation/federation-router.js +360 -0
- package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
- package/packages/sdk/src/federation/index.js +3 -0
- package/packages/sdk/src/index.js +1796 -0
- package/packages/sdk/src/intelligence/contradiction.js +337 -0
- package/packages/sdk/src/intelligence/decision-engine.js +155 -0
- package/packages/sdk/src/intelligence/index.js +4 -0
- package/packages/sdk/src/intelligence/ontology.js +122 -0
- package/packages/sdk/src/intelligence/temporal.js +123 -0
- package/packages/sdk/src/market-client.js +142 -0
- package/packages/sdk/src/mesh-client.js +110 -0
- package/packages/sdk/src/middleware/index.js +3 -0
- package/packages/sdk/src/middleware/langchain.js +159 -0
- package/packages/sdk/src/middleware/llamaindex.js +101 -0
- package/packages/sdk/src/middleware/vercel-ai.js +112 -0
- package/packages/sdk/src/rag-client.js +85 -0
- package/packages/sdk/src/swarm-orchestrator.js +260 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
- package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
- package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
- package/packages/snapcompact/index.d.ts +284 -0
- package/packages/snapcompact/package.json +25 -0
- package/packages/snapcompact/src/index.js +716 -0
- package/packages/storage/PACKAGE_CONTRACT.md +1 -1
- package/packages/terminal-console/animations.mjs +240 -0
- package/packages/terminal-console/auto-anchor.mjs +220 -0
- package/packages/terminal-console/banner.mjs +91 -0
- package/packages/terminal-console/commands.mjs +459 -0
- package/packages/terminal-console/delegation.mjs +152 -0
- package/packages/terminal-console/index.mjs +5 -0
- package/packages/terminal-console/outbox.mjs +143 -0
- package/packages/terminal-console/phantom-bridge.mjs +637 -0
- package/packages/terminal-console/repl.mjs +136 -0
- package/packages/terminal-console/signer-store.mjs +130 -0
- package/packages/terminal-console/solana-rpc.mjs +214 -0
- package/packages/terminal-console/solana-transport.mjs +189 -0
- package/packages/terminal-tui/dashboard.mjs +214 -0
- package/packages/terminal-tui/index.mjs +28 -0
- package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
- package/packages/terminal-tui/telemetry-hud.mjs +137 -0
- package/packages/vault/index.d.ts +449 -0
- package/packages/vault/package.json +27 -0
- package/packages/vault/src/e2ee.mjs +393 -0
- package/packages/vault/src/enclave.js +481 -0
- package/packages/vault/src/erasure.js +207 -0
- package/packages/vault/src/index.js +1018 -155
- package/packages/vault/src/persistence.js +307 -0
- package/packages/vault/src/poseidon.js +354 -0
- package/packages/vault/src/receipt.js +459 -0
- package/scripts/benchmark-optical-context.mjs +166 -0
- package/scripts/bootstrap-enigma.mjs +502 -0
- package/scripts/build-edge-backend-workers.mjs +20 -5
- package/scripts/build-goal-completion-audit.mjs +72 -25
- package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
- package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
- package/scripts/build-hosted-probe-worker.mjs +19 -4
- package/scripts/build-installer-assets.mjs +41 -21
- package/scripts/build-operator-evidence-starter.mjs +59 -1
- package/scripts/build-production-backend-env-kit.mjs +2 -0
- package/scripts/build-production-unblocker.mjs +3 -0
- package/scripts/check.mjs +17 -3
- package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
- package/scripts/install-enigma-local.mjs +18 -5
- package/scripts/release-audit.mjs +65 -109
- package/scripts/release-provenance.mjs +6 -0
- package/scripts/run-backend-readiness-smoke.mjs +112 -10
- package/scripts/scan-secrets.mjs +1 -0
- package/scripts/simulate-production-env.mjs +7 -2
- package/scripts/validate-hosted-backend-live.mjs +112 -1
- package/specs/antibody-pack-v1.schema.json +95 -0
- package/specs/antigen-envelope-v1.schema.json +81 -0
- package/specs/boundary-manifest-v1.schema.json +35 -35
- package/specs/capsule-v1.schema.json +55 -55
- package/specs/claim-boundary-manifest-v1.schema.json +22 -22
- package/specs/claim-ledger-v1.schema.json +291 -0
- package/specs/context-passport-v1.schema.json +59 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -26
- package/specs/evidence-packet-v1.schema.json +177 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
- package/specs/immune-scan-report-v1.schema.json +112 -0
- package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
- package/specs/memory-atom-v1.schema.json +59 -0
- package/specs/memory-event-v1.schema.json +42 -42
- package/specs/passport-v1.schema.json +50 -50
- package/specs/proof-of-non-use-v1.schema.json +65 -0
- package/specs/quarantine-record-v1.schema.json +126 -0
- package/specs/receipt-v1.schema.json +61 -61
- package/specs/state-checkpoint-v1.schema.json +37 -37
- package/specs/trust-bundle-v1.schema.json +56 -56
- package/specs/trust-card-v1.schema.json +119 -0
- package/docs/proof-network-launch-plan.md +0 -421
- package/packages/metering/PACKAGE_CONTRACT.md +0 -20
- package/scripts/build-ai-orchestration-plan.mjs +0 -248
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
|
|
4
|
+
export const ENIGMA_CODE_SESSION_SCHEMA = 'enigma.code_session.v1';
|
|
5
|
+
const TERMINAL = new Set(['stopped', 'burned', 'failed']);
|
|
6
|
+
const DEFAULT_ALLOWED_COMMANDS = Object.freeze(['node', 'npm', 'npx']);
|
|
7
|
+
const WRITE_FILE_PROGRAM = `
|
|
8
|
+
const fs=require('node:fs');const path=require('node:path');
|
|
9
|
+
const root='/workspace';const relative=process.argv[1];const target=path.resolve(root,relative);
|
|
10
|
+
if(!target.startsWith(root+'/'))throw new Error('path escapes workspace');
|
|
11
|
+
fs.mkdirSync(path.dirname(target),{recursive:true});const chunks=[];
|
|
12
|
+
process.stdin.on('data',c=>chunks.push(c));process.stdin.on('end',()=>fs.writeFileSync(target,Buffer.concat(chunks),{mode:0o660}));
|
|
13
|
+
`;
|
|
14
|
+
const LIST_FILES_PROGRAM = `
|
|
15
|
+
const fs=require('node:fs');const path=require('node:path');const root='/workspace';const out=[];
|
|
16
|
+
function walk(dir,depth=0){if(depth>24)throw new Error('workspace nesting limit exceeded');for(const e of fs.readdirSync(dir,{withFileTypes:true})){if(out.length>=2000)throw new Error('workspace file limit exceeded');const p=path.join(dir,e.name);if(e.isDirectory())walk(p,depth+1);else if(e.isFile()){const s=fs.statSync(p);out.push({path:path.relative(root,p).replaceAll('\\\\','/'),bytes:s.size,modifiedAt:s.mtimeMs})}}}
|
|
17
|
+
walk(root);process.stdout.write(JSON.stringify(out.sort((a,b)=>a.path.localeCompare(b.path))));
|
|
18
|
+
`;
|
|
19
|
+
const READ_FILE_PROGRAM = `
|
|
20
|
+
const fs=require('node:fs');const path=require('node:path');const root='/workspace';const target=path.resolve(root,process.argv[1]);
|
|
21
|
+
if(!target.startsWith(root+'/'))throw new Error('path escapes workspace');process.stdout.write(fs.readFileSync(target).toString('base64'));
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
function requiredString(value, field, maxLength = 1_000_000) {
|
|
25
|
+
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${field} must be a non-empty string`);
|
|
26
|
+
if (value.length > maxLength) throw new TypeError(`${field} exceeds ${maxLength} characters`);
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function boundedInteger(value, field, minimum, maximum, fallback) {
|
|
31
|
+
const candidate = value === undefined ? fallback : value;
|
|
32
|
+
if (!Number.isInteger(candidate) || candidate < minimum || candidate > maximum) {
|
|
33
|
+
throw new TypeError(`${field} must be an integer from ${minimum} to ${maximum}`);
|
|
34
|
+
}
|
|
35
|
+
return candidate;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function safeRelativePath(value, field = 'path') {
|
|
39
|
+
const normalized = requiredString(value, field, 512).replaceAll('\\', '/').split('/').filter((part) => part && part !== '.').join('/');
|
|
40
|
+
if (!normalized || normalized.split('/').some((part) => part === '..') || normalized.startsWith('/') || /^[A-Za-z]:/.test(normalized)) {
|
|
41
|
+
throw new TypeError(`${field} must remain inside the sandbox workspace`);
|
|
42
|
+
}
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function publicSession(session) {
|
|
47
|
+
return {
|
|
48
|
+
schema: ENIGMA_CODE_SESSION_SCHEMA,
|
|
49
|
+
id: session.id,
|
|
50
|
+
provider: session.provider.id,
|
|
51
|
+
status: session.status,
|
|
52
|
+
language: session.language,
|
|
53
|
+
image: session.image,
|
|
54
|
+
imageId: session.imageId,
|
|
55
|
+
network: 'none',
|
|
56
|
+
createdAt: session.createdAt,
|
|
57
|
+
expiresAt: session.expiresAt,
|
|
58
|
+
eventCursor: session.events.length,
|
|
59
|
+
isolation: {
|
|
60
|
+
boundary: 'oci-container',
|
|
61
|
+
rootFilesystem: 'read-only',
|
|
62
|
+
capabilities: 'none',
|
|
63
|
+
noNewPrivileges: true,
|
|
64
|
+
workspace: 'ephemeral-tmpfs',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function addEvent(session, type, data = {}) {
|
|
70
|
+
const event = Object.freeze({ cursor: session.events.length + 1, type, at: Date.now(), ...data });
|
|
71
|
+
session.events.push(event);
|
|
72
|
+
if (session.events.length > 2_000) session.events.splice(0, session.events.length - 2_000);
|
|
73
|
+
return event;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function runProcess(binary, args, options = {}) {
|
|
77
|
+
const timeoutMs = options.timeoutMs || 30_000;
|
|
78
|
+
const maxOutputBytes = options.maxOutputBytes || 2 * 1024 * 1024;
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
const child = spawn(binary, args, {
|
|
81
|
+
windowsHide: true,
|
|
82
|
+
stdio: [options.stdin === undefined ? 'ignore' : 'pipe', 'pipe', 'pipe'],
|
|
83
|
+
env: options.env || process.env,
|
|
84
|
+
});
|
|
85
|
+
let stdout = Buffer.alloc(0);
|
|
86
|
+
let stderr = Buffer.alloc(0);
|
|
87
|
+
let settled = false;
|
|
88
|
+
let timedOut = false;
|
|
89
|
+
options.onSpawn?.(child);
|
|
90
|
+
const append = (current, chunk, stream) => {
|
|
91
|
+
options.onOutput?.(stream, chunk.toString('utf8'));
|
|
92
|
+
if (current.length >= maxOutputBytes) return current;
|
|
93
|
+
return Buffer.concat([current, chunk.subarray(0, maxOutputBytes - current.length)]);
|
|
94
|
+
};
|
|
95
|
+
child.stdout.on('data', (chunk) => { stdout = append(stdout, chunk, 'stdout'); });
|
|
96
|
+
child.stderr.on('data', (chunk) => { stderr = append(stderr, chunk, 'stderr'); });
|
|
97
|
+
child.once('error', (error) => {
|
|
98
|
+
if (!settled) {
|
|
99
|
+
settled = true;
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
reject(error);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
if (options.stdin !== undefined) child.stdin.end(options.stdin);
|
|
105
|
+
const timer = setTimeout(() => {
|
|
106
|
+
if (!settled) {
|
|
107
|
+
timedOut = true;
|
|
108
|
+
child.kill('SIGKILL');
|
|
109
|
+
}
|
|
110
|
+
}, timeoutMs);
|
|
111
|
+
child.once('exit', (code, signal) => {
|
|
112
|
+
if (settled) return;
|
|
113
|
+
settled = true;
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
resolve({
|
|
116
|
+
child,
|
|
117
|
+
code,
|
|
118
|
+
signal,
|
|
119
|
+
timedOut,
|
|
120
|
+
stdout: stdout.toString('utf8'),
|
|
121
|
+
stderr: stderr.toString('utf8'),
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function createOciSandboxProvider(options = {}) {
|
|
128
|
+
const id = String(options.id || 'oci-isolated-code');
|
|
129
|
+
const binary = String(options.binary || process.env.ENIGMA_OCI_RUNTIME || 'docker');
|
|
130
|
+
const image = String(options.image || process.env.ENIGMA_CODE_SANDBOX_IMAGE || 'node:24-bookworm-slim');
|
|
131
|
+
const pullPolicy = options.pullPolicy || 'missing';
|
|
132
|
+
if (!['never', 'missing', 'always'].includes(pullPolicy)) throw new TypeError('pullPolicy must be never, missing, or always');
|
|
133
|
+
const maxFileBytes = boundedInteger(options.maxFileBytes, 'maxFileBytes', 1_024, 32 * 1024 * 1024, 4 * 1024 * 1024);
|
|
134
|
+
const maxWorkspaceBytes = boundedInteger(options.maxWorkspaceBytes, 'maxWorkspaceBytes', maxFileBytes, 256 * 1024 * 1024, 32 * 1024 * 1024);
|
|
135
|
+
const memoryBytes = boundedInteger(options.memoryBytes, 'memoryBytes', 64 * 1024 * 1024, 8 * 1024 * 1024 * 1024, 512 * 1024 * 1024);
|
|
136
|
+
const pidsLimit = boundedInteger(options.pidsLimit, 'pidsLimit', 8, 512, 64);
|
|
137
|
+
const cpus = Number(options.cpus ?? 1);
|
|
138
|
+
if (!Number.isFinite(cpus) || cpus <= 0 || cpus > 16) throw new TypeError('cpus must be from 0.1 to 16');
|
|
139
|
+
const allowedCommands = new Set(options.allowedCommands || DEFAULT_ALLOWED_COMMANDS);
|
|
140
|
+
let prepared = null;
|
|
141
|
+
|
|
142
|
+
async function cli(args, config = {}) {
|
|
143
|
+
const result = await runProcess(binary, args, config);
|
|
144
|
+
if (result.code !== 0) {
|
|
145
|
+
const detail = (result.timedOut ? 'container engine command timed out' : result.stderr || result.stdout || `exit ${result.code}`).trim().slice(0, 2_000);
|
|
146
|
+
throw new Error(`OCI runtime failed: ${detail}`);
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function prepare() {
|
|
152
|
+
if (prepared) return prepared;
|
|
153
|
+
prepared = (async () => {
|
|
154
|
+
await cli(['version', '--format', '{{.Server.Version}}'], { timeoutMs: 20_000, maxOutputBytes: 16_384 });
|
|
155
|
+
if (pullPolicy === 'always') await cli(['pull', image], { timeoutMs: 10 * 60_000 });
|
|
156
|
+
let inspection;
|
|
157
|
+
try {
|
|
158
|
+
inspection = await cli(['image', 'inspect', '--format', '{{.Id}}', image], { timeoutMs: 20_000 });
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (pullPolicy !== 'missing') throw new Error(`sandbox image ${image} is unavailable and pulling is disabled`);
|
|
161
|
+
await cli(['pull', image], { timeoutMs: 10 * 60_000 });
|
|
162
|
+
inspection = await cli(['image', 'inspect', '--format', '{{.Id}}', image], { timeoutMs: 20_000 });
|
|
163
|
+
}
|
|
164
|
+
const imageId = requiredString(inspection.stdout, 'image id', 256).trim();
|
|
165
|
+
if (!/^sha256:[a-f0-9]{64}$/i.test(imageId)) throw new Error('OCI runtime returned an invalid image id');
|
|
166
|
+
if (options.expectedImageId && imageId !== options.expectedImageId) throw new Error('sandbox image digest does not match expectedImageId');
|
|
167
|
+
return { image, imageId };
|
|
168
|
+
})().catch((error) => { prepared = null; throw error; });
|
|
169
|
+
return prepared;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function exec(containerName, args, config = {}) {
|
|
173
|
+
return cli(['exec', '--user', '1000:1000', '--workdir', '/workspace', ...(config.interactive ? ['-i'] : []), containerName, ...args], config);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return Object.freeze({
|
|
177
|
+
id,
|
|
178
|
+
languages: Object.freeze(['javascript']),
|
|
179
|
+
allowedCommands: Object.freeze([...allowedCommands]),
|
|
180
|
+
prepare,
|
|
181
|
+
async createWorkspace() {
|
|
182
|
+
const pinned = await prepare();
|
|
183
|
+
const name = `enigma-code-${randomUUID()}`;
|
|
184
|
+
await cli([
|
|
185
|
+
'create', '--name', name,
|
|
186
|
+
'--label', 'com.enigma.runtime=code-sandbox',
|
|
187
|
+
'--network', 'none',
|
|
188
|
+
'--read-only',
|
|
189
|
+
'--pids-limit', String(pidsLimit),
|
|
190
|
+
'--memory', String(memoryBytes),
|
|
191
|
+
'--memory-swap', String(memoryBytes),
|
|
192
|
+
'--cpus', String(cpus),
|
|
193
|
+
'--cap-drop', 'ALL',
|
|
194
|
+
'--security-opt', 'no-new-privileges:true',
|
|
195
|
+
'--ipc', 'none',
|
|
196
|
+
'--ulimit', 'nofile=256:256',
|
|
197
|
+
'--tmpfs', `/workspace:rw,nosuid,nodev,exec,uid=1000,gid=1000,mode=0770,size=${maxWorkspaceBytes}`,
|
|
198
|
+
'--tmpfs', '/tmp:rw,nosuid,nodev,noexec,uid=1000,gid=1000,mode=0770,size=67108864',
|
|
199
|
+
'--user', '1000:1000',
|
|
200
|
+
'--workdir', '/workspace',
|
|
201
|
+
'--env', 'HOME=/tmp',
|
|
202
|
+
'--env', 'TMPDIR=/tmp',
|
|
203
|
+
'--entrypoint', 'node',
|
|
204
|
+
pinned.imageId,
|
|
205
|
+
'-e', 'setInterval(()=>{},2147483647)',
|
|
206
|
+
], { timeoutMs: 30_000 });
|
|
207
|
+
try {
|
|
208
|
+
await cli(['start', name], { timeoutMs: 30_000 });
|
|
209
|
+
return { containerName: name, ...pinned };
|
|
210
|
+
} catch (error) {
|
|
211
|
+
await runProcess(binary, ['rm', '-f', name], { timeoutMs: 20_000 }).catch(() => {});
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
async writeFile(workspace, relativePath, data) {
|
|
216
|
+
if (!Buffer.isBuffer(data)) data = Buffer.from(data);
|
|
217
|
+
if (data.length > maxFileBytes) throw new TypeError(`file exceeds ${maxFileBytes} bytes`);
|
|
218
|
+
const current = await this.listArtifacts(workspace);
|
|
219
|
+
const oldBytes = current.find((file) => file.path === relativePath)?.bytes || 0;
|
|
220
|
+
const total = current.reduce((sum, file) => sum + file.bytes, 0) - oldBytes + data.length;
|
|
221
|
+
if (total > maxWorkspaceBytes) throw new TypeError('sandbox workspace quota exceeded');
|
|
222
|
+
await exec(workspace.containerName, ['node', '-e', WRITE_FILE_PROGRAM, relativePath], {
|
|
223
|
+
interactive: true,
|
|
224
|
+
stdin: data,
|
|
225
|
+
timeoutMs: 30_000,
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
execute(workspace, request, hooks = {}) {
|
|
229
|
+
const command = Array.isArray(request.command) && request.command.length
|
|
230
|
+
? request.command.map(String)
|
|
231
|
+
: ['node', safeRelativePath(request.entry || 'main.js', 'entry')];
|
|
232
|
+
const executable = requiredString(command[0], 'command', 128);
|
|
233
|
+
if (!allowedCommands.has(executable)) throw new TypeError(`sandbox command is not allowed: ${executable}`);
|
|
234
|
+
for (const argument of command.slice(1)) {
|
|
235
|
+
if (argument.includes('\0') || argument.length > 8_192) throw new TypeError('sandbox command contains an invalid argument');
|
|
236
|
+
}
|
|
237
|
+
const timeoutMs = boundedInteger(request.timeoutMs, 'timeoutMs', 100, 120_000, 10_000);
|
|
238
|
+
const maxOutputBytes = boundedInteger(request.maxOutputBytes, 'maxOutputBytes', 1_024, 2 * 1024 * 1024, 256 * 1024);
|
|
239
|
+
let activeChild = null;
|
|
240
|
+
const completion = runProcess(binary, [
|
|
241
|
+
'exec', '--user', '1000:1000', '--workdir', '/workspace', workspace.containerName, ...command,
|
|
242
|
+
], {
|
|
243
|
+
timeoutMs,
|
|
244
|
+
maxOutputBytes,
|
|
245
|
+
onOutput: hooks.onOutput,
|
|
246
|
+
onSpawn(child) { activeChild = child; },
|
|
247
|
+
}).then(async (result) => {
|
|
248
|
+
if (result.timedOut) {
|
|
249
|
+
await runProcess(binary, ['kill', workspace.containerName], { timeoutMs: 10_000 }).catch(() => {});
|
|
250
|
+
}
|
|
251
|
+
return { code: result.code, signal: result.signal, timedOut: result.timedOut };
|
|
252
|
+
});
|
|
253
|
+
return { get child() { return activeChild; }, completion };
|
|
254
|
+
},
|
|
255
|
+
async listArtifacts(workspace) {
|
|
256
|
+
const result = await exec(workspace.containerName, ['node', '-e', LIST_FILES_PROGRAM], { timeoutMs: 30_000, maxOutputBytes: 8 * 1024 * 1024 });
|
|
257
|
+
const files = JSON.parse(result.stdout || '[]');
|
|
258
|
+
return files.filter((file) => file && typeof file.path === 'string' && Number.isFinite(file.bytes));
|
|
259
|
+
},
|
|
260
|
+
async readArtifact(workspace, relativePath) {
|
|
261
|
+
const result = await exec(workspace.containerName, ['node', '-e', READ_FILE_PROGRAM, relativePath], { timeoutMs: 30_000, maxOutputBytes: Math.ceil(maxFileBytes * 1.4) });
|
|
262
|
+
const data = Buffer.from(result.stdout, 'base64');
|
|
263
|
+
if (data.length > maxFileBytes) throw new Error('artifact exceeds readable file limit');
|
|
264
|
+
return data;
|
|
265
|
+
},
|
|
266
|
+
async stop(workspace) {
|
|
267
|
+
await cli(['stop', '--time', '2', workspace.containerName], { timeoutMs: 10_000 });
|
|
268
|
+
},
|
|
269
|
+
async destroy(workspace) {
|
|
270
|
+
await cli(['rm', '-f', '--volumes', workspace.containerName], { timeoutMs: 20_000 });
|
|
271
|
+
const verification = await runProcess(binary, ['container', 'inspect', workspace.containerName], {
|
|
272
|
+
timeoutMs: 20_000,
|
|
273
|
+
maxOutputBytes: 16_384,
|
|
274
|
+
});
|
|
275
|
+
if (verification.code === 0) throw new Error('OCI cleanup verification failed: container still exists');
|
|
276
|
+
const detail = `${verification.stderr}\n${verification.stdout}`;
|
|
277
|
+
if (!/no such (?:object|container)/i.test(detail)) {
|
|
278
|
+
throw new Error(`OCI cleanup verification failed: ${detail.trim().slice(0, 1_000)}`);
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function createCodeSandboxRuntime(options = {}) {
|
|
285
|
+
const provider = options.provider || createOciSandboxProvider(options.oci || {});
|
|
286
|
+
if (!provider || typeof provider.createWorkspace !== 'function' || typeof provider.execute !== 'function') {
|
|
287
|
+
throw new TypeError('code sandbox provider requires createWorkspace() and execute()');
|
|
288
|
+
}
|
|
289
|
+
const ttlMs = boundedInteger(options.ttlMs, 'ttlMs', 60_000, 24 * 60 * 60_000, 60 * 60_000);
|
|
290
|
+
const sessions = new Map();
|
|
291
|
+
|
|
292
|
+
async function getSession(id, { allowTerminal = false } = {}) {
|
|
293
|
+
const session = sessions.get(requiredString(id, 'session id', 512));
|
|
294
|
+
if (!session) throw new Error('code session not found');
|
|
295
|
+
if (session.status === 'cleanup_failed' && !allowTerminal) throw new Error('code session cleanup failed; retry burn');
|
|
296
|
+
if (Date.now() >= session.expiresAt && session.status !== 'burned') await burn(session.id, 'expired');
|
|
297
|
+
if (!allowTerminal && TERMINAL.has(session.status)) throw new Error(`code session is ${session.status}`);
|
|
298
|
+
return session;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function burn(id, reason = 'requested') {
|
|
302
|
+
const session = sessions.get(requiredString(id, 'session id', 512));
|
|
303
|
+
if (!session) throw new Error('code session not found');
|
|
304
|
+
if (session.status === 'burned') return publicSession(session);
|
|
305
|
+
session.activeRun?.child?.kill('SIGKILL');
|
|
306
|
+
session.activeRun = null;
|
|
307
|
+
try {
|
|
308
|
+
await provider.destroy(session.workspace);
|
|
309
|
+
} catch (error) {
|
|
310
|
+
session.status = 'cleanup_failed';
|
|
311
|
+
addEvent(session, 'cleanup.failed', { message: error.message });
|
|
312
|
+
const cleanupError = new Error(`sandbox cleanup failed; retry burn: ${error.message}`);
|
|
313
|
+
cleanupError.code = 'cleanup_failed';
|
|
314
|
+
throw cleanupError;
|
|
315
|
+
}
|
|
316
|
+
session.status = 'burned';
|
|
317
|
+
addEvent(session, 'session.burned', { reason });
|
|
318
|
+
return publicSession(session);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return Object.freeze({
|
|
322
|
+
async available() {
|
|
323
|
+
try { await provider.prepare?.(); return { available: true, provider: provider.id }; }
|
|
324
|
+
catch (error) { return { available: false, provider: provider.id, error: error.message }; }
|
|
325
|
+
},
|
|
326
|
+
async create(input = {}) {
|
|
327
|
+
const language = String(input.language || 'javascript').toLowerCase();
|
|
328
|
+
if (!(provider.languages || []).includes(language)) throw new TypeError(`unsupported sandbox language: ${language}`);
|
|
329
|
+
const workspace = await provider.createWorkspace({ language });
|
|
330
|
+
const now = Date.now();
|
|
331
|
+
const session = {
|
|
332
|
+
id: randomUUID(), provider, language, workspace, status: 'ready', createdAt: now, expiresAt: now + ttlMs,
|
|
333
|
+
image: workspace.image || null, imageId: workspace.imageId || null, events: [], activeRun: null,
|
|
334
|
+
};
|
|
335
|
+
sessions.set(session.id, session);
|
|
336
|
+
addEvent(session, 'session.ready');
|
|
337
|
+
return publicSession(session);
|
|
338
|
+
},
|
|
339
|
+
async upload(id, input = {}) {
|
|
340
|
+
const session = await getSession(id);
|
|
341
|
+
if (session.status === 'running') throw new Error('cannot upload while code is running');
|
|
342
|
+
const relativePath = safeRelativePath(input.path);
|
|
343
|
+
const encoding = input.encoding || 'utf8';
|
|
344
|
+
if (encoding !== 'utf8' && encoding !== 'base64') throw new TypeError('encoding must be utf8 or base64');
|
|
345
|
+
const data = Buffer.from(requiredString(input.data, 'data'), encoding);
|
|
346
|
+
await provider.writeFile(session.workspace, relativePath, data);
|
|
347
|
+
addEvent(session, 'file.created', { path: relativePath, bytes: data.length });
|
|
348
|
+
return { ok: true, path: relativePath, bytes: data.length };
|
|
349
|
+
},
|
|
350
|
+
async execute(id, input = {}) {
|
|
351
|
+
const session = await getSession(id);
|
|
352
|
+
if (session.status === 'running') throw new Error('code session is already running');
|
|
353
|
+
session.status = 'running';
|
|
354
|
+
addEvent(session, 'command.start', { command: input.command || ['node', input.entry || 'main.js'] });
|
|
355
|
+
try {
|
|
356
|
+
const run = provider.execute(session.workspace, input, {
|
|
357
|
+
onOutput(stream, data) { addEvent(session, 'command.output', { stream, data }); },
|
|
358
|
+
});
|
|
359
|
+
session.activeRun = run;
|
|
360
|
+
const result = await run.completion;
|
|
361
|
+
session.activeRun = null;
|
|
362
|
+
if (result.timedOut) {
|
|
363
|
+
session.status = 'failed';
|
|
364
|
+
addEvent(session, 'error', { ...result, message: 'sandbox execution timed out and the container was terminated' });
|
|
365
|
+
return { ok: false, ...result, artifacts: [], session: publicSession(session) };
|
|
366
|
+
}
|
|
367
|
+
session.status = 'ready';
|
|
368
|
+
const artifacts = await provider.listArtifacts(session.workspace);
|
|
369
|
+
addEvent(session, result.code === 0 ? 'done' : 'error', { ...result, artifacts });
|
|
370
|
+
return { ok: result.code === 0, ...result, artifacts, session: publicSession(session) };
|
|
371
|
+
} catch (error) {
|
|
372
|
+
session.activeRun = null;
|
|
373
|
+
session.status = 'failed';
|
|
374
|
+
addEvent(session, 'error', { message: error.message });
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
async events(id, after = 0) {
|
|
379
|
+
const session = await getSession(id, { allowTerminal: true });
|
|
380
|
+
const cursor = Number.isInteger(after) && after >= 0 ? after : 0;
|
|
381
|
+
return { session: publicSession(session), events: session.events.filter((event) => event.cursor > cursor) };
|
|
382
|
+
},
|
|
383
|
+
async artifacts(id) {
|
|
384
|
+
const session = await getSession(id, { allowTerminal: true });
|
|
385
|
+
if (session.status === 'burned') return [];
|
|
386
|
+
return provider.listArtifacts(session.workspace);
|
|
387
|
+
},
|
|
388
|
+
async artifact(id, relativePath) {
|
|
389
|
+
const session = await getSession(id);
|
|
390
|
+
return provider.readArtifact(session.workspace, safeRelativePath(relativePath));
|
|
391
|
+
},
|
|
392
|
+
async stop(id) {
|
|
393
|
+
const session = await getSession(id, { allowTerminal: true });
|
|
394
|
+
if (session.status === 'burned') return publicSession(session);
|
|
395
|
+
session.activeRun?.child?.kill('SIGKILL');
|
|
396
|
+
session.activeRun = null;
|
|
397
|
+
await provider.stop?.(session.workspace);
|
|
398
|
+
session.status = 'stopped';
|
|
399
|
+
addEvent(session, 'session.stopped');
|
|
400
|
+
return publicSession(session);
|
|
401
|
+
},
|
|
402
|
+
burn,
|
|
403
|
+
async close() {
|
|
404
|
+
await Promise.all([...sessions.values()].filter((session) => session.status !== 'burned').map((session) => burn(session.id, 'runtime-close')));
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
export const ENIGMA_PROTOCOL_VERSION = '2026-08-25';
|
|
2
|
+
|
|
3
|
+
function deepFreeze(value) {
|
|
4
|
+
if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
|
|
5
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
6
|
+
return Object.freeze(value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const ENIGMA_PLATFORM_CONTRACT = deepFreeze({
|
|
10
|
+
brand: {
|
|
11
|
+
product: 'Enigma Cortex',
|
|
12
|
+
assistant: 'Enigma',
|
|
13
|
+
privateHandoffScheme: 'enigma://private',
|
|
14
|
+
adaptiveRouter: 'Enigma Weave',
|
|
15
|
+
trainingPlane: 'Enigma Reflex',
|
|
16
|
+
},
|
|
17
|
+
privacy: {
|
|
18
|
+
modes: ['off', 'smart', 'strict'],
|
|
19
|
+
smartDecisions: ['local', 'remote-redacted', 'private-route', 'block'],
|
|
20
|
+
promptRetention: false,
|
|
21
|
+
outputRetention: false,
|
|
22
|
+
rawUsageRows: false,
|
|
23
|
+
networkPrivacy: 'transport-dependent',
|
|
24
|
+
},
|
|
25
|
+
endpoints: {
|
|
26
|
+
health: 'GET /api/health',
|
|
27
|
+
models: 'GET /v1/models',
|
|
28
|
+
chat: 'POST /v1/chat/completions',
|
|
29
|
+
images: 'POST /v1/images/generations',
|
|
30
|
+
imageModels: 'GET /v1/images/models',
|
|
31
|
+
videoQueue: 'POST /v1/videos/queue',
|
|
32
|
+
videoRetrieve: 'POST /v1/videos/retrieve',
|
|
33
|
+
videoModels: 'GET /v1/videos/models',
|
|
34
|
+
browserSessions: 'POST /v1/browser/sessions',
|
|
35
|
+
browserSession: '/v1/browser/sessions/:sessionId',
|
|
36
|
+
codeSessions: 'POST /v1/code/sessions',
|
|
37
|
+
codeSession: '/v1/code/sessions/:sessionId',
|
|
38
|
+
usage: 'GET /v1/usage',
|
|
39
|
+
credits: 'GET /v1/credits',
|
|
40
|
+
apiKeys: '/v1/api-keys',
|
|
41
|
+
quote: 'POST /v1/payments/quote',
|
|
42
|
+
x402: 'POST /v1/x402/chat/completions',
|
|
43
|
+
mcp: 'POST /mcp',
|
|
44
|
+
oauthProtectedResource: 'GET /.well-known/oauth-protected-resource/mcp',
|
|
45
|
+
oauthServer: 'GET /.well-known/oauth-authorization-server',
|
|
46
|
+
},
|
|
47
|
+
chat: {
|
|
48
|
+
request: {
|
|
49
|
+
required: ['model', 'messages'],
|
|
50
|
+
optional: [
|
|
51
|
+
'temperature',
|
|
52
|
+
'max_tokens',
|
|
53
|
+
'stream',
|
|
54
|
+
'privacy_mode',
|
|
55
|
+
'privacy_proof',
|
|
56
|
+
'reasoning_effort',
|
|
57
|
+
'connectors',
|
|
58
|
+
'web_search',
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
stream: {
|
|
62
|
+
transport: 'server-sent-events',
|
|
63
|
+
terminalFrame: '[DONE]',
|
|
64
|
+
eventTypes: ['delta', 'thinking', 'citation', 'privacy', 'route', 'usage', 'receipt'],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
images: {
|
|
68
|
+
formats: ['webp', 'png', 'jpeg'],
|
|
69
|
+
width: { min: 256, max: 2048 },
|
|
70
|
+
height: { min: 256, max: 2048 },
|
|
71
|
+
variants: { min: 1, max: 4 },
|
|
72
|
+
retention: 'caller-controlled',
|
|
73
|
+
},
|
|
74
|
+
video: {
|
|
75
|
+
lifecycle: ['queued', 'running', 'succeeded', 'failed', 'cancelled', 'expired'],
|
|
76
|
+
inputs: ['text', 'image'],
|
|
77
|
+
output: 'video/mp4',
|
|
78
|
+
retrieval: 'poll-or-provider-webhook',
|
|
79
|
+
},
|
|
80
|
+
browser: {
|
|
81
|
+
lifecycle: ['created', 'starting', 'ready', 'burning', 'burned', 'failed'],
|
|
82
|
+
controls: ['navigate', 'click', 'type', 'keypress', 'scroll', 'back', 'forward', 'reload'],
|
|
83
|
+
maxTabs: 5,
|
|
84
|
+
burnClears: ['cookies', 'cache', 'history', 'downloads', 'temporary-profile'],
|
|
85
|
+
ssrfPolicy: 'resolve-and-deny-private-special-use-addresses',
|
|
86
|
+
},
|
|
87
|
+
code: {
|
|
88
|
+
lifecycle: ['created', 'ready', 'running', 'waiting-approval', 'stopped', 'burned', 'failed'],
|
|
89
|
+
events: [
|
|
90
|
+
'session.ready',
|
|
91
|
+
'command.start',
|
|
92
|
+
'command.output',
|
|
93
|
+
'file.created',
|
|
94
|
+
'file.modified',
|
|
95
|
+
'approval.requested',
|
|
96
|
+
'preview.ready',
|
|
97
|
+
'done',
|
|
98
|
+
'error',
|
|
99
|
+
],
|
|
100
|
+
isolation: 'ephemeral-workspace-plus-provider-enforced-resource-policy',
|
|
101
|
+
},
|
|
102
|
+
oauth: {
|
|
103
|
+
grantTypes: ['authorization_code', 'refresh_token'],
|
|
104
|
+
responseTypes: ['code'],
|
|
105
|
+
tokenEndpointAuthMethods: ['none', 'client_secret_basic', 'client_secret_post'],
|
|
106
|
+
codeChallengeMethods: ['S256'],
|
|
107
|
+
dynamicClientRegistration: 'policy-gated',
|
|
108
|
+
nativeRedirectSchemes: ['enigma-ios'],
|
|
109
|
+
accessTokenTransport: 'authorization-bearer-header',
|
|
110
|
+
scopes: [
|
|
111
|
+
'mcp:invoke',
|
|
112
|
+
'models:invoke',
|
|
113
|
+
'images:generate',
|
|
114
|
+
'video:generate',
|
|
115
|
+
'code:execute',
|
|
116
|
+
'browser:control',
|
|
117
|
+
'usage:read',
|
|
118
|
+
'credits:create',
|
|
119
|
+
'offline_access',
|
|
120
|
+
],
|
|
121
|
+
mcpScope: 'mcp:invoke',
|
|
122
|
+
},
|
|
123
|
+
credits: {
|
|
124
|
+
representation: 'accountless-pseudonymous-ledger',
|
|
125
|
+
custody: 'ephemeral-access-token-plus-rotating-one-time-recovery-code',
|
|
126
|
+
credentialVerifierStorage: 'salted-scrypt-hashes-only',
|
|
127
|
+
ledgerStorage: 'pseudonymous-vault-ids-balances-reservations-ledger-entries-and-timestamps',
|
|
128
|
+
balanceUnit: 'microcredits',
|
|
129
|
+
fundingBoundary: 'payment records link the pseudonymous vault to the funding rail',
|
|
130
|
+
},
|
|
131
|
+
settlement: {
|
|
132
|
+
rails: ['solana-usdc-transfer', 'solana-token-burn', 'stripe-subscription', 'x402-v2'],
|
|
133
|
+
verification: 'finalized-chain-evidence-or-verified-stripe-webhook',
|
|
134
|
+
x402: {
|
|
135
|
+
paymentRequiredStatus: 402,
|
|
136
|
+
requestHeader: 'PAYMENT-SIGNATURE',
|
|
137
|
+
requiredHeader: 'PAYMENT-REQUIRED',
|
|
138
|
+
responseHeader: 'PAYMENT-RESPONSE',
|
|
139
|
+
settlementBeforeExecution: true,
|
|
140
|
+
privacyBoundary: 'public-chain-unless-caller-selects-a-real-private-settlement-route',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
mcp: {
|
|
144
|
+
transport: 'streamable-http',
|
|
145
|
+
resource: '/mcp',
|
|
146
|
+
tools: [
|
|
147
|
+
'enigma_health',
|
|
148
|
+
'enigma_routing_contract',
|
|
149
|
+
'enigma_list_models',
|
|
150
|
+
'enigma_start_private_session',
|
|
151
|
+
'enigma_call_private_completion',
|
|
152
|
+
'enigma_quote_completion',
|
|
153
|
+
'enigma_create_x402_completion_request',
|
|
154
|
+
'enigma_generate_image',
|
|
155
|
+
],
|
|
156
|
+
privatePromptBoundary: 'sensitive prompts are entered inside Enigma, never in the host tool arguments',
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
export function platformContract() {
|
|
161
|
+
return ENIGMA_PLATFORM_CONTRACT;
|
|
162
|
+
}
|