@docmana/sdk 0.3.5 → 0.4.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.
Files changed (47) hide show
  1. package/README.md +115 -247
  2. package/dist/api/execution-result.d.ts +3 -0
  3. package/dist/api/execution-status.d.ts +6 -0
  4. package/dist/api/run-flow.d.ts +6 -0
  5. package/dist/cli.mjs +217 -257
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/client.d.ts +21 -0
  8. package/dist/config.d.ts +21 -0
  9. package/dist/errors.d.ts +55 -0
  10. package/dist/files/resolve-input.d.ts +11 -0
  11. package/dist/http/http-client.d.ts +26 -0
  12. package/dist/index.d.ts +4 -349
  13. package/dist/index.js +159 -298
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +159 -298
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/models/docmana-api-document-execution-result.model.d.ts +9 -0
  18. package/dist/models/docmana-api-document-request.model.d.ts +15 -0
  19. package/dist/models/docmana-api-execution-result.model.d.ts +24 -0
  20. package/dist/models/docmana-api-node-result.model.d.ts +28 -0
  21. package/dist/models/docmana-classification-result.model.d.ts +3 -0
  22. package/dist/models/docmana-conclusion-result.model.d.ts +3 -0
  23. package/dist/models/docmana-cross-validation-result.model.d.ts +3 -0
  24. package/dist/models/docmana-document-mapping.model.d.ts +4 -0
  25. package/dist/models/docmana-document-result.model.d.ts +11 -0
  26. package/dist/models/docmana-execution-result.model.d.ts +15 -0
  27. package/dist/models/docmana-extraction-result.model.d.ts +3 -0
  28. package/dist/models/docmana-metadata-extraction-result.model.d.ts +3 -0
  29. package/dist/models/docmana-node-result.model.d.ts +7 -0
  30. package/dist/models/docmana-score-node-result.model.d.ts +5 -0
  31. package/dist/models/docmana-validation-result.model.d.ts +3 -0
  32. package/dist/models/document-content.model.d.ts +4 -0
  33. package/dist/models/execution-progress.model.d.ts +4 -0
  34. package/dist/models/execution-status.enum.d.ts +1 -0
  35. package/dist/models/flow-configs.model.d.ts +16 -0
  36. package/dist/models/flow-edge.model.d.ts +4 -0
  37. package/dist/models/flow-node-type.enum.d.ts +1 -0
  38. package/dist/models/flow-node.model.d.ts +33 -0
  39. package/dist/models/flow.model.d.ts +11 -0
  40. package/dist/models/index.d.ts +26 -0
  41. package/dist/models/node-translation-result.model.d.ts +7 -0
  42. package/dist/models/physical-document.model.d.ts +9 -0
  43. package/dist/models/virtual-document.model.d.ts +10 -0
  44. package/dist/polling/poll.d.ts +15 -0
  45. package/dist/types.d.ts +76 -0
  46. package/package.json +17 -14
  47. package/dist/index.d.cts +0 -349
package/dist/index.js CHANGED
@@ -34,29 +34,33 @@ module.exports = __toCommonJS(index_exports);
34
34
 
35
35
  // src/config.ts
36
36
  var DEFAULTS = {
37
- apiBaseUrl: "https://api.docmana.ai",
38
37
  tokenEndpoint: "https://4fe70f5b-e013-4f65-9fa7-3109a33beba5.ciamlogin.com/4fe70f5b-e013-4f65-9fa7-3109a33beba5/oauth2/v2.0/token",
39
38
  scope: "api://d781e6ba-cc08-4618-8099-ad968abd2b9e/.default",
40
39
  timeoutMs: 3e5,
41
- pollIntervalMs: 2e3
40
+ pollIntervalMs: 2e3,
41
+ pollMaxIntervalMs: 1e4
42
42
  };
