@sogni-ai/expo-client 1.0.0-alpha.10
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/CHANGELOG.md +69 -0
- package/README.md +411 -0
- package/dist/cjs/Account/index.d.ts +60 -0
- package/dist/cjs/Account/index.d.ts.map +1 -0
- package/dist/cjs/Account/index.js +188 -0
- package/dist/cjs/Account/index.js.map +1 -0
- package/dist/cjs/Account/types.d.ts +43 -0
- package/dist/cjs/Account/types.d.ts.map +1 -0
- package/dist/cjs/Account/types.js +18 -0
- package/dist/cjs/Account/types.js.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/events.d.ts +139 -0
- package/dist/cjs/ApiClient/WebSocketClient/events.d.ts.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/events.js +3 -0
- package/dist/cjs/ApiClient/WebSocketClient/events.js.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/index.d.ts +45 -0
- package/dist/cjs/ApiClient/WebSocketClient/index.d.ts.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/index.js +283 -0
- package/dist/cjs/ApiClient/WebSocketClient/index.js.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/normalize.d.ts +45 -0
- package/dist/cjs/ApiClient/WebSocketClient/normalize.d.ts.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/normalize.js +245 -0
- package/dist/cjs/ApiClient/WebSocketClient/normalize.js.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/types.d.ts +9 -0
- package/dist/cjs/ApiClient/WebSocketClient/types.d.ts.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/types.js +3 -0
- package/dist/cjs/ApiClient/WebSocketClient/types.js.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/wireTypes.d.ts +161 -0
- package/dist/cjs/ApiClient/WebSocketClient/wireTypes.d.ts.map +1 -0
- package/dist/cjs/ApiClient/WebSocketClient/wireTypes.js +11 -0
- package/dist/cjs/ApiClient/WebSocketClient/wireTypes.js.map +1 -0
- package/dist/cjs/ApiClient/index.d.ts +60 -0
- package/dist/cjs/ApiClient/index.d.ts.map +1 -0
- package/dist/cjs/ApiClient/index.js +87 -0
- package/dist/cjs/ApiClient/index.js.map +1 -0
- package/dist/cjs/Chat/ChatStream.d.ts +42 -0
- package/dist/cjs/Chat/ChatStream.d.ts.map +1 -0
- package/dist/cjs/Chat/ChatStream.js +146 -0
- package/dist/cjs/Chat/ChatStream.js.map +1 -0
- package/dist/cjs/Chat/index.d.ts +61 -0
- package/dist/cjs/Chat/index.d.ts.map +1 -0
- package/dist/cjs/Chat/index.js +179 -0
- package/dist/cjs/Chat/index.js.map +1 -0
- package/dist/cjs/Chat/tools.d.ts +13 -0
- package/dist/cjs/Chat/tools.d.ts.map +1 -0
- package/dist/cjs/Chat/tools.js +22 -0
- package/dist/cjs/Chat/tools.js.map +1 -0
- package/dist/cjs/Chat/types.d.ts +153 -0
- package/dist/cjs/Chat/types.d.ts.map +1 -0
- package/dist/cjs/Chat/types.js +3 -0
- package/dist/cjs/Chat/types.js.map +1 -0
- package/dist/cjs/Projects/ControlNet.d.ts +30 -0
- package/dist/cjs/Projects/ControlNet.d.ts.map +1 -0
- package/dist/cjs/Projects/ControlNet.js +45 -0
- package/dist/cjs/Projects/ControlNet.js.map +1 -0
- package/dist/cjs/Projects/createJobRequestMessage.d.ts +11 -0
- package/dist/cjs/Projects/createJobRequestMessage.d.ts.map +1 -0
- package/dist/cjs/Projects/createJobRequestMessage.js +239 -0
- package/dist/cjs/Projects/createJobRequestMessage.js.map +1 -0
- package/dist/cjs/Projects/index.d.ts +96 -0
- package/dist/cjs/Projects/index.d.ts.map +1 -0
- package/dist/cjs/Projects/index.js +536 -0
- package/dist/cjs/Projects/index.js.map +1 -0
- package/dist/cjs/Projects/restNormalize.d.ts +60 -0
- package/dist/cjs/Projects/restNormalize.d.ts.map +1 -0
- package/dist/cjs/Projects/restNormalize.js +89 -0
- package/dist/cjs/Projects/restNormalize.js.map +1 -0
- package/dist/cjs/Projects/types.d.ts +233 -0
- package/dist/cjs/Projects/types.d.ts.map +1 -0
- package/dist/cjs/Projects/types.js +3 -0
- package/dist/cjs/Projects/types.js.map +1 -0
- package/dist/cjs/Projects/utils.d.ts +23 -0
- package/dist/cjs/Projects/utils.d.ts.map +1 -0
- package/dist/cjs/Projects/utils.js +65 -0
- package/dist/cjs/Projects/utils.js.map +1 -0
- package/dist/cjs/index.d.ts +63 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +116 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/AuthManager/ApiKeyAuthManager.d.ts +15 -0
- package/dist/cjs/lib/AuthManager/ApiKeyAuthManager.d.ts.map +1 -0
- package/dist/cjs/lib/AuthManager/ApiKeyAuthManager.js +47 -0
- package/dist/cjs/lib/AuthManager/ApiKeyAuthManager.js.map +1 -0
- package/dist/cjs/lib/AuthManager/AuthManagerBase.d.ts +23 -0
- package/dist/cjs/lib/AuthManager/AuthManagerBase.d.ts.map +1 -0
- package/dist/cjs/lib/AuthManager/AuthManagerBase.js +14 -0
- package/dist/cjs/lib/AuthManager/AuthManagerBase.js.map +1 -0
- package/dist/cjs/lib/AuthManager/AuthStorage.d.ts +11 -0
- package/dist/cjs/lib/AuthManager/AuthStorage.d.ts.map +1 -0
- package/dist/cjs/lib/AuthManager/AuthStorage.js +50 -0
- package/dist/cjs/lib/AuthManager/AuthStorage.js.map +1 -0
- package/dist/cjs/lib/AuthManager/TokenAuthManager.d.ts +35 -0
- package/dist/cjs/lib/AuthManager/TokenAuthManager.d.ts.map +1 -0
- package/dist/cjs/lib/AuthManager/TokenAuthManager.js +164 -0
- package/dist/cjs/lib/AuthManager/TokenAuthManager.js.map +1 -0
- package/dist/cjs/lib/AuthManager/index.d.ts +7 -0
- package/dist/cjs/lib/AuthManager/index.d.ts.map +1 -0
- package/dist/cjs/lib/AuthManager/index.js +13 -0
- package/dist/cjs/lib/AuthManager/index.js.map +1 -0
- package/dist/cjs/lib/Cache.d.ts +12 -0
- package/dist/cjs/lib/Cache.d.ts.map +1 -0
- package/dist/cjs/lib/Cache.js +36 -0
- package/dist/cjs/lib/Cache.js.map +1 -0
- package/dist/cjs/lib/DefaultLogger.d.ts +17 -0
- package/dist/cjs/lib/DefaultLogger.d.ts.map +1 -0
- package/dist/cjs/lib/DefaultLogger.js +36 -0
- package/dist/cjs/lib/DefaultLogger.js.map +1 -0
- package/dist/cjs/lib/RestClient.d.ts +18 -0
- package/dist/cjs/lib/RestClient.d.ts.map +1 -0
- package/dist/cjs/lib/RestClient.js +67 -0
- package/dist/cjs/lib/RestClient.js.map +1 -0
- package/dist/cjs/lib/TypedEventEmitter.d.ts +16 -0
- package/dist/cjs/lib/TypedEventEmitter.d.ts.map +1 -0
- package/dist/cjs/lib/TypedEventEmitter.js +46 -0
- package/dist/cjs/lib/TypedEventEmitter.js.map +1 -0
- package/dist/cjs/lib/base64.d.ts +3 -0
- package/dist/cjs/lib/base64.d.ts.map +1 -0
- package/dist/cjs/lib/base64.js +21 -0
- package/dist/cjs/lib/base64.js.map +1 -0
- package/dist/cjs/lib/getUUID.d.ts +12 -0
- package/dist/cjs/lib/getUUID.d.ts.map +1 -0
- package/dist/cjs/lib/getUUID.js +29 -0
- package/dist/cjs/lib/getUUID.js.map +1 -0
- package/dist/cjs/lib/mediaInput.d.ts +33 -0
- package/dist/cjs/lib/mediaInput.d.ts.map +1 -0
- package/dist/cjs/lib/mediaInput.js +32 -0
- package/dist/cjs/lib/mediaInput.js.map +1 -0
- package/dist/cjs/lib/utils.d.ts +10 -0
- package/dist/cjs/lib/utils.d.ts.map +1 -0
- package/dist/cjs/lib/utils.js +24 -0
- package/dist/cjs/lib/utils.js.map +1 -0
- package/dist/cjs/types/ErrorData.d.ts +7 -0
- package/dist/cjs/types/ErrorData.d.ts.map +1 -0
- package/dist/cjs/types/ErrorData.js +3 -0
- package/dist/cjs/types/ErrorData.js.map +1 -0
- package/dist/cjs/types/json.d.ts +6 -0
- package/dist/cjs/types/json.d.ts.map +1 -0
- package/dist/cjs/types/json.js +3 -0
- package/dist/cjs/types/json.js.map +1 -0
- package/dist/cjs/types/token.d.ts +2 -0
- package/dist/cjs/types/token.d.ts.map +1 -0
- package/dist/cjs/types/token.js +3 -0
- package/dist/cjs/types/token.js.map +1 -0
- package/dist/cjs/version.d.ts +2 -0
- package/dist/cjs/version.d.ts.map +1 -0
- package/dist/cjs/version.js +5 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/cjs/wallet.d.ts +59 -0
- package/dist/cjs/wallet.d.ts.map +1 -0
- package/dist/cjs/wallet.js +125 -0
- package/dist/cjs/wallet.js.map +1 -0
- package/dist/esm/Account/index.js +183 -0
- package/dist/esm/Account/index.js.map +1 -0
- package/dist/esm/Account/types.js +15 -0
- package/dist/esm/Account/types.js.map +1 -0
- package/dist/esm/ApiClient/WebSocketClient/events.js +2 -0
- package/dist/esm/ApiClient/WebSocketClient/events.js.map +1 -0
- package/dist/esm/ApiClient/WebSocketClient/index.js +278 -0
- package/dist/esm/ApiClient/WebSocketClient/index.js.map +1 -0
- package/dist/esm/ApiClient/WebSocketClient/normalize.js +229 -0
- package/dist/esm/ApiClient/WebSocketClient/normalize.js.map +1 -0
- package/dist/esm/ApiClient/WebSocketClient/types.js +2 -0
- package/dist/esm/ApiClient/WebSocketClient/types.js.map +1 -0
- package/dist/esm/ApiClient/WebSocketClient/wireTypes.js +10 -0
- package/dist/esm/ApiClient/WebSocketClient/wireTypes.js.map +1 -0
- package/dist/esm/ApiClient/index.js +80 -0
- package/dist/esm/ApiClient/index.js.map +1 -0
- package/dist/esm/Chat/ChatStream.js +144 -0
- package/dist/esm/Chat/ChatStream.js.map +1 -0
- package/dist/esm/Chat/index.js +174 -0
- package/dist/esm/Chat/index.js.map +1 -0
- package/dist/esm/Chat/tools.js +19 -0
- package/dist/esm/Chat/tools.js.map +1 -0
- package/dist/esm/Chat/types.js +2 -0
- package/dist/esm/Chat/types.js.map +1 -0
- package/dist/esm/Projects/ControlNet.js +41 -0
- package/dist/esm/Projects/ControlNet.js.map +1 -0
- package/dist/esm/Projects/createJobRequestMessage.js +236 -0
- package/dist/esm/Projects/createJobRequestMessage.js.map +1 -0
- package/dist/esm/Projects/index.js +531 -0
- package/dist/esm/Projects/index.js.map +1 -0
- package/dist/esm/Projects/restNormalize.js +86 -0
- package/dist/esm/Projects/restNormalize.js.map +1 -0
- package/dist/esm/Projects/types.js +2 -0
- package/dist/esm/Projects/types.js.map +1 -0
- package/dist/esm/Projects/utils.js +55 -0
- package/dist/esm/Projects/utils.js.map +1 -0
- package/dist/esm/index.js +72 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/AuthManager/ApiKeyAuthManager.js +42 -0
- package/dist/esm/lib/AuthManager/ApiKeyAuthManager.js.map +1 -0
- package/dist/esm/lib/AuthManager/AuthManagerBase.js +9 -0
- package/dist/esm/lib/AuthManager/AuthManagerBase.js.map +1 -0
- package/dist/esm/lib/AuthManager/AuthStorage.js +13 -0
- package/dist/esm/lib/AuthManager/AuthStorage.js.map +1 -0
- package/dist/esm/lib/AuthManager/TokenAuthManager.js +159 -0
- package/dist/esm/lib/AuthManager/TokenAuthManager.js.map +1 -0
- package/dist/esm/lib/AuthManager/index.js +5 -0
- package/dist/esm/lib/AuthManager/index.js.map +1 -0
- package/dist/esm/lib/Cache.js +33 -0
- package/dist/esm/lib/Cache.js.map +1 -0
- package/dist/esm/lib/DefaultLogger.js +32 -0
- package/dist/esm/lib/DefaultLogger.js.map +1 -0
- package/dist/esm/lib/RestClient.js +62 -0
- package/dist/esm/lib/RestClient.js.map +1 -0
- package/dist/esm/lib/TypedEventEmitter.js +44 -0
- package/dist/esm/lib/TypedEventEmitter.js.map +1 -0
- package/dist/esm/lib/base64.js +17 -0
- package/dist/esm/lib/base64.js.map +1 -0
- package/dist/esm/lib/getUUID.js +26 -0
- package/dist/esm/lib/getUUID.js.map +1 -0
- package/dist/esm/lib/mediaInput.js +28 -0
- package/dist/esm/lib/mediaInput.js.map +1 -0
- package/dist/esm/lib/utils.js +19 -0
- package/dist/esm/lib/utils.js.map +1 -0
- package/dist/esm/types/ErrorData.js +2 -0
- package/dist/esm/types/ErrorData.js.map +1 -0
- package/dist/esm/types/json.js +2 -0
- package/dist/esm/types/json.js.map +1 -0
- package/dist/esm/types/token.js +2 -0
- package/dist/esm/types/token.js.map +1 -0
- package/dist/esm/version.js +2 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esm/wallet.js +117 -0
- package/dist/esm/wallet.js.map +1 -0
- package/package.json +92 -0
- package/src/Account/index.ts +214 -0
- package/src/Account/types.ts +61 -0
- package/src/ApiClient/WebSocketClient/events.ts +168 -0
- package/src/ApiClient/WebSocketClient/index.ts +345 -0
- package/src/ApiClient/WebSocketClient/normalize.ts +287 -0
- package/src/ApiClient/WebSocketClient/types.ts +10 -0
- package/src/ApiClient/WebSocketClient/wireTypes.ts +183 -0
- package/src/ApiClient/index.ts +147 -0
- package/src/Chat/ChatStream.ts +164 -0
- package/src/Chat/index.ts +224 -0
- package/src/Chat/tools.ts +23 -0
- package/src/Chat/types.ts +165 -0
- package/src/Projects/ControlNet.ts +84 -0
- package/src/Projects/createJobRequestMessage.ts +241 -0
- package/src/Projects/index.ts +608 -0
- package/src/Projects/restNormalize.ts +154 -0
- package/src/Projects/types.ts +266 -0
- package/src/Projects/utils.ts +60 -0
- package/src/index.ts +217 -0
- package/src/lib/AuthManager/ApiKeyAuthManager.ts +52 -0
- package/src/lib/AuthManager/AuthManagerBase.ts +35 -0
- package/src/lib/AuthManager/AuthStorage.ts +21 -0
- package/src/lib/AuthManager/TokenAuthManager.ts +179 -0
- package/src/lib/AuthManager/index.ts +8 -0
- package/src/lib/Cache.ts +45 -0
- package/src/lib/DefaultLogger.ts +47 -0
- package/src/lib/RestClient.ts +77 -0
- package/src/lib/TypedEventEmitter.ts +52 -0
- package/src/lib/base64.ts +17 -0
- package/src/lib/getUUID.ts +27 -0
- package/src/lib/mediaInput.ts +54 -0
- package/src/lib/utils.ts +21 -0
- package/src/types/ErrorData.ts +7 -0
- package/src/types/json.ts +5 -0
- package/src/types/token.ts +1 -0
- package/src/version.ts +1 -0
- package/src/wallet.ts +158 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# [1.0.0-alpha.10](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.9...v1.0.0-alpha.10) (2026-05-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* use noble pbkdf2 and correct expo-standard-web-crypto setup ([0ca4de9](https://github.com/Sogni-AI/expo-client/commit/0ca4de92ccef231e3033600ba6f83dfa829a3f6b))
|
|
7
|
+
|
|
8
|
+
# [1.0.0-alpha.9](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.8...v1.0.0-alpha.9) (2026-05-12)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* app-state reconnect and projects.fetch REST hydration ([671aeea](https://github.com/Sogni-AI/expo-client/commit/671aeea9dc3a6e6a1c4a16a0ef4ea8f03aee4a56))
|
|
14
|
+
|
|
15
|
+
# [1.0.0-alpha.8](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) (2026-05-12)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **chat:** add tool-calling helpers and autoExecuteTools loop ([103803a](https://github.com/Sogni-AI/expo-client/commit/103803a3bd272ee80b71f4bc83c14f78b9118cea))
|
|
21
|
+
|
|
22
|
+
# [1.0.0-alpha.7](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2026-05-12)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* add Chat API for LLM completions ([ee68f1a](https://github.com/Sogni-AI/expo-client/commit/ee68f1aee065ea0dd673ebb0365194d1dcae1c99))
|
|
28
|
+
|
|
29
|
+
# [1.0.0-alpha.6](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) (2026-05-12)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* add video and audio generation ([ba90ac6](https://github.com/Sogni-AI/expo-client/commit/ba90ac672f8e9aee8184fa48fcb4c02b536f57a8))
|
|
35
|
+
|
|
36
|
+
# [1.0.0-alpha.5](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2026-05-12)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
* add img2img, ControlNet, and context images ([dcd9b6d](https://github.com/Sogni-AI/expo-client/commit/dcd9b6da092449d9ce3cb1f0f253540efa5f70d8))
|
|
42
|
+
|
|
43
|
+
# [1.0.0-alpha.4](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2026-05-12)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### Features
|
|
47
|
+
|
|
48
|
+
* add username+password login and signup via wallet derivation ([4fc095f](https://github.com/Sogni-AI/expo-client/commit/4fc095fab997d631b062fc6352b774965065dd60))
|
|
49
|
+
|
|
50
|
+
# [1.0.0-alpha.3](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) (2026-05-12)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
* add image generation via ProjectsApi ([392d3ca](https://github.com/Sogni-AI/expo-client/commit/392d3caeb7a7980e646b2ba9046554a5dbaf262e))
|
|
56
|
+
|
|
57
|
+
# [1.0.0-alpha.2](https://github.com/Sogni-AI/expo-client/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2026-05-12)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Features
|
|
61
|
+
|
|
62
|
+
* add WebSocket client and AccountApi ([b58b3ae](https://github.com/Sogni-AI/expo-client/commit/b58b3aed2fe55a27e3f01bee8c6df1e0e186af58))
|
|
63
|
+
|
|
64
|
+
# 1.0.0-alpha.1 (2026-05-12)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Features
|
|
68
|
+
|
|
69
|
+
* add authentication, REST client, and core lib utilities ([23053b5](https://github.com/Sogni-AI/expo-client/commit/23053b52430122bf04a812aef8cf25e7c01a73dd))
|
package/README.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# @sogni-ai/expo-client
|
|
2
|
+
|
|
3
|
+
Expo / React Native SDK for the [Sogni Supernet](https://sogni.ai) — AI image, video & audio generation plus LLM chat over WebSocket.
|
|
4
|
+
|
|
5
|
+
> **Status:** Early development. Public API is unstable until 1.0. Published to npm under the `alpha` dist-tag.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx expo install @sogni-ai/expo-client@alpha expo-secure-store expo-standard-web-crypto
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Polyfill `crypto.getRandomValues` at your app entry point (e.g. `app/_layout.tsx` for Expo Router or `App.tsx` for classic Expo):
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { polyfillWebCrypto } from 'expo-standard-web-crypto';
|
|
19
|
+
polyfillWebCrypto();
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This is required for the SDK to generate UUIDs and (optionally) fresh wallets. PBKDF2 for username+password login is done in pure JS via `@noble/hashes`, so no `crypto.subtle` polyfill is needed.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Create a client with an API key
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { SogniClient } from '@sogni-ai/expo-client';
|
|
30
|
+
|
|
31
|
+
const sogni = await SogniClient.create({
|
|
32
|
+
appId: 'my-app',
|
|
33
|
+
apiKey: 'sk_...'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Authenticated — fetch profile
|
|
37
|
+
const me = await sogni.account.me();
|
|
38
|
+
|
|
39
|
+
// Subscribe to account state changes (balance, network, etc.)
|
|
40
|
+
const unsubscribe = sogni.account.onChange((snapshot) => {
|
|
41
|
+
console.log(snapshot);
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Token-based session (auto-restored from secure storage)
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const sogni = await SogniClient.create({ appId: 'my-app' });
|
|
49
|
+
|
|
50
|
+
if (sogni.isAuthenticated) {
|
|
51
|
+
// Tokens were restored from previous session
|
|
52
|
+
await sogni.account.me();
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Log in with username + password
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const sogni = await SogniClient.create({ appId: 'my-app' });
|
|
60
|
+
const session = await sogni.account.login('alice', 'correct-horse-battery-staple');
|
|
61
|
+
// JWT tokens are auto-persisted to SecureStore — they survive app restarts.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The SDK derives a deterministic wallet from your credentials on-device
|
|
65
|
+
(PBKDF2: SHA-256, 10,000 iterations, salt = username, 32-byte key), then
|
|
66
|
+
signs an EIP-712 authentication message which the server validates. The
|
|
67
|
+
password never leaves the device and the same credentials produce the
|
|
68
|
+
same wallet on every device — no wallet file to back up.
|
|
69
|
+
|
|
70
|
+
### Sign up
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
const session = await sogni.account.signup({
|
|
74
|
+
username: 'alice',
|
|
75
|
+
email: 'alice@example.com',
|
|
76
|
+
password: 'correct-horse-battery-staple',
|
|
77
|
+
subscribe: true,
|
|
78
|
+
turnstileToken: turnstileTokenFromCaptcha
|
|
79
|
+
});
|
|
80
|
+
// Auto-logged in after signup.
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`turnstileToken` comes from Cloudflare Turnstile, which the Sogni API
|
|
84
|
+
requires for signup. Wire it up via `react-native-turnstile` or an
|
|
85
|
+
Expo-friendly equivalent.
|
|
86
|
+
|
|
87
|
+
### Generate an image
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { SogniClient } from '@sogni-ai/expo-client';
|
|
91
|
+
|
|
92
|
+
const sogni = await SogniClient.create({ appId: 'my-app', apiKey: 'sk_...' });
|
|
93
|
+
|
|
94
|
+
// Wait for the WebSocket to authenticate before listing models
|
|
95
|
+
await new Promise<void>((resolve) => {
|
|
96
|
+
if (sogni.account.current.networkStatus === 'connected') resolve();
|
|
97
|
+
else {
|
|
98
|
+
const off = sogni.account.onChange((s) => {
|
|
99
|
+
if (s.networkStatus === 'connected') {
|
|
100
|
+
off();
|
|
101
|
+
resolve();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const models = await sogni.projects.getAvailableModels();
|
|
108
|
+
const model = models.find((m) => m.media === 'image' && m.workerCount > 0);
|
|
109
|
+
if (!model) throw new Error('No image models available right now');
|
|
110
|
+
|
|
111
|
+
const project = await sogni.projects.create({
|
|
112
|
+
modelId: model.id,
|
|
113
|
+
positivePrompt: 'a watercolor painting of a fox in autumn',
|
|
114
|
+
numberOfMedia: 1,
|
|
115
|
+
steps: 20,
|
|
116
|
+
guidance: 7.5
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Watch progress
|
|
120
|
+
const unsubscribe = sogni.projects.subscribe(project.id, (p) => {
|
|
121
|
+
console.log(`${p.status} — ${Math.round(p.progress * 100)}%`);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Wait for completion and get URLs
|
|
125
|
+
const urls = await sogni.projects.waitForCompletion(project.id);
|
|
126
|
+
unsubscribe();
|
|
127
|
+
console.log('Done:', urls);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`Project` is a plain serializable object — `project.id`, `project.status`, `project.jobs[]`, `project.resultUrls[]`. Drop it into Redux/Zustand/MMKV directly. Subscribe by ID; the SDK keeps an internal cache and garbage-collects projects 30 seconds after they reach a terminal state.
|
|
131
|
+
|
|
132
|
+
### img2img with an init image
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import * as ImagePicker from 'expo-image-picker';
|
|
136
|
+
|
|
137
|
+
const pick = await ImagePicker.launchImageLibraryAsync({ quality: 1 });
|
|
138
|
+
const asset = pick.assets![0]; // { uri, type, fileName, ... }
|
|
139
|
+
|
|
140
|
+
const project = await sogni.projects.create({
|
|
141
|
+
modelId: 'flux1-schnell-fp8',
|
|
142
|
+
positivePrompt: 'cinematic, painterly',
|
|
143
|
+
numberOfMedia: 1,
|
|
144
|
+
startingImage: { uri: asset.uri, type: asset.type, name: asset.fileName },
|
|
145
|
+
startingImageStrength: 0.7
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const urls = await sogni.projects.waitForCompletion(project.id);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### ControlNet
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const project = await sogni.projects.create({
|
|
155
|
+
modelId: 'sdxl-base',
|
|
156
|
+
positivePrompt: 'a fox in a forest',
|
|
157
|
+
numberOfMedia: 1,
|
|
158
|
+
controlNet: {
|
|
159
|
+
name: 'canny',
|
|
160
|
+
image: { uri: edgeAsset.uri, type: edgeAsset.type },
|
|
161
|
+
strength: 0.8,
|
|
162
|
+
mode: 'balanced'
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Multi-reference (context) images
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
const project = await sogni.projects.create({
|
|
171
|
+
modelId: 'gpt-image-2',
|
|
172
|
+
positivePrompt: 'merge the style of these references',
|
|
173
|
+
numberOfMedia: 1,
|
|
174
|
+
contextImages: [
|
|
175
|
+
{ uri: ref1.uri, type: ref1.type },
|
|
176
|
+
{ uri: ref2.uri, type: ref2.type }
|
|
177
|
+
]
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The SDK uploads images via signed PUT URLs before sending the generation request — no manual upload step required.
|
|
182
|
+
|
|
183
|
+
### Generate a video (LTX-2.3)
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
const project = await sogni.projects.create({
|
|
187
|
+
type: 'video',
|
|
188
|
+
modelId: 'ltx23-22b-fp8_t2v_distilled',
|
|
189
|
+
positivePrompt: 'a paper boat drifting down a river at sunset',
|
|
190
|
+
numberOfMedia: 1,
|
|
191
|
+
duration: 5, // seconds
|
|
192
|
+
fps: 24
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const urls = await sogni.projects.waitForCompletion(project.id);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The SDK derives frame count from `duration` and `fps` per the model's
|
|
199
|
+
conventions (LTX-2.3 snaps to `1 + n*8`, WAN 2.2 always generates at
|
|
200
|
+
16 fps regardless of the `fps` value, etc.). Override with explicit
|
|
201
|
+
`frames` if needed.
|
|
202
|
+
|
|
203
|
+
For image-to-video (first/last frame conditioning), pass `referenceImage`
|
|
204
|
+
and optionally `referenceImageEnd` as MediaInput. The SDK uploads them
|
|
205
|
+
before sending the generation request:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const project = await sogni.projects.create({
|
|
209
|
+
type: 'video',
|
|
210
|
+
modelId: 'ltx23-22b-fp8_i2v_distilled',
|
|
211
|
+
positivePrompt: 'the still painting comes to life',
|
|
212
|
+
numberOfMedia: 1,
|
|
213
|
+
duration: 4,
|
|
214
|
+
fps: 24,
|
|
215
|
+
referenceImage: pickerResult.assets[0]
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Generate music (ACE-Step 1.5)
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
const project = await sogni.projects.create({
|
|
223
|
+
type: 'audio',
|
|
224
|
+
modelId: 'ace_step_1.5_turbo',
|
|
225
|
+
positivePrompt: 'upbeat lo-fi hip-hop with mellow piano',
|
|
226
|
+
numberOfMedia: 1,
|
|
227
|
+
duration: 30, // seconds, 10-600
|
|
228
|
+
bpm: 90
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const urls = await sogni.projects.waitForCompletion(project.id);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
For instrumental music, omit `lyrics`. For songs, pass `lyrics` and
|
|
235
|
+
optionally `language`.
|
|
236
|
+
|
|
237
|
+
### Chat with an LLM (streaming)
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
const models = sogni.chat.getAvailableModels();
|
|
241
|
+
const modelId = Object.keys(models)[0]; // pick whichever you prefer
|
|
242
|
+
|
|
243
|
+
const stream = await sogni.chat.completions.create({
|
|
244
|
+
model: modelId,
|
|
245
|
+
messages: [
|
|
246
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
247
|
+
{ role: 'user', content: 'Write a haiku about React Native.' }
|
|
248
|
+
],
|
|
249
|
+
stream: true,
|
|
250
|
+
temperature: 0.7
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
for await (const chunk of stream) {
|
|
254
|
+
process.stdout.write(chunk.content);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const result = await stream.result;
|
|
258
|
+
console.log('\nfinishReason:', result.finishReason, 'tokens:', result.usage);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Chat (non-streaming)
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
const result = await sogni.chat.completions.create({
|
|
265
|
+
model: modelId,
|
|
266
|
+
messages: [{ role: 'user', content: 'Explain WebSockets in one sentence.' }]
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
console.log(result.content);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Multimodal (vision)
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import * as ImagePicker from 'expo-image-picker';
|
|
276
|
+
import * as FileSystem from 'expo-file-system';
|
|
277
|
+
|
|
278
|
+
const pick = await ImagePicker.launchImageLibraryAsync({ base64: true });
|
|
279
|
+
const dataUri = `data:${pick.assets![0].mimeType};base64,${pick.assets![0].base64}`;
|
|
280
|
+
|
|
281
|
+
const result = await sogni.chat.completions.create({
|
|
282
|
+
model: modelId, // must be a vision-capable model (Qwen 3.5 VLM, etc.)
|
|
283
|
+
messages: [
|
|
284
|
+
{
|
|
285
|
+
role: 'user',
|
|
286
|
+
content: [
|
|
287
|
+
{ type: 'text', text: 'What is in this image?' },
|
|
288
|
+
{ type: 'image_url', image_url: { url: dataUri } }
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
]
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Tool calling — describe a photo as structured JSON
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
import { parseToolCallArguments } from '@sogni-ai/expo-client';
|
|
299
|
+
import * as ImagePicker from 'expo-image-picker';
|
|
300
|
+
|
|
301
|
+
const pick = await ImagePicker.launchImageLibraryAsync({ base64: true });
|
|
302
|
+
const dataUri = `data:${pick.assets![0].mimeType};base64,${pick.assets![0].base64}`;
|
|
303
|
+
|
|
304
|
+
const tools = [
|
|
305
|
+
{
|
|
306
|
+
type: 'function' as const,
|
|
307
|
+
function: {
|
|
308
|
+
name: 'save_photo_description',
|
|
309
|
+
description: 'Save a structured description of the user-provided photo.',
|
|
310
|
+
parameters: {
|
|
311
|
+
type: 'object',
|
|
312
|
+
properties: {
|
|
313
|
+
summary: { type: 'string', description: 'One-sentence summary' },
|
|
314
|
+
tags: {
|
|
315
|
+
type: 'array',
|
|
316
|
+
items: { type: 'string' },
|
|
317
|
+
description: 'Up to 8 short tags'
|
|
318
|
+
},
|
|
319
|
+
mood: { type: 'string', description: 'e.g. cheerful, melancholic' }
|
|
320
|
+
},
|
|
321
|
+
required: ['summary', 'tags']
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
const result = await sogni.chat.completions.create({
|
|
328
|
+
model: visionModelId,
|
|
329
|
+
tools,
|
|
330
|
+
tool_choice: { type: 'function', function: { name: 'save_photo_description' } },
|
|
331
|
+
messages: [
|
|
332
|
+
{
|
|
333
|
+
role: 'user',
|
|
334
|
+
content: [
|
|
335
|
+
{ type: 'text', text: 'Look at this photo and call the save_photo_description tool.' },
|
|
336
|
+
{ type: 'image_url', image_url: { url: dataUri } }
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
if (result.tool_calls?.length) {
|
|
343
|
+
const args = parseToolCallArguments<{
|
|
344
|
+
summary: string;
|
|
345
|
+
tags: string[];
|
|
346
|
+
mood?: string;
|
|
347
|
+
}>(result.tool_calls[0]);
|
|
348
|
+
console.log(args.summary, args.tags, args.mood);
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Multi-round tool execution (`autoExecuteTools`)
|
|
353
|
+
|
|
354
|
+
For agent-style flows where the model might call multiple tools in
|
|
355
|
+
sequence (e.g., "look up X, then summarize Y"), pass
|
|
356
|
+
`autoExecuteTools: true` and an `onToolCall` handler. The SDK runs the
|
|
357
|
+
loop until the model answers without calling more tools:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
const result = await sogni.chat.completions.create({
|
|
361
|
+
model: modelId,
|
|
362
|
+
messages: [{ role: 'user', content: 'What is the weather in Kyiv?' }],
|
|
363
|
+
tools: [getWeatherTool],
|
|
364
|
+
autoExecuteTools: true,
|
|
365
|
+
maxToolRounds: 5,
|
|
366
|
+
onToolCall: async (call) => {
|
|
367
|
+
const args = parseToolCallArguments<{ city: string }>(call);
|
|
368
|
+
const weather = await fetchWeather(args.city);
|
|
369
|
+
return JSON.stringify(weather);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// result.content is the model's final natural-language answer
|
|
374
|
+
// result.toolHistory[] shows each round
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Sogni hosted tools (the `sogni_*` family that lets the LLM directly
|
|
378
|
+
trigger image/video/music generation server-side) are coming in a
|
|
379
|
+
follow-up release.
|
|
380
|
+
|
|
381
|
+
## Account snapshot shape
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
interface AccountSnapshot {
|
|
385
|
+
authenticated: boolean;
|
|
386
|
+
networkStatus: 'connected' | 'disconnected' | 'connecting';
|
|
387
|
+
network: 'fast' | 'relaxed' | null;
|
|
388
|
+
balance: Balances;
|
|
389
|
+
walletAddress: string | null;
|
|
390
|
+
username: string | null;
|
|
391
|
+
email: string | null;
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Snapshots are plain data — drop them straight into Redux/Zustand/MMKV without conversion.
|
|
396
|
+
|
|
397
|
+
## Imports
|
|
398
|
+
|
|
399
|
+
| Path | Purpose |
|
|
400
|
+
| --- | --- |
|
|
401
|
+
| `@sogni-ai/expo-client` | Main SDK |
|
|
402
|
+
| `@sogni-ai/expo-client/wallet` | Wallet creation & EIP-712 signing (tree-shakable; only pulled in if you use it) |
|
|
403
|
+
|
|
404
|
+
## Requirements
|
|
405
|
+
|
|
406
|
+
- Expo SDK 50 or newer
|
|
407
|
+
- React Native 0.73 or newer
|
|
408
|
+
|
|
409
|
+
## License
|
|
410
|
+
|
|
411
|
+
ISC
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import ApiClient from '../ApiClient';
|
|
2
|
+
import TypedEventEmitter from '../lib/TypedEventEmitter';
|
|
3
|
+
import { AccountSnapshot, Balances, LoginData, MeData, SignupParams } from './types';
|
|
4
|
+
interface AccountEvents {
|
|
5
|
+
change: AccountSnapshot;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Account API: authentication, current-user info, balance.
|
|
9
|
+
*
|
|
10
|
+
* login() and signup() derive a deterministic wallet from username + password
|
|
11
|
+
* via PBKDF2(password, username, 10000 iter, SHA-256, 32 bytes), then sign an
|
|
12
|
+
* EIP-712 authentication or signup message with that wallet. The wallet
|
|
13
|
+
* private key never leaves the device.
|
|
14
|
+
*
|
|
15
|
+
* login()/signup() require token-based auth (the default). For API-key auth,
|
|
16
|
+
* use the apiKey config option in SogniClient.create() instead.
|
|
17
|
+
*/
|
|
18
|
+
declare class AccountApi extends TypedEventEmitter<AccountEvents> {
|
|
19
|
+
private _client;
|
|
20
|
+
private _snapshot;
|
|
21
|
+
private _walletNetwork;
|
|
22
|
+
constructor(client: ApiClient, options?: {
|
|
23
|
+
testnet?: boolean;
|
|
24
|
+
});
|
|
25
|
+
/** Read-only snapshot of the current account state. */
|
|
26
|
+
get current(): Readonly<AccountSnapshot>;
|
|
27
|
+
/** Subscribe to account state changes. Returns an unsubscribe function. */
|
|
28
|
+
onChange(listener: (snapshot: AccountSnapshot) => void): () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Log in with username + password. Derives the user's wallet on-device,
|
|
31
|
+
* signs an EIP-712 authentication message, and exchanges it for JWT tokens
|
|
32
|
+
* which are then persisted to SecureStore.
|
|
33
|
+
*/
|
|
34
|
+
login(username: string, password: string, options?: {
|
|
35
|
+
appSource?: string;
|
|
36
|
+
}): Promise<LoginData>;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new account. Derives the user's wallet on-device, signs the
|
|
39
|
+
* EIP-712 signup payload, and exchanges it for JWT tokens (the user is
|
|
40
|
+
* automatically logged in on success).
|
|
41
|
+
*/
|
|
42
|
+
signup(params: SignupParams): Promise<LoginData>;
|
|
43
|
+
/** Fetch the current user's profile data from REST. Updates the snapshot. */
|
|
44
|
+
me(): Promise<MeData>;
|
|
45
|
+
/**
|
|
46
|
+
* Force-refresh the current user's balance from REST. Balance also updates
|
|
47
|
+
* automatically via socket events — call this only when you need a synchronous
|
|
48
|
+
* fetch (e.g., on screen mount before the socket has reconnected).
|
|
49
|
+
*/
|
|
50
|
+
refreshBalance(): Promise<Balances>;
|
|
51
|
+
/**
|
|
52
|
+
* Log out and clear all auth state. Closes the WebSocket and removes any
|
|
53
|
+
* persisted tokens. Safe to call even if not authenticated.
|
|
54
|
+
*/
|
|
55
|
+
logout(): Promise<void>;
|
|
56
|
+
private _getNonce;
|
|
57
|
+
private _update;
|
|
58
|
+
}
|
|
59
|
+
export default AccountApi;
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Account/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAoC,MAAM,cAAc,CAAC;AAChE,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AAGzD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,MAAM,EACN,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB,UAAU,aAAa;IACrB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,cAAM,UAAW,SAAQ,iBAAiB,CAAC,aAAa,CAAC;IACvD,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAgB;gBAE1B,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO;IAiClE,uDAAuD;IACvD,IAAI,OAAO,IAAI,QAAQ,CAAC,eAAe,CAAC,CAEvC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAInE;;;;OAIG;IACG,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GACnC,OAAO,CAAC,SAAS,CAAC;IAsBrB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC;IAuCtD,6EAA6E;IACvE,EAAE,IAAI,OAAO,CAAC,MAAM,CAAC;IAU3B;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC;IAMzC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAaf,SAAS;IAOvB,OAAO,CAAC,OAAO;CAMhB;AAUD,eAAe,UAAU,CAAC"}
|