@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.
- package/README.md +115 -247
- package/dist/api/execution-result.d.ts +3 -0
- package/dist/api/execution-status.d.ts +6 -0
- package/dist/api/run-flow.d.ts +6 -0
- package/dist/cli.mjs +217 -257
- package/dist/cli.mjs.map +1 -1
- package/dist/client.d.ts +21 -0
- package/dist/config.d.ts +21 -0
- package/dist/errors.d.ts +55 -0
- package/dist/files/resolve-input.d.ts +11 -0
- package/dist/http/http-client.d.ts +26 -0
- package/dist/index.d.ts +4 -349
- package/dist/index.js +159 -298
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +159 -298
- package/dist/index.mjs.map +1 -1
- package/dist/models/docmana-api-document-execution-result.model.d.ts +9 -0
- package/dist/models/docmana-api-document-request.model.d.ts +15 -0
- package/dist/models/docmana-api-execution-result.model.d.ts +24 -0
- package/dist/models/docmana-api-node-result.model.d.ts +28 -0
- package/dist/models/docmana-classification-result.model.d.ts +3 -0
- package/dist/models/docmana-conclusion-result.model.d.ts +3 -0
- package/dist/models/docmana-cross-validation-result.model.d.ts +3 -0
- package/dist/models/docmana-document-mapping.model.d.ts +4 -0
- package/dist/models/docmana-document-result.model.d.ts +11 -0
- package/dist/models/docmana-execution-result.model.d.ts +15 -0
- package/dist/models/docmana-extraction-result.model.d.ts +3 -0
- package/dist/models/docmana-metadata-extraction-result.model.d.ts +3 -0
- package/dist/models/docmana-node-result.model.d.ts +7 -0
- package/dist/models/docmana-score-node-result.model.d.ts +5 -0
- package/dist/models/docmana-validation-result.model.d.ts +3 -0
- package/dist/models/document-content.model.d.ts +4 -0
- package/dist/models/execution-progress.model.d.ts +4 -0
- package/dist/models/execution-status.enum.d.ts +1 -0
- package/dist/models/flow-configs.model.d.ts +16 -0
- package/dist/models/flow-edge.model.d.ts +4 -0
- package/dist/models/flow-node-type.enum.d.ts +1 -0
- package/dist/models/flow-node.model.d.ts +33 -0
- package/dist/models/flow.model.d.ts +11 -0
- package/dist/models/index.d.ts +26 -0
- package/dist/models/node-translation-result.model.d.ts +7 -0
- package/dist/models/physical-document.model.d.ts +9 -0
- package/dist/models/virtual-document.model.d.ts +10 -0
- package/dist/polling/poll.d.ts +15 -0
- package/dist/types.d.ts +76 -0
- package/package.json +17 -14
- 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.
|
|
45
|
-
if (!config.
|
|
46
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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.
|
|
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(
|
|
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.
|
|
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/
|
|
334
|
-
async function
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
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", `/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
454
|
-
const
|
|
455
|
-
|
|
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
|
-
|
|
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
|
-
|
|
561
|
-
const executionResultId = await runFlow(
|
|
392
|
+
return runFlow(
|
|
562
393
|
this.http,
|
|
563
394
|
flowId,
|
|
564
|
-
|
|
395
|
+
parts,
|
|
565
396
|
input.signal,
|
|
566
|
-
input.
|
|
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
|
-
|
|
574
|
-
const executionResultId = await runFlow(
|
|
405
|
+
return runFlow(
|
|
575
406
|
this.http,
|
|
576
407
|
flowId,
|
|
577
|
-
|
|
408
|
+
parts,
|
|
578
409
|
input.signal,
|
|
579
|
-
input.
|
|
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
|
-
|
|
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 () =>
|
|
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 = {
|