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,232 @@
|
|
|
1
|
+
const JSON_TYPE = 'application/json; charset=utf-8';
|
|
2
|
+
|
|
3
|
+
function writeJson(res, status, value, headers = {}) {
|
|
4
|
+
const body = JSON.stringify(value);
|
|
5
|
+
res.writeHead(status, {
|
|
6
|
+
'Content-Type': JSON_TYPE,
|
|
7
|
+
'Content-Length': Buffer.byteLength(body),
|
|
8
|
+
'Cache-Control': 'no-store',
|
|
9
|
+
'X-Content-Type-Options': 'nosniff',
|
|
10
|
+
...headers,
|
|
11
|
+
});
|
|
12
|
+
res.end(body);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function routeError(error) {
|
|
16
|
+
const status = error?.statusCode || (error instanceof TypeError ? 400 : 500);
|
|
17
|
+
return { status, body: { error: { code: error?.code || (status === 400 ? 'invalid_request' : 'platform_error'), message: error?.message || 'platform request failed' } } };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function readJson(req, maxBytes = 1024 * 1024) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const chunks = [];
|
|
23
|
+
let bytes = 0;
|
|
24
|
+
let rejected = false;
|
|
25
|
+
req.on('data', (chunk) => {
|
|
26
|
+
if (rejected) return;
|
|
27
|
+
bytes += chunk.length;
|
|
28
|
+
if (bytes > maxBytes) {
|
|
29
|
+
rejected = true;
|
|
30
|
+
const error = new Error(`request body exceeds ${maxBytes} bytes`);
|
|
31
|
+
error.code = 'payload_too_large';
|
|
32
|
+
error.statusCode = 413;
|
|
33
|
+
reject(error);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
chunks.push(chunk);
|
|
37
|
+
});
|
|
38
|
+
req.once('error', reject);
|
|
39
|
+
req.once('end', () => {
|
|
40
|
+
if (rejected) return;
|
|
41
|
+
try { resolve(JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')); }
|
|
42
|
+
catch { const error = new TypeError('request body must be valid JSON'); error.code = 'invalid_json'; reject(error); }
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function match(pathname, expression) {
|
|
48
|
+
const value = expression.exec(pathname);
|
|
49
|
+
return value ? value.slice(1).map(decodeURIComponent) : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function unavailable(capability) {
|
|
53
|
+
const error = new Error(`${capability} runtime is not configured`);
|
|
54
|
+
error.code = 'runtime_unavailable';
|
|
55
|
+
error.statusCode = 503;
|
|
56
|
+
return error;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function createInferenceHttpHandler(options = {}) {
|
|
60
|
+
const chat = options.chat || null;
|
|
61
|
+
const images = options.images || null;
|
|
62
|
+
const videos = options.videos || null;
|
|
63
|
+
const code = options.code || null;
|
|
64
|
+
const browser = options.browser || null;
|
|
65
|
+
const authorize = options.authorize;
|
|
66
|
+
if (typeof authorize !== 'function') throw new TypeError('platform HTTP handler requires an explicit authorizer');
|
|
67
|
+
|
|
68
|
+
async function handle(req, res, url) {
|
|
69
|
+
if (!url.pathname.startsWith('/v1/')) return false;
|
|
70
|
+
try {
|
|
71
|
+
let authorized = false;
|
|
72
|
+
try {
|
|
73
|
+
authorized = await authorize(req, res);
|
|
74
|
+
} catch {
|
|
75
|
+
if (!res.writableEnded) writeJson(res, 401, { error: { code: 'authorization_failed', message: 'platform authorization failed' } });
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (!authorized) {
|
|
79
|
+
if (!res.writableEnded) writeJson(res, 401, { error: { code: 'unauthorized', message: 'platform authorization required' } });
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (req.method === 'GET' && url.pathname === '/v1/platform') {
|
|
83
|
+
writeJson(res, 200, { object: 'enigma.platform', capabilities: { chat: Boolean(chat), images: Boolean(images), videos: Boolean(videos), code: Boolean(code), browser: Boolean(browser) } });
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (req.method === 'GET' && url.pathname === '/v1/models') {
|
|
87
|
+
if (!chat) throw unavailable('chat');
|
|
88
|
+
writeJson(res, 200, { object: 'list', data: chat.listModels() });
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
if (req.method === 'POST' && url.pathname === '/v1/chat/completions') {
|
|
92
|
+
if (!chat) throw unavailable('chat');
|
|
93
|
+
const payload = await readJson(req, 8 * 1024 * 1024);
|
|
94
|
+
if (payload.stream === true) {
|
|
95
|
+
res.writeHead(200, { 'Content-Type': 'text/event-stream; charset=utf-8', 'Cache-Control': 'no-store, no-transform', Connection: 'keep-alive', 'X-Accel-Buffering': 'no' });
|
|
96
|
+
try {
|
|
97
|
+
await chat.complete(payload, { onEvent(event) { if (!res.writableEnded) res.write(`data: ${JSON.stringify(event)}\n\n`); } });
|
|
98
|
+
if (!res.writableEnded) res.end('data: [DONE]\n\n');
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (!res.writableEnded) res.end(`data: ${JSON.stringify({ error: routeError(error).body.error })}\n\ndata: [DONE]\n\n`);
|
|
101
|
+
}
|
|
102
|
+
} else writeJson(res, 200, await chat.complete(payload));
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (req.method === 'GET' && url.pathname === '/v1/images/models') {
|
|
106
|
+
if (!images) throw unavailable('images');
|
|
107
|
+
writeJson(res, 200, { object: 'list', data: images.listModels() });
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
if (req.method === 'POST' && url.pathname === '/v1/images/generations') {
|
|
111
|
+
if (!images) throw unavailable('images');
|
|
112
|
+
writeJson(res, 200, await images.generate(await readJson(req, 20 * 1024 * 1024)));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
if (req.method === 'GET' && url.pathname === '/v1/videos/models') {
|
|
116
|
+
if (!videos) throw unavailable('videos');
|
|
117
|
+
writeJson(res, 200, { object: 'list', data: videos.listModels() });
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
if (req.method === 'POST' && url.pathname === '/v1/videos/queue') {
|
|
121
|
+
if (!videos) throw unavailable('videos');
|
|
122
|
+
writeJson(res, 202, await videos.queue(await readJson(req, 20 * 1024 * 1024)));
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (req.method === 'POST' && url.pathname === '/v1/videos/retrieve') {
|
|
126
|
+
if (!videos) throw unavailable('videos');
|
|
127
|
+
const payload = await readJson(req);
|
|
128
|
+
writeJson(res, 200, await videos.retrieve(payload.id));
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
if (req.method === 'POST' && url.pathname === '/v1/code/sessions') {
|
|
132
|
+
if (!code) throw unavailable('code');
|
|
133
|
+
writeJson(res, 201, { session: await code.create(await readJson(req)) });
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
let route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/uploads$/);
|
|
137
|
+
if (req.method === 'POST' && route) {
|
|
138
|
+
if (!code) throw unavailable('code');
|
|
139
|
+
writeJson(res, 201, await code.upload(route[0], await readJson(req, 8 * 1024 * 1024)));
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/execute$/);
|
|
143
|
+
if (req.method === 'POST' && route) {
|
|
144
|
+
if (!code) throw unavailable('code');
|
|
145
|
+
writeJson(res, 200, await code.execute(route[0], await readJson(req)));
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/events$/);
|
|
149
|
+
if (req.method === 'GET' && route) {
|
|
150
|
+
if (!code) throw unavailable('code');
|
|
151
|
+
writeJson(res, 200, await code.events(route[0], Number(url.searchParams.get('after') || 0)));
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/artifacts$/);
|
|
155
|
+
if (req.method === 'GET' && route) {
|
|
156
|
+
if (!code) throw unavailable('code');
|
|
157
|
+
writeJson(res, 200, { artifacts: await code.artifacts(route[0]) });
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/artifacts\/(.+)$/);
|
|
161
|
+
if (req.method === 'GET' && route) {
|
|
162
|
+
if (!code) throw unavailable('code');
|
|
163
|
+
const artifact = await code.artifact(route[0], route[1]);
|
|
164
|
+
res.writeHead(200, { 'Content-Type': 'application/octet-stream', 'Content-Length': artifact.length, 'Cache-Control': 'no-store' });
|
|
165
|
+
res.end(artifact);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)\/stop$/);
|
|
169
|
+
if (req.method === 'POST' && route) {
|
|
170
|
+
if (!code) throw unavailable('code');
|
|
171
|
+
writeJson(res, 200, { session: await code.stop(route[0]) });
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
route = match(url.pathname, /^\/v1\/code\/sessions\/([^/]+)$/);
|
|
175
|
+
if (req.method === 'DELETE' && route) {
|
|
176
|
+
if (!code) throw unavailable('code');
|
|
177
|
+
writeJson(res, 200, { session: await code.burn(route[0]) });
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
if (req.method === 'POST' && url.pathname === '/v1/browser/sessions') {
|
|
181
|
+
if (!browser) throw unavailable('browser');
|
|
182
|
+
writeJson(res, 201, { session: await browser.create(await readJson(req)) });
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)\/status$/);
|
|
186
|
+
if (req.method === 'GET' && route) {
|
|
187
|
+
if (!browser) throw unavailable('browser');
|
|
188
|
+
writeJson(res, 200, { session: await browser.status(route[0]) });
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)\/connect$/);
|
|
192
|
+
if (req.method === 'POST' && route) {
|
|
193
|
+
if (!browser) throw unavailable('browser');
|
|
194
|
+
writeJson(res, 200, { session: await browser.connect(route[0]) });
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)\/navigate$/);
|
|
198
|
+
if (req.method === 'POST' && route) {
|
|
199
|
+
if (!browser) throw unavailable('browser');
|
|
200
|
+
writeJson(res, 200, { session: await browser.navigate(route[0], await readJson(req)) });
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)\/control$/);
|
|
204
|
+
if (req.method === 'POST' && route) {
|
|
205
|
+
if (!browser) throw unavailable('browser');
|
|
206
|
+
writeJson(res, 200, await browser.control(route[0], await readJson(req)));
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)\/render$/);
|
|
210
|
+
if (req.method === 'GET' && route) {
|
|
211
|
+
if (!browser) throw unavailable('browser');
|
|
212
|
+
writeJson(res, 200, { render: await browser.render(route[0]) });
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
route = match(url.pathname, /^\/v1\/browser\/sessions\/([^/]+)$/);
|
|
216
|
+
if (req.method === 'DELETE' && route) {
|
|
217
|
+
if (!browser) throw unavailable('browser');
|
|
218
|
+
writeJson(res, 200, { session: await browser.burn(route[0]) });
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
writeJson(res, 404, { error: { code: 'not_found', message: 'platform route not found' } });
|
|
222
|
+
return true;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (res.writableEnded || res.destroyed) return true;
|
|
225
|
+
const routed = routeError(error);
|
|
226
|
+
writeJson(res, routed.status, routed.body);
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return Object.freeze({ handle });
|
|
232
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export const ENIGMA_IMAGE_JOB_SCHEMA = 'enigma.image_job.v1';
|
|
4
|
+
export const ENIGMA_IMAGE_RESULT_SCHEMA = 'enigma.image_result.v1';
|
|
5
|
+
|
|
6
|
+
const FORMATS = new Set(['png', 'jpeg', 'webp']);
|
|
7
|
+
const runtimeReferenceKey = randomBytes(32);
|
|
8
|
+
|
|
9
|
+
function requiredString(value, field, maxLength = 16_000) {
|
|
10
|
+
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${field} must be a non-empty string`);
|
|
11
|
+
const normalized = value.trim();
|
|
12
|
+
if (normalized.length > maxLength) throw new TypeError(`${field} exceeds ${maxLength} characters`);
|
|
13
|
+
return normalized;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function boundedInteger(value, field, minimum, maximum, fallback) {
|
|
17
|
+
const candidate = value === undefined ? fallback : value;
|
|
18
|
+
if (!Number.isInteger(candidate) || candidate < minimum || candidate > maximum) {
|
|
19
|
+
throw new TypeError(`${field} must be an integer from ${minimum} to ${maximum}`);
|
|
20
|
+
}
|
|
21
|
+
return candidate;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function boundedNumber(value, field, minimum, maximum, fallback) {
|
|
25
|
+
const candidate = value === undefined ? fallback : value;
|
|
26
|
+
if (typeof candidate !== 'number' || !Number.isFinite(candidate) || candidate < minimum || candidate > maximum) {
|
|
27
|
+
throw new TypeError(`${field} must be a finite number from ${minimum} to ${maximum}`);
|
|
28
|
+
}
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function promptReference(prompt) {
|
|
33
|
+
return createHmac('sha256', runtimeReferenceKey).update(prompt).digest('hex');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizedAsset(asset, format) {
|
|
37
|
+
if (!asset || typeof asset !== 'object') throw new TypeError('image provider returned an invalid asset');
|
|
38
|
+
if (typeof asset.url === 'string') {
|
|
39
|
+
const url = new URL(asset.url);
|
|
40
|
+
if (url.protocol !== 'https:' && url.protocol !== 'data:') throw new TypeError('image asset URL must use HTTPS or data:');
|
|
41
|
+
return { url: url.toString(), format: asset.format || format };
|
|
42
|
+
}
|
|
43
|
+
if (typeof asset.base64 === 'string') {
|
|
44
|
+
if (asset.base64.length > 32 * 1024 * 1024) throw new TypeError('image asset exceeds the 24 MiB decoded limit');
|
|
45
|
+
return { base64: asset.base64, format: asset.format || format };
|
|
46
|
+
}
|
|
47
|
+
throw new TypeError('image provider asset requires url or base64');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function normalizeImageRequest(input = {}) {
|
|
51
|
+
const prompt = requiredString(input.prompt, 'prompt');
|
|
52
|
+
const model = requiredString(input.model, 'model', 160);
|
|
53
|
+
const format = input.format === undefined ? 'webp' : String(input.format).toLowerCase();
|
|
54
|
+
if (!FORMATS.has(format)) throw new TypeError('format must be png, jpeg, or webp');
|
|
55
|
+
return {
|
|
56
|
+
prompt,
|
|
57
|
+
model,
|
|
58
|
+
negativePrompt: typeof input.negativePrompt === 'string' ? input.negativePrompt.slice(0, 8_000) : '',
|
|
59
|
+
width: boundedInteger(input.width, 'width', 256, 2_048, 1_024),
|
|
60
|
+
height: boundedInteger(input.height, 'height', 256, 2_048, 1_024),
|
|
61
|
+
steps: boundedInteger(input.steps, 'steps', 1, 100, 30),
|
|
62
|
+
cfgScale: boundedNumber(input.cfgScale, 'cfgScale', 1, 30, 7.5),
|
|
63
|
+
variants: boundedInteger(input.variants, 'variants', 1, 4, 1),
|
|
64
|
+
format,
|
|
65
|
+
seed: input.seed === undefined ? null : boundedInteger(input.seed, 'seed', 0, 2_147_483_647, 0),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function createOpenAIImageProvider(options = {}) {
|
|
70
|
+
const id = requiredString(options.id || 'openai-images', 'provider id', 160);
|
|
71
|
+
const baseUrl = new URL(options.baseUrl || 'https://api.openai.com/v1/');
|
|
72
|
+
const models = new Set((options.models || []).map((model) => requiredString(model, 'model', 160)));
|
|
73
|
+
if (models.size === 0) throw new TypeError('OpenAI image provider requires at least one model');
|
|
74
|
+
const apiKey = requiredString(options.apiKey, 'apiKey', 4_096);
|
|
75
|
+
return Object.freeze({
|
|
76
|
+
id,
|
|
77
|
+
models: Object.freeze([...models]),
|
|
78
|
+
async generate(request, context = {}) {
|
|
79
|
+
if (!models.has(request.model)) throw new TypeError(`model ${request.model} is not configured for ${id}`);
|
|
80
|
+
const endpoint = new URL('images/generations', baseUrl);
|
|
81
|
+
const response = await fetch(endpoint, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
model: request.model,
|
|
86
|
+
prompt: request.negativePrompt ? `${request.prompt}\n\nAvoid: ${request.negativePrompt}` : request.prompt,
|
|
87
|
+
n: request.variants,
|
|
88
|
+
size: `${request.width}x${request.height}`,
|
|
89
|
+
response_format: 'b64_json',
|
|
90
|
+
}),
|
|
91
|
+
signal: context.signal,
|
|
92
|
+
});
|
|
93
|
+
const payload = await response.json();
|
|
94
|
+
if (!response.ok) throw new Error(`image provider ${id} failed with HTTP ${response.status}`);
|
|
95
|
+
if (!Array.isArray(payload.data)) throw new Error(`image provider ${id} returned no data array`);
|
|
96
|
+
return {
|
|
97
|
+
assets: payload.data.map((item) => item.b64_json
|
|
98
|
+
? { base64: item.b64_json, format: request.format }
|
|
99
|
+
: { url: item.url, format: request.format }),
|
|
100
|
+
providerRequestId: response.headers.get('x-request-id') || null,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function createImageBackend(options = {}) {
|
|
107
|
+
const providers = new Map();
|
|
108
|
+
for (const provider of options.providers || []) {
|
|
109
|
+
if (!provider || typeof provider.generate !== 'function') throw new TypeError('image provider requires generate()');
|
|
110
|
+
const id = requiredString(provider.id, 'provider id', 160);
|
|
111
|
+
if (providers.has(id)) throw new TypeError(`duplicate image provider: ${id}`);
|
|
112
|
+
const models = [...new Set((provider.models || []).map((model) => requiredString(model, 'model', 160)))];
|
|
113
|
+
if (models.length === 0) throw new TypeError(`image provider ${id} requires models`);
|
|
114
|
+
providers.set(id, Object.freeze({ ...provider, id, models: Object.freeze(models) }));
|
|
115
|
+
}
|
|
116
|
+
const modelRoutes = new Map();
|
|
117
|
+
for (const provider of providers.values()) {
|
|
118
|
+
for (const model of provider.models) {
|
|
119
|
+
if (modelRoutes.has(model)) throw new TypeError(`image model has multiple providers without an explicit router: ${model}`);
|
|
120
|
+
modelRoutes.set(model, provider);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const timeoutMs = boundedInteger(options.timeoutMs, 'timeoutMs', 1_000, 15 * 60_000, 120_000);
|
|
124
|
+
|
|
125
|
+
return Object.freeze({
|
|
126
|
+
listModels() {
|
|
127
|
+
return [...modelRoutes].map(([model, provider]) => ({ model, provider: provider.id, modality: 'image' }));
|
|
128
|
+
},
|
|
129
|
+
async quote(input) {
|
|
130
|
+
const request = normalizeImageRequest(input);
|
|
131
|
+
const provider = modelRoutes.get(request.model);
|
|
132
|
+
if (!provider) throw new Error(`no image provider configured for model ${request.model}`);
|
|
133
|
+
const quote = typeof provider.quote === 'function' ? await provider.quote(request) : null;
|
|
134
|
+
return {
|
|
135
|
+
schema: 'enigma.image_quote.v1',
|
|
136
|
+
model: request.model,
|
|
137
|
+
provider: provider.id,
|
|
138
|
+
variants: request.variants,
|
|
139
|
+
...(quote && typeof quote === 'object' ? quote : { amount: null, asset: null }),
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
async generate(input = {}) {
|
|
143
|
+
const request = normalizeImageRequest(input);
|
|
144
|
+
const provider = modelRoutes.get(request.model);
|
|
145
|
+
if (!provider) throw new Error(`no image provider configured for model ${request.model}`);
|
|
146
|
+
const controller = new AbortController();
|
|
147
|
+
const timer = setTimeout(() => controller.abort(new Error('image generation timed out')), timeoutMs);
|
|
148
|
+
const startedAt = Date.now();
|
|
149
|
+
try {
|
|
150
|
+
const generated = await provider.generate(request, { signal: controller.signal });
|
|
151
|
+
const assets = (generated?.assets || []).map((asset) => normalizedAsset(asset, request.format));
|
|
152
|
+
if (assets.length !== request.variants) {
|
|
153
|
+
throw new Error(`image provider ${provider.id} returned ${assets.length} assets; expected ${request.variants}`);
|
|
154
|
+
}
|
|
155
|
+
const result = {
|
|
156
|
+
schema: ENIGMA_IMAGE_RESULT_SCHEMA,
|
|
157
|
+
job: {
|
|
158
|
+
schema: ENIGMA_IMAGE_JOB_SCHEMA,
|
|
159
|
+
model: request.model,
|
|
160
|
+
provider: provider.id,
|
|
161
|
+
width: request.width,
|
|
162
|
+
height: request.height,
|
|
163
|
+
variants: request.variants,
|
|
164
|
+
format: request.format,
|
|
165
|
+
promptRef: promptReference(request.prompt),
|
|
166
|
+
},
|
|
167
|
+
assets,
|
|
168
|
+
durationMs: Date.now() - startedAt,
|
|
169
|
+
providerRequestId: generated?.providerRequestId || null,
|
|
170
|
+
retention: 'caller_controlled',
|
|
171
|
+
};
|
|
172
|
+
await options.onUsage?.({
|
|
173
|
+
modality: 'image',
|
|
174
|
+
provider: provider.id,
|
|
175
|
+
model: request.model,
|
|
176
|
+
units: assets.length,
|
|
177
|
+
durationMs: result.durationMs,
|
|
178
|
+
promptRef: result.job.promptRef,
|
|
179
|
+
});
|
|
180
|
+
return result;
|
|
181
|
+
} finally {
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './contracts.js';
|
|
2
|
+
export * from './privacy.js';
|
|
3
|
+
export * from './model-router.js';
|
|
4
|
+
export * from './chat.js';
|
|
5
|
+
export * from './image.js';
|
|
6
|
+
export * from './video.js';
|
|
7
|
+
export * from './code.js';
|
|
8
|
+
export * from './browser.js';
|
|
9
|
+
export * from './http.js';
|
|
10
|
+
export * from './platform.js';
|