43
43
  function resolveConfig(config) {
44
- if (!config.clientId) throw new Error("DocmanaConfig.clientId is required");
45
- if (!config.clientSecret) throw new Error("DocmanaConfig.clientSecret is required");
46
- const apiBaseUrl = (config.apiBaseUrl ?? DEFAULTS.apiBaseUrl).replace(/\/+$/, "");
44
+ if (!config.apiBaseUrl) throw new Error("DocmanaConfig.apiBaseUrl is required");
45
+ if (!config.accessToken && !config.getAccessToken) {
46
+ throw new Error("DocmanaConfig.accessToken or DocmanaConfig.getAccessToken is required");
47
+ }
48
+ const apiBaseUrl = normalizeApiBaseUrl(config.apiBaseUrl);
47
49
  return {
48
- clientId: config.clientId,
49
- clientSecret: config.clientSecret,
50
50
  apiBaseUrl,
51
- tokenEndpoint: config.tokenEndpoint ?? DEFAULTS.tokenEndpoint,
52
- scope: config.scope ?? DEFAULTS.scope,
51
+ accessToken: config.accessToken,
52
+ getAccessToken: config.getAccessToken,
53
53
  timeoutMs: config.timeoutMs ?? DEFAULTS.timeoutMs,
54
54
  pollIntervalMs: config.pollIntervalMs ?? DEFAULTS.pollIntervalMs,
55
+ pollMaxIntervalMs: config.pollMaxIntervalMs ?? DEFAULTS.pollMaxIntervalMs,
55
56
  fetchImpl: config.fetch ?? fetch,
56
- headers: config.headers ?? {},
57
- tokenCache: config.tokenCache
57
+ headers: config.headers ?? {}
58
58
  };
59
59
  }
60
+ function normalizeApiBaseUrl(value) {
61
+ const trimmed = value.replace(/\/+$/, "");
62
+ return /\/v\d+$/i.test(trimmed) ? trimmed : `${trimmed}/v1`;
63
+ }
60
64
 
61
65
  // src/errors.ts
62
66
  var DocmanaError = class extends Error {
@@ -111,7 +115,14 @@ var DocmanaAbortError = class extends DocmanaError {
111
115
  super(message, { code: "aborted" });
112
116
  }
113
117
  };
