@trainly/react 1.1.0 → 1.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/dist/TrainlyProvider.d.ts +2 -1
- package/dist/TrainlyProvider.js +194 -22
- package/package.json +1 -1
|
@@ -8,7 +8,8 @@ export interface TrainlyProviderProps {
|
|
|
8
8
|
baseUrl?: string;
|
|
9
9
|
userId?: string;
|
|
10
10
|
userEmail?: string;
|
|
11
|
+
getToken?: () => Promise<string | null>;
|
|
11
12
|
}
|
|
12
13
|
export declare function TrainlyProvider({ children, appSecret, apiKey, appId, // NEW: For V1 authentication
|
|
13
|
-
baseUrl, userId, userEmail, }: TrainlyProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
baseUrl, userId, userEmail, getToken, }: TrainlyProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
14
15
|
export declare function useTrainlyContext(): TrainlyContextValue;
|
package/dist/TrainlyProvider.js
CHANGED
|
@@ -52,7 +52,7 @@ export function TrainlyProvider(_a) {
|
|
|
52
52
|
var _this = this;
|
|
53
53
|
var children = _a.children, appSecret = _a.appSecret, apiKey = _a.apiKey, appId = _a.appId, // NEW: For V1 authentication
|
|
54
54
|
_b = _a.baseUrl, // NEW: For V1 authentication
|
|
55
|
-
baseUrl = _b === void 0 ? "http://localhost:8000" : _b, userId = _a.userId, userEmail = _a.userEmail;
|
|
55
|
+
baseUrl = _b === void 0 ? "http://localhost:8000" : _b, userId = _a.userId, userEmail = _a.userEmail, getToken = _a.getToken;
|
|
56
56
|
var client = React.useState(function () {
|
|
57
57
|
return new TrainlyClient({
|
|
58
58
|
appSecret: appSecret,
|
|
@@ -67,9 +67,67 @@ export function TrainlyProvider(_a) {
|
|
|
67
67
|
var _d = React.useState(false), isConnected = _d[0], setIsConnected = _d[1];
|
|
68
68
|
var _e = React.useState(null), error = _e[0], setError = _e[1];
|
|
69
69
|
var _f = React.useState([]), messages = _f[0], setMessages = _f[1];
|
|
70
|
-
|
|
70
|
+
var _g = React.useState(null), currentToken = _g[0], setCurrentToken = _g[1];
|
|
71
|
+
var refreshIntervalRef = React.useRef(null);
|
|
72
|
+
// Auto-connect on mount (only for non-OAuth modes)
|
|
71
73
|
React.useEffect(function () {
|
|
72
|
-
|
|
74
|
+
if (!appId && !getToken) {
|
|
75
|
+
connect();
|
|
76
|
+
}
|
|
77
|
+
}, []);
|
|
78
|
+
// NEW: Automatic OAuth state management
|
|
79
|
+
React.useEffect(function () {
|
|
80
|
+
if (!getToken || !appId)
|
|
81
|
+
return;
|
|
82
|
+
var manageOAuthConnection = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
83
|
+
var token, error_1;
|
|
84
|
+
return __generator(this, function (_a) {
|
|
85
|
+
switch (_a.label) {
|
|
86
|
+
case 0:
|
|
87
|
+
_a.trys.push([0, 6, , 7]);
|
|
88
|
+
return [4 /*yield*/, getToken()];
|
|
89
|
+
case 1:
|
|
90
|
+
token = _a.sent();
|
|
91
|
+
if (!(token && token !== currentToken)) return [3 /*break*/, 4];
|
|
92
|
+
if (!(!isConnected || token !== currentToken)) return [3 /*break*/, 3];
|
|
93
|
+
console.log("🔐 New OAuth session detected, connecting to Trainly...");
|
|
94
|
+
return [4 /*yield*/, connectWithOAuthToken(token)];
|
|
95
|
+
case 2:
|
|
96
|
+
_a.sent();
|
|
97
|
+
_a.label = 3;
|
|
98
|
+
case 3: return [3 /*break*/, 5];
|
|
99
|
+
case 4:
|
|
100
|
+
if (!token && isConnected) {
|
|
101
|
+
// User signed out, disconnect from Trainly
|
|
102
|
+
console.log("🚪 User signed out, disconnecting from Trainly...");
|
|
103
|
+
clearRefreshInterval();
|
|
104
|
+
setIsConnected(false);
|
|
105
|
+
setCurrentToken(null);
|
|
106
|
+
setError(null);
|
|
107
|
+
}
|
|
108
|
+
_a.label = 5;
|
|
109
|
+
case 5: return [3 /*break*/, 7];
|
|
110
|
+
case 6:
|
|
111
|
+
error_1 = _a.sent();
|
|
112
|
+
console.error("OAuth state management error:", error_1);
|
|
113
|
+
return [3 /*break*/, 7];
|
|
114
|
+
case 7: return [2 /*return*/];
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}); };
|
|
118
|
+
// Check OAuth state immediately
|
|
119
|
+
manageOAuthConnection();
|
|
120
|
+
// Set up periodic OAuth state checking (every 10 seconds)
|
|
121
|
+
var stateCheckInterval = setInterval(manageOAuthConnection, 10000);
|
|
122
|
+
return function () {
|
|
123
|
+
clearInterval(stateCheckInterval);
|
|
124
|
+
};
|
|
125
|
+
}, [getToken, appId, currentToken, isConnected]);
|
|
126
|
+
// Cleanup on unmount
|
|
127
|
+
React.useEffect(function () {
|
|
128
|
+
return function () {
|
|
129
|
+
clearRefreshInterval();
|
|
130
|
+
};
|
|
73
131
|
}, []);
|
|
74
132
|
var connect = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
75
133
|
var err_1;
|
|
@@ -100,7 +158,62 @@ export function TrainlyProvider(_a) {
|
|
|
100
158
|
}
|
|
101
159
|
});
|
|
102
160
|
}); };
|
|
103
|
-
//
|
|
161
|
+
// Clear any existing refresh interval
|
|
162
|
+
var clearRefreshInterval = function () {
|
|
163
|
+
if (refreshIntervalRef.current) {
|
|
164
|
+
clearInterval(refreshIntervalRef.current);
|
|
165
|
+
refreshIntervalRef.current = null;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
// Set up automatic token refresh
|
|
169
|
+
var setupTokenRefresh = function (token) {
|
|
170
|
+
if (!getToken || !appId)
|
|
171
|
+
return;
|
|
172
|
+
// Clear any existing interval
|
|
173
|
+
clearRefreshInterval();
|
|
174
|
+
// Decode token to get expiration (without verification)
|
|
175
|
+
try {
|
|
176
|
+
var payload = JSON.parse(atob(token.split(".")[1]));
|
|
177
|
+
var exp = payload.exp * 1000; // Convert to milliseconds
|
|
178
|
+
var now = Date.now();
|
|
179
|
+
var timeUntilExpiry = exp - now;
|
|
180
|
+
// Refresh 30 seconds before expiry (or immediately if already expired)
|
|
181
|
+
var refreshIn = Math.max(timeUntilExpiry - 30000, 1000);
|
|
182
|
+
console.log("\uD83D\uDD04 Token refresh scheduled in ".concat(Math.round(refreshIn / 1000), " seconds"));
|
|
183
|
+
refreshIntervalRef.current = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
184
|
+
var newToken, error_2;
|
|
185
|
+
return __generator(this, function (_a) {
|
|
186
|
+
switch (_a.label) {
|
|
187
|
+
case 0:
|
|
188
|
+
_a.trys.push([0, 4, , 5]);
|
|
189
|
+
console.log("🔄 Auto-refreshing token...");
|
|
190
|
+
return [4 /*yield*/, getToken()];
|
|
191
|
+
case 1:
|
|
192
|
+
newToken = _a.sent();
|
|
193
|
+
if (!(newToken && newToken !== currentToken)) return [3 /*break*/, 3];
|
|
194
|
+
return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
|
|
195
|
+
case 2:
|
|
196
|
+
_a.sent();
|
|
197
|
+
setCurrentToken(newToken);
|
|
198
|
+
setupTokenRefresh(newToken); // Schedule next refresh
|
|
199
|
+
console.log("✅ Token auto-refreshed successfully");
|
|
200
|
+
_a.label = 3;
|
|
201
|
+
case 3: return [3 /*break*/, 5];
|
|
202
|
+
case 4:
|
|
203
|
+
error_2 = _a.sent();
|
|
204
|
+
console.error("❌ Auto token refresh failed:", error_2);
|
|
205
|
+
setIsConnected(false);
|
|
206
|
+
return [3 /*break*/, 5];
|
|
207
|
+
case 5: return [2 /*return*/];
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}); }, refreshIn);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
console.warn("Could not decode token for refresh scheduling:", error);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
// NEW: V1 OAuth Token connection method with auto-refresh
|
|
104
217
|
var connectWithOAuthToken = function (idToken) { return __awaiter(_this, void 0, void 0, function () {
|
|
105
218
|
var err_2;
|
|
106
219
|
return __generator(this, function (_a) {
|
|
@@ -112,7 +225,10 @@ export function TrainlyProvider(_a) {
|
|
|
112
225
|
return [4 /*yield*/, client.connectWithOAuthToken(idToken)];
|
|
113
226
|
case 1:
|
|
114
227
|
_a.sent();
|
|
228
|
+
setCurrentToken(idToken);
|
|
115
229
|
setIsConnected(true);
|
|
230
|
+
// Set up automatic token refresh
|
|
231
|
+
setupTokenRefresh(idToken);
|
|
116
232
|
return [3 /*break*/, 4];
|
|
117
233
|
case 2:
|
|
118
234
|
err_2 = _a.sent();
|
|
@@ -131,11 +247,11 @@ export function TrainlyProvider(_a) {
|
|
|
131
247
|
});
|
|
132
248
|
}); };
|
|
133
249
|
var ask = function (question) { return __awaiter(_this, void 0, void 0, function () {
|
|
134
|
-
var response, err_3,
|
|
250
|
+
var response, err_3, errorMessage, newToken, response, refreshError_1, error_3;
|
|
135
251
|
return __generator(this, function (_a) {
|
|
136
252
|
switch (_a.label) {
|
|
137
253
|
case 0:
|
|
138
|
-
_a.trys.push([0, 2,
|
|
254
|
+
_a.trys.push([0, 2, 10, 11]);
|
|
139
255
|
setIsLoading(true);
|
|
140
256
|
setError(null);
|
|
141
257
|
return [4 /*yield*/, client.ask(question)];
|
|
@@ -144,22 +260,50 @@ export function TrainlyProvider(_a) {
|
|
|
144
260
|
return [2 /*return*/, response.answer];
|
|
145
261
|
case 2:
|
|
146
262
|
err_3 = _a.sent();
|
|
147
|
-
|
|
263
|
+
errorMessage = err_3 instanceof Error ? err_3.message : String(err_3);
|
|
264
|
+
if (!(getToken &&
|
|
265
|
+
appId &&
|
|
266
|
+
(errorMessage.includes("401") ||
|
|
267
|
+
errorMessage.includes("authentication") ||
|
|
268
|
+
errorMessage.includes("Unauthorized")))) return [3 /*break*/, 9];
|
|
269
|
+
_a.label = 3;
|
|
270
|
+
case 3:
|
|
271
|
+
_a.trys.push([3, 8, , 9]);
|
|
272
|
+
console.log("🔄 Token expired, refreshing...");
|
|
273
|
+
return [4 /*yield*/, getToken()];
|
|
274
|
+
case 4:
|
|
275
|
+
newToken = _a.sent();
|
|
276
|
+
if (!newToken) return [3 /*break*/, 7];
|
|
277
|
+
return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
|
|
278
|
+
case 5:
|
|
279
|
+
_a.sent();
|
|
280
|
+
return [4 /*yield*/, client.ask(question)];
|
|
281
|
+
case 6:
|
|
282
|
+
response = _a.sent();
|
|
283
|
+
console.log("✅ Query succeeded after token refresh");
|
|
284
|
+
return [2 /*return*/, response.answer];
|
|
285
|
+
case 7: return [3 /*break*/, 9];
|
|
286
|
+
case 8:
|
|
287
|
+
refreshError_1 = _a.sent();
|
|
288
|
+
console.error("❌ Token refresh failed:", refreshError_1);
|
|
289
|
+
return [3 /*break*/, 9];
|
|
290
|
+
case 9:
|
|
291
|
+
error_3 = {
|
|
148
292
|
code: "QUERY_FAILED",
|
|
149
293
|
message: "Failed to get answer",
|
|
150
294
|
details: err_3,
|
|
151
295
|
};
|
|
152
|
-
setError(
|
|
153
|
-
throw
|
|
154
|
-
case
|
|
296
|
+
setError(error_3);
|
|
297
|
+
throw error_3;
|
|
298
|
+
case 10:
|
|
155
299
|
setIsLoading(false);
|
|
156
300
|
return [7 /*endfinally*/];
|
|
157
|
-
case
|
|
301
|
+
case 11: return [2 /*return*/];
|
|
158
302
|
}
|
|
159
303
|
});
|
|
160
304
|
}); };
|
|
161
305
|
var askWithCitations = function (question) { return __awaiter(_this, void 0, void 0, function () {
|
|
162
|
-
var response, err_4,
|
|
306
|
+
var response, err_4, error_4;
|
|
163
307
|
return __generator(this, function (_a) {
|
|
164
308
|
switch (_a.label) {
|
|
165
309
|
case 0:
|
|
@@ -175,13 +319,13 @@ export function TrainlyProvider(_a) {
|
|
|
175
319
|
}];
|
|
176
320
|
case 2:
|
|
177
321
|
err_4 = _a.sent();
|
|
178
|
-
|
|
322
|
+
error_4 = {
|
|
179
323
|
code: "QUERY_FAILED",
|
|
180
324
|
message: "Failed to get answer with citations",
|
|
181
325
|
details: err_4,
|
|
182
326
|
};
|
|
183
|
-
setError(
|
|
184
|
-
throw
|
|
327
|
+
setError(error_4);
|
|
328
|
+
throw error_4;
|
|
185
329
|
case 3:
|
|
186
330
|
setIsLoading(false);
|
|
187
331
|
return [7 /*endfinally*/];
|
|
@@ -190,11 +334,11 @@ export function TrainlyProvider(_a) {
|
|
|
190
334
|
});
|
|
191
335
|
}); };
|
|
192
336
|
var upload = function (file) { return __awaiter(_this, void 0, void 0, function () {
|
|
193
|
-
var result, err_5,
|
|
337
|
+
var result, err_5, errorMessage, newToken, result, refreshError_2, error_5;
|
|
194
338
|
return __generator(this, function (_a) {
|
|
195
339
|
switch (_a.label) {
|
|
196
340
|
case 0:
|
|
197
|
-
_a.trys.push([0, 2,
|
|
341
|
+
_a.trys.push([0, 2, 10, 11]);
|
|
198
342
|
setIsLoading(true);
|
|
199
343
|
setError(null);
|
|
200
344
|
return [4 /*yield*/, client.upload(file)];
|
|
@@ -203,17 +347,45 @@ export function TrainlyProvider(_a) {
|
|
|
203
347
|
return [2 /*return*/, result];
|
|
204
348
|
case 2:
|
|
205
349
|
err_5 = _a.sent();
|
|
206
|
-
|
|
350
|
+
errorMessage = err_5 instanceof Error ? err_5.message : String(err_5);
|
|
351
|
+
if (!(getToken &&
|
|
352
|
+
appId &&
|
|
353
|
+
(errorMessage.includes("401") ||
|
|
354
|
+
errorMessage.includes("authentication") ||
|
|
355
|
+
errorMessage.includes("Unauthorized")))) return [3 /*break*/, 9];
|
|
356
|
+
_a.label = 3;
|
|
357
|
+
case 3:
|
|
358
|
+
_a.trys.push([3, 8, , 9]);
|
|
359
|
+
console.log("🔄 Token expired during upload, refreshing...");
|
|
360
|
+
return [4 /*yield*/, getToken()];
|
|
361
|
+
case 4:
|
|
362
|
+
newToken = _a.sent();
|
|
363
|
+
if (!newToken) return [3 /*break*/, 7];
|
|
364
|
+
return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
|
|
365
|
+
case 5:
|
|
366
|
+
_a.sent();
|
|
367
|
+
return [4 /*yield*/, client.upload(file)];
|
|
368
|
+
case 6:
|
|
369
|
+
result = _a.sent();
|
|
370
|
+
console.log("✅ Upload succeeded after token refresh");
|
|
371
|
+
return [2 /*return*/, result];
|
|
372
|
+
case 7: return [3 /*break*/, 9];
|
|
373
|
+
case 8:
|
|
374
|
+
refreshError_2 = _a.sent();
|
|
375
|
+
console.error("❌ Token refresh failed:", refreshError_2);
|
|
376
|
+
return [3 /*break*/, 9];
|
|
377
|
+
case 9:
|
|
378
|
+
error_5 = {
|
|
207
379
|
code: "UPLOAD_FAILED",
|
|
208
380
|
message: "Failed to upload file",
|
|
209
381
|
details: err_5,
|
|
210
382
|
};
|
|
211
|
-
setError(
|
|
212
|
-
throw
|
|
213
|
-
case
|
|
383
|
+
setError(error_5);
|
|
384
|
+
throw error_5;
|
|
385
|
+
case 10:
|
|
214
386
|
setIsLoading(false);
|
|
215
387
|
return [7 /*endfinally*/];
|
|
216
|
-
case
|
|
388
|
+
case 11: return [2 /*return*/];
|
|
217
389
|
}
|
|
218
390
|
});
|
|
219
391
|
}); };
|