@docmana/sdk 0.2.2 → 0.3.1
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/CHANGELOG.md +19 -8
- package/dist/cli.mjs +368 -64
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.cts +237 -12
- package/dist/index.d.ts +237 -12
- package/dist/index.js +165 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +165 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.
|
|
4
|
-
- Fix `
|
|
5
|
-
|
|
6
|
-
## 0.
|
|
7
|
-
-
|
|
8
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.1
|
|
4
|
+
- Fix: upload all files in a single `/upload` call (one folder UUID) instead of one call per file. Sending each file separately made Docmana treat them as distinct documents, which breaks multi-document flows ("Node already present" when the same flow node is built per document).
|
|
5
|
+
|
|
6
|
+
## 0.3.0
|
|
7
|
+
- Relocated mapper logic and tests to `src/mappers/`.
|
|
8
|
+
- Renamed SDK models to `DocmanaX` and API models to `DocmanaApiX` to distinguish raw backend types from clean public SDK types.
|
|
9
|
+
- Pluralized `classification` results into a `classifications` key-value record on document results.
|
|
10
|
+
- Nested dynamic extraction fields inside a dedicated `data` record on node results to prevent property name collisions.
|
|
11
|
+
- Restructured node result interfaces to remove `score` and `feedback` from `DocmanaExtractionResult` and `DocmanaMetadataExtractionResult` (via new `DocmanaScoreNodeResult` interface).
|
|
12
|
+
- Excluded internal fields `result` and `documentType` from mapped SDK results.
|
|
13
|
+
|
|
14
|
+
## 0.2.2
|
|
15
|
+
- Fix `package-lock.json`.
|
|
16
|
+
|
|
17
|
+
## 0.2.1
|
|
18
|
+
- 400 responses now throw `DocmanaRequestError` (was `DocmanaAuthError`); add `Incompleted` to `ExecutionStatus`.
|
|
19
|
+
|
|
9
20
|
## 0.2.0
|
|
10
21
|
- `RunFlowInput.once` selects the ad-hoc `run_once_flow` endpoint (current/draft flow) instead of the published `run_flow`.
|
|
11
22
|
- `DocmanaConfig.headers` are sent on every API request (e.g. `X-Selected-Organization`), without overriding the bearer token or per-request headers.
|
package/dist/cli.mjs
CHANGED
|
@@ -44,9 +44,11 @@ var DocmanaRequestError = class extends DocmanaError {
|
|
|
44
44
|
};
|
|
45
45
|
var DocmanaExecutionError = class extends DocmanaError {
|
|
46
46
|
errors;
|
|
47
|
-
|
|
47
|
+
result;
|
|
48
|
+
constructor(message, errors = [], result) {
|
|
48
49
|
super(message, { code: "execution_failed" });
|
|
49
50
|
this.errors = errors;
|
|
51
|
+
this.result = result;
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
var DocmanaTimeoutError = class extends DocmanaError {
|
|
@@ -306,14 +308,12 @@ async function resolveInputs(input) {
|
|
|
306
308
|
|
|
307
309
|
// src/api/upload.ts
|
|
308
310
|
async function uploadFiles(http, parts, signal) {
|
|
309
|
-
const
|
|
311
|
+
const form = new FormData();
|
|
310
312
|
for (const part of parts) {
|
|
311
|
-
const form = new FormData();
|
|
312
313
|
form.append("files", new File([part.data], part.filename, { type: part.contentType }));
|
|
313
|
-
const res = await http.requestJson("POST", "/upload", { body: form, signal });
|
|
314
|
-
ids.push(res.id);
|
|
315
314
|
}
|
|
316
|
-
|
|
315
|
+
const res = await http.requestJson("POST", "/upload", { body: form, signal });
|
|
316
|
+
return [res.id];
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
// src/api/run-flow.ts
|
|
@@ -356,6 +356,156 @@ async function pollUntilTerminal(opts) {
|
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
+
// src/mappers/mapper.ts
|
|
360
|
+
function extractNodeFields(rawNode, targetLanguage) {
|
|
361
|
+
const metadataFields = /* @__PURE__ */ new Set([
|
|
362
|
+
"node_id",
|
|
363
|
+
"node_name",
|
|
364
|
+
"node_type",
|
|
365
|
+
"feature_name",
|
|
366
|
+
"running_time",
|
|
367
|
+
"status",
|
|
368
|
+
"score",
|
|
369
|
+
"feedback",
|
|
370
|
+
"translations",
|
|
371
|
+
"tokens",
|
|
372
|
+
"input_tokens",
|
|
373
|
+
"output_tokens",
|
|
374
|
+
"errors",
|
|
375
|
+
"mana",
|
|
376
|
+
"model",
|
|
377
|
+
"tool_calls",
|
|
378
|
+
"prompt_id",
|
|
379
|
+
"prompt",
|
|
380
|
+
"prompt_name",
|
|
381
|
+
"label",
|
|
382
|
+
"scoreDescription",
|
|
383
|
+
"score_description",
|
|
384
|
+
"result",
|
|
385
|
+
"documentType"
|
|
386
|
+
]);
|
|
387
|
+
let sourceObj = rawNode;
|
|
388
|
+
if (targetLanguage) {
|
|
389
|
+
const translations = rawNode.translations;
|
|
390
|
+
if (!translations || !translations[targetLanguage]) {
|
|
391
|
+
throw new DocmanaError(
|
|
392
|
+
`Translation for language '${targetLanguage}' is missing on node '${rawNode.node_name || rawNode.node_id}'`,
|
|
393
|
+
{ code: "translation_missing", status: 400 }
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
sourceObj = translations[targetLanguage];
|
|
397
|
+
}
|
|
398
|
+
const dynamicFields = {};
|
|
399
|
+
for (const [key, value] of Object.entries(sourceObj)) {
|
|
400
|
+
if (!metadataFields.has(key)) {
|
|
401
|
+
dynamicFields[key] = value;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const sdkNode = {
|
|
405
|
+
status: rawNode.status || "Unknown"
|
|
406
|
+
};
|
|
407
|
+
if (rawNode.errors && rawNode.errors.length > 0) {
|
|
408
|
+
sdkNode.errors = rawNode.errors;
|
|
409
|
+
}
|
|
410
|
+
const nodeType = rawNode.node_type || "";
|
|
411
|
+
const isScoreNode = /^(Validation|Classification|CrossValidation|Conclusion)$/i.test(nodeType);
|
|
412
|
+
if (isScoreNode) {
|
|
413
|
+
if (rawNode.score !== void 0 && rawNode.score !== null) {
|
|
414
|
+
sdkNode.score = rawNode.score;
|
|
415
|
+
}
|
|
416
|
+
if (rawNode.feedback !== void 0 && rawNode.feedback !== null) {
|
|
417
|
+
sdkNode.feedback = rawNode.feedback;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (Object.keys(dynamicFields).length > 0) {
|
|
421
|
+
sdkNode.data = dynamicFields;
|
|
422
|
+
}
|
|
423
|
+
return sdkNode;
|
|
424
|
+
}
|
|
425
|
+
function mapExecutionResult(raw, targetLanguage) {
|
|
426
|
+
const sdkResult = {
|
|
427
|
+
status: raw.status || "Unknown",
|
|
428
|
+
executionId: String(raw.execution_id || raw.executionResultId || raw.execution_result_id || ""),
|
|
429
|
+
documents: {
|
|
430
|
+
mappings: []
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
if (raw.errors && raw.errors.length > 0) {
|
|
434
|
+
sdkResult.errors = raw.errors;
|
|
435
|
+
}
|
|
436
|
+
const results = raw.results || [];
|
|
437
|
+
for (const item of results) {
|
|
438
|
+
const isDocSpecific = !!item.document;
|
|
439
|
+
if (isDocSpecific && item.document) {
|
|
440
|
+
const docReq = item.document;
|
|
441
|
+
const docKey = docReq.doc_key || "unknown_doc";
|
|
442
|
+
const docName = docReq.name || "";
|
|
443
|
+
sdkResult.documents.mappings.push({
|
|
444
|
+
name: docName,
|
|
445
|
+
reference: docKey
|
|
446
|
+
});
|
|
447
|
+
const docResult = {
|
|
448
|
+
status: item.status || docReq.status || "Unknown",
|
|
449
|
+
extractions: {},
|
|
450
|
+
validations: {}
|
|
451
|
+
};
|
|
452
|
+
const nodeResults = item.node_results || [];
|
|
453
|
+
for (const node of nodeResults) {
|
|
454
|
+
const nodeType = node.node_type || "";
|
|
455
|
+
const nodeName = node.node_name || node.node_id || "unknown_node";
|
|
456
|
+
if (/^Classification$/i.test(nodeType)) {
|
|
457
|
+
const mappedNode = extractNodeFields(node, targetLanguage);
|
|
458
|
+
if (!docResult.classifications) {
|
|
459
|
+
docResult.classifications = {};
|
|
460
|
+
}
|
|
461
|
+
docResult.classifications[nodeName] = mappedNode;
|
|
462
|
+
} else if (/^MetadataExtraction$/i.test(nodeType)) {
|
|
463
|
+
docResult.metadataExtraction = extractNodeFields(node, targetLanguage);
|
|
464
|
+
} else if (/^Extraction$/i.test(nodeType)) {
|
|
465
|
+
if (docResult.extractions) {
|
|
466
|
+
docResult.extractions[nodeName] = extractNodeFields(node, targetLanguage);
|
|
467
|
+
}
|
|
468
|
+
} else if (/^Validation$/i.test(nodeType)) {
|
|
469
|
+
if (docResult.validations) {
|
|
470
|
+
docResult.validations[nodeName] = extractNodeFields(node, targetLanguage);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (docResult.extractions && Object.keys(docResult.extractions).length === 0) {
|
|
475
|
+
delete docResult.extractions;
|
|
476
|
+
}
|
|
477
|
+
if (docResult.validations && Object.keys(docResult.validations).length === 0) {
|
|
478
|
+
delete docResult.validations;
|
|
479
|
+
}
|
|
480
|
+
sdkResult.documents[docKey] = docResult;
|
|
481
|
+
} else {
|
|
482
|
+
const nodeResults = item.node_results || [];
|
|
483
|
+
for (const node of nodeResults) {
|
|
484
|
+
const nodeType = node.node_type || "";
|
|
485
|
+
const nodeName = node.node_name || node.node_id || "unknown_node";
|
|
486
|
+
if (/^CrossValidation$/i.test(nodeType)) {
|
|
487
|
+
if (!sdkResult.crossValidations) {
|
|
488
|
+
sdkResult.crossValidations = {};
|
|
489
|
+
}
|
|
490
|
+
sdkResult.crossValidations[nodeName] = extractNodeFields(
|
|
491
|
+
node,
|
|
492
|
+
targetLanguage
|
|
493
|
+
);
|
|
494
|
+
} else if (/^(Conclusion|Finish)$/i.test(nodeType)) {
|
|
495
|
+
if (!sdkResult.conclusions) {
|
|
496
|
+
sdkResult.conclusions = {};
|
|
497
|
+
}
|
|
498
|
+
sdkResult.conclusions[nodeName] = extractNodeFields(
|
|
499
|
+
node,
|
|
500
|
+
targetLanguage
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return sdkResult;
|
|
507
|
+
}
|
|
508
|
+
|
|
359
509
|
// src/client.ts
|
|
360
510
|
var Docmana = class {
|
|
361
511
|
config;
|
|
@@ -392,8 +542,9 @@ var Docmana = class {
|
|
|
392
542
|
async getStatus(executionResultId, signal) {
|
|
393
543
|
return getStatus(this.http, executionResultId, signal);
|
|
394
544
|
}
|
|
395
|
-
async getResult(executionResultId, signal) {
|
|
396
|
-
|
|
545
|
+
async getResult(executionResultId, signal, language) {
|
|
546
|
+
const rawResult = await getResult(this.http, executionResultId, signal);
|
|
547
|
+
return mapExecutionResult(rawResult, language);
|
|
397
548
|
}
|
|
398
549
|
async runFlow(flowId, input) {
|
|
399
550
|
const { executionResultId } = await this.runFlowAsync(flowId, input);
|
|
@@ -403,9 +554,13 @@ var Docmana = class {
|
|
|
403
554
|
timeoutMs: input.timeoutMs ?? this.config.timeoutMs,
|
|
404
555
|
signal: input.signal
|
|
405
556
|
});
|
|
406
|
-
const result = await this.getResult(executionResultId, input.signal);
|
|
557
|
+
const result = await this.getResult(executionResultId, input.signal, input.language);
|
|
407
558
|
if (result.status === "Failed") {
|
|
408
|
-
throw new DocmanaExecutionError(
|
|
559
|
+
throw new DocmanaExecutionError(
|
|
560
|
+
`Flow ${flowId} execution failed`,
|
|
561
|
+
result.errors ?? [],
|
|
562
|
+
result
|
|
563
|
+
);
|
|
409
564
|
}
|
|
410
565
|
return result;
|
|
411
566
|
}
|
|
@@ -418,6 +573,15 @@ var CliUsageError = class extends Error {
|
|
|
418
573
|
this.name = "CliUsageError";
|
|
419
574
|
}
|
|
420
575
|
};
|
|
576
|
+
var CliSilentError = class extends Error {
|
|
577
|
+
exitCode;
|
|
578
|
+
constructor(exitCode = 1) {
|
|
579
|
+
super();
|
|
580
|
+
this.name = "CliSilentError";
|
|
581
|
+
this.exitCode = exitCode;
|
|
582
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
583
|
+
}
|
|
584
|
+
};
|
|
421
585
|
var HELP = {
|
|
422
586
|
root: "Run Docmana document-analysis flows.",
|
|
423
587
|
flow: "Manage and run Docmana flows.",
|
|
@@ -441,6 +605,9 @@ async function runCli(argv = process.argv.slice(2), env = process.env, io = {
|
|
|
441
605
|
await program.parseAsync(argv, { from: "user" });
|
|
442
606
|
return 0;
|
|
443
607
|
} catch (err) {
|
|
608
|
+
if (err instanceof CliSilentError) {
|
|
609
|
+
return err.exitCode;
|
|
610
|
+
}
|
|
444
611
|
if (err instanceof CliUsageError) {
|
|
445
612
|
io.stderr(`Error: ${err.message}
|
|
446
613
|
`);
|
|
@@ -467,7 +634,7 @@ function buildProgram(env, io, clientFactory, deps) {
|
|
|
467
634
|
const flow = program.command("flow").description(HELP.flow).action(() => {
|
|
468
635
|
io.stdout(flow.helpInformation());
|
|
469
636
|
});
|
|
470
|
-
flow.command("run").description(HELP.run).argument("<flow-id>", "Docmana flow id").requiredOption("--files <csv>", "Comma-separated file paths to upload").option("--client-id <id>", "OAuth2 client id; defaults to DOCMANA_CLIENT_ID").option("--client-secret <secret>", "OAuth2 client secret; defaults to DOCMANA_CLIENT_SECRET").option("--api-url <url>", "Docmana API base URL; defaults to DOCMANA_API_URL").option("--token-url <url>", "OAuth2 token endpoint; defaults to DOCMANA_TOKEN_URL").option("--scope <scope>", "OAuth2 scope; defaults to DOCMANA_SCOPE").option("--organisation <id>", "Docmana organisation id; defaults to DOCMANA_ORGANISATION").option("--config <path>", `Config file path; defaults to ./${DEFAULT_CONFIG_FILE}`).option("--token-cache <path>", `Token cache path; defaults to ./${DEFAULT_TOKEN_CACHE_FILE}`).option("--json", "Print the raw JSON result").action(async (flowId, options) => {
|
|
637
|
+
flow.command("run").description(HELP.run).argument("<flow-id>", "Docmana flow id").requiredOption("--files <csv>", "Comma-separated file paths to upload").option("--client-id <id>", "OAuth2 client id; defaults to DOCMANA_CLIENT_ID").option("--client-secret <secret>", "OAuth2 client secret; defaults to DOCMANA_CLIENT_SECRET").option("--api-url <url>", "Docmana API base URL; defaults to DOCMANA_API_URL").option("--token-url <url>", "OAuth2 token endpoint; defaults to DOCMANA_TOKEN_URL").option("--scope <scope>", "OAuth2 scope; defaults to DOCMANA_SCOPE").option("--organisation <id>", "Docmana organisation id; defaults to DOCMANA_ORGANISATION").option("--config <path>", `Config file path; defaults to ./${DEFAULT_CONFIG_FILE}`).option("--token-cache <path>", `Token cache path; defaults to ./${DEFAULT_TOKEN_CACHE_FILE}`).option("--json", "Print the raw JSON result").option("--language <lang>", "Translate output to specified language").action(async (flowId, options) => {
|
|
471
638
|
await runFlowCommand(flowId, options, env, io, clientFactory, deps);
|
|
472
639
|
});
|
|
473
640
|
const config = program.command("config").description(HELP.config).action(() => {
|
|
@@ -479,50 +646,77 @@ function buildProgram(env, io, clientFactory, deps) {
|
|
|
479
646
|
return program;
|
|
480
647
|
}
|
|
481
648
|
async function runFlowCommand(flowId, options, env, io, clientFactory, deps) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
649
|
+
try {
|
|
650
|
+
const files = parseFiles(options.files);
|
|
651
|
+
const cliConfig = await loadCliConfig(options.config, getCwd(deps), Boolean(options.config));
|
|
652
|
+
const clientId = firstNonEmpty(options.clientId, env.DOCMANA_CLIENT_ID, cliConfig.clientId);
|
|
653
|
+
const clientSecret = firstNonEmpty(
|
|
654
|
+
options.clientSecret,
|
|
655
|
+
env.DOCMANA_CLIENT_SECRET,
|
|
656
|
+
cliConfig.clientSecret
|
|
657
|
+
);
|
|
658
|
+
const organisation = firstNonEmpty(
|
|
659
|
+
options.organisation,
|
|
660
|
+
env.DOCMANA_ORGANISATION,
|
|
661
|
+
cliConfig.organisation
|
|
662
|
+
);
|
|
663
|
+
const apiBaseUrl = firstNonEmpty(options.apiUrl, env.DOCMANA_API_URL, cliConfig.apiBaseUrl);
|
|
664
|
+
const tokenEndpoint = firstNonEmpty(
|
|
665
|
+
options.tokenUrl,
|
|
666
|
+
env.DOCMANA_TOKEN_URL,
|
|
667
|
+
cliConfig.tokenEndpoint
|
|
668
|
+
);
|
|
669
|
+
const scope = firstNonEmpty(options.scope, env.DOCMANA_SCOPE, cliConfig.scope);
|
|
670
|
+
if (!clientId)
|
|
671
|
+
throw new CliUsageError("Missing client id. Use --client-id or DOCMANA_CLIENT_ID.");
|
|
672
|
+
if (!clientSecret) {
|
|
673
|
+
throw new CliUsageError(
|
|
674
|
+
"Missing client secret. Use --client-secret or DOCMANA_CLIENT_SECRET."
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
if (!organisation) {
|
|
678
|
+
throw new CliUsageError("Missing organisation. Use --organisation or DOCMANA_ORGANISATION.");
|
|
679
|
+
}
|
|
680
|
+
const client = clientFactory({
|
|
681
|
+
clientId,
|
|
682
|
+
clientSecret,
|
|
683
|
+
apiBaseUrl,
|
|
684
|
+
tokenEndpoint,
|
|
685
|
+
scope,
|
|
686
|
+
headers: { "X-Selected-Organization": organisation },
|
|
687
|
+
tokenCache: createFileTokenCache(resolveTokenCachePath(options.tokenCache, getCwd(deps)))
|
|
688
|
+
});
|
|
689
|
+
const result = await client.runFlow(flowId, {
|
|
690
|
+
files: files.map((path) => ({ path })),
|
|
691
|
+
language: options.language
|
|
692
|
+
});
|
|
693
|
+
if (options.json) {
|
|
694
|
+
io.stdout(`${JSON.stringify(result, null, 2)}
|
|
695
|
+
`);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
io.stdout(formatHumanResult(result));
|
|
699
|
+
} catch (err) {
|
|
700
|
+
if (options.json) {
|
|
701
|
+
if (err instanceof DocmanaExecutionError && err.result) {
|
|
702
|
+
io.stdout(`${JSON.stringify(err.result, null, 2)}
|
|
703
|
+
`);
|
|
704
|
+
} else {
|
|
705
|
+
const errorPayload = {
|
|
706
|
+
error: err instanceof Error ? err.message : String(err)
|
|
707
|
+
};
|
|
708
|
+
if (err instanceof DocmanaError) {
|
|
709
|
+
errorPayload.code = err.code;
|
|
710
|
+
if (err.status !== void 0) errorPayload.status = err.status;
|
|
711
|
+
if (err.requestId !== void 0) errorPayload.requestId = err.requestId;
|
|
712
|
+
}
|
|
713
|
+
io.stdout(`${JSON.stringify(errorPayload, null, 2)}
|
|
522
714
|
`);
|
|
523
|
-
|
|
715
|
+
}
|
|
716
|
+
throw new CliSilentError(err instanceof CliUsageError ? 2 : 1);
|
|
717
|
+
}
|
|
718
|
+
throw err;
|
|
524
719
|
}
|
|
525
|
-
io.stdout(formatHumanResult(result));
|
|
526
720
|
}
|
|
527
721
|
async function loginCommand(options, env, io, deps) {
|
|
528
722
|
const auth = await resolveAuthConfig(options, env, deps);
|
|
@@ -726,31 +920,141 @@ function firstNonEmpty(...values) {
|
|
|
726
920
|
}
|
|
727
921
|
function formatHumanResult(result) {
|
|
728
922
|
const lines = ["Docmana flow completed", `Status: ${String(result.status ?? "Unknown")}`];
|
|
729
|
-
const executionId = result.
|
|
923
|
+
const executionId = result.executionId;
|
|
730
924
|
if (executionId) lines.push(`Execution id: ${String(executionId)}`);
|
|
731
|
-
if (
|
|
732
|
-
|
|
733
|
-
|
|
925
|
+
if (result.documents && result.documents.mappings) {
|
|
926
|
+
lines.push(`Results: ${result.documents.mappings.length}`);
|
|
927
|
+
}
|
|
928
|
+
if (result.errors && result.errors.length > 0) {
|
|
929
|
+
lines.push(`Errors: ${result.errors.length}`);
|
|
930
|
+
}
|
|
931
|
+
const previewData = {};
|
|
932
|
+
if (result.documents && result.documents.mappings) {
|
|
933
|
+
for (const mapping of result.documents.mappings.slice(0, 3)) {
|
|
934
|
+
const docKey = mapping.reference;
|
|
935
|
+
previewData[mapping.name] = result.documents[docKey];
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
const preview = formatResultsPreview(previewData);
|
|
734
939
|
if (preview) lines.push("", "Result preview:", preview);
|
|
735
940
|
lines.push("", "Use --json to print the complete result payload.");
|
|
736
941
|
return `${lines.join("\n")}
|
|
737
942
|
`;
|
|
738
943
|
}
|
|
739
944
|
function formatResultsPreview(results) {
|
|
740
|
-
if (!
|
|
741
|
-
const preview = JSON.stringify(results
|
|
945
|
+
if (!results) return void 0;
|
|
946
|
+
const preview = JSON.stringify(results, null, 2);
|
|
742
947
|
if (!preview) return void 0;
|
|
743
948
|
return preview.length > 2e3 ? `${preview.slice(0, 2e3)}
|
|
744
949
|
...` : preview;
|
|
745
950
|
}
|
|
746
951
|
function formatRuntimeError(err) {
|
|
952
|
+
return formatHumanError(err);
|
|
953
|
+
}
|
|
954
|
+
function formatHumanError(err) {
|
|
747
955
|
if (err instanceof DocmanaExecutionError) {
|
|
748
|
-
const
|
|
749
|
-
|
|
956
|
+
const lines = [`Error: ${err.message}`];
|
|
957
|
+
if (err.errors && err.errors.length > 0) {
|
|
958
|
+
lines.push("Global errors:");
|
|
959
|
+
for (const e of err.errors) {
|
|
960
|
+
lines.push(` - ${formatSingleError(e)}`);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
const result = err.result;
|
|
964
|
+
if (result) {
|
|
965
|
+
if (result.documents && result.documents.mappings && result.documents.mappings.length > 0) {
|
|
966
|
+
lines.push("Document execution results:");
|
|
967
|
+
for (const mapping of result.documents.mappings) {
|
|
968
|
+
const docKey = mapping.reference;
|
|
969
|
+
const docName = mapping.name;
|
|
970
|
+
const docResult = result.documents[docKey];
|
|
971
|
+
if (docResult) {
|
|
972
|
+
const status = docResult.status || "Unknown";
|
|
973
|
+
const nodes = [];
|
|
974
|
+
if (docResult.classifications) nodes.push(...Object.values(docResult.classifications));
|
|
975
|
+
if (docResult.metadataExtraction) nodes.push(docResult.metadataExtraction);
|
|
976
|
+
if (docResult.extractions) nodes.push(...Object.values(docResult.extractions));
|
|
977
|
+
if (docResult.validations) nodes.push(...Object.values(docResult.validations));
|
|
978
|
+
const hasNodeFailures = nodes.some(
|
|
979
|
+
(n) => n.status === "Failed" || n.errors && n.errors.length > 0
|
|
980
|
+
);
|
|
981
|
+
if (docResult.status === "Failed" || hasNodeFailures) {
|
|
982
|
+
lines.push(` - Document: ${docName} (Status: ${status})`);
|
|
983
|
+
if (docResult.classifications) {
|
|
984
|
+
for (const [nodeName, node] of Object.entries(docResult.classifications)) {
|
|
985
|
+
if (node.errors && node.errors.length > 0) {
|
|
986
|
+
lines.push(` Classification: ${nodeName} (Status: ${node.status})`);
|
|
987
|
+
for (const nodeErr of node.errors) {
|
|
988
|
+
lines.push(` - ${nodeErr}`);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
if (docResult.metadataExtraction?.errors && docResult.metadataExtraction.errors.length > 0) {
|
|
994
|
+
lines.push(
|
|
995
|
+
` MetadataExtraction: (Status: ${docResult.metadataExtraction.status})`
|
|
996
|
+
);
|
|
997
|
+
for (const nodeErr of docResult.metadataExtraction.errors) {
|
|
998
|
+
lines.push(` - ${nodeErr}`);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
if (docResult.extractions) {
|
|
1002
|
+
for (const [nodeName, node] of Object.entries(docResult.extractions)) {
|
|
1003
|
+
if (node.status === "Failed" || node.errors && node.errors.length > 0) {
|
|
1004
|
+
lines.push(` Extraction: ${nodeName} (Status: ${node.status})`);
|
|
1005
|
+
if (node.errors) {
|
|
1006
|
+
for (const nodeErr of node.errors) {
|
|
1007
|
+
lines.push(` - ${nodeErr}`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
if (docResult.validations) {
|
|
1014
|
+
for (const [nodeName, node] of Object.entries(docResult.validations)) {
|
|
1015
|
+
if (node.status === "Failed" || node.errors && node.errors.length > 0) {
|
|
1016
|
+
lines.push(` Validation: ${nodeName} (Status: ${node.status})`);
|
|
1017
|
+
if (node.errors) {
|
|
1018
|
+
for (const nodeErr of node.errors) {
|
|
1019
|
+
lines.push(` - ${nodeErr}`);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
} else {
|
|
1026
|
+
lines.push(` - Document: ${docName} (Status: ${status})`);
|
|
1027
|
+
}
|
|
1028
|
+
} else {
|
|
1029
|
+
lines.push(` - Document: ${docName} (Status: Unknown)`);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
return lines.join("\n");
|
|
1035
|
+
}
|
|
1036
|
+
if (err instanceof DocmanaError) {
|
|
1037
|
+
return `Error: ${err.message} (Code: ${err.code})`;
|
|
1038
|
+
}
|
|
1039
|
+
if (err instanceof Error) {
|
|
1040
|
+
return `Error: ${err.message}`;
|
|
1041
|
+
}
|
|
1042
|
+
return `Error: ${String(err)}`;
|
|
1043
|
+
}
|
|
1044
|
+
function formatSingleError(e) {
|
|
1045
|
+
if (typeof e === "string") return e;
|
|
1046
|
+
if (e && typeof e === "object") {
|
|
1047
|
+
const obj = e;
|
|
1048
|
+
if (typeof obj.msg === "string") return obj.msg;
|
|
1049
|
+
if (typeof obj.message === "string") return obj.message;
|
|
1050
|
+
if (typeof obj.error === "string") return obj.error;
|
|
1051
|
+
try {
|
|
1052
|
+
return JSON.stringify(e);
|
|
1053
|
+
} catch {
|
|
1054
|
+
return String(e);
|
|
1055
|
+
}
|
|
750
1056
|
}
|
|
751
|
-
|
|
752
|
-
if (err instanceof Error) return err.message;
|
|
753
|
-
return "Unexpected error";
|
|
1057
|
+
return String(e);
|
|
754
1058
|
}
|
|
755
1059
|
function isDirectRun() {
|
|
756
1060
|
const entry = process.argv[1];
|