@trainly/react 1.6.3 → 2.0.0

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.
@@ -45,13 +45,75 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
45
45
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
46
  }
47
47
  };
48
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
49
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
50
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
51
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
52
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
53
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
54
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
55
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
56
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
57
+ function fulfill(value) { resume("next", value); }
58
+ function reject(value) { resume("throw", value); }
59
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
60
+ };
61
+ import { TestingClient } from "./TestingClient";
62
+ import { FineTuningClient } from "./FineTuningClient";
63
+ import { ConfigClient } from "./ConfigClient";
64
+ import { AnalyticsClient } from "./AnalyticsClient";
65
+ import { VersionsClient } from "./VersionsClient";
48
66
  var TrainlyClient = /** @class */ (function () {
49
67
  function TrainlyClient(config) {
50
68
  this.scopedToken = null;
51
69
  this.currentUserId = null;
52
70
  this.isV1Mode = false;
53
- this.config = config;
71
+ this._config = config;
72
+ this._initSubClients();
54
73
  }
74
+ TrainlyClient.prototype._initSubClients = function () {
75
+ var _this = this;
76
+ var baseUrl = this._config.baseUrl || "https://api.trainlyai.com";
77
+ var chatId = this._config.chatId || "";
78
+ var getHeaders = function () { return _this._getHeaders(); };
79
+ // Determine authentication mode and initialize appropriate sub-clients
80
+ var authMode = this._detectAuthMode();
81
+ if (authMode === "api_key") {
82
+ // Full access for API key mode
83
+ this.testing = new TestingClient(baseUrl, chatId, getHeaders);
84
+ this.fineTuning = new FineTuningClient(baseUrl, chatId, getHeaders);
85
+ this.config = new ConfigClient(baseUrl, chatId, getHeaders);
86
+ this.analytics = new AnalyticsClient(baseUrl, chatId, getHeaders);
87
+ this.versions = new VersionsClient(baseUrl, chatId, getHeaders);
88
+ }
89
+ else if (authMode === "v1_oauth" || authMode === "app_secret") {
90
+ // Limited access for V1 OAuth and app secret modes
91
+ this.testing = new TestingClient(baseUrl, chatId, getHeaders);
92
+ this.config = new ConfigClient(baseUrl, chatId, getHeaders, true); // readonly
93
+ this.analytics = new AnalyticsClient(baseUrl, chatId, getHeaders, true); // limited
94
+ }
95
+ };
96
+ TrainlyClient.prototype._detectAuthMode = function () {
97
+ if (this._config.apiKey)
98
+ return "api_key";
99
+ if (this._config.appId)
100
+ return "v1_oauth";
101
+ if (this._config.appSecret)
102
+ return "app_secret";
103
+ return "unknown";
104
+ };
105
+ TrainlyClient.prototype._getHeaders = function () {
106
+ var headers = {
107
+ "Content-Type": "application/json",
108
+ };
109
+ if (this.scopedToken) {
110
+ headers["Authorization"] = "Bearer ".concat(this.scopedToken);
111
+ }
112
+ if (this.isV1Mode && this._config.appId) {
113
+ headers["X-App-ID"] = this._config.appId;
114
+ }
115
+ return headers;
116
+ };
55
117
  /**
56
118
  * NEW: Connect using V1 Trusted Issuer authentication with OAuth ID token
57
119
  * This method allows users to authenticate directly with their OAuth provider tokens
@@ -62,16 +124,16 @@ var TrainlyClient = /** @class */ (function () {
62
124
  return __generator(this, function (_a) {
63
125
  switch (_a.label) {
64
126
  case 0:
65
- if (!this.config.appId) {
127
+ if (!this._config.appId) {
66
128
  throw new Error("appId is required for V1 authentication.");
67
129
  }
68
130
  // For V1, we use the ID token directly - no need to provision
69
131
  this.scopedToken = idToken;
70
132
  this.isV1Mode = true;
71
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/profile"), {
133
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/profile"), {
72
134
  headers: {
73
135
  Authorization: "Bearer ".concat(idToken),
74
- "X-App-ID": this.config.appId,
136
+ "X-App-ID": this._config.appId,
75
137
  },
76
138
  })];
77
139
  case 1:
@@ -100,23 +162,23 @@ var TrainlyClient = /** @class */ (function () {
100
162
  return __generator(this, function (_a) {
101
163
  switch (_a.label) {
102
164
  case 0:
103
- if (this.config.apiKey) {
165
+ if (this._config.apiKey) {
104
166
  // Direct API key mode - no additional setup needed
105
- this.scopedToken = this.config.apiKey;
167
+ this.scopedToken = this._config.apiKey;
106
168
  return [2 /*return*/];
107
169
  }
108
- if (!this.config.appSecret) {
170
+ if (!this._config.appSecret) {
109
171
  throw new Error("Either appSecret or apiKey must be provided");
110
172
  }
111
173
  // App secret mode - provision user
112
174
  // Ensure we use the same user ID consistently
113
175
  if (!this.currentUserId) {
114
- this.currentUserId = this.config.userId || this.generateAnonymousId();
176
+ this.currentUserId = this._config.userId || this.generateAnonymousId();
115
177
  }
116
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/privacy/apps/users/provision"), {
178
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/privacy/apps/users/provision"), {
117
179
  method: "POST",
118
180
  headers: {
119
- Authorization: "Bearer ".concat(this.config.appSecret),
181
+ Authorization: "Bearer ".concat(this._config.appSecret),
120
182
  "Content-Type": "application/json",
121
183
  },
122
184
  body: JSON.stringify({
@@ -151,7 +213,7 @@ var TrainlyClient = /** @class */ (function () {
151
213
  if (!this.scopedToken) {
152
214
  throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
153
215
  }
154
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
216
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 5];
155
217
  params = {
156
218
  messages: JSON.stringify([{ role: "user", content: question }]),
157
219
  response_tokens: "150",
@@ -161,11 +223,11 @@ var TrainlyClient = /** @class */ (function () {
161
223
  Object.keys(options.scope_filters).length > 0) {
162
224
  params.scope_filters = JSON.stringify(options.scope_filters);
163
225
  }
164
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/query"), {
226
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/query"), {
165
227
  method: "POST",
166
228
  headers: {
167
229
  Authorization: "Bearer ".concat(this.scopedToken),
168
- "X-App-ID": this.config.appId,
230
+ "X-App-ID": this._config.appId,
169
231
  "Content-Type": "application/x-www-form-urlencoded",
170
232
  },
171
233
  body: new URLSearchParams(params),
@@ -185,21 +247,21 @@ var TrainlyClient = /** @class */ (function () {
185
247
  citations: includeCitations ? data_1.citations || [] : [],
186
248
  }];
187
249
  case 5:
188
- url = this.config.apiKey
189
- ? "".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/answer_question")
190
- : "".concat(this.config.baseUrl, "/v1/privacy/query");
250
+ url = this._config.apiKey
251
+ ? "".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/answer_question")
252
+ : "".concat(this._config.baseUrl, "/v1/privacy/query");
191
253
  headers = {
192
254
  "Content-Type": "application/json",
193
255
  };
194
256
  body = { question: question };
195
- if (this.config.apiKey) {
196
- headers["Authorization"] = "Bearer ".concat(this.config.apiKey);
257
+ if (this._config.apiKey) {
258
+ headers["Authorization"] = "Bearer ".concat(this._config.apiKey);
197
259
  }
198
260
  else {
199
261
  headers["x-scoped-token"] = this.scopedToken;
200
262
  // Use the same user ID that was used during provisioning
201
263
  body.end_user_id =
202
- this.currentUserId || this.config.userId || this.generateAnonymousId();
264
+ this.currentUserId || this._config.userId || this.generateAnonymousId();
203
265
  body.include_citations = options.includeCitations || false;
204
266
  }
205
267
  return [4 /*yield*/, fetch(url, {
@@ -225,6 +287,175 @@ var TrainlyClient = /** @class */ (function () {
225
287
  });
226
288
  });
227
289
  };
290
+ TrainlyClient.prototype.askStream = function (question_1) {
291
+ return __asyncGenerator(this, arguments, function askStream_1(question, options) {
292
+ var params, response, error, reader, decoder, buffer, _a, done, value, lines, _i, lines_1, line, data, parsed, e_1, response, error, reader, decoder, buffer, _b, done, value, lines, _c, lines_2, line, data, parsed, e_2;
293
+ var _d, _e, _f, _g;
294
+ if (options === void 0) { options = {}; }
295
+ return __generator(this, function (_h) {
296
+ switch (_h.label) {
297
+ case 0:
298
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 18];
299
+ if (!this.scopedToken) {
300
+ throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
301
+ }
302
+ params = {
303
+ messages: JSON.stringify([{ role: "user", content: question }]),
304
+ response_tokens: "150",
305
+ stream: "true",
306
+ };
307
+ if (options.scope_filters &&
308
+ Object.keys(options.scope_filters).length > 0) {
309
+ params.scope_filters = JSON.stringify(options.scope_filters);
310
+ }
311
+ return [4 /*yield*/, __await(fetch("".concat(this._config.baseUrl, "/v1/me/chats/query"), {
312
+ method: "POST",
313
+ headers: {
314
+ Authorization: "Bearer ".concat(this.scopedToken),
315
+ "X-App-ID": this._config.appId,
316
+ "Content-Type": "application/x-www-form-urlencoded",
317
+ Accept: "text/event-stream",
318
+ },
319
+ body: new URLSearchParams(params),
320
+ }))];
321
+ case 1:
322
+ response = _h.sent();
323
+ if (!!response.ok) return [3 /*break*/, 3];
324
+ return [4 /*yield*/, __await(response.json())];
325
+ case 2:
326
+ error = _h.sent();
327
+ throw new Error("V1 streaming query failed: ".concat(error.detail || response.statusText));
328
+ case 3:
329
+ reader = (_d = response.body) === null || _d === void 0 ? void 0 : _d.getReader();
330
+ if (!reader)
331
+ throw new Error("No response body for streaming");
332
+ decoder = new TextDecoder();
333
+ buffer = "";
334
+ _h.label = 4;
335
+ case 4:
336
+ if (!true) return [3 /*break*/, 16];
337
+ return [4 /*yield*/, __await(reader.read())];
338
+ case 5:
339
+ _a = _h.sent(), done = _a.done, value = _a.value;
340
+ if (done)
341
+ return [3 /*break*/, 16];
342
+ buffer += decoder.decode(value, { stream: true });
343
+ lines = buffer.split("\n");
344
+ buffer = lines.pop() || "";
345
+ _i = 0, lines_1 = lines;
346
+ _h.label = 6;
347
+ case 6:
348
+ if (!(_i < lines_1.length)) return [3 /*break*/, 15];
349
+ line = lines_1[_i];
350
+ if (!line.startsWith("data: ")) return [3 /*break*/, 14];
351
+ data = line.slice(6).trim();
352
+ if (!(data === "[DONE]")) return [3 /*break*/, 8];
353
+ return [4 /*yield*/, __await(void 0)];
354
+ case 7: return [2 /*return*/, _h.sent()];
355
+ case 8:
356
+ _h.trys.push([8, 13, , 14]);
357
+ parsed = JSON.parse(data);
358
+ if (!(parsed.type === "content")) return [3 /*break*/, 11];
359
+ (_e = options.onChunk) === null || _e === void 0 ? void 0 : _e.call(options, parsed.data);
360
+ return [4 /*yield*/, __await(parsed.data)];
361
+ case 9: return [4 /*yield*/, _h.sent()];
362
+ case 10:
363
+ _h.sent();
364
+ return [3 /*break*/, 12];
365
+ case 11:
366
+ if (parsed.type === "error") {
367
+ throw new Error(parsed.data);
368
+ }
369
+ _h.label = 12;
370
+ case 12: return [3 /*break*/, 14];
371
+ case 13:
372
+ e_1 = _h.sent();
373
+ if (e_1 instanceof SyntaxError)
374
+ return [3 /*break*/, 14];
375
+ throw e_1;
376
+ case 14:
377
+ _i++;
378
+ return [3 /*break*/, 6];
379
+ case 15: return [3 /*break*/, 4];
380
+ case 16: return [4 /*yield*/, __await(void 0)];
381
+ case 17: return [2 /*return*/, _h.sent()];
382
+ case 18:
383
+ if (!this._config.apiKey) return [3 /*break*/, 36];
384
+ return [4 /*yield*/, __await(fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/answer_question_stream"), {
385
+ method: "POST",
386
+ headers: {
387
+ Authorization: "Bearer ".concat(this._config.apiKey),
388
+ "Content-Type": "application/json",
389
+ Accept: "text/event-stream",
390
+ },
391
+ body: JSON.stringify({ question: question }),
392
+ }))];
393
+ case 19:
394
+ response = _h.sent();
395
+ if (!!response.ok) return [3 /*break*/, 21];
396
+ return [4 /*yield*/, __await(response.json())];
397
+ case 20:
398
+ error = _h.sent();
399
+ throw new Error("Streaming query failed: ".concat(error.detail || response.statusText));
400
+ case 21:
401
+ reader = (_f = response.body) === null || _f === void 0 ? void 0 : _f.getReader();
402
+ if (!reader)
403
+ throw new Error("No response body for streaming");
404
+ decoder = new TextDecoder();
405
+ buffer = "";
406
+ _h.label = 22;
407
+ case 22:
408
+ if (!true) return [3 /*break*/, 34];
409
+ return [4 /*yield*/, __await(reader.read())];
410
+ case 23:
411
+ _b = _h.sent(), done = _b.done, value = _b.value;
412
+ if (done)
413
+ return [3 /*break*/, 34];
414
+ buffer += decoder.decode(value, { stream: true });
415
+ lines = buffer.split("\n");
416
+ buffer = lines.pop() || "";
417
+ _c = 0, lines_2 = lines;
418
+ _h.label = 24;
419
+ case 24:
420
+ if (!(_c < lines_2.length)) return [3 /*break*/, 33];
421
+ line = lines_2[_c];
422
+ if (!line.startsWith("data: ")) return [3 /*break*/, 32];
423
+ data = line.slice(6).trim();
424
+ if (!(data === "[DONE]")) return [3 /*break*/, 26];
425
+ return [4 /*yield*/, __await(void 0)];
426
+ case 25: return [2 /*return*/, _h.sent()];
427
+ case 26:
428
+ _h.trys.push([26, 31, , 32]);
429
+ parsed = JSON.parse(data);
430
+ if (!(parsed.type === "content")) return [3 /*break*/, 29];
431
+ (_g = options.onChunk) === null || _g === void 0 ? void 0 : _g.call(options, parsed.data);
432
+ return [4 /*yield*/, __await(parsed.data)];
433
+ case 27: return [4 /*yield*/, _h.sent()];
434
+ case 28:
435
+ _h.sent();
436
+ return [3 /*break*/, 30];
437
+ case 29:
438
+ if (parsed.type === "error") {
439
+ throw new Error(parsed.data);
440
+ }
441
+ _h.label = 30;
442
+ case 30: return [3 /*break*/, 32];
443
+ case 31:
444
+ e_2 = _h.sent();
445
+ if (e_2 instanceof SyntaxError)
446
+ return [3 /*break*/, 32];
447
+ throw e_2;
448
+ case 32:
449
+ _c++;
450
+ return [3 /*break*/, 24];
451
+ case 33: return [3 /*break*/, 22];
452
+ case 34: return [4 /*yield*/, __await(void 0)];
453
+ case 35: return [2 /*return*/, _h.sent()];
454
+ case 36: throw new Error("Streaming is not supported in app secret mode");
455
+ }
456
+ });
457
+ });
458
+ };
228
459
  TrainlyClient.prototype.upload = function (file, scopeValues) {
229
460
  return __awaiter(this, void 0, void 0, function () {
230
461
  var formData, response, error, data, formData, response, error, result, fileId, sizeBytes, status_1, processed, err_1, presignedResponse, error, _a, upload_url, upload_headers, formData, uploadResponse;
@@ -235,18 +466,18 @@ var TrainlyClient = /** @class */ (function () {
235
466
  if (!this.scopedToken) {
236
467
  throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
237
468
  }
238
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
469
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 5];
239
470
  formData = new FormData();
240
471
  formData.append("file", file);
241
472
  // Add scope values if provided
242
473
  if (scopeValues && Object.keys(scopeValues).length > 0) {
243
474
  formData.append("scope_values", JSON.stringify(scopeValues));
244
475
  }
245
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/upload"), {
476
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files/upload"), {
246
477
  method: "POST",
247
478
  headers: {
248
479
  Authorization: "Bearer ".concat(this.scopedToken),
249
- "X-App-ID": this.config.appId,
480
+ "X-App-ID": this._config.appId,
250
481
  },
251
482
  body: formData,
252
483
  })];
@@ -267,15 +498,15 @@ var TrainlyClient = /** @class */ (function () {
267
498
  message: data.message || "File uploaded to your permanent private subchat",
268
499
  }];
269
500
  case 5:
270
- if (!this.config.apiKey) return [3 /*break*/, 14];
501
+ if (!this._config.apiKey) return [3 /*break*/, 14];
271
502
  formData = new FormData();
272
503
  formData.append("file", file);
273
504
  // Always send scope_values (default empty object) to match Python SDK behavior
274
505
  formData.append("scope_values", JSON.stringify(scopeValues && Object.keys(scopeValues).length > 0 ? scopeValues : {}));
275
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/upload_with_scopes"), {
506
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/upload_with_scopes"), {
276
507
  method: "POST",
277
508
  headers: {
278
- Authorization: "Bearer ".concat(this.config.apiKey),
509
+ Authorization: "Bearer ".concat(this._config.apiKey),
279
510
  },
280
511
  body: formData,
281
512
  })];
@@ -323,7 +554,7 @@ var TrainlyClient = /** @class */ (function () {
323
554
  size: sizeBytes,
324
555
  message: result.message || "File uploaded successfully",
325
556
  }];
326
- case 14: return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/privacy/upload/presigned-url"), {
557
+ case 14: return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/privacy/upload/presigned-url"), {
327
558
  method: "POST",
328
559
  headers: {
329
560
  "Content-Type": "application/json",
@@ -331,7 +562,7 @@ var TrainlyClient = /** @class */ (function () {
331
562
  },
332
563
  body: JSON.stringify({
333
564
  end_user_id: this.currentUserId ||
334
- this.config.userId ||
565
+ this._config.userId ||
335
566
  this.generateAnonymousId(),
336
567
  filename: file.name,
337
568
  file_type: file.type,
@@ -378,7 +609,7 @@ var TrainlyClient = /** @class */ (function () {
378
609
  if (!this.scopedToken) {
379
610
  throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
380
611
  }
381
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
612
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 5];
382
613
  formData = new FormData();
383
614
  formData.append("text_content", text);
384
615
  formData.append("content_name", contentName);
@@ -386,11 +617,11 @@ var TrainlyClient = /** @class */ (function () {
386
617
  if (scopeValues && Object.keys(scopeValues).length > 0) {
387
618
  formData.append("scope_values", JSON.stringify(scopeValues));
388
619
  }
389
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/upload"), {
620
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files/upload"), {
390
621
  method: "POST",
391
622
  headers: {
392
623
  Authorization: "Bearer ".concat(this.scopedToken),
393
- "X-App-ID": this.config.appId,
624
+ "X-App-ID": this._config.appId,
394
625
  },
395
626
  body: formData,
396
627
  })];
@@ -433,7 +664,7 @@ var TrainlyClient = /** @class */ (function () {
433
664
  if (files.length > 10) {
434
665
  throw new Error("Too many files. Maximum 10 files per bulk upload.");
435
666
  }
436
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
667
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 5];
437
668
  formData_1 = new FormData();
438
669
  // Append all files to the form data
439
670
  files.forEach(function (file) {
@@ -443,11 +674,11 @@ var TrainlyClient = /** @class */ (function () {
443
674
  if (scopeValues && Object.keys(scopeValues).length > 0) {
444
675
  formData_1.append("scope_values", JSON.stringify(scopeValues));
445
676
  }
446
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/upload-bulk"), {
677
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files/upload-bulk"), {
447
678
  method: "POST",
448
679
  headers: {
449
680
  Authorization: "Bearer ".concat(this.scopedToken),
450
- "X-App-ID": this.config.appId,
681
+ "X-App-ID": this._config.appId,
451
682
  },
452
683
  body: formData_1,
453
684
  })];
@@ -545,7 +776,7 @@ var TrainlyClient = /** @class */ (function () {
545
776
  if (textContents.length > 10) {
546
777
  throw new Error("Too many items. Maximum 10 items per bulk upload.");
547
778
  }
548
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
779
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 5];
549
780
  formData = new FormData();
550
781
  texts = textContents.map(function (tc) { return tc.text; });
551
782
  names = textContents.map(function (tc) { return tc.contentName; });
@@ -555,11 +786,11 @@ var TrainlyClient = /** @class */ (function () {
555
786
  if (scopeValues && Object.keys(scopeValues).length > 0) {
556
787
  formData.append("scope_values", JSON.stringify(scopeValues));
557
788
  }
558
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/upload-bulk"), {
789
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files/upload-bulk"), {
559
790
  method: "POST",
560
791
  headers: {
561
792
  Authorization: "Bearer ".concat(this.scopedToken),
562
- "X-App-ID": this.config.appId,
793
+ "X-App-ID": this._config.appId,
563
794
  },
564
795
  body: formData,
565
796
  })];
@@ -652,11 +883,11 @@ var TrainlyClient = /** @class */ (function () {
652
883
  if (!this.scopedToken) {
653
884
  throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
654
885
  }
655
- if (!this.config.apiKey) return [3 /*break*/, 5];
656
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/files"), {
886
+ if (!this._config.apiKey) return [3 /*break*/, 5];
887
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/files"), {
657
888
  method: "GET",
658
889
  headers: {
659
- Authorization: "Bearer ".concat(this.config.apiKey),
890
+ Authorization: "Bearer ".concat(this._config.apiKey),
660
891
  },
661
892
  })];
662
893
  case 1:
@@ -685,12 +916,12 @@ var TrainlyClient = /** @class */ (function () {
685
916
  total_size_bytes: (_c = data.total_size_bytes) !== null && _c !== void 0 ? _c : 0,
686
917
  }];
687
918
  case 5:
688
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 10];
689
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files"), {
919
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 10];
920
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files"), {
690
921
  method: "GET",
691
922
  headers: {
692
923
  Authorization: "Bearer ".concat(this.scopedToken),
693
- "X-App-ID": this.config.appId,
924
+ "X-App-ID": this._config.appId,
694
925
  },
695
926
  })];
696
927
  case 6:
@@ -725,11 +956,11 @@ var TrainlyClient = /** @class */ (function () {
725
956
  if (!fileId) {
726
957
  throw new Error("File ID is required");
727
958
  }
728
- if (!this.config.apiKey) return [3 /*break*/, 5];
729
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/files/").concat(encodeURIComponent(fileId)), {
959
+ if (!this._config.apiKey) return [3 /*break*/, 5];
960
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/files/").concat(encodeURIComponent(fileId)), {
730
961
  method: "DELETE",
731
962
  headers: {
732
- Authorization: "Bearer ".concat(this.config.apiKey),
963
+ Authorization: "Bearer ".concat(this._config.apiKey),
733
964
  },
734
965
  })];
735
966
  case 1:
@@ -762,12 +993,12 @@ var TrainlyClient = /** @class */ (function () {
762
993
  size_bytes_freed: (_c = data.size_bytes_freed) !== null && _c !== void 0 ? _c : 0,
763
994
  }];
764
995
  case 5:
765
- if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 10];
766
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/").concat(encodeURIComponent(fileId)), {
996
+ if (!(this.isV1Mode && this._config.appId)) return [3 /*break*/, 10];
997
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/me/chats/files/").concat(encodeURIComponent(fileId)), {
767
998
  method: "DELETE",
768
999
  headers: {
769
1000
  Authorization: "Bearer ".concat(this.scopedToken),
770
- "X-App-ID": this.config.appId,
1001
+ "X-App-ID": this._config.appId,
771
1002
  },
772
1003
  })];
773
1004
  case 6:
@@ -801,10 +1032,10 @@ var TrainlyClient = /** @class */ (function () {
801
1032
  _a.label = 1;
802
1033
  case 1:
803
1034
  if (!true) return [3 /*break*/, 9];
804
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/files/").concat(encodeURIComponent(fileId), "/status"), {
1035
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/files/").concat(encodeURIComponent(fileId), "/status"), {
805
1036
  method: "GET",
806
1037
  headers: {
807
- Authorization: "Bearer ".concat(this.config.apiKey),
1038
+ Authorization: "Bearer ".concat(this._config.apiKey),
808
1039
  },
809
1040
  })];
810
1041
  case 2:
@@ -846,8 +1077,8 @@ var TrainlyClient = /** @class */ (function () {
846
1077
  });
847
1078
  };
848
1079
  TrainlyClient.prototype.getChatId = function () {
849
- if (this.config.chatId) {
850
- return this.config.chatId;
1080
+ if (this._config.chatId) {
1081
+ return this._config.chatId;
851
1082
  }
852
1083
  return this.extractChatId();
853
1084
  };
@@ -858,13 +1089,13 @@ var TrainlyClient = /** @class */ (function () {
858
1089
  return __generator(this, function (_a) {
859
1090
  switch (_a.label) {
860
1091
  case 0:
861
- if (!this.config.apiKey) {
1092
+ if (!this._config.apiKey) {
862
1093
  throw new Error("API key required to get chat settings");
863
1094
  }
864
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/settings"), {
1095
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/settings"), {
865
1096
  method: "GET",
866
1097
  headers: {
867
- Authorization: "Bearer ".concat(this.config.apiKey),
1098
+ Authorization: "Bearer ".concat(this._config.apiKey),
868
1099
  },
869
1100
  })];
870
1101
  case 1:
@@ -887,14 +1118,14 @@ var TrainlyClient = /** @class */ (function () {
887
1118
  return __generator(this, function (_a) {
888
1119
  switch (_a.label) {
889
1120
  case 0:
890
- if (!this.config.apiKey) {
1121
+ if (!this._config.apiKey) {
891
1122
  throw new Error("API key required to update chat settings");
892
1123
  }
893
- return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/").concat(this.getChatId(), "/settings"), {
1124
+ return [4 /*yield*/, fetch("".concat(this._config.baseUrl, "/v1/").concat(this.getChatId(), "/settings"), {
894
1125
  method: "POST",
895
1126
  headers: {
896
1127
  "Content-Type": "application/json",
897
- Authorization: "Bearer ".concat(this.config.apiKey),
1128
+ Authorization: "Bearer ".concat(this._config.apiKey),
898
1129
  },
899
1130
  body: JSON.stringify(settings),
900
1131
  })];
@@ -913,11 +1144,11 @@ var TrainlyClient = /** @class */ (function () {
913
1144
  });
914
1145
  };
915
1146
  TrainlyClient.prototype.extractChatId = function () {
916
- if (!this.config.apiKey) {
1147
+ if (!this._config.apiKey) {
917
1148
  throw new Error("API key not provided");
918
1149
  }
919
1150
  // Extract chat ID from API key format: tk_chat_id_rest
920
- var parts = this.config.apiKey.split("_");
1151
+ var parts = this._config.apiKey.split("_");
921
1152
  if (parts.length < 3) {
922
1153
  throw new Error("Invalid API key format");
923
1154
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Versions client for publishing and managing configuration versions.
3
+ */
4
+ import { PublishedVersion, VersionDiff } from "../types";
5
+ export declare class VersionsClient {
6
+ private baseUrl;
7
+ private chatId;
8
+ private getHeaders;
9
+ constructor(baseUrl: string, chatId: string, getHeaders: () => HeadersInit);
10
+ private request;
11
+ publish(version: string, description?: string): Promise<PublishedVersion>;
12
+ listVersions(page?: number, limit?: number): Promise<PublishedVersion[]>;
13
+ getVersion(versionId: string): Promise<PublishedVersion>;
14
+ rollback(versionId: string): Promise<boolean>;
15
+ compareVersions(versionA: string, versionB: string): Promise<VersionDiff>;
16
+ getUnpublishedChanges(): Promise<boolean>;
17
+ getActiveVersion(): Promise<PublishedVersion | null>;
18
+ }