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,227 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
#if canImport(FoundationNetworking)
|
|
3
|
+
import FoundationNetworking
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
public actor EnigmaAPIClient {
|
|
7
|
+
public typealias TokenProvider = @Sendable () async throws -> String?
|
|
8
|
+
|
|
9
|
+
private let baseURL: URL
|
|
10
|
+
private let session: URLSession
|
|
11
|
+
private let tokenProvider: TokenProvider
|
|
12
|
+
private let encoder: JSONEncoder
|
|
13
|
+
private let decoder: JSONDecoder
|
|
14
|
+
|
|
15
|
+
public init(baseURL: URL, session: URLSession = .shared, tokenProvider: @escaping TokenProvider) throws {
|
|
16
|
+
guard let scheme = baseURL.scheme?.lowercased(), let host = baseURL.host?.lowercased() else { throw EnigmaAPIError.invalidBaseURL }
|
|
17
|
+
let loopback = ["localhost", "127.0.0.1", "::1"].contains(host)
|
|
18
|
+
guard scheme == "https" || (scheme == "http" && loopback) else { throw EnigmaAPIError.invalidBaseURL }
|
|
19
|
+
self.baseURL = baseURL
|
|
20
|
+
self.session = session
|
|
21
|
+
self.tokenProvider = tokenProvider
|
|
22
|
+
encoder = JSONEncoder()
|
|
23
|
+
decoder = JSONDecoder()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public func platform() async throws -> PlatformResponse {
|
|
27
|
+
try await request(path: "/v1/platform", method: "GET", response: PlatformResponse.self)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public func models() async throws -> [PlatformModel] {
|
|
31
|
+
try await request(path: "/v1/models", method: "GET", response: ModelListResponse.self).data
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public func imageModels() async throws -> [PlatformModel] {
|
|
35
|
+
try await request(path: "/v1/images/models", method: "GET", response: ModelListResponse.self).data
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public func videoModels() async throws -> [PlatformModel] {
|
|
39
|
+
try await request(path: "/v1/videos/models", method: "GET", response: ModelListResponse.self).data
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func complete(_ input: ChatCompletionRequest) async throws -> ChatCompletionResponse {
|
|
43
|
+
try await request(path: "/v1/chat/completions", method: "POST", body: input, response: ChatCompletionResponse.self, maximumBytes: 8 * 1_024 * 1_024)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public func generateImage(_ input: ImageGenerationRequest) async throws -> ImageGenerationResponse {
|
|
47
|
+
try await request(path: "/v1/images/generations", method: "POST", body: input, response: ImageGenerationResponse.self, maximumBytes: 34 * 1_024 * 1_024)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
public func queueVideo(_ input: VideoQueueRequest) async throws -> VideoJob {
|
|
52
|
+
try await request(path: "/v1/videos/queue", method: "POST", body: input, response: VideoJob.self)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public func retrieveVideo(id: String) async throws -> VideoRetrieveResponse {
|
|
56
|
+
try await request(path: "/v1/videos/retrieve", method: "POST", body: IdentifierBody(id: id), response: VideoRetrieveResponse.self, maximumBytes: 34 * 1_024 * 1_024)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public func createCodeSession() async throws -> CodeSession {
|
|
60
|
+
try await request(path: "/v1/code/sessions", method: "POST", body: LanguageBody(language: "javascript"), response: CodeSessionEnvelope.self).session
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public func uploadCode(sessionID: String, source: String) async throws {
|
|
64
|
+
let _: OperationOK = try await request(
|
|
65
|
+
path: "/v1/code/sessions/\(pathSegment(sessionID))/uploads",
|
|
66
|
+
method: "POST",
|
|
67
|
+
body: CodeUploadRequest(data: source),
|
|
68
|
+
response: OperationOK.self
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public func executeCode(sessionID: String) async throws -> CodeExecutionResponse {
|
|
73
|
+
try await request(
|
|
74
|
+
path: "/v1/code/sessions/\(pathSegment(sessionID))/execute",
|
|
75
|
+
method: "POST",
|
|
76
|
+
body: CodeExecuteRequest(),
|
|
77
|
+
response: CodeExecutionResponse.self
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public func codeEvents(sessionID: String) async throws -> [CodeEvent] {
|
|
82
|
+
try await request(path: "/v1/code/sessions/\(pathSegment(sessionID))/events", method: "GET", response: CodeEventsResponse.self).events
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public func burnCodeSession(id: String) async throws -> CodeSession {
|
|
86
|
+
try await request(path: "/v1/code/sessions/\(pathSegment(id))", method: "DELETE", response: CodeSessionEnvelope.self).session
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public func createBrowserSession() async throws -> BrowserSession {
|
|
90
|
+
try await request(path: "/v1/browser/sessions", method: "POST", body: EmptyBody(), response: BrowserSessionEnvelope.self).session
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public func connectBrowserSession(id: String) async throws -> BrowserSession {
|
|
94
|
+
try await request(path: "/v1/browser/sessions/\(pathSegment(id))/connect", method: "POST", body: EmptyBody(), response: BrowserSessionEnvelope.self).session
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public func navigateBrowserSession(id: String, url: String) async throws -> BrowserSession {
|
|
98
|
+
try await request(path: "/v1/browser/sessions/\(pathSegment(id))/navigate", method: "POST", body: BrowserNavigateRequest(url: url), response: BrowserSessionEnvelope.self).session
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public func burnBrowserSession(id: String) async throws -> BrowserSession {
|
|
102
|
+
try await request(path: "/v1/browser/sessions/\(pathSegment(id))", method: "DELETE", response: BrowserSessionEnvelope.self).session
|
|
103
|
+
}
|
|
104
|
+
public func createCreditsVault() async throws -> CreditsSessionResponse {
|
|
105
|
+
try await request(path: "/v1/credits/vaults", method: "POST", body: EmptyBody(), response: CreditsSessionResponse.self)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public func recoverCreditsVault(code: String) async throws -> CreditsSessionResponse {
|
|
109
|
+
try await request(path: "/v1/credits/recover", method: "POST", body: RecoveryBody(recoveryCode: code), response: CreditsSessionResponse.self)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public func creditsStatus(accessToken: String) async throws -> CreditsVault {
|
|
113
|
+
try await request(path: "/v1/credits", method: "GET", response: CreditsStatusResponse.self, overrideBearer: accessToken).vault
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public func creditPackages() async throws -> [CreditPackage] {
|
|
117
|
+
try await request(path: "/v1/payments/packages", method: "GET", response: CreditPackagesResponse.self).packages
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public func usage(days: Int = 30) async throws -> UsageAggregate {
|
|
121
|
+
let safeDays = min(400, max(1, days))
|
|
122
|
+
return try await request(path: "/v1/usage?days=\(safeDays)", method: "GET", response: UsageAggregate.self)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private func request<Response: Decodable & Sendable>(
|
|
126
|
+
path: String,
|
|
127
|
+
method: String,
|
|
128
|
+
response: Response.Type,
|
|
129
|
+
maximumBytes: Int = 2 * 1_024 * 1_024,
|
|
130
|
+
overrideBearer: String? = nil
|
|
131
|
+
) async throws -> Response {
|
|
132
|
+
try await request(path: path, method: method, bodyData: nil, response: response, maximumBytes: maximumBytes, overrideBearer: overrideBearer)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private func request<Body: Encodable & Sendable, Response: Decodable & Sendable>(
|
|
136
|
+
path: String,
|
|
137
|
+
method: String,
|
|
138
|
+
body: Body,
|
|
139
|
+
response: Response.Type,
|
|
140
|
+
maximumBytes: Int = 2 * 1_024 * 1_024,
|
|
141
|
+
overrideBearer: String? = nil
|
|
142
|
+
) async throws -> Response {
|
|
143
|
+
try await request(path: path, method: method, bodyData: try encoder.encode(body), response: response, maximumBytes: maximumBytes, overrideBearer: overrideBearer)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private func request<Response: Decodable & Sendable>(
|
|
147
|
+
path: String,
|
|
148
|
+
method: String,
|
|
149
|
+
bodyData: Data?,
|
|
150
|
+
response: Response.Type,
|
|
151
|
+
maximumBytes: Int,
|
|
152
|
+
overrideBearer: String?
|
|
153
|
+
) async throws -> Response {
|
|
154
|
+
guard let url = URL(string: path, relativeTo: baseURL)?.absoluteURL,
|
|
155
|
+
url.scheme == baseURL.scheme, url.host == baseURL.host, url.port == baseURL.port else {
|
|
156
|
+
throw EnigmaAPIError.invalidBaseURL
|
|
157
|
+
}
|
|
158
|
+
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 120)
|
|
159
|
+
request.httpMethod = method
|
|
160
|
+
request.httpBody = bodyData
|
|
161
|
+
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
|
162
|
+
request.setValue("no-store", forHTTPHeaderField: "Cache-Control")
|
|
163
|
+
if bodyData != nil { request.setValue("application/json", forHTTPHeaderField: "Content-Type") }
|
|
164
|
+
let token: String?
|
|
165
|
+
if let overrideBearer { token = overrideBearer }
|
|
166
|
+
else { token = try await tokenProvider() }
|
|
167
|
+
if let token, !token.isEmpty { request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") }
|
|
168
|
+
else if path.hasPrefix("/v1/") && overrideBearer == nil { throw EnigmaAPIError.unauthenticated }
|
|
169
|
+
|
|
170
|
+
let (data, urlResponse) = try await session.data(for: request, delegate: nil)
|
|
171
|
+
guard let http = urlResponse as? HTTPURLResponse else { throw EnigmaAPIError.invalidResponse }
|
|
172
|
+
if data.count > maximumBytes { throw EnigmaAPIError.responseTooLarge }
|
|
173
|
+
guard (200..<300).contains(http.statusCode) else {
|
|
174
|
+
let envelope = try? decoder.decode(APIErrorEnvelope.self, from: data)
|
|
175
|
+
throw EnigmaAPIError.server(
|
|
176
|
+
status: http.statusCode,
|
|
177
|
+
code: envelope?.error.code,
|
|
178
|
+
message: envelope?.error.message ?? HTTPURLResponse.localizedString(forStatusCode: http.statusCode)
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
do { return try decoder.decode(Response.self, from: data) }
|
|
182
|
+
catch { throw EnigmaAPIError.invalidResponse }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private func pathSegment(_ value: String) -> String {
|
|
186
|
+
let allowed = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-._~"))
|
|
187
|
+
return value.addingPercentEncoding(withAllowedCharacters: allowed) ?? ""
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private struct EmptyBody: Codable, Sendable {}
|
|
192
|
+
private struct RecoveryBody: Codable, Sendable { let recoveryCode: String }
|
|
193
|
+
private struct IdentifierBody: Codable, Sendable { let id: String }
|
|
194
|
+
private struct LanguageBody: Codable, Sendable { let language: String }
|
|
195
|
+
private struct OperationOK: Codable, Sendable { let ok: Bool }
|
|
196
|
+
|
|
197
|
+
public struct OAuthAuthorizationServerMetadata: Codable, Sendable {
|
|
198
|
+
public let issuer: String
|
|
199
|
+
public let authorizationEndpoint: String
|
|
200
|
+
public let tokenEndpoint: String
|
|
201
|
+
public let registrationEndpoint: String?
|
|
202
|
+
public let scopesSupported: [String]?
|
|
203
|
+
|
|
204
|
+
enum CodingKeys: String, CodingKey {
|
|
205
|
+
case issuer
|
|
206
|
+
case authorizationEndpoint = "authorization_endpoint"
|
|
207
|
+
case tokenEndpoint = "token_endpoint"
|
|
208
|
+
case registrationEndpoint = "registration_endpoint"
|
|
209
|
+
case scopesSupported = "scopes_supported"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public struct OAuthTokenResponse: Codable, Sendable {
|
|
214
|
+
public let accessToken: String
|
|
215
|
+
public let tokenType: String
|
|
216
|
+
public let expiresIn: Int
|
|
217
|
+
public let refreshToken: String?
|
|
218
|
+
public let scope: String
|
|
219
|
+
|
|
220
|
+
enum CodingKeys: String, CodingKey {
|
|
221
|
+
case accessToken = "access_token"
|
|
222
|
+
case tokenType = "token_type"
|
|
223
|
+
case expiresIn = "expires_in"
|
|
224
|
+
case refreshToken = "refresh_token"
|
|
225
|
+
case scope
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public enum EnigmaRole: String, Codable, Sendable {
|
|
4
|
+
case system, user, assistant, tool
|
|
5
|
+
}
|
|
6
|
+
public enum EnigmaOAuthScopes {
|
|
7
|
+
public static let iOSPlatform = [
|
|
8
|
+
"models:invoke",
|
|
9
|
+
"images:generate",
|
|
10
|
+
"video:generate",
|
|
11
|
+
"code:execute",
|
|
12
|
+
"browser:control",
|
|
13
|
+
"usage:read",
|
|
14
|
+
"credits:create",
|
|
15
|
+
"offline_access",
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
public struct EnigmaMessage: Identifiable, Codable, Hashable, Sendable {
|
|
21
|
+
public let id: UUID
|
|
22
|
+
public let role: EnigmaRole
|
|
23
|
+
public var content: String
|
|
24
|
+
public let createdAt: Date
|
|
25
|
+
|
|
26
|
+
public init(id: UUID = UUID(), role: EnigmaRole, content: String, createdAt: Date = Date()) {
|
|
27
|
+
self.id = id
|
|
28
|
+
self.role = role
|
|
29
|
+
self.content = content
|
|
30
|
+
self.createdAt = createdAt
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
enum CodingKeys: String, CodingKey { case role, content }
|
|
34
|
+
|
|
35
|
+
public init(from decoder: Decoder) throws {
|
|
36
|
+
let values = try decoder.container(keyedBy: CodingKeys.self)
|
|
37
|
+
id = UUID()
|
|
38
|
+
role = try values.decode(EnigmaRole.self, forKey: .role)
|
|
39
|
+
content = try values.decode(String.self, forKey: .content)
|
|
40
|
+
createdAt = Date()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public func encode(to encoder: Encoder) throws {
|
|
44
|
+
var values = encoder.container(keyedBy: CodingKeys.self)
|
|
45
|
+
try values.encode(role, forKey: .role)
|
|
46
|
+
try values.encode(content, forKey: .content)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public struct ChatCompletionRequest: Codable, Sendable {
|
|
51
|
+
public var messages: [EnigmaMessage]
|
|
52
|
+
public var model: String
|
|
53
|
+
public var privacyMode: String
|
|
54
|
+
public var temperature: Double
|
|
55
|
+
public var maxTokens: Int
|
|
56
|
+
public var requirePrivateRoute: Bool
|
|
57
|
+
|
|
58
|
+
public init(messages: [EnigmaMessage], model: String = "enigma-auto", privacyMode: String = "smart", temperature: Double = 0.7, maxTokens: Int = 2_048, requirePrivateRoute: Bool = false) {
|
|
59
|
+
self.messages = messages
|
|
60
|
+
self.model = model
|
|
61
|
+
self.privacyMode = privacyMode
|
|
62
|
+
self.temperature = temperature
|
|
63
|
+
self.maxTokens = maxTokens
|
|
64
|
+
self.requirePrivateRoute = requirePrivateRoute
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
enum CodingKeys: String, CodingKey {
|
|
68
|
+
case messages, model, temperature
|
|
69
|
+
case privacyMode = "privacy_mode"
|
|
70
|
+
case maxTokens = "max_tokens"
|
|
71
|
+
case requirePrivateRoute = "require_private_route"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public struct TokenUsage: Codable, Hashable, Sendable {
|
|
76
|
+
public let promptTokens: Int?
|
|
77
|
+
public let completionTokens: Int?
|
|
78
|
+
public let totalTokens: Int?
|
|
79
|
+
|
|
80
|
+
enum CodingKeys: String, CodingKey {
|
|
81
|
+
case promptTokens = "prompt_tokens"
|
|
82
|
+
case completionTokens = "completion_tokens"
|
|
83
|
+
case totalTokens = "total_tokens"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public struct RouteDisclosure: Codable, Hashable, Sendable {
|
|
88
|
+
public let provider: String?
|
|
89
|
+
public let model: String?
|
|
90
|
+
public let trust: String?
|
|
91
|
+
public let retentionPolicy: String?
|
|
92
|
+
|
|
93
|
+
enum CodingKeys: String, CodingKey {
|
|
94
|
+
case provider, model, trust
|
|
95
|
+
case retentionPolicy = "retention_policy"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public struct ChatCompletionResponse: Codable, Sendable {
|
|
100
|
+
public struct Choice: Codable, Sendable {
|
|
101
|
+
public struct Message: Codable, Sendable {
|
|
102
|
+
public let role: String
|
|
103
|
+
public let content: String
|
|
104
|
+
}
|
|
105
|
+
public let index: Int
|
|
106
|
+
public let message: Message
|
|
107
|
+
public let finishReason: String?
|
|
108
|
+
|
|
109
|
+
enum CodingKeys: String, CodingKey {
|
|
110
|
+
case index, message
|
|
111
|
+
case finishReason = "finish_reason"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public struct Parameters: Codable, Sendable {
|
|
116
|
+
public let route: RouteDisclosure?
|
|
117
|
+
public let retention: String?
|
|
118
|
+
public let elapsedMilliseconds: Int?
|
|
119
|
+
|
|
120
|
+
enum CodingKeys: String, CodingKey {
|
|
121
|
+
case route, retention
|
|
122
|
+
case elapsedMilliseconds = "elapsed_ms"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public let id: String
|
|
127
|
+
public let model: String
|
|
128
|
+
public let choices: [Choice]
|
|
129
|
+
public let usage: TokenUsage?
|
|
130
|
+
public let enigmaParameters: Parameters?
|
|
131
|
+
|
|
132
|
+
enum CodingKeys: String, CodingKey {
|
|
133
|
+
case id, model, choices, usage
|
|
134
|
+
case enigmaParameters = "enigma_parameters"
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public var answer: String { choices.first?.message.content ?? "" }
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public struct PlatformModel: Identifiable, Codable, Hashable, Sendable {
|
|
141
|
+
public var id: String { model ?? routeID ?? UUID().uuidString }
|
|
142
|
+
public let model: String?
|
|
143
|
+
public let routeID: String?
|
|
144
|
+
public let provider: String?
|
|
145
|
+
public let ownedBy: String?
|
|
146
|
+
public let trust: String?
|
|
147
|
+
public let retentionPolicy: String?
|
|
148
|
+
public let capabilities: [String]?
|
|
149
|
+
|
|
150
|
+
enum CodingKeys: String, CodingKey {
|
|
151
|
+
case model, provider, trust, capabilities
|
|
152
|
+
case routeID = "id"
|
|
153
|
+
case ownedBy = "owned_by"
|
|
154
|
+
case retentionPolicy = "retention_policy"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public struct ModelListResponse: Codable, Sendable {
|
|
159
|
+
public let data: [PlatformModel]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public struct PlatformResponse: Codable, Sendable {
|
|
163
|
+
public struct Capabilities: Codable, Sendable {
|
|
164
|
+
public let chat: Bool
|
|
165
|
+
public let images: Bool
|
|
166
|
+
public let videos: Bool
|
|
167
|
+
public let code: Bool
|
|
168
|
+
public let browser: Bool
|
|
169
|
+
}
|
|
170
|
+
public let capabilities: Capabilities
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public struct ImageGenerationRequest: Codable, Sendable {
|
|
174
|
+
public let prompt: String
|
|
175
|
+
public let model: String
|
|
176
|
+
public let width: Int
|
|
177
|
+
public let height: Int
|
|
178
|
+
public let variants: Int
|
|
179
|
+
public let format: String
|
|
180
|
+
|
|
181
|
+
public init(prompt: String, model: String, width: Int = 1_024, height: Int = 1_024, variants: Int = 1, format: String = "webp") {
|
|
182
|
+
self.prompt = prompt
|
|
183
|
+
self.model = model
|
|
184
|
+
self.width = width
|
|
185
|
+
self.height = height
|
|
186
|
+
self.variants = variants
|
|
187
|
+
self.format = format
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public struct GeneratedImageAsset: Codable, Hashable, Sendable {
|
|
192
|
+
public let url: String?
|
|
193
|
+
public let base64: String?
|
|
194
|
+
public let format: String
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public struct ImageGenerationResponse: Codable, Sendable {
|
|
198
|
+
public let assets: [GeneratedImageAsset]
|
|
199
|
+
public let retention: String
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public struct CreditsVault: Codable, Sendable {
|
|
203
|
+
public let id: String
|
|
204
|
+
public let balanceMicrocredits: Int64
|
|
205
|
+
public let reservedMicrocredits: Int64
|
|
206
|
+
public let availableMicrocredits: Int64
|
|
207
|
+
public let creditScale: Int64
|
|
208
|
+
public let recoveryVersion: Int
|
|
209
|
+
public let accountIdentityStored: Bool
|
|
210
|
+
public let privacyBoundary: String
|
|
211
|
+
public let paymentFundingBoundary: String?
|
|
212
|
+
|
|
213
|
+
public var balance: Decimal { Decimal(balanceMicrocredits) / Decimal(creditScale) }
|
|
214
|
+
public var available: Decimal { Decimal(availableMicrocredits) / Decimal(creditScale) }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public struct CreditsSessionResponse: Codable, Sendable {
|
|
218
|
+
public let vault: CreditsVault
|
|
219
|
+
public let recoveryCode: String
|
|
220
|
+
public let accessToken: String
|
|
221
|
+
public let accessExpiresAt: String
|
|
222
|
+
public let secretsShownOnce: Bool
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public struct CreditsStatusResponse: Codable, Sendable {
|
|
226
|
+
public let vault: CreditsVault
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public struct CreditPackage: Identifiable, Codable, Sendable {
|
|
230
|
+
public let id: String
|
|
231
|
+
public let label: String
|
|
232
|
+
public let creditsMicrocredits: Int64
|
|
233
|
+
public let rails: [String]
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public struct CreditPackagesResponse: Codable, Sendable {
|
|
237
|
+
public let packages: [CreditPackage]
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public struct UsageAggregate: Codable, Sendable {
|
|
241
|
+
public struct Totals: Codable, Sendable {
|
|
242
|
+
public let eventCount: Int
|
|
243
|
+
public let inputUnits: Int
|
|
244
|
+
public let outputUnits: Int
|
|
245
|
+
public let units: Int
|
|
246
|
+
public let knownCostMicrousd: Int
|
|
247
|
+
public let unpricedEvents: Int
|
|
248
|
+
}
|
|
249
|
+
public let totals: Totals
|
|
250
|
+
public let costBoundary: String
|
|
251
|
+
public let contentStored: Bool
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public struct APIErrorEnvelope: Codable, Sendable {
|
|
255
|
+
public struct Detail: Codable, Sendable {
|
|
256
|
+
public let code: String?
|
|
257
|
+
public let message: String?
|
|
258
|
+
}
|
|
259
|
+
public let error: Detail
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public enum EnigmaAPIError: LocalizedError, Sendable {
|
|
263
|
+
case invalidBaseURL
|
|
264
|
+
case unauthenticated
|
|
265
|
+
case invalidResponse
|
|
266
|
+
case server(status: Int, code: String?, message: String)
|
|
267
|
+
case responseTooLarge
|
|
268
|
+
|
|
269
|
+
public var errorDescription: String? {
|
|
270
|
+
switch self {
|
|
271
|
+
case .invalidBaseURL: return "Enter a valid HTTPS Enigma server URL."
|
|
272
|
+
case .unauthenticated: return "Connect this device to Enigma first."
|
|
273
|
+
case .invalidResponse: return "Enigma returned an invalid response."
|
|
274
|
+
case let .server(_, _, message): return message
|
|
275
|
+
case .responseTooLarge: return "Enigma returned more data than this screen accepts."
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public struct PKCEPair: Equatable, Sendable {
|
|
4
|
+
public let verifier: String
|
|
5
|
+
public let challenge: String
|
|
6
|
+
|
|
7
|
+
public init(verifier: String, challenge: String) {
|
|
8
|
+
self.verifier = verifier
|
|
9
|
+
self.challenge = challenge
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public enum PKCE {
|
|
14
|
+
public static func create(byteCount: Int = 48) -> PKCEPair {
|
|
15
|
+
precondition((32...96).contains(byteCount))
|
|
16
|
+
var generator = SystemRandomNumberGenerator()
|
|
17
|
+
let bytes = (0..<byteCount).map { _ in UInt8.random(in: .min ... .max, using: &generator) }
|
|
18
|
+
let verifier = base64URL(Data(bytes))
|
|
19
|
+
return PKCEPair(verifier: verifier, challenge: base64URL(Data(SHA256.hash(Array(verifier.utf8)))))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public static func challenge(for verifier: String) -> String {
|
|
23
|
+
base64URL(Data(SHA256.hash(Array(verifier.utf8))))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private static func base64URL(_ data: Data) -> String {
|
|
27
|
+
data.base64EncodedString()
|
|
28
|
+
.replacingOccurrences(of: "+", with: "-")
|
|
29
|
+
.replacingOccurrences(of: "/", with: "_")
|
|
30
|
+
.replacingOccurrences(of: "=", with: "")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private enum SHA256 {
|
|
35
|
+
private static let initial: [UInt32] = [
|
|
36
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
37
|
+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
38
|
+
]
|
|
39
|
+
private static let constants: [UInt32] = [
|
|
40
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
41
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
42
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
43
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
44
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
45
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
46
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
47
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
static func hash(_ input: [UInt8]) -> [UInt8] {
|
|
51
|
+
var message = input
|
|
52
|
+
let bitLength = UInt64(message.count) * 8
|
|
53
|
+
message.append(0x80)
|
|
54
|
+
while message.count % 64 != 56 { message.append(0) }
|
|
55
|
+
message.append(contentsOf: withUnsafeBytes(of: bitLength.bigEndian, Array.init))
|
|
56
|
+
var state = initial
|
|
57
|
+
var words = [UInt32](repeating: 0, count: 64)
|
|
58
|
+
|
|
59
|
+
for offset in stride(from: 0, to: message.count, by: 64) {
|
|
60
|
+
for index in 0..<16 {
|
|
61
|
+
let start = offset + index * 4
|
|
62
|
+
words[index] = UInt32(message[start]) << 24
|
|
63
|
+
| UInt32(message[start + 1]) << 16
|
|
64
|
+
| UInt32(message[start + 2]) << 8
|
|
65
|
+
| UInt32(message[start + 3])
|
|
66
|
+
}
|
|
67
|
+
for index in 16..<64 {
|
|
68
|
+
let s0 = rotateRight(words[index - 15], 7) ^ rotateRight(words[index - 15], 18) ^ (words[index - 15] >> 3)
|
|
69
|
+
let s1 = rotateRight(words[index - 2], 17) ^ rotateRight(words[index - 2], 19) ^ (words[index - 2] >> 10)
|
|
70
|
+
words[index] = words[index - 16] &+ s0 &+ words[index - 7] &+ s1
|
|
71
|
+
}
|
|
72
|
+
var a = state[0], b = state[1], c = state[2], d = state[3]
|
|
73
|
+
var e = state[4], f = state[5], g = state[6], h = state[7]
|
|
74
|
+
for index in 0..<64 {
|
|
75
|
+
let sigma1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25)
|
|
76
|
+
let choice = (e & f) ^ ((~e) & g)
|
|
77
|
+
let temp1 = h &+ sigma1 &+ choice &+ constants[index] &+ words[index]
|
|
78
|
+
let sigma0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)
|
|
79
|
+
let majority = (a & b) ^ (a & c) ^ (b & c)
|
|
80
|
+
let temp2 = sigma0 &+ majority
|
|
81
|
+
h = g; g = f; f = e; e = d &+ temp1
|
|
82
|
+
d = c; c = b; b = a; a = temp1 &+ temp2
|
|
83
|
+
}
|
|
84
|
+
state[0] &+= a; state[1] &+= b; state[2] &+= c; state[3] &+= d
|
|
85
|
+
state[4] &+= e; state[5] &+= f; state[6] &+= g; state[7] &+= h
|
|
86
|
+
}
|
|
87
|
+
return state.flatMap { word in
|
|
88
|
+
let value = word.bigEndian
|
|
89
|
+
return withUnsafeBytes(of: value, Array.init)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private static func rotateRight(_ value: UInt32, _ count: UInt32) -> UInt32 {
|
|
94
|
+
(value >> count) | (value << (32 - count))
|
|
95
|
+
}
|
|
96
|
+
}
|