114
- function errorFromResponse(status, message, requestId) {
118
+ var DocmanaRateLimitError = class extends DocmanaError {
119
+ retryAfterMs;
120
+ constructor(message, opts = {}) {
121
+ super(message, { ...opts, code: "rate_limited" });
122
+ this.retryAfterMs = opts.retryAfterMs;
123
+ }
124
+ };
125
+ function errorFromResponse(status, message, requestId, retryAfterMs) {
115
126
  const opts = { status, requestId };
116
127
  switch (status) {
117
128
  case 400:
@@ -122,91 +133,13 @@ function errorFromResponse(status, message, requestId) {
122
133
  return new DocmanaPermissionError(message, opts);
123
134
  case 404:
124
135
  return new DocmanaNotFoundError(message, opts);
136
+ case 429:
137
+ return new DocmanaRateLimitError(message, { ...opts, retryAfterMs });
125
138
  default:
126
139
  return new DocmanaError(message, opts);
127
140
  }
128
141
  }
129
142
 
130
- // src/auth/token-manager.ts
131
- var SAFETY_MARGIN_MS = 6e4;
132
- var TokenManager = class {
133
- constructor(opts) {
134
- this.opts = opts;
135
- }
136
- opts;
137
- token = null;
138
- expiresAt = 0;
139
- inflight = null;
140
- invalidate() {
141
- this.token = null;
142
- this.expiresAt = 0;
143
- void this.opts.tokenCache?.clear().catch(() => void 0);
144
- }
145
- async getToken() {
146
- if (this.token && Date.now() < this.expiresAt) return this.token;
147
- const cached = await this.readCachedToken();
148
- if (cached) return cached;
149
- if (this.inflight) return this.inflight;
150
- this.inflight = this.acquire().finally(() => {
151
- this.inflight = null;
152
- });
153
- return this.inflight;
154
- }
155
- async acquire() {
156
- const body = new URLSearchParams({
157
- grant_type: "client_credentials",
158
- client_id: this.opts.clientId,
159
- client_secret: this.opts.clientSecret,
160
- scope: this.opts.scope
161
- });
162
- const res = await this.opts.fetchImpl(this.opts.tokenEndpoint, {
163
- method: "POST",
164
- headers: { "content-type": "application/x-www-form-urlencoded" },
165
- body: body.toString()
166
- });
167
- if (!res.ok) {
168
- throw new DocmanaAuthError("Failed to acquire Docmana access token", { status: res.status });
169
- }
170
- const json = await res.json();
171
- if (typeof json.access_token !== "string" || json.access_token.length === 0 || typeof json.expires_in !== "number" || !Number.isFinite(json.expires_in)) {
172
- throw new DocmanaAuthError("Malformed token response from Docmana CIAM", {
173
- status: res.status
174
- });
175
- }
176
- this.token = json.access_token;
177
- this.expiresAt = Date.now() + json.expires_in * 1e3 - SAFETY_MARGIN_MS;
178
- await this.writeCachedToken().catch(() => void 0);
179
- return this.token;
180
- }
181
- async readCachedToken() {
182
- if (!this.opts.tokenCache) return null;
183
- let entry;
184
- try {
185
- entry = await this.opts.tokenCache.read();
186
- } catch {
187
- return null;
188
- }
189
- if (!entry) return null;
190
- if (entry.clientId !== this.opts.clientId || entry.tokenEndpoint !== this.opts.tokenEndpoint || entry.scope !== this.opts.scope || Date.now() >= entry.expiresAt) {
191
- await this.opts.tokenCache.clear().catch(() => void 0);
192
- return null;
193
- }
194
- this.token = entry.accessToken;
195
- this.expiresAt = entry.expiresAt;
196
- return this.token;
197
- }
198
- async writeCachedToken() {
199
- if (!this.opts.tokenCache || !this.token) return;
200
- await this.opts.tokenCache.write({
201
- accessToken: this.token,
202
- expiresAt: this.expiresAt,
203
- clientId: this.opts.clientId,
204
- tokenEndpoint: this.opts.tokenEndpoint,
205
- scope: this.opts.scope
206
- });
207
- }
208
- };
209
-
210
143
  // src/http/http-client.ts
211
144
  var HttpClient = class {
212
145
  constructor(opts) {
@@ -225,19 +158,23 @@ var HttpClient = class {
225
158
  }
226
159
  async requestRaw(method, path, options = {}) {
227
160
  let res = await this.send(method, path, options);
228
- if (res.status === 401) {
229
- this.opts.tokenManager.invalidate();
230
- res = await this.send(method, path, options);
161
+ if (res.status === 401 && this.opts.getAccessToken) {
162
+ res = await this.send(method, path, options, true);
231
163
  }
232
164
  if (!res.ok) {
233
165
  const requestId = res.headers.get("x-request-id") ?? void 0;
234
166
  const message = await this.extractMessage(res);
235
- throw errorFromResponse(res.status, message, requestId);
167
+ throw errorFromResponse(
168
+ res.status,
169
+ message,
170
+ requestId,
171
+ parseRetryAfterMs(res.headers.get("retry-after"))
172
+ );
236
173
  }
237
174
  return res;
238
175
  }
239
- async send(method, path, options) {
240
- const token = await this.opts.tokenManager.getToken();
176
+ async send(method, path, options, forceRefresh = false) {
177
+ const token = await this.resolveToken(forceRefresh);
241
178
  const url = new URL(this.opts.apiBaseUrl + path);
242
179
  for (const [k, v] of Object.entries(options.query ?? {})) url.searchParams.set(k, v);
243
180
  const headers = {
@@ -259,6 +196,13 @@ var HttpClient = class {
259
196
  throw err;
260
197
  }
261
198
  }
199
+ async resolveToken(forceRefresh) {
200
+ const token = this.opts.getAccessToken ? await this.opts.getAccessToken(forceRefresh ? { forceRefresh: true } : void 0) : this.opts.accessToken;
201
+ if (!token) {
202
+ throw new DocmanaError("Missing Docmana access token", { code: "auth_missing" });
203
+ }
204
+ return token;
205
+ }
262
206
  async extractMessage(res) {
263
207
  try {
264
208
  const data = await res.clone().json();
@@ -268,6 +212,18 @@ var HttpClient = class {
268
212
  }
269
213
  }
270
214
  };
215
+ function parseRetryAfterMs(value) {
216
+ if (!value) return void 0;
217
+ const seconds = Number(value);
218
+ if (Number.isFinite(seconds) && seconds >= 0) {
219
+ return seconds * 1e3;
220
+ }
221
+ const retryAt = Date.parse(value);
222
+ if (!Number.isNaN(retryAt)) {
223
+ return Math.max(0, retryAt - Date.now());
224
+ }
225
+ return void 0;
226
+ }
271
227
 
272
228
  // src/files/resolve-input.ts
273
229
  var import_promises = require("fs/promises");
@@ -299,16 +255,19 @@ async function streamToBuffer(stream) {
299
255
  for await (const chunk of stream) chunks.push(Buffer.from(chunk));
300
256
  return Buffer.concat(chunks);
301
257
  }
258
+ function toBlobBytes(bytes) {
259
+ return new Uint8Array(bytes);
260
+ }
302
261
  async function resolveOne(input, fallbackName) {
303
262
  if (typeof input === "string" || isPathInput(input)) {
304
263
  const path = typeof input === "string" ? input : input.path;
305
264
  const data = await (0, import_promises.readFile)(path);
306
265
  const filename = (0, import_node_path.basename)(path);
307
- return { data: new Blob([data]), filename, contentType: contentTypeFor(filename) };
266
+ return { data: new Blob([toBlobBytes(data)]), filename, contentType: contentTypeFor(filename) };
308
267
  }
309
268
  if (input instanceof Uint8Array) {
310
269
  return {
311
- data: new Blob([input]),
270
+ data: new Blob([toBlobBytes(input)]),
312
271
  filename: fallbackName,
313
272
  contentType: contentTypeFor(fallbackName)
314
273
  };
@@ -316,7 +275,7 @@ async function resolveOne(input, fallbackName) {
316
275
  if (isReadable(input)) {
317
276
  const buf = await streamToBuffer(input);
318
277
  return {
319
- data: new Blob([buf]),
278
+ data: new Blob([toBlobBytes(buf)]),
320
279
  filename: fallbackName,
321
280
  contentType: contentTypeFor(fallbackName)
322
281
  };
@@ -330,39 +289,43 @@ async function resolveInputs(input) {
330
289
  return Promise.all(list.map((item) => resolveOne(item, fallback)));
331
290
  }
332
291
 
333
- // src/api/upload.ts
334
- async function uploadFiles(http, parts, signal) {
292
+ // src/api/run-flow.ts
293
+ async function runFlow(http, flowId, parts, signal, useDraftVersion = false, context, callbackUrl, language) {
335
294
  const form = new FormData();
336
295
  for (const part of parts) {
337
296
  form.append("files", new File([part.data], part.filename, { type: part.contentType }));
338
297
  }
339
- const res = await http.requestJson("POST", "/upload", { body: form, signal });
340
- return [res.id];
341
- }
342
-
343
- // src/api/run-flow.ts
344
- async function runFlow(http, flowId, uuidFiles, signal, once = false, context, callbackUrl) {
345
- const path = once ? `/flows/run_once_flow/${flowId}` : `/flows/run_flow/${flowId}`;
346
- const body = { uuid_files: uuidFiles };
347
- if (context !== void 0) body.json_context = context;
348
- if (callbackUrl !== void 0) body.callback_url = callbackUrl;
349
- const res = await http.requestJson("POST", path, {
350
- query: { async_mode: "true" },
351
- headers: { "content-type": "application/json" },
352
- body: JSON.stringify(body),
353
- signal
354
- });
355
- return res.execution_result_id;
298
+ if (context !== void 0) form.append("json_context", JSON.stringify(context));
299
+ if (callbackUrl !== void 0) form.append("callback_url", callbackUrl);
300
+ if (language !== void 0) form.append("language", language);
301
+ if (useDraftVersion) form.append("useDraftVersion", "true");
302
+ return http.requestJson(
303
+ "POST",
304
+ `/flows/${flowId}/execute-async`,
305
+ { body: form, signal }
306
+ );
356
307
  }
357
308
 
358
309
  // src/api/execution-status.ts
359
310
  async function getStatus(http, executionResultId, signal) {
360
- return http.requestJson("GET", `/flows/execution-status/${executionResultId}`, { signal });
311
+ const res = await http.requestRaw("GET", `/executions/${executionResultId}/status`, { signal });
312
+ const text = await res.text();
313
+ const body = text ? JSON.parse(text) : { status: "" };
314
+ const pollAfterMs = parsePositiveInt(res.headers.get("x-poll-after"));
315
+ return pollAfterMs === void 0 ? body : { ...body, pollAfterMs };
316
+ }
317
+ function parsePositiveInt(value) {
318
+ if (!value) return void 0;
319
+ const parsed = Number(value);
320
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
361
321
  }
362
322
 
363
323
  // src/api/execution-result.ts
364
- async function getResult(http, executionResultId, signal) {
365
- return http.requestJson("GET", `/flows/execution-result/${executionResultId}`, { signal });
324
+ async function getResult(http, executionResultId, signal, language) {
325
+ return http.requestJson("GET", `/executions/${executionResultId}/result`, {
326
+ query: language ? { language } : void 0,
327
+ signal
328
+ });
366
329
  }
367
330
 
368
331
  // src/polling/poll.ts
@@ -372,166 +335,42 @@ async function pollUntilTerminal(opts) {
372
335
  const sleep = opts.sleep ?? defaultSleep;
373
336
  const start = Date.now();
374
337
  const elapsed = opts.elapsed ?? (() => Date.now() - start);
338
+ const random = opts.random ?? Math.random;
339
+ let fallbackAttempt = 0;
375
340
  for (; ; ) {
376
341
  if (opts.signal?.aborted) throw new DocmanaAbortError("Polling aborted");
377
- const status = await opts.check();
342
+ let result;
343
+ try {
344
+ result = normalizePollResult(await opts.check());
345
+ } catch (err) {
346
+ if (!(err instanceof DocmanaRateLimitError)) throw err;
347
+ if (elapsed() >= opts.timeoutMs) {
348
+ throw new DocmanaTimeoutError(`Execution did not finish within ${opts.timeoutMs}ms`);
349
+ }
350
+ await sleep(err.retryAfterMs ?? opts.intervalMs);
351
+ continue;
352
+ }
353
+ const { status } = result;
378
354
  if (TERMINAL.has(status)) return status;
379
355
  if (elapsed() >= opts.timeoutMs) {
380
356
  throw new DocmanaTimeoutError(`Execution did not finish within ${opts.timeoutMs}ms`);
381
357
  }
382
- await sleep(opts.intervalMs);
358
+ const fallbackDelay = fullJitterDelay(
359
+ opts.intervalMs,
360
+ opts.maxIntervalMs,
361
+ fallbackAttempt,
362
+ random
363
+ );
364
+ fallbackAttempt += 1;
365
+ await sleep(result.nextDelayMs ?? fallbackDelay);
383
366
  }
384
367
  }
385
-
386
- // src/mappers/mapper.ts
387
- function extractNodeFields(rawNode, targetLanguage) {
388
- const metadataFields = /* @__PURE__ */ new Set([
389
- "node_id",
390
- "node_name",
391
- "node_type",
392
- "feature_name",
393
- "running_time",
394
- "status",
395
- "score",
396
- "feedback",
397
- "translations",
398
- "tokens",
399
- "input_tokens",
400
- "output_tokens",
401
- "errors",
402
- "mana",
403
- "model",
404
- "tool_calls",
405
- "prompt_id",
406
- "prompt",
407
- "prompt_name",
408
- "label",
409
- "scoreDescription",
410
- "score_description",
411
- "result",
412
- "documentType"
413
- ]);
414
- let sourceObj = rawNode;
415
- if (targetLanguage) {
416
- const translations = rawNode.translations;
417
- if (!translations || !translations[targetLanguage]) {
418
- throw new DocmanaError(
419
- `Translation for language '${targetLanguage}' is missing on node '${rawNode.node_name || rawNode.node_id}'`,
420
- { code: "translation_missing", status: 400 }
421
- );
422
- }
423
- sourceObj = translations[targetLanguage];
424
- }
425
- const dynamicFields = {};
426
- for (const [key, value] of Object.entries(sourceObj)) {
427
- if (!metadataFields.has(key)) {
428
- dynamicFields[key] = value;
429
- }
430
- }
431
- const sdkNode = {
432
- status: rawNode.status || "Unknown"
433
- };
434
- if (rawNode.errors && rawNode.errors.length > 0) {
435
- sdkNode.errors = rawNode.errors;
436
- }
437
- const nodeType = rawNode.node_type || "";
438
- const isScoreNode = /^(Validation|Classification|CrossValidation|Conclusion|Finish)$/i.test(
439
- nodeType
440
- );
441
- if (isScoreNode && rawNode.score !== void 0 && rawNode.score !== null) {
442
- sdkNode.score = rawNode.score;
443
- }
444
- const feedback = sourceObj.feedback ?? rawNode.feedback;
445
- if (feedback !== void 0 && feedback !== null) {
446
- sdkNode.feedback = feedback;
447
- }
448
- if (Object.keys(dynamicFields).length > 0) {
449
- sdkNode.data = dynamicFields;
450
- }
451
- return sdkNode;
368
+ function normalizePollResult(result) {
369
+ return typeof result === "string" ? { status: result } : result;
452
370
  }
453
- function mapExecutionResult(raw, targetLanguage) {
454
- const sdkResult = {
455
- status: raw.status || "Unknown",
456
- executionId: String(raw.execution_id || raw.executionResultId || raw.execution_result_id || ""),
457
- documents: {
458
- mappings: []
459
- }
460
- };
461
- if (raw.errors && raw.errors.length > 0) {
462
- sdkResult.errors = raw.errors;
463
- }
464
- const results = raw.results || [];
465
- for (const item of results) {
466
- const isDocSpecific = !!item.document;
467
- if (isDocSpecific && item.document) {
468
- const docReq = item.document;
469
- const docKey = docReq.doc_key || "unknown_doc";
470
- const docName = docReq.name || "";
471
- sdkResult.documents.mappings.push({
472
- name: docName,
473
- reference: docKey
474
- });
475
- const docResult = {
476
- status: item.status || docReq.status || "Unknown",
477
- extractions: {},
478
- validations: {}
479
- };
480
- const nodeResults = item.node_results || [];
481
- for (const node of nodeResults) {
482
- const nodeType = node.node_type || "";
483
- const nodeName = node.node_name || node.node_id || "unknown_node";
484
- if (/^Classification$/i.test(nodeType)) {
485
- const mappedNode = extractNodeFields(node, targetLanguage);
486
- if (!docResult.classifications) {
487
- docResult.classifications = {};
488
- }
489
- docResult.classifications[nodeName] = mappedNode;
490
- } else if (/^MetadataExtraction$/i.test(nodeType)) {
491
- docResult.metadataExtraction = extractNodeFields(node, targetLanguage);
492
- } else if (/^Extraction$/i.test(nodeType)) {
493
- if (docResult.extractions) {
494
- docResult.extractions[nodeName] = extractNodeFields(node, targetLanguage);
495
- }
496
- } else if (/^Validation$/i.test(nodeType)) {
497
- if (docResult.validations) {
498
- docResult.validations[nodeName] = extractNodeFields(node, targetLanguage);
499
- }
500
- }
501
- }
502
- if (docResult.extractions && Object.keys(docResult.extractions).length === 0) {
503
- delete docResult.extractions;
504
- }
505
- if (docResult.validations && Object.keys(docResult.validations).length === 0) {
506
- delete docResult.validations;
507
- }
508
- sdkResult.documents[docKey] = docResult;
509
- } else {
510
- const nodeResults = item.node_results || [];
511
- for (const node of nodeResults) {
512
- const nodeType = node.node_type || "";
513
- const nodeName = node.node_name || node.node_id || "unknown_node";
514
- if (/^CrossValidation$/i.test(nodeType)) {
515
- if (!sdkResult.crossValidations) {
516
- sdkResult.crossValidations = {};
517
- }
518
- sdkResult.crossValidations[nodeName] = extractNodeFields(
519
- node,
520
- targetLanguage
521
- );
522
- } else if (/^(Conclusion|Finish)$/i.test(nodeType)) {
523
- if (!sdkResult.conclusions) {
524
- sdkResult.conclusions = {};
525
- }
526
- sdkResult.conclusions[nodeName] = extractNodeFields(
527
- node,
528
- targetLanguage
529
- );
530
- }
531
- }
532
- }
533
- }
534
- return sdkResult;
371
+ function fullJitterDelay(intervalMs, maxIntervalMs, attempt, random) {
372
+ const capDelay = Math.min(maxIntervalMs, intervalMs * 2 ** attempt);
373
+ return Math.round(intervalMs + random() * (capDelay - intervalMs));
535
374
  }
536
375
 
537
376
  // src/client.ts
@@ -540,60 +379,79 @@ var Docmana = class {
540
379
  http;
541
380
  constructor(config) {
542
381
  this.config = resolveConfig(config);
543
- const tokenManager = new TokenManager({
544
- clientId: this.config.clientId,
545
- clientSecret: this.config.clientSecret,
546
- tokenEndpoint: this.config.tokenEndpoint,
547
- scope: this.config.scope,
548
- fetchImpl: this.config.fetchImpl,
549
- tokenCache: this.config.tokenCache
550
- });
551
382
  this.http = new HttpClient({
552
383
  apiBaseUrl: this.config.apiBaseUrl,
553
384
  fetchImpl: this.config.fetchImpl,
554
- tokenManager,
385
+ accessToken: this.config.accessToken,
386
+ getAccessToken: this.config.getAccessToken,
555
387
  headers: this.config.headers
556
388
  });
557
389
  }
558
390
  async runFlowAsync(flowId, input) {
559
391
  const parts = await resolveInputs(input);
560
- const fileIds = await uploadFiles(this.http, parts, input.signal);
561
- const executionResultId = await runFlow(
392
+ return runFlow(
562
393
  this.http,
563
394
  flowId,
564
- fileIds,
395
+ parts,
565
396
  input.signal,
566
- input.once ?? false,
567
- input.context
397
+ input.useDraftVersion ?? false,
398
+ input.context,
399
+ void 0,
400
+ input.language
568
401
  );
569
- return { executionResultId, fileIds };
570
402
  }
571
403
  async runFlowWithCallback(flowId, input) {
572
404
  const parts = await resolveInputs(input);
573
- const fileIds = await uploadFiles(this.http, parts, input.signal);
574
- const executionResultId = await runFlow(
405
+ return runFlow(
575
406
  this.http,
576
407
  flowId,
577
- fileIds,
408
+ parts,
578
409
  input.signal,
579
- input.once ?? false,
410
+ input.useDraftVersion ?? false,
580
411
  input.context,
581
- input.callbackUrl
412
+ input.callbackUrl,
413
+ input.language
582
414
  );
583
- return { executionResultId, fileIds };
584
415
  }
585
416
  async getStatus(executionResultId, signal) {
586
417
  return getStatus(this.http, executionResultId, signal);
587
418
  }
588
419
  async getResult(executionResultId, signal, language) {
589
- const rawResult = await getResult(this.http, executionResultId, signal);
590
- return mapExecutionResult(rawResult, language);
420
+ return getResult(this.http, executionResultId, signal, language);
591
421
  }
592
422
  async runFlow(flowId, input) {
593
423
  const { executionResultId } = await this.runFlowAsync(flowId, input);
424
+ let attempt = 0;
425
+ const startedAt = Date.now();
594
426
  await pollUntilTerminal({
595
- check: async () => (await this.getStatus(executionResultId, input.signal)).status,
427
+ check: async () => {
428
+ attempt += 1;
429
+ try {
430
+ const statusResult = await this.getStatus(executionResultId, input.signal);
431
+ const status = statusResult.status;
432
+ const nextPollAfterMs = this.isTerminalStatus(status) ? void 0 : statusResult.pollAfterMs;
433
+ input.onPoll?.({
434
+ executionResultId,
435
+ status,
436
+ attempt,
437
+ elapsedMs: Date.now() - startedAt,
438
+ nextPollAfterMs
439
+ });
440
+ return { status, nextDelayMs: nextPollAfterMs };
441
+ } catch (err) {
442
+ if (err instanceof DocmanaRateLimitError) {
443
+ input.onRateLimit?.({
444
+ executionResultId,
445
+ attempt,
446
+ elapsedMs: Date.now() - startedAt,
447
+ retryAfterMs: err.retryAfterMs ?? input.pollIntervalMs ?? this.config.pollIntervalMs
448
+ });
449
+ }
450
+ throw err;
451
+ }
452
+ },
596
453
  intervalMs: input.pollIntervalMs ?? this.config.pollIntervalMs,
454
+ maxIntervalMs: input.pollMaxIntervalMs ?? this.config.pollMaxIntervalMs,
597
455
  timeoutMs: input.timeoutMs ?? this.config.timeoutMs,
598
456
  signal: input.signal
599
457
  });
@@ -607,6 +465,9 @@ var Docmana = class {
607
465
  }
608
466
  return result;
609
467
  }
468
+ isTerminalStatus(status) {
469
+ return status === "Completed" || status === "Failed";
470
+ }
610
471
  };
611
472
  // Annotate the CommonJS export names for ESM import in node:
612
473
  0 && (module.exports = {