@gpt-core/client 0.10.13 → 0.10.21

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/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  PresignedUploadSchema: () => PresignedUploadSchema,
42
42
  RateLimitError: () => RateLimitError,
43
43
  RegisterRequestSchema: () => RegisterRequestSchema,
44
+ RetryTimeoutError: () => RetryTimeoutError,
44
45
  SearchRequestSchema: () => SearchRequestSchema,
45
46
  ServerError: () => ServerError,
46
47
  ThreadCreateSchema: () => ThreadCreateSchema,
@@ -152,6 +153,7 @@ __export(index_exports, {
152
153
  getExtractionResults: () => getExtractionResults,
153
154
  getExtractionResultsById: () => getExtractionResultsById,
154
155
  getExtractionResultsDocumentByDocumentId: () => getExtractionResultsDocumentByDocumentId,
156
+ getExtractionResultsDocumentByDocumentIdHistory: () => getExtractionResultsDocumentByDocumentIdHistory,
155
157
  getExtractionResultsWorkspaceByWorkspaceId: () => getExtractionResultsWorkspaceByWorkspaceId,
156
158
  getExtractionSchemaDiscoveriesById: () => getExtractionSchemaDiscoveriesById,
157
159
  getFieldTemplates: () => getFieldTemplates,
@@ -570,6 +572,7 @@ __export(sdk_gen_exports, {
570
572
  getExtractionResults: () => getExtractionResults,
571
573
  getExtractionResultsById: () => getExtractionResultsById,
572
574
  getExtractionResultsDocumentByDocumentId: () => getExtractionResultsDocumentByDocumentId,
575
+ getExtractionResultsDocumentByDocumentIdHistory: () => getExtractionResultsDocumentByDocumentIdHistory,
573
576
  getExtractionResultsWorkspaceByWorkspaceId: () => getExtractionResultsWorkspaceByWorkspaceId,
574
577
  getExtractionSchemaDiscoveriesById: () => getExtractionSchemaDiscoveriesById,
575
578
  getFieldTemplates: () => getFieldTemplates,
@@ -1813,7 +1816,12 @@ var patchApiKeysByIdRevoke = (options) => (options.client ?? client).patch({
1813
1816
  }
1814
1817
  });
1815
1818
  var getAiChunksDocumentByDocumentId = (options) => (options.client ?? client).get({
1816
- querySerializer: { parameters: { fields: { object: { style: "form" } } } },
1819
+ querySerializer: {
1820
+ parameters: {
1821
+ filter: { object: { style: "form" } },
1822
+ fields: { object: { style: "form" } }
1823
+ }
1824
+ },
1817
1825
  security: [{ scheme: "bearer", type: "http" }],
1818
1826
  url: "/ai/chunks/document/{document_id}",
1819
1827
  ...options
@@ -4864,6 +4872,18 @@ var patchAiConversationsById = (options) => (options.client ?? client).patch({
4864
4872
  ...options.headers
4865
4873
  }
4866
4874
  });
4875
+ var getExtractionResultsDocumentByDocumentIdHistory = (options) => (options.client ?? client).get({
4876
+ querySerializer: {
4877
+ parameters: {
4878
+ filter: { object: { style: "form" } },
4879
+ page: { object: { style: "form" } },
4880
+ fields: { object: { style: "form" } }
4881
+ }
4882
+ },
4883
+ security: [{ scheme: "bearer", type: "http" }],
4884
+ url: "/extraction/results/document/{document_id}/history",
4885
+ ...options
4886
+ });
4867
4887
  var getInvitationsMe = (options) => (options.client ?? client).get({
4868
4888
  querySerializer: {
4869
4889
  parameters: {
@@ -5366,10 +5386,35 @@ function handleApiError(error) {
5366
5386
  } else if (error?.message) {
5367
5387
  message = error.message;
5368
5388
  }
5389
+ const sensitiveHeaderPatterns = [
5390
+ "set-cookie",
5391
+ "authorization",
5392
+ "x-application-key",
5393
+ "x-api-key",
5394
+ "cookie",
5395
+ "x-forwarded-for",
5396
+ "x-real-ip",
5397
+ "proxy-authorization",
5398
+ "x-client-ip",
5399
+ "x-forwarded",
5400
+ "cf-connecting-ip",
5401
+ "x-cluster-client-ip"
5402
+ ];
5403
+ const filterSensitiveHeaders = (hdrs) => {
5404
+ if (!hdrs) return void 0;
5405
+ const entries = hdrs instanceof Headers ? Array.from(hdrs.entries()) : Object.entries(hdrs);
5406
+ const filtered = entries.filter(([key]) => {
5407
+ const lowerKey = key.toLowerCase();
5408
+ return !sensitiveHeaderPatterns.some(
5409
+ (pattern) => lowerKey.includes(pattern)
5410
+ );
5411
+ });
5412
+ return filtered.length > 0 ? Object.fromEntries(filtered) : void 0;
5413
+ };
5369
5414
  const errorOptions = {
5370
5415
  statusCode,
5371
5416
  requestId,
5372
- headers: headers ? headers.entries ? Object.fromEntries(headers.entries()) : Object.fromEntries(Object.entries(headers)) : void 0,
5417
+ headers: filterSensitiveHeaders(headers),
5373
5418
  body,
5374
5419
  cause: error
5375
5420
  };
@@ -5385,7 +5430,11 @@ function handleApiError(error) {
5385
5430
  throw new ValidationError(message, errors, errorOptions);
5386
5431
  case 429: {
5387
5432
  const retryAfter = headers?.get?.("retry-after") || headers?.["retry-after"];
5388
- throw new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : void 0, errorOptions);
5433
+ throw new RateLimitError(
5434
+ message,
5435
+ retryAfter ? parseInt(retryAfter, 10) : void 0,
5436
+ errorOptions
5437
+ );
5389
5438
  }
5390
5439
  case 500:
5391
5440
  case 502:
@@ -5503,15 +5552,20 @@ var DEFAULT_RETRY_CONFIG = {
5503
5552
  // 1 second
5504
5553
  maxDelay: 32e3,
5505
5554
  // 32 seconds
5506
- retryableStatusCodes: [429, 500, 502, 503, 504]
5555
+ retryableStatusCodes: [429, 500, 502, 503, 504],
5556
+ totalTimeout: 3e5,
5557
+ // 5 minutes total timeout
5558
+ maxRetryAfter: 60
5559
+ // Max 60 seconds from Retry-After header
5507
5560
  };
5508
5561
  function isRetryableError(error, retryableStatusCodes) {
5509
5562
  const statusCode = error?.status || error?.statusCode || error?.response?.status;
5510
5563
  return retryableStatusCodes.includes(statusCode);
5511
5564
  }
5512
- function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter) {
5513
- if (retryAfter) {
5514
- return Math.min(retryAfter * 1e3, maxDelay);
5565
+ function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter, maxRetryAfter = 60) {
5566
+ if (retryAfter !== void 0 && retryAfter > 0) {
5567
+ const cappedRetryAfter = Math.min(retryAfter, maxRetryAfter);
5568
+ return Math.min(cappedRetryAfter * 1e3, maxDelay);
5515
5569
  }
5516
5570
  const exponentialDelay = initialDelay * Math.pow(2, attempt);
5517
5571
  const jitter = Math.random() * 0.3 * exponentialDelay;
@@ -5521,9 +5575,26 @@ function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter) {
5521
5575
  function sleep(ms) {
5522
5576
  return new Promise((resolve) => setTimeout(resolve, ms));
5523
5577
  }
5578
+ var RetryTimeoutError = class extends Error {
5579
+ constructor(message, lastError) {
5580
+ super(message);
5581
+ this.lastError = lastError;
5582
+ this.name = "RetryTimeoutError";
5583
+ }
5584
+ };
5524
5585
  async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
5525
5586
  let lastError;
5587
+ const startTime = Date.now();
5588
+ const totalTimeout = config.totalTimeout ?? DEFAULT_RETRY_CONFIG.totalTimeout;
5589
+ const maxRetryAfter = config.maxRetryAfter ?? DEFAULT_RETRY_CONFIG.maxRetryAfter;
5526
5590
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
5591
+ const elapsed = Date.now() - startTime;
5592
+ if (elapsed >= totalTimeout) {
5593
+ throw new RetryTimeoutError(
5594
+ `Retry timeout exceeded after ${elapsed}ms (limit: ${totalTimeout}ms)`,
5595
+ lastError
5596
+ );
5597
+ }
5527
5598
  try {
5528
5599
  return await fn();
5529
5600
  } catch (error) {
@@ -5532,14 +5603,29 @@ async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
5532
5603
  throw error;
5533
5604
  }
5534
5605
  const errorWithHeaders = error;
5535
- const retryAfter = errorWithHeaders?.response?.headers?.get?.("retry-after") || errorWithHeaders?.response?.headers?.["retry-after"] || errorWithHeaders?.headers?.get?.("retry-after") || errorWithHeaders?.headers?.["retry-after"];
5536
- const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : void 0;
5606
+ const headers = errorWithHeaders?.response?.headers || errorWithHeaders?.headers;
5607
+ const retryAfter = headers?.get?.("retry-after") || headers?.["retry-after"];
5608
+ let retryAfterSeconds;
5609
+ if (retryAfter) {
5610
+ const parsed = parseInt(String(retryAfter), 10);
5611
+ if (!isNaN(parsed) && parsed > 0 && parsed <= maxRetryAfter) {
5612
+ retryAfterSeconds = parsed;
5613
+ }
5614
+ }
5537
5615
  const delay = calculateBackoff(
5538
5616
  attempt,
5539
5617
  config.initialDelay,
5540
5618
  config.maxDelay,
5541
- retryAfterSeconds
5619
+ retryAfterSeconds,
5620
+ maxRetryAfter
5542
5621
  );
5622
+ const remainingTimeout = totalTimeout - (Date.now() - startTime);
5623
+ if (delay >= remainingTimeout) {
5624
+ throw new RetryTimeoutError(
5625
+ `Retry would exceed timeout (delay: ${delay}ms, remaining: ${remainingTimeout}ms)`,
5626
+ lastError
5627
+ );
5628
+ }
5543
5629
  await sleep(delay);
5544
5630
  }
5545
5631
  }
@@ -5573,15 +5659,35 @@ async function* paginateAll(fetcher, options = {}) {
5573
5659
  page++;
5574
5660
  }
5575
5661
  }
5662
+ var DEFAULT_LIMIT = 1e4;
5663
+ var WARNING_THRESHOLD = 1e3;
5576
5664
  async function paginateToArray(fetcher, options = {}) {
5665
+ const safeOptions = {
5666
+ pageSize: options.pageSize || 20,
5667
+ // Security: Apply default limit to prevent unbounded memory usage
5668
+ limit: options.limit ?? DEFAULT_LIMIT
5669
+ };
5670
+ if (!options.limit && typeof process !== "undefined" && process.env?.NODE_ENV !== "test") {
5671
+ console.warn(
5672
+ `[GPT Core SDK] Fetching up to ${DEFAULT_LIMIT} items. For large datasets, consider using paginateAll() with streaming instead.`
5673
+ );
5674
+ }
5675
+ if (safeOptions.limit > WARNING_THRESHOLD) {
5676
+ console.warn(
5677
+ `[GPT Core SDK] Fetching more than ${WARNING_THRESHOLD} items may consume significant memory.`
5678
+ );
5679
+ }
5577
5680
  const results = [];
5578
- for await (const item of paginateAll(fetcher, options)) {
5681
+ for await (const item of paginateAll(fetcher, safeOptions)) {
5579
5682
  results.push(item);
5580
5683
  }
5581
5684
  return results;
5582
5685
  }
5583
5686
 
5584
5687
  // src/streaming.ts
5688
+ var DEFAULT_STREAM_TIMEOUT = 3e5;
5689
+ var DEFAULT_MAX_CHUNKS = 1e4;
5690
+ var DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
5585
5691
  async function* streamSSE(response, options = {}) {
5586
5692
  if (!response.body) {
5587
5693
  throw new Error("Response body is null");
@@ -5589,8 +5695,25 @@ async function* streamSSE(response, options = {}) {
5589
5695
  const reader = response.body.getReader();
5590
5696
  const decoder = new TextDecoder();
5591
5697
  let buffer = "";
5698
+ const timeout = options.timeout ?? DEFAULT_STREAM_TIMEOUT;
5699
+ const maxChunks = options.maxChunks ?? DEFAULT_MAX_CHUNKS;
5700
+ const maxBufferSize = options.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;
5701
+ const startTime = Date.now();
5702
+ let chunkCount = 0;
5703
+ let bufferSize = 0;
5592
5704
  try {
5593
5705
  while (true) {
5706
+ const elapsed = Date.now() - startTime;
5707
+ if (elapsed > timeout) {
5708
+ reader.cancel();
5709
+ throw new Error(
5710
+ `Stream timeout exceeded after ${elapsed}ms (limit: ${timeout}ms)`
5711
+ );
5712
+ }
5713
+ if (chunkCount >= maxChunks) {
5714
+ reader.cancel();
5715
+ throw new Error(`Maximum chunk limit exceeded (${maxChunks})`);
5716
+ }
5594
5717
  const { done, value } = await reader.read();
5595
5718
  if (done) {
5596
5719
  break;
@@ -5599,6 +5722,13 @@ async function* streamSSE(response, options = {}) {
5599
5722
  reader.cancel();
5600
5723
  throw new Error("Stream aborted");
5601
5724
  }
5725
+ bufferSize += value.length;
5726
+ if (bufferSize > maxBufferSize) {
5727
+ reader.cancel();
5728
+ throw new Error(
5729
+ `Stream buffer size exceeded (${bufferSize} bytes, limit: ${maxBufferSize})`
5730
+ );
5731
+ }
5602
5732
  buffer += decoder.decode(value, { stream: true });
5603
5733
  const lines = buffer.split("\n");
5604
5734
  buffer = lines.pop() || "";
@@ -5608,6 +5738,7 @@ async function* streamSSE(response, options = {}) {
5608
5738
  if (data === "[DONE]" || data.trim() === "") {
5609
5739
  continue;
5610
5740
  }
5741
+ chunkCount++;
5611
5742
  try {
5612
5743
  const parsed = JSON.parse(data);
5613
5744
  yield parsed;
@@ -5872,6 +6003,7 @@ var index_default = gptCore;
5872
6003
  PresignedUploadSchema,
5873
6004
  RateLimitError,
5874
6005
  RegisterRequestSchema,
6006
+ RetryTimeoutError,
5875
6007
  SearchRequestSchema,
5876
6008
  ServerError,
5877
6009
  ThreadCreateSchema,
@@ -5982,6 +6114,7 @@ var index_default = gptCore;
5982
6114
  getExtractionResults,
5983
6115
  getExtractionResultsById,
5984
6116
  getExtractionResultsDocumentByDocumentId,
6117
+ getExtractionResultsDocumentByDocumentIdHistory,
5985
6118
  getExtractionResultsWorkspaceByWorkspaceId,
5986
6119
  getExtractionSchemaDiscoveriesById,
5987
6120
  getFieldTemplates,
package/dist/index.mjs CHANGED
@@ -105,6 +105,7 @@ __export(sdk_gen_exports, {
105
105
  getExtractionResults: () => getExtractionResults,
106
106
  getExtractionResultsById: () => getExtractionResultsById,
107
107
  getExtractionResultsDocumentByDocumentId: () => getExtractionResultsDocumentByDocumentId,
108
+ getExtractionResultsDocumentByDocumentIdHistory: () => getExtractionResultsDocumentByDocumentIdHistory,
108
109
  getExtractionResultsWorkspaceByWorkspaceId: () => getExtractionResultsWorkspaceByWorkspaceId,
109
110
  getExtractionSchemaDiscoveriesById: () => getExtractionSchemaDiscoveriesById,
110
111
  getFieldTemplates: () => getFieldTemplates,
@@ -1348,7 +1349,12 @@ var patchApiKeysByIdRevoke = (options) => (options.client ?? client).patch({
1348
1349
  }
1349
1350
  });
1350
1351
  var getAiChunksDocumentByDocumentId = (options) => (options.client ?? client).get({
1351
- querySerializer: { parameters: { fields: { object: { style: "form" } } } },
1352
+ querySerializer: {
1353
+ parameters: {
1354
+ filter: { object: { style: "form" } },
1355
+ fields: { object: { style: "form" } }
1356
+ }
1357
+ },
1352
1358
  security: [{ scheme: "bearer", type: "http" }],
1353
1359
  url: "/ai/chunks/document/{document_id}",
1354
1360
  ...options
@@ -4399,6 +4405,18 @@ var patchAiConversationsById = (options) => (options.client ?? client).patch({
4399
4405
  ...options.headers
4400
4406
  }
4401
4407
  });
4408
+ var getExtractionResultsDocumentByDocumentIdHistory = (options) => (options.client ?? client).get({
4409
+ querySerializer: {
4410
+ parameters: {
4411
+ filter: { object: { style: "form" } },
4412
+ page: { object: { style: "form" } },
4413
+ fields: { object: { style: "form" } }
4414
+ }
4415
+ },
4416
+ security: [{ scheme: "bearer", type: "http" }],
4417
+ url: "/extraction/results/document/{document_id}/history",
4418
+ ...options
4419
+ });
4402
4420
  var getInvitationsMe = (options) => (options.client ?? client).get({
4403
4421
  querySerializer: {
4404
4422
  parameters: {
@@ -4901,10 +4919,35 @@ function handleApiError(error) {
4901
4919
  } else if (error?.message) {
4902
4920
  message = error.message;
4903
4921
  }
4922
+ const sensitiveHeaderPatterns = [
4923
+ "set-cookie",
4924
+ "authorization",
4925
+ "x-application-key",
4926
+ "x-api-key",
4927
+ "cookie",
4928
+ "x-forwarded-for",
4929
+ "x-real-ip",
4930
+ "proxy-authorization",
4931
+ "x-client-ip",
4932
+ "x-forwarded",
4933
+ "cf-connecting-ip",
4934
+ "x-cluster-client-ip"
4935
+ ];
4936
+ const filterSensitiveHeaders = (hdrs) => {
4937
+ if (!hdrs) return void 0;
4938
+ const entries = hdrs instanceof Headers ? Array.from(hdrs.entries()) : Object.entries(hdrs);
4939
+ const filtered = entries.filter(([key]) => {
4940
+ const lowerKey = key.toLowerCase();
4941
+ return !sensitiveHeaderPatterns.some(
4942
+ (pattern) => lowerKey.includes(pattern)
4943
+ );
4944
+ });
4945
+ return filtered.length > 0 ? Object.fromEntries(filtered) : void 0;
4946
+ };
4904
4947
  const errorOptions = {
4905
4948
  statusCode,
4906
4949
  requestId,
4907
- headers: headers ? headers.entries ? Object.fromEntries(headers.entries()) : Object.fromEntries(Object.entries(headers)) : void 0,
4950
+ headers: filterSensitiveHeaders(headers),
4908
4951
  body,
4909
4952
  cause: error
4910
4953
  };
@@ -4920,7 +4963,11 @@ function handleApiError(error) {
4920
4963
  throw new ValidationError(message, errors, errorOptions);
4921
4964
  case 429: {
4922
4965
  const retryAfter = headers?.get?.("retry-after") || headers?.["retry-after"];
4923
- throw new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : void 0, errorOptions);
4966
+ throw new RateLimitError(
4967
+ message,
4968
+ retryAfter ? parseInt(retryAfter, 10) : void 0,
4969
+ errorOptions
4970
+ );
4924
4971
  }
4925
4972
  case 500:
4926
4973
  case 502:
@@ -5038,15 +5085,20 @@ var DEFAULT_RETRY_CONFIG = {
5038
5085
  // 1 second
5039
5086
  maxDelay: 32e3,
5040
5087
  // 32 seconds
5041
- retryableStatusCodes: [429, 500, 502, 503, 504]
5088
+ retryableStatusCodes: [429, 500, 502, 503, 504],
5089
+ totalTimeout: 3e5,
5090
+ // 5 minutes total timeout
5091
+ maxRetryAfter: 60
5092
+ // Max 60 seconds from Retry-After header
5042
5093
  };
5043
5094
  function isRetryableError(error, retryableStatusCodes) {
5044
5095
  const statusCode = error?.status || error?.statusCode || error?.response?.status;
5045
5096
  return retryableStatusCodes.includes(statusCode);
5046
5097
  }
5047
- function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter) {
5048
- if (retryAfter) {
5049
- return Math.min(retryAfter * 1e3, maxDelay);
5098
+ function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter, maxRetryAfter = 60) {
5099
+ if (retryAfter !== void 0 && retryAfter > 0) {
5100
+ const cappedRetryAfter = Math.min(retryAfter, maxRetryAfter);
5101
+ return Math.min(cappedRetryAfter * 1e3, maxDelay);
5050
5102
  }
5051
5103
  const exponentialDelay = initialDelay * Math.pow(2, attempt);
5052
5104
  const jitter = Math.random() * 0.3 * exponentialDelay;
@@ -5056,9 +5108,26 @@ function calculateBackoff(attempt, initialDelay, maxDelay, retryAfter) {
5056
5108
  function sleep(ms) {
5057
5109
  return new Promise((resolve) => setTimeout(resolve, ms));
5058
5110
  }
5111
+ var RetryTimeoutError = class extends Error {
5112
+ constructor(message, lastError) {
5113
+ super(message);
5114
+ this.lastError = lastError;
5115
+ this.name = "RetryTimeoutError";
5116
+ }
5117
+ };
5059
5118
  async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
5060
5119
  let lastError;
5120
+ const startTime = Date.now();
5121
+ const totalTimeout = config.totalTimeout ?? DEFAULT_RETRY_CONFIG.totalTimeout;
5122
+ const maxRetryAfter = config.maxRetryAfter ?? DEFAULT_RETRY_CONFIG.maxRetryAfter;
5061
5123
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
5124
+ const elapsed = Date.now() - startTime;
5125
+ if (elapsed >= totalTimeout) {
5126
+ throw new RetryTimeoutError(
5127
+ `Retry timeout exceeded after ${elapsed}ms (limit: ${totalTimeout}ms)`,
5128
+ lastError
5129
+ );
5130
+ }
5062
5131
  try {
5063
5132
  return await fn();
5064
5133
  } catch (error) {
@@ -5067,14 +5136,29 @@ async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
5067
5136
  throw error;
5068
5137
  }
5069
5138
  const errorWithHeaders = error;
5070
- const retryAfter = errorWithHeaders?.response?.headers?.get?.("retry-after") || errorWithHeaders?.response?.headers?.["retry-after"] || errorWithHeaders?.headers?.get?.("retry-after") || errorWithHeaders?.headers?.["retry-after"];
5071
- const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : void 0;
5139
+ const headers = errorWithHeaders?.response?.headers || errorWithHeaders?.headers;
5140
+ const retryAfter = headers?.get?.("retry-after") || headers?.["retry-after"];
5141
+ let retryAfterSeconds;
5142
+ if (retryAfter) {
5143
+ const parsed = parseInt(String(retryAfter), 10);
5144
+ if (!isNaN(parsed) && parsed > 0 && parsed <= maxRetryAfter) {
5145
+ retryAfterSeconds = parsed;
5146
+ }
5147
+ }
5072
5148
  const delay = calculateBackoff(
5073
5149
  attempt,
5074
5150
  config.initialDelay,
5075
5151
  config.maxDelay,
5076
- retryAfterSeconds
5152
+ retryAfterSeconds,
5153
+ maxRetryAfter
5077
5154
  );
5155
+ const remainingTimeout = totalTimeout - (Date.now() - startTime);
5156
+ if (delay >= remainingTimeout) {
5157
+ throw new RetryTimeoutError(
5158
+ `Retry would exceed timeout (delay: ${delay}ms, remaining: ${remainingTimeout}ms)`,
5159
+ lastError
5160
+ );
5161
+ }
5078
5162
  await sleep(delay);
5079
5163
  }
5080
5164
  }
@@ -5108,15 +5192,35 @@ async function* paginateAll(fetcher, options = {}) {
5108
5192
  page++;
5109
5193
  }
5110
5194
  }
5195
+ var DEFAULT_LIMIT = 1e4;
5196
+ var WARNING_THRESHOLD = 1e3;
5111
5197
  async function paginateToArray(fetcher, options = {}) {
5198
+ const safeOptions = {
5199
+ pageSize: options.pageSize || 20,
5200
+ // Security: Apply default limit to prevent unbounded memory usage
5201
+ limit: options.limit ?? DEFAULT_LIMIT
5202
+ };
5203
+ if (!options.limit && typeof process !== "undefined" && process.env?.NODE_ENV !== "test") {
5204
+ console.warn(
5205
+ `[GPT Core SDK] Fetching up to ${DEFAULT_LIMIT} items. For large datasets, consider using paginateAll() with streaming instead.`
5206
+ );
5207
+ }
5208
+ if (safeOptions.limit > WARNING_THRESHOLD) {
5209
+ console.warn(
5210
+ `[GPT Core SDK] Fetching more than ${WARNING_THRESHOLD} items may consume significant memory.`
5211
+ );
5212
+ }
5112
5213
  const results = [];
5113
- for await (const item of paginateAll(fetcher, options)) {
5214
+ for await (const item of paginateAll(fetcher, safeOptions)) {
5114
5215
  results.push(item);
5115
5216
  }
5116
5217
  return results;
5117
5218
  }
5118
5219
 
5119
5220
  // src/streaming.ts
5221
+ var DEFAULT_STREAM_TIMEOUT = 3e5;
5222
+ var DEFAULT_MAX_CHUNKS = 1e4;
5223
+ var DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
5120
5224
  async function* streamSSE(response, options = {}) {
5121
5225
  if (!response.body) {
5122
5226
  throw new Error("Response body is null");
@@ -5124,8 +5228,25 @@ async function* streamSSE(response, options = {}) {
5124
5228
  const reader = response.body.getReader();
5125
5229
  const decoder = new TextDecoder();
5126
5230
  let buffer = "";
5231
+ const timeout = options.timeout ?? DEFAULT_STREAM_TIMEOUT;
5232
+ const maxChunks = options.maxChunks ?? DEFAULT_MAX_CHUNKS;
5233
+ const maxBufferSize = options.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;
5234
+ const startTime = Date.now();
5235
+ let chunkCount = 0;
5236
+ let bufferSize = 0;
5127
5237
  try {
5128
5238
  while (true) {
5239
+ const elapsed = Date.now() - startTime;
5240
+ if (elapsed > timeout) {
5241
+ reader.cancel();
5242
+ throw new Error(
5243
+ `Stream timeout exceeded after ${elapsed}ms (limit: ${timeout}ms)`
5244
+ );
5245
+ }
5246
+ if (chunkCount >= maxChunks) {
5247
+ reader.cancel();
5248
+ throw new Error(`Maximum chunk limit exceeded (${maxChunks})`);
5249
+ }
5129
5250
  const { done, value } = await reader.read();
5130
5251
  if (done) {
5131
5252
  break;
@@ -5134,6 +5255,13 @@ async function* streamSSE(response, options = {}) {
5134
5255
  reader.cancel();
5135
5256
  throw new Error("Stream aborted");
5136
5257
  }
5258
+ bufferSize += value.length;
5259
+ if (bufferSize > maxBufferSize) {
5260
+ reader.cancel();
5261
+ throw new Error(
5262
+ `Stream buffer size exceeded (${bufferSize} bytes, limit: ${maxBufferSize})`
5263
+ );
5264
+ }
5137
5265
  buffer += decoder.decode(value, { stream: true });
5138
5266
  const lines = buffer.split("\n");
5139
5267
  buffer = lines.pop() || "";
@@ -5143,6 +5271,7 @@ async function* streamSSE(response, options = {}) {
5143
5271
  if (data === "[DONE]" || data.trim() === "") {
5144
5272
  continue;
5145
5273
  }
5274
+ chunkCount++;
5146
5275
  try {
5147
5276
  const parsed = JSON.parse(data);
5148
5277
  yield parsed;
@@ -5406,6 +5535,7 @@ export {
5406
5535
  PresignedUploadSchema,
5407
5536
  RateLimitError,
5408
5537
  RegisterRequestSchema,
5538
+ RetryTimeoutError,
5409
5539
  SearchRequestSchema,
5410
5540
  ServerError,
5411
5541
  ThreadCreateSchema,
@@ -5517,6 +5647,7 @@ export {
5517
5647
  getExtractionResults,
5518
5648
  getExtractionResultsById,
5519
5649
  getExtractionResultsDocumentByDocumentId,
5650
+ getExtractionResultsDocumentByDocumentIdHistory,
5520
5651
  getExtractionResultsWorkspaceByWorkspaceId,
5521
5652
  getExtractionSchemaDiscoveriesById,
5522
5653
  getFieldTemplates,
package/llms.txt CHANGED
@@ -265,6 +265,7 @@ client.setConfig({
265
265
  - `getExtractionResults()` - List results
266
266
  - `getExtractionResultsById()` - Get results
267
267
  - `getExtractionResultsDocumentByDocumentId()` - Get document
268
+ - `getExtractionResultsDocumentByDocumentIdHistory()` - Get history
268
269
  - `getExtractionResultsWorkspaceByWorkspaceId()` - Get workspace
269
270
  - `patchExtractionResultsById()` - Update results
270
271
  - `patchExtractionResultsByIdRegenerate()` - Update regenerate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpt-core/client",
3
- "version": "0.10.13",
3
+ "version": "0.10.21",
4
4
  "description": "TypeScript SDK for GPT Core Client API - Document extraction, AI agents, and workspace management",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -46,20 +46,20 @@
46
46
  "license": "MIT",
47
47
  "repository": {
48
48
  "type": "git",
49
- "url": "https://github.com/GPT-Integrators/gpt-core-sdks.git",
50
- "directory": "ts/packages/client"
49
+ "url": "https://github.com/GPT-Integrators/gpt-core-client-sdk.git"
51
50
  },
51
+ "homepage": "https://gpt-integrators.github.io/gpt-core-client-sdk",
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
55
  "scripts": {
56
- "generate": "openapi-ts",
57
- "typecheck": "tsc --noEmit",
58
- "build": "npm run typecheck && tsup src/index.ts --format cjs,esm --dts",
59
- "test": "vitest run",
60
- "test:watch": "vitest",
61
- "test:ui": "vitest --ui",
62
- "test:coverage": "vitest run --coverage"
56
+ "generate": "bunx openapi-ts",
57
+ "typecheck": "bunx tsc --noEmit",
58
+ "build": "bun run typecheck && bunx tsup src/index.ts --format cjs,esm --dts",
59
+ "test": "bunx vitest run",
60
+ "test:watch": "bunx vitest",
61
+ "test:ui": "bunx vitest --ui",
62
+ "test:coverage": "bunx vitest run --coverage"
63
63
  },
64
64
  "dependencies": {
65
65
  "eventsource-parser": "^3.0.6",