onairos 2.1.2 → 2.1.3
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/BACKEND_INTEGRATION_SUMMARY.md +159 -0
- package/SDK_QUICK_REFERENCE.md +408 -0
- package/dist/onairos.bundle.js +1 -1
- package/dist/onairos.bundle.js.map +1 -1
- package/dist/onairos.esm.js +1 -1
- package/dist/onairos.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/DataRequest.js +51 -8
- package/src/iframe/dataRequestHandler.js +153 -19
- package/src/mobile/MobileDataRequestPage.jsx +44 -3
- package/test-enhanced-live-mode.html +65 -3
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Backend Integration Summary
|
|
2
|
+
|
|
3
|
+
## 🎯 Issues Fixed
|
|
4
|
+
|
|
5
|
+
### ✅ **Visual Feedback for Data Selections**
|
|
6
|
+
- **Added custom checkboxes** with visual checkmarks when selected
|
|
7
|
+
- **Enhanced styling** with hover effects, selection highlights, and smooth transitions
|
|
8
|
+
- **Real-time visual updates** when users toggle data types
|
|
9
|
+
- **Modern UI design** with consistent styling across all components
|
|
10
|
+
|
|
11
|
+
### ✅ **Backend API Format Compatibility**
|
|
12
|
+
- **Fixed API request format** to match backend expectations
|
|
13
|
+
- **Implemented Info structure** as required by the backend route
|
|
14
|
+
- **Proper data type mapping** from frontend to backend confirmations
|
|
15
|
+
- **Correct endpoint usage** for live vs test modes
|
|
16
|
+
|
|
17
|
+
## 🔧 Data Type Mapping
|
|
18
|
+
|
|
19
|
+
Frontend data types are now correctly mapped to backend confirmation types:
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const dataTypeMapping = {
|
|
23
|
+
'basic': 'Medium', // Basic info -> Medium data analysis
|
|
24
|
+
'personality': 'Large', // Personality -> Large/full analysis
|
|
25
|
+
'preferences': 'Traits' // Preferences -> Traits data
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 📡 API Request Format
|
|
30
|
+
|
|
31
|
+
### Live Mode (Production)
|
|
32
|
+
```javascript
|
|
33
|
+
POST https://api2.onairos.uk/getAPIurlMobile
|
|
34
|
+
{
|
|
35
|
+
"Info": {
|
|
36
|
+
"storage": "local",
|
|
37
|
+
"appId": "YourApp",
|
|
38
|
+
"confirmations": [
|
|
39
|
+
{"data": "Medium", "date": "2024-01-15T10:30:00Z"},
|
|
40
|
+
{"data": "Large", "date": "2024-01-15T10:30:00Z"}
|
|
41
|
+
],
|
|
42
|
+
"EncryptedUserPin": "pending_pin_integration",
|
|
43
|
+
"account": "user@example.com",
|
|
44
|
+
"proofMode": false,
|
|
45
|
+
"Domain": "yourapp.com",
|
|
46
|
+
"web3Type": "standard",
|
|
47
|
+
"OthentSub": null
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Test Mode (Development)
|
|
53
|
+
```javascript
|
|
54
|
+
POST https://api2.onairos.uk/inferenceTest
|
|
55
|
+
{
|
|
56
|
+
"approvedData": ["basic", "personality"],
|
|
57
|
+
"userEmail": "user@example.com",
|
|
58
|
+
"appName": "TestApp",
|
|
59
|
+
"testMode": true,
|
|
60
|
+
"timestamp": "2024-01-15T10:30:00Z"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 🏗️ Backend Route Compatibility
|
|
65
|
+
|
|
66
|
+
The implementation now correctly matches your backend route expectations:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// Your backend route expects:
|
|
70
|
+
const Web3Type = req.body.Info.web3Type;
|
|
71
|
+
const confirmations = req.body.Info.confirmations;
|
|
72
|
+
const domain = req.body.Info.Domain;
|
|
73
|
+
const EncryptedUserPin = req.body.Info.EncryptedUserPin;
|
|
74
|
+
const OthentSub = req.body.Info.OthentSub;
|
|
75
|
+
const proofMode = req.body.Info.proofMode;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
✅ All these fields are now provided in the correct `Info` structure.
|
|
79
|
+
|
|
80
|
+
## 🎨 Visual Improvements
|
|
81
|
+
|
|
82
|
+
### Enhanced Data Request UI
|
|
83
|
+
- **Custom checkboxes** with blue checkmarks
|
|
84
|
+
- **Selection highlighting** with blue borders and background
|
|
85
|
+
- **Smooth animations** and hover effects
|
|
86
|
+
- **Better typography** and spacing
|
|
87
|
+
- **Visual feedback** when items are selected/deselected
|
|
88
|
+
|
|
89
|
+
### Updated Button Styling
|
|
90
|
+
- **Gradient buttons** with improved hover states
|
|
91
|
+
- **Icon integration** for better UX
|
|
92
|
+
- **Consistent styling** across all components
|
|
93
|
+
|
|
94
|
+
## 🔄 Callback Logic
|
|
95
|
+
|
|
96
|
+
### Auto Mode False (Default)
|
|
97
|
+
Returns API URL for manual calling:
|
|
98
|
+
```javascript
|
|
99
|
+
{
|
|
100
|
+
success: true,
|
|
101
|
+
apiUrl: "https://api2.onairos.uk/getAPIurlMobile",
|
|
102
|
+
approvedData: ["basic", "personality"],
|
|
103
|
+
Info: { /* backend format */ },
|
|
104
|
+
message: "Data request approved. Use the provided API URL to fetch user data."
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Auto Mode True
|
|
109
|
+
Makes API request automatically and returns results:
|
|
110
|
+
```javascript
|
|
111
|
+
{
|
|
112
|
+
success: true,
|
|
113
|
+
apiResponse: { /* API response data */ },
|
|
114
|
+
apiUrl: "https://api2.onairos.uk/getAPIurlMobile",
|
|
115
|
+
approvedData: ["basic", "personality"]
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 📱 Component Updates
|
|
120
|
+
|
|
121
|
+
### Files Modified:
|
|
122
|
+
1. **`dataRequestHandler.js`** - Enhanced popup with visual feedback and backend format
|
|
123
|
+
2. **`onairosButton.jsx`** - Added testMode parameter support
|
|
124
|
+
3. **`DataRequest.js`** - Updated with backend format and visual improvements
|
|
125
|
+
4. **`MobileDataRequestPage.jsx`** - Aligned with new API structure
|
|
126
|
+
5. **`test-enhanced-live-mode.html`** - Comprehensive testing interface
|
|
127
|
+
|
|
128
|
+
## 🧪 Testing
|
|
129
|
+
|
|
130
|
+
Use the enhanced test file (`test-enhanced-live-mode.html`) to verify:
|
|
131
|
+
|
|
132
|
+
### Visual Testing
|
|
133
|
+
- [ ] Checkmarks appear when data types are selected
|
|
134
|
+
- [ ] Selection highlighting works correctly
|
|
135
|
+
- [ ] Hover effects and animations function properly
|
|
136
|
+
|
|
137
|
+
### API Integration Testing
|
|
138
|
+
- [ ] Live mode sends correct `Info` structure
|
|
139
|
+
- [ ] Test mode uses simple format for testing
|
|
140
|
+
- [ ] Data type mapping works correctly (basic→Medium, etc.)
|
|
141
|
+
- [ ] Auto fetch modes work as expected
|
|
142
|
+
|
|
143
|
+
### Backend Compatibility
|
|
144
|
+
- [ ] Requests match your backend route expectations
|
|
145
|
+
- [ ] All required fields are present in `Info` object
|
|
146
|
+
- [ ] Confirmations array has correct format
|
|
147
|
+
- [ ] Domain and other metadata included
|
|
148
|
+
|
|
149
|
+
## 🚀 Ready for Production
|
|
150
|
+
|
|
151
|
+
The implementation is now fully compatible with your backend requirements:
|
|
152
|
+
|
|
153
|
+
✅ **Visual feedback** - Users see checkmarks when selecting data types
|
|
154
|
+
✅ **Correct API format** - Sends `Info` structure as expected by backend
|
|
155
|
+
✅ **Data mapping** - Frontend types correctly mapped to backend confirmations
|
|
156
|
+
✅ **Test/Live modes** - Proper endpoint switching with format handling
|
|
157
|
+
✅ **Callback logic** - Returns API URL or results based on auto mode
|
|
158
|
+
|
|
159
|
+
All APIs now follow the SDK_QUICK_REFERENCE.md format and your backend route expectations!
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# SDK Quick Reference Guide
|
|
2
|
+
|
|
3
|
+
## 🚀 Essential Endpoints & Flows
|
|
4
|
+
|
|
5
|
+
### Base URL: `https://api2.onairos.uk`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🔐 Authentication Headers
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// Pattern 1: API Key + User JWT (Primary)
|
|
13
|
+
const headers = {
|
|
14
|
+
'x-api-key': 'ona_your_32_character_api_key',
|
|
15
|
+
'Authorization': `Bearer ${userJwtToken}`,
|
|
16
|
+
'Content-Type': 'application/json'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Pattern 2: User JWT Only (Enoch users)
|
|
20
|
+
const headers = {
|
|
21
|
+
'Authorization': `Bearer ${userJwtToken}`,
|
|
22
|
+
'Content-Type': 'application/json'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Testing: Admin key bypasses validation
|
|
26
|
+
const adminKey = 'OnairosIsAUnicorn2025';
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 📧 Email Verification Flow
|
|
32
|
+
|
|
33
|
+
### Request Code
|
|
34
|
+
```http
|
|
35
|
+
POST /email/verification
|
|
36
|
+
{
|
|
37
|
+
"email": "user@example.com",
|
|
38
|
+
"action": "request"
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Verify Code & Get JWT
|
|
43
|
+
```http
|
|
44
|
+
POST /email/verification
|
|
45
|
+
{
|
|
46
|
+
"email": "user@example.com",
|
|
47
|
+
"action": "verify",
|
|
48
|
+
"code": "123456"
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Response (New User)**:
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"success": true,
|
|
56
|
+
"isNewUser": true,
|
|
57
|
+
"token": "eyJhbGciOiJIUzI1NiIs...",
|
|
58
|
+
"userName": "user123",
|
|
59
|
+
"enochInstructions": {
|
|
60
|
+
"recommendedFlow": "onboarding"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Response (Existing User)**:
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"success": true,
|
|
69
|
+
"isNewUser": false,
|
|
70
|
+
"token": "eyJhbGciOiJIUzI1NiIs...",
|
|
71
|
+
"existingUserData": {
|
|
72
|
+
"hasExistingData": true,
|
|
73
|
+
"summary": {
|
|
74
|
+
"connectionsCount": 3,
|
|
75
|
+
"traitsCount": 5
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"enochInstructions": {
|
|
79
|
+
"recommendedFlow": "dashboard"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 🔒 PIN Management
|
|
87
|
+
|
|
88
|
+
### Store PIN
|
|
89
|
+
```http
|
|
90
|
+
POST /store-pin/mobile
|
|
91
|
+
Authorization: Bearer {userJwtToken}
|
|
92
|
+
{
|
|
93
|
+
"username": "user123",
|
|
94
|
+
"pin": "MySecure1!"
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**PIN Requirements**: 8+ chars, 1 uppercase, 1 symbol
|
|
99
|
+
|
|
100
|
+
### Check PIN Status
|
|
101
|
+
```http
|
|
102
|
+
GET /store-pin/status/{username}
|
|
103
|
+
→ {"success": true, "hasPinStored": true}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 🔗 OAuth Connectors
|
|
109
|
+
|
|
110
|
+
### YouTube Native Auth
|
|
111
|
+
```http
|
|
112
|
+
POST /youtube/native-auth
|
|
113
|
+
x-api-key: {apiKey}
|
|
114
|
+
Authorization: Bearer {userJwt}
|
|
115
|
+
{
|
|
116
|
+
"userAccountInfo": {
|
|
117
|
+
"username": "user123",
|
|
118
|
+
"email": "user@example.com",
|
|
119
|
+
"channelName": "My Channel",
|
|
120
|
+
"channelId": "UCxxxxx"
|
|
121
|
+
},
|
|
122
|
+
"accessToken": "ya29.a0AfH6SMC...",
|
|
123
|
+
"refreshToken": "4/0AX4XfWi...",
|
|
124
|
+
"idToken": "eyJhbGciOiJSUzI1NiIs..."
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Critical OAuth Config**:
|
|
129
|
+
```javascript
|
|
130
|
+
{
|
|
131
|
+
offlineAccess: true,
|
|
132
|
+
forceCodeForRefreshToken: true,
|
|
133
|
+
prompt: 'consent',
|
|
134
|
+
scopes: ['https://www.googleapis.com/auth/youtube.readonly', 'openid', 'profile', 'email']
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Other Platforms
|
|
139
|
+
- **LinkedIn**: `POST /linkedin/authorize`
|
|
140
|
+
- **Reddit**: `POST /reddit/authorize`
|
|
141
|
+
- **Pinterest**: `POST /pinterest/authorize`
|
|
142
|
+
- **Instagram**: `POST /instagram/authorize`
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 📊 Data Requests
|
|
147
|
+
|
|
148
|
+
### Get Data API URL
|
|
149
|
+
```http
|
|
150
|
+
POST /getAPIurlMobile
|
|
151
|
+
{
|
|
152
|
+
"Info": {
|
|
153
|
+
"storage": "local",
|
|
154
|
+
"appId": "your_app_id",
|
|
155
|
+
"confirmations": [{"data": "Large", "date": "2024-01-15T10:30:00Z"}],
|
|
156
|
+
"EncryptedUserPin": "encrypted_pin_data",
|
|
157
|
+
"account": "user123",
|
|
158
|
+
"proofMode": false
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Response**:
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"apiUrl": "https://api2.onairos.uk/mobileInferenceNoProof",
|
|
167
|
+
"token": "eyJhbGciOiJIUzI1NiIs..."
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Get Traits
|
|
172
|
+
```http
|
|
173
|
+
POST /traits
|
|
174
|
+
Authorization: Bearer {inferenceToken}
|
|
175
|
+
→ {"traits": {"openness": 0.75, "conscientiousness": 0.68}}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Mobile Inference
|
|
179
|
+
```http
|
|
180
|
+
POST /mobileInferenceNoProof
|
|
181
|
+
Authorization: Bearer {inferenceToken}
|
|
182
|
+
{"Input": "text_to_analyze"}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 👤 User Data
|
|
188
|
+
|
|
189
|
+
### Connected Accounts
|
|
190
|
+
```http
|
|
191
|
+
GET /connected-accounts?username={username}
|
|
192
|
+
→ {
|
|
193
|
+
"connectedAccounts": [
|
|
194
|
+
{
|
|
195
|
+
"platform": "YouTube",
|
|
196
|
+
"accountName": "My Channel",
|
|
197
|
+
"status": "active",
|
|
198
|
+
"hasData": true
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Connection Health
|
|
205
|
+
```http
|
|
206
|
+
GET /youtube/connection-status/{username}
|
|
207
|
+
→ {
|
|
208
|
+
"success": true,
|
|
209
|
+
"connectionStatus": "healthy",
|
|
210
|
+
"needsReauth": false,
|
|
211
|
+
"tokenDetails": {
|
|
212
|
+
"hasRefreshToken": true,
|
|
213
|
+
"isExpired": false
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 🏋️ Training & Models
|
|
221
|
+
|
|
222
|
+
### Training Progress (WebSocket)
|
|
223
|
+
```javascript
|
|
224
|
+
socket.emit('startTraining', {
|
|
225
|
+
username: 'user123',
|
|
226
|
+
encryptionMode: true,
|
|
227
|
+
platforms: ['youtube', 'linkedin']
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Receive updates
|
|
231
|
+
socket.on('trainingUpdate', (data) => {
|
|
232
|
+
console.log(`Progress: ${data.progress}% - ${data.stage}`);
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Download Model
|
|
237
|
+
```http
|
|
238
|
+
POST /mobile-training/download-model
|
|
239
|
+
Authorization: Bearer {userJwt}
|
|
240
|
+
→ {
|
|
241
|
+
"model": "base64_encoded_model_data",
|
|
242
|
+
"encryption": {"iv": "base64_iv", "key": "base64_key"}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 🚨 Error Codes
|
|
249
|
+
|
|
250
|
+
| Code | Description | Action |
|
|
251
|
+
|------|-------------|---------|
|
|
252
|
+
| `MISSING_API_KEY` | No API key provided | Add x-api-key header |
|
|
253
|
+
| `INVALID_CODE` | Wrong verification code | Ask user to re-enter |
|
|
254
|
+
| `USER_NOT_FOUND` | User doesn't exist | Create new account |
|
|
255
|
+
| `PIN_REQUIRED` | PIN not set | Redirect to PIN setup |
|
|
256
|
+
| `RATE_LIMITED` | Too many requests | Wait and retry |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 💻 Actual Implementation Patterns
|
|
261
|
+
|
|
262
|
+
### Direct API Calls (Your Actual Pattern)
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
// 1. Email Verification (Direct)
|
|
266
|
+
const verifyEmail = async (email, code, apiKey) => {
|
|
267
|
+
const response = await fetch('https://api2.onairos.uk/email/verification', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
headers: {
|
|
270
|
+
'x-api-key': apiKey,
|
|
271
|
+
'Content-Type': 'application/json'
|
|
272
|
+
},
|
|
273
|
+
body: JSON.stringify({
|
|
274
|
+
email: email,
|
|
275
|
+
action: 'verify',
|
|
276
|
+
code: code
|
|
277
|
+
})
|
|
278
|
+
});
|
|
279
|
+
return await response.json();
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// 2. YouTube Mobile Signin (Your Actual Pattern)
|
|
283
|
+
const connectYouTubeMobile = async (tokens, username, apiKey) => {
|
|
284
|
+
const response = await fetch('https://api2.onairos.uk/youtube/mobileSignin', {
|
|
285
|
+
method: 'POST',
|
|
286
|
+
headers: {
|
|
287
|
+
'x-api-key': apiKey,
|
|
288
|
+
'Content-Type': 'application/json'
|
|
289
|
+
},
|
|
290
|
+
body: JSON.stringify({
|
|
291
|
+
idToken: tokens.idToken,
|
|
292
|
+
accessToken: tokens.accessToken,
|
|
293
|
+
serverAuthCode: tokens.serverAuthCode,
|
|
294
|
+
username: username
|
|
295
|
+
})
|
|
296
|
+
});
|
|
297
|
+
return await response.json();
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// 3. Mobile Training (WebSocket + HTTP)
|
|
301
|
+
const startMobileTraining = async (userJwt, socketId, platforms) => {
|
|
302
|
+
const response = await fetch('https://api2.onairos.uk/mobile-training/clean', {
|
|
303
|
+
method: 'POST',
|
|
304
|
+
headers: {
|
|
305
|
+
'Authorization': `Bearer ${userJwt}`,
|
|
306
|
+
'Content-Type': 'application/json'
|
|
307
|
+
},
|
|
308
|
+
body: JSON.stringify({
|
|
309
|
+
socketId: socketId,
|
|
310
|
+
connectedPlatforms: platforms
|
|
311
|
+
})
|
|
312
|
+
});
|
|
313
|
+
return await response.json();
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// 4. Data Request (Your Info Pattern)
|
|
317
|
+
const requestDataAccess = async (userInfo) => {
|
|
318
|
+
const response = await fetch('https://api2.onairos.uk/getAPIurlMobile', {
|
|
319
|
+
method: 'POST',
|
|
320
|
+
headers: {
|
|
321
|
+
'Content-Type': 'application/json'
|
|
322
|
+
},
|
|
323
|
+
body: JSON.stringify({
|
|
324
|
+
Info: {
|
|
325
|
+
storage: "local",
|
|
326
|
+
appId: userInfo.appId,
|
|
327
|
+
confirmations: userInfo.confirmations,
|
|
328
|
+
EncryptedUserPin: userInfo.encryptedPin,
|
|
329
|
+
account: userInfo.username,
|
|
330
|
+
proofMode: false
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
return await response.json();
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// 5. Mobile Model Download (Your Actual Pattern)
|
|
338
|
+
const downloadModel = async (username) => {
|
|
339
|
+
const response = await fetch('https://api2.onairos.uk/sendMobileModel', {
|
|
340
|
+
method: 'POST',
|
|
341
|
+
headers: {
|
|
342
|
+
'Content-Type': 'application/json'
|
|
343
|
+
},
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
Info: {
|
|
346
|
+
username: username
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
});
|
|
350
|
+
return await response.json();
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## ✅ Implementation Checklist
|
|
357
|
+
|
|
358
|
+
- [ ] **Auth**: Email verification + JWT storage
|
|
359
|
+
- [ ] **PIN**: Secure PIN storage with validation
|
|
360
|
+
- [ ] **OAuth**: Proper refresh token handling
|
|
361
|
+
- [ ] **Data**: Training + inference flows
|
|
362
|
+
- [ ] **Errors**: Handle all error codes gracefully
|
|
363
|
+
- [ ] **Testing**: Use admin key for development
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### WebSocket Training Pattern
|
|
368
|
+
```javascript
|
|
369
|
+
// Complete training flow example
|
|
370
|
+
const runMobileTraining = async (jwtToken, username, platforms) => {
|
|
371
|
+
// 1. Connect to WebSocket
|
|
372
|
+
const socket = io('https://api2.onairos.uk');
|
|
373
|
+
|
|
374
|
+
// 2. Set up listeners
|
|
375
|
+
socket.on('trainingUpdate', (data) => {
|
|
376
|
+
console.log(`Progress: ${data.progress}% - ${data.stage}`);
|
|
377
|
+
updateTrainingUI(data);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
socket.on('trainingCompleted', (data) => {
|
|
381
|
+
console.log('Training completed!', data);
|
|
382
|
+
showTrainingComplete(data);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// 3. Start training via HTTP
|
|
386
|
+
const response = await fetch('https://api2.onairos.uk/mobile-training/clean', {
|
|
387
|
+
method: 'POST',
|
|
388
|
+
headers: {
|
|
389
|
+
'Authorization': `Bearer ${jwtToken}`,
|
|
390
|
+
'Content-Type': 'application/json'
|
|
391
|
+
},
|
|
392
|
+
body: JSON.stringify({
|
|
393
|
+
socketId: socket.id,
|
|
394
|
+
connectedPlatforms: platforms
|
|
395
|
+
})
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
return await response.json();
|
|
399
|
+
};
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Key Implementation Points:**
|
|
403
|
+
1. **Use direct fetch calls** - no SDK wrapper needed
|
|
404
|
+
2. **Follow Info pattern** for data requests: `{Info: {username: "..."}}`
|
|
405
|
+
3. **WebSocket + HTTP combo** for training with real-time updates
|
|
406
|
+
4. **serverAuthCode is refresh token** in OAuth flows
|
|
407
|
+
5. **Store JWT securely** (Keychain/Keystore)
|
|
408
|
+
6. **Test with admin key** (`OnairosIsAUnicorn2025`) before production
|