onairos 2.1.1 → 2.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onairos",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "dependencies": {
5
5
  "@react-oauth/google": "^0.12.1",
6
6
  "@telegram-apps/sdk-react": "^2.0.25",
@@ -3,29 +3,22 @@ import React, { useState } from 'react';
3
3
  const dataTypes = [
4
4
  {
5
5
  id: 'basic',
6
- name: 'Basic Information',
7
- description: 'Name, email, and essential account details',
6
+ name: 'Basic Info',
7
+ description: 'Essential profile information and account details',
8
8
  icon: '👤',
9
- required: true // Cannot be deselected
10
- },
11
- {
12
- id: 'memories',
13
- name: 'Memories',
14
- description: 'Preferences and interests',
15
- icon: '🧠',
16
9
  required: false
17
10
  },
18
11
  {
19
- id: 'social',
20
- name: 'Social Activity',
21
- description: 'Posts, likes, and social interactions',
22
- icon: '📱',
12
+ id: 'personality',
13
+ name: 'Personality',
14
+ description: 'Personality traits, behavioral patterns and insights',
15
+ icon: '🧠',
23
16
  required: false
24
17
  },
25
18
  {
26
19
  id: 'preferences',
27
20
  name: 'Preferences',
28
- description: 'Settings and customization choices',
21
+ description: 'User preferences, settings and choices',
29
22
  icon: '⚙️',
30
23
  required: false
31
24
  }
@@ -35,12 +28,12 @@ export default function DataRequest({
35
28
  onComplete,
36
29
  userEmail,
37
30
  appName = 'App',
38
- autoFetch = true
31
+ autoFetch = false,
32
+ testMode = false
39
33
  }) {
40
34
  const [selectedData, setSelectedData] = useState({
41
- basic: true, // Always selected by default
42
- memories: false,
43
- social: false,
35
+ basic: false, // User can choose
36
+ personality: false,
44
37
  preferences: false
45
38
  });
46
39
  const [isSubmitting, setIsSubmitting] = useState(false);
@@ -49,9 +42,6 @@ export default function DataRequest({
49
42
  const [apiError, setApiError] = useState(null);
50
43
 
51
44
  const handleDataToggle = (dataId) => {
52
- // Don't allow toggling basic information (it's required)
53
- if (dataId === 'basic') return;
54
-
55
45
  setSelectedData(prev => ({
56
46
  ...prev,
57
47
  [dataId]: !prev[dataId]
@@ -83,39 +73,84 @@ export default function DataRequest({
83
73
  // Create a unique user hash for this request
84
74
  const userHash = generateUserHash(userEmail);
85
75
 
86
- // Prepare the request with selected data types
87
- const requestData = {
76
+ // Get selected data types
77
+ const approvedData = Object.entries(selectedData)
78
+ .filter(([key, value]) => value)
79
+ .map(([key]) => key);
80
+
81
+ // Determine API endpoint based on test mode
82
+ const apiEndpoint = testMode
83
+ ? 'https://api2.onairos.uk/inferenceTest'
84
+ : 'https://api2.onairos.uk/inference';
85
+
86
+ // Prepare the base result
87
+ const baseResult = {
88
88
  userHash,
89
89
  appName,
90
- requestedData: Object.entries(selectedData)
91
- .filter(([key, value]) => value)
92
- .map(([key]) => key),
90
+ approvedData,
91
+ apiUrl: apiEndpoint,
92
+ testMode,
93
93
  timestamp: new Date().toISOString()
94
94
  };
95
95
 
96
- // In a real implementation, you would make an API call here
97
96
  if (autoFetch) {
98
- // Simulate API call
99
- await new Promise(resolve => setTimeout(resolve, 2000));
100
-
101
- // Mock response data
102
- const mockData = {
103
- success: true,
104
- userHash,
105
- data: {
106
- basic: selectedData.basic ? { name: "John Doe", email: userEmail } : null,
107
- memories: selectedData.memories ? { interests: ["technology", "travel"], preferences: ["dark mode", "notifications"] } : null,
108
- social: selectedData.social ? { posts: 45, likes: 230, connections: 156 } : null,
109
- preferences: selectedData.preferences ? { theme: "dark", language: "en", notifications: true } : null
97
+ // Auto mode true: make API request and return results
98
+ try {
99
+ const response = await fetch(apiEndpoint, {
100
+ method: 'POST',
101
+ headers: {
102
+ 'Content-Type': 'application/json',
103
+ },
104
+ body: JSON.stringify({
105
+ approvedData,
106
+ userEmail,
107
+ appName,
108
+ testMode,
109
+ timestamp: new Date().toISOString()
110
+ })
111
+ });
112
+
113
+ if (!response.ok) {
114
+ throw new Error(`API call failed with status: ${response.status}`);
115
+ }
116
+
117
+ const apiData = await response.json();
118
+
119
+ // Format response according to test mode requirements
120
+ let formattedData = apiData;
121
+ if (testMode && apiData) {
122
+ formattedData = {
123
+ InferenceResult: {
124
+ output: apiData.croppedInference || apiData.output || apiData.inference,
125
+ traits: apiData.traitResult || apiData.traits || apiData.personalityData
126
+ }
127
+ };
110
128
  }
129
+
130
+ setApiResponse(formattedData);
131
+ return {
132
+ ...baseResult,
133
+ apiResponse: formattedData,
134
+ success: true
135
+ };
136
+ } catch (error) {
137
+ setApiError(error.message);
138
+ return {
139
+ ...baseResult,
140
+ apiError: error.message,
141
+ success: false
142
+ };
143
+ }
144
+ } else {
145
+ // Auto mode false (default): return API endpoint URL for manual calling
146
+ return {
147
+ ...baseResult,
148
+ success: true,
149
+ message: 'Data request approved. Use the provided API URL to fetch user data.'
111
150
  };
112
-
113
- setApiResponse(mockData);
114
151
  }
115
-
116
- return requestData;
117
152
  } catch (error) {
118
- setApiError(`Failed to fetch data: ${error.message}`);
153
+ setApiError(`Failed to process request: ${error.message}`);
119
154
  return null;
120
155
  } finally {
121
156
  setIsLoadingApi(false);
@@ -127,17 +162,10 @@ export default function DataRequest({
127
162
  setIsSubmitting(true);
128
163
 
129
164
  try {
130
- const requestData = await fetchUserData();
165
+ const result = await fetchUserData();
131
166
 
132
- if (requestData) {
133
- onComplete({
134
- selectedData,
135
- requestData,
136
- apiResponse,
137
- userEmail,
138
- appName,
139
- timestamp: new Date().toISOString()
140
- });
167
+ if (result) {
168
+ onComplete(result);
141
169
  }
142
170
  } catch (error) {
143
171
  setApiError(`Submission failed: ${error.message}`);
@@ -38,12 +38,12 @@ function getPopupUrl() {
38
38
  * Creates popup content dynamically as fallback
39
39
  */
40
40
  function createDynamicPopupContent(data) {
41
- const { requestData = [], webpageName = 'App', userData = {}, autoFetch = true, appIcon = null } = data;
41
+ const { requestData = [], webpageName = 'App', userData = {}, autoFetch = false, testMode = false, appIcon = null } = data;
42
42
 
43
43
  const defaultDataTypes = [
44
- { id: 'profile', name: 'Profile Information', description: 'Basic profile data and preferences', icon: '👤' },
45
- { id: 'personality', name: 'Personality data', description: 'Personality traits and Insights', icon: '📊' },
46
- { id: 'preferences', name: 'User Preferences', description: 'Preferences and choices', icon: '⚙️' }
44
+ { id: 'basic', name: 'Basic Info', description: 'Essential profile information and account details', icon: '👤' },
45
+ { id: 'personality', name: 'Personality', description: 'Personality traits, behavioral patterns and insights', icon: '🧠' },
46
+ { id: 'preferences', name: 'Preferences', description: 'User preferences, settings and choices', icon: '⚙️' }
47
47
  ];
48
48
 
49
49
  const dataTypes = Array.isArray(requestData) && requestData.length > 0
@@ -82,27 +82,44 @@ function createDynamicPopupContent(data) {
82
82
  <p class="text-gray-600">${webpageName} is requesting access to your data</p>
83
83
  </div>
84
84
 
85
- <div class="space-y-3 mb-6" id="dataTypes">
85
+ <div class="space-y-4 mb-6" id="dataTypes">
86
86
  ${dataTypes.map(type => `
87
- <label class="flex items-center p-3 border rounded-lg cursor-pointer hover:bg-gray-50">
88
- <input type="checkbox" class="mr-3" data-id="${type.id}">
89
- <div class="flex-1">
90
- <div class="flex items-center">
91
- <span class="text-xl mr-2">${type.icon}</span>
92
- <span class="font-medium">${type.name}</span>
87
+ <label class="group relative flex items-start p-4 border-2 border-gray-200 rounded-xl cursor-pointer hover:border-blue-300 hover:bg-blue-50 transition-all duration-200 shadow-sm hover:shadow-md">
88
+ <div class="flex items-center h-5">
89
+ <input type="checkbox" class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 focus:ring-2" data-id="${type.id}">
90
+ </div>
91
+ <div class="ml-4 flex-1">
92
+ <div class="flex items-center mb-2">
93
+ <span class="text-2xl mr-3 group-hover:scale-110 transition-transform duration-200">${type.icon}</span>
94
+ <span class="font-semibold text-gray-900 text-lg">${type.name}</span>
93
95
  </div>
94
- <p class="text-sm text-gray-600 mt-1">${type.description}</p>
96
+ <p class="text-sm text-gray-600 leading-relaxed">${type.description}</p>
97
+ </div>
98
+ <div class="absolute top-4 right-4 w-6 h-6 border-2 border-gray-300 rounded-md group-hover:border-blue-400 transition-colors duration-200 bg-white">
99
+ <svg class="w-4 h-4 text-blue-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200" fill="currentColor" viewBox="0 0 20 20">
100
+ <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
101
+ </svg>
95
102
  </div>
96
103
  </label>
97
104
  `).join('')}
98
105
  </div>
99
106
 
100
- <div class="flex space-x-3">
101
- <button id="rejectBtn" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50">
102
- Reject
107
+ <div class="flex space-x-4">
108
+ <button id="rejectBtn" class="flex-1 px-6 py-3 border-2 border-gray-300 rounded-xl text-gray-700 font-semibold hover:bg-gray-50 hover:border-gray-400 transition-all duration-200 focus:ring-2 focus:ring-gray-300">
109
+ <span class="flex items-center justify-center">
110
+ <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
111
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
112
+ </svg>
113
+ Decline
114
+ </span>
103
115
  </button>
104
- <button id="approveBtn" class="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
105
- Approve
116
+ <button id="approveBtn" class="flex-1 px-6 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-xl font-semibold hover:from-blue-700 hover:to-blue-800 transition-all duration-200 shadow-lg hover:shadow-xl focus:ring-2 focus:ring-blue-500">
117
+ <span class="flex items-center justify-center">
118
+ <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
119
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
120
+ </svg>
121
+ Allow Access
122
+ </span>
106
123
  </button>
107
124
  </div>
108
125
 
@@ -118,18 +135,25 @@ function createDynamicPopupContent(data) {
118
135
  const checkboxes = document.querySelectorAll('input[type="checkbox"]');
119
136
 
120
137
  const autoFetch = ${autoFetch};
138
+ const testMode = ${testMode};
121
139
  const userEmail = '${userData.email || ''}';
122
140
  const appName = '${webpageName}';
123
141
 
142
+ // Determine API endpoint based on test mode
143
+ const apiEndpoint = testMode
144
+ ? 'https://api2.onairos.uk/inferenceTest'
145
+ : 'https://api2.onairos.uk/inference';
146
+
124
147
  async function makeApiCall(approvedData) {
125
- const response = await fetch('https://api2.onairos.uk/inferenceTest', {
148
+ const response = await fetch(apiEndpoint, {
126
149
  method: 'POST',
127
150
  headers: { 'Content-Type': 'application/json' },
128
151
  body: JSON.stringify({
129
152
  approvedData,
130
153
  userEmail,
131
154
  appName,
132
- timestamp: new Date().toISOString()
155
+ timestamp: new Date().toISOString(),
156
+ testMode: testMode
133
157
  })
134
158
  });
135
159
 
@@ -137,7 +161,19 @@ function createDynamicPopupContent(data) {
137
161
  throw new Error(\`API call failed with status: \${response.status}\`);
138
162
  }
139
163
 
140
- return await response.json();
164
+ const data = await response.json();
165
+
166
+ // Format response according to test mode requirements
167
+ if (testMode && data) {
168
+ return {
169
+ InferenceResult: {
170
+ output: data.croppedInference || data.output || data.inference,
171
+ traits: data.traitResult || data.traits || data.personalityData
172
+ }
173
+ };
174
+ }
175
+
176
+ return data;
141
177
  }
142
178
 
143
179
  approveBtn.addEventListener('click', async () => {
@@ -159,27 +195,39 @@ function createDynamicPopupContent(data) {
159
195
  approved: approved,
160
196
  timestamp: new Date().toISOString(),
161
197
  userEmail: userEmail,
162
- appName: appName
198
+ appName: appName,
199
+ testMode: testMode
163
200
  };
164
201
 
165
202
  let finalResult = baseResult;
166
203
 
167
204
  if (autoFetch) {
205
+ // Auto mode true: make API request and return results
168
206
  try {
169
207
  status.textContent = 'Making API call...';
170
208
  const apiData = await makeApiCall(approved);
171
209
  finalResult = {
172
210
  ...baseResult,
173
211
  apiResponse: apiData,
174
- apiUrl: 'https://api2.onairos.uk/inferenceTest'
212
+ apiUrl: apiEndpoint,
213
+ success: true
175
214
  };
176
215
  } catch (error) {
177
216
  finalResult = {
178
217
  ...baseResult,
179
218
  apiError: error.message,
180
- apiUrl: 'https://api2.onairos.uk/inferenceTest'
219
+ apiUrl: apiEndpoint,
220
+ success: false
181
221
  };
182
222
  }
223
+ } else {
224
+ // Auto mode false (default): return API endpoint URL for manual calling
225
+ finalResult = {
226
+ ...baseResult,
227
+ apiUrl: apiEndpoint,
228
+ success: true,
229
+ message: 'Data request approved. Use the provided API URL to fetch user data.'
230
+ };
183
231
  }
184
232
 
185
233
  window.opener.postMessage(finalResult, '*');
@@ -397,18 +445,36 @@ export function listenForPopupMessages(callback, options = {}) {
397
445
  /**
398
446
  * Make API call with user's approved data
399
447
  * @param {Array} approvedData - Array of approved data types
400
- * @param {string} apiUrl - API endpoint URL
448
+ * @param {Object} options - API call options
449
+ * @param {string} options.apiUrl - API endpoint URL
450
+ * @param {boolean} options.testMode - Whether to use test mode
451
+ * @param {string} options.userEmail - User email
452
+ * @param {string} options.appName - App name
401
453
  * @returns {Promise} Promise resolving to API response
402
454
  */
403
- async function makeApiCall(approvedData, apiUrl = 'https://api2.onairos.uk/inferenceTest') {
455
+ async function makeApiCall(approvedData, options = {}) {
456
+ const {
457
+ apiUrl = 'https://api2.onairos.uk/inference',
458
+ testMode = false,
459
+ userEmail = '',
460
+ appName = 'App'
461
+ } = options;
462
+
404
463
  try {
405
- const response = await fetch(apiUrl, {
464
+ const endpoint = testMode
465
+ ? 'https://api2.onairos.uk/inferenceTest'
466
+ : apiUrl;
467
+
468
+ const response = await fetch(endpoint, {
406
469
  method: 'POST',
407
470
  headers: {
408
471
  'Content-Type': 'application/json',
409
472
  },
410
473
  body: JSON.stringify({
411
474
  approvedData,
475
+ userEmail,
476
+ appName,
477
+ testMode,
412
478
  timestamp: new Date().toISOString()
413
479
  })
414
480
  });
@@ -418,6 +484,17 @@ async function makeApiCall(approvedData, apiUrl = 'https://api2.onairos.uk/infer
418
484
  }
419
485
 
420
486
  const data = await response.json();
487
+
488
+ // Format response according to test mode requirements
489
+ if (testMode && data) {
490
+ return {
491
+ InferenceResult: {
492
+ output: data.croppedInference || data.output || data.inference,
493
+ traits: data.traitResult || data.traits || data.personalityData
494
+ }
495
+ };
496
+ }
497
+
421
498
  return data;
422
499
  } catch (error) {
423
500
  console.error('API call error:', error);
@@ -61,10 +61,17 @@ const MobileDataRequestPage = ({
61
61
  return;
62
62
  }
63
63
 
64
+ // Determine API endpoint based on test mode (default to live)
65
+ const testMode = false; // Can be made configurable
66
+ const apiEndpoint = testMode
67
+ ? 'https://api2.onairos.uk/inferenceTest'
68
+ : 'https://api2.onairos.uk/inference';
69
+
64
70
  // Create API response with the updated URL
65
71
  const apiResponse = {
66
72
  success: true,
67
- apiUrl: "https://api2.onairos.uk/inferenceTest",
73
+ apiUrl: apiEndpoint,
74
+ testMode: testMode,
68
75
  approvedRequests: selectedConnections.current
69
76
  };
70
77
 
@@ -9,7 +9,8 @@ export function OnairosButton({
9
9
  webpageName,
10
10
  inferenceData = null,
11
11
  onComplete = null,
12
- autoFetch = true,
12
+ autoFetch = false,
13
+ testMode = false,
13
14
  proofMode = false,
14
15
  textLayout = 'below',
15
16
  textColor = 'white',
@@ -146,7 +147,7 @@ export function OnairosButton({
146
147
  return (
147
148
  <EmailAuth
148
149
  onSuccess={handleEmailAuthSuccess}
149
- testMode={true} // Set to false in production
150
+ testMode={testMode} // Use the testMode prop from initialization
150
151
  />
151
152
  );
152
153
 
@@ -176,6 +177,7 @@ export function OnairosButton({
176
177
  requestData={requestData}
177
178
  appName={webpageName}
178
179
  autoFetch={autoFetch}
180
+ testMode={testMode}
179
181
  appIcon={appIcon}
180
182
  />
181
183
  );