@yadsh/dsh-qa-surface 0.6.0 → 0.7.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 +148 -9
- package/capability-policy.json +1 -1
- package/cordis.patch.yml +2 -1
- package/lib/access/capability-catalog.js +144 -0
- package/lib/access/capability-catalog.js.map +1 -0
- package/lib/access/model.js +379 -0
- package/lib/access/model.js.map +1 -0
- package/lib/access/role-repository.js +195 -0
- package/lib/access/role-repository.js.map +1 -0
- package/lib/access/service.js +380 -0
- package/lib/access/service.js.map +1 -0
- package/lib/access/skill-metadata.js +234 -0
- package/lib/access/skill-metadata.js.map +1 -0
- package/lib/account-remotes.js +20 -10
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +202 -3
- package/lib/accounts/store.js.map +1 -1
- package/lib/admin/conversation-log.js +256 -0
- package/lib/admin/conversation-log.js.map +1 -0
- package/lib/admin/index.js +17 -0
- package/lib/admin/index.js.map +1 -0
- package/lib/admin/metrics.js +103 -0
- package/lib/admin/metrics.js.map +1 -0
- package/lib/admin/paging.js +23 -0
- package/lib/admin/paging.js.map +1 -0
- package/lib/admin/permissions.js +50 -0
- package/lib/admin/permissions.js.map +1 -0
- package/lib/admin/quality-store.js +485 -0
- package/lib/admin/quality-store.js.map +1 -0
- package/lib/admin/queue.js +107 -0
- package/lib/admin/queue.js.map +1 -0
- package/lib/admin/redaction.js +45 -0
- package/lib/admin/redaction.js.map +1 -0
- package/lib/admin/service.js +897 -0
- package/lib/admin/service.js.map +1 -0
- package/lib/admin/session-log.js +142 -0
- package/lib/admin/session-log.js.map +1 -0
- package/lib/attestation.js +6 -0
- package/lib/attestation.js.map +1 -1
- package/lib/cli.js +9 -6
- package/lib/cli.js.map +1 -1
- package/lib/client/QaSessionController.js +65 -15
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +144 -6
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +1 -0
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +458 -0
- package/lib/client/admin/QaAdmin.js.map +1 -0
- package/lib/client/admin/format.js +177 -0
- package/lib/client/admin/format.js.map +1 -0
- package/lib/client/admin/pages/Conversations.js +114 -0
- package/lib/client/admin/pages/Conversations.js.map +1 -0
- package/lib/client/admin/pages/Overview.js +24 -0
- package/lib/client/admin/pages/Overview.js.map +1 -0
- package/lib/client/admin/pages/Quality.js +71 -0
- package/lib/client/admin/pages/Quality.js.map +1 -0
- package/lib/client/admin/pages/Review.js +93 -0
- package/lib/client/admin/pages/Review.js.map +1 -0
- package/lib/client/admin/pages/Users.js +95 -0
- package/lib/client/admin/pages/Users.js.map +1 -0
- package/lib/client/admin/routes.js +127 -0
- package/lib/client/admin/routes.js.map +1 -0
- package/lib/client/admin/shared.js +91 -0
- package/lib/client/admin/shared.js.map +1 -0
- package/lib/client/admin/styles.js +111 -0
- package/lib/client/admin/styles.js.map +1 -0
- package/lib/client/attestation.js +14 -2
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/components/QaChangelog.js +48 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaHeader.js +3 -3
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +61 -2
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/create-session.js +1 -1
- package/lib/client/create-session.js.map +1 -1
- package/lib/client/index.js +33 -1
- package/lib/client/index.js.map +1 -1
- package/lib/client/project-session-state.js +10 -5
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/role/RoleSelector.js +31 -0
- package/lib/client/role/RoleSelector.js.map +1 -0
- package/lib/client/session-sources.js +37 -1
- package/lib/client/session-sources.js.map +1 -1
- package/lib/client/settings/card.js +2 -2
- package/lib/client/settings/card.js.map +1 -1
- package/lib/client/settings/sections.js +0 -1
- package/lib/client/settings/sections.js.map +1 -1
- package/lib/client/styles.js +32 -0
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js +1 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client.js +10786 -5684
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/defaults.js +0 -2
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config.js +0 -249
- package/lib/config.js.map +1 -1
- package/lib/enforcement/skill-policy.js +172 -0
- package/lib/enforcement/skill-policy.js.map +1 -0
- package/lib/enforcement/tool-grants.js +151 -0
- package/lib/enforcement/tool-grants.js.map +1 -0
- package/lib/index.js +230 -44
- package/lib/index.js.map +1 -1
- package/lib/personal-skills/service.js +10 -3
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/qa-tools/index.js +4 -0
- package/lib/qa-tools/index.js.map +1 -1
- package/lib/resolve-config.js +0 -2
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +111 -32
- package/lib/secure-session.js.map +1 -1
- package/lib/typert.host.js +2237 -202
- package/lib/typert.remote-client.d.ts +49 -3
- package/lib/typert.remote-client.js +1863 -183
- package/lib/types/access/capability-catalog.d.ts +37 -0
- package/lib/types/access/model.d.ts +60 -0
- package/lib/types/access/role-repository.d.ts +32 -0
- package/lib/types/access/service.d.ts +57 -0
- package/lib/types/access/skill-metadata.d.ts +53 -0
- package/lib/types/account-remotes.d.ts +6 -0
- package/lib/types/accounts/errors.d.ts +1 -1
- package/lib/types/accounts/file.d.ts +16 -5
- package/lib/types/accounts/store.d.ts +83 -3
- package/lib/types/admin/conversation-log.d.ts +39 -0
- package/lib/types/admin/index.d.ts +24 -0
- package/lib/types/admin/metrics.d.ts +29 -0
- package/lib/types/admin/paging.d.ts +33 -0
- package/lib/types/admin/permissions.d.ts +10 -0
- package/lib/types/admin/quality-store.d.ts +82 -0
- package/lib/types/admin/queue.d.ts +21 -0
- package/lib/types/admin/redaction.d.ts +29 -0
- package/lib/types/admin/service.d.ts +105 -0
- package/lib/types/admin/session-log.d.ts +53 -0
- package/lib/types/attestation.d.ts +2 -0
- package/lib/types/client/QaSessionController.d.ts +14 -1
- package/lib/types/client/QaSurface.d.ts +7 -1
- package/lib/types/client/admin/QaAdmin.d.ts +17 -0
- package/lib/types/client/admin/format.d.ts +43 -0
- package/lib/types/client/admin/pages/Conversations.d.ts +21 -0
- package/lib/types/client/admin/pages/Overview.d.ts +13 -0
- package/lib/types/client/admin/pages/Quality.d.ts +18 -0
- package/lib/types/client/admin/pages/Review.d.ts +15 -0
- package/lib/types/client/admin/pages/Users.d.ts +22 -0
- package/lib/types/client/admin/routes.d.ts +50 -0
- package/lib/types/client/admin/shared.d.ts +53 -0
- package/lib/types/client/admin/styles.d.ts +11 -0
- package/lib/types/client/attestation.d.ts +8 -1
- package/lib/types/client/components/QaHeader.d.ts +5 -1
- package/lib/types/client/components/QaMessage.d.ts +14 -1
- package/lib/types/client/create-session.d.ts +2 -0
- package/lib/types/client/project-session-state.d.ts +2 -0
- package/lib/types/client/role/RoleSelector.d.ts +14 -0
- package/lib/types/client/session-sources.d.ts +9 -0
- package/lib/types/client/settings/sections.d.ts +0 -1
- package/lib/types/client/types.d.ts +39 -2
- package/lib/types/enforcement/skill-policy.d.ts +29 -0
- package/lib/types/enforcement/tool-grants.d.ts +84 -0
- package/lib/types/index.d.ts +62 -14
- package/lib/types/qa-tools/index.d.ts +2 -0
- package/lib/types/secure-session.d.ts +19 -1
- package/lib/types/types.d.ts +574 -5
- package/package.json +3 -3
- package/lib/client/settings/sections/documents.js +0 -88
- package/lib/client/settings/sections/documents.js.map +0 -1
- package/lib/documents/artifacts/ids.js +0 -43
- package/lib/documents/artifacts/ids.js.map +0 -1
- package/lib/documents/artifacts/manifest.js +0 -66
- package/lib/documents/artifacts/manifest.js.map +0 -1
- package/lib/documents/artifacts/store.js +0 -169
- package/lib/documents/artifacts/store.js.map +0 -1
- package/lib/documents/capabilities.js +0 -93
- package/lib/documents/capabilities.js.map +0 -1
- package/lib/documents/config.js +0 -302
- package/lib/documents/config.js.map +0 -1
- package/lib/documents/defaults.js +0 -78
- package/lib/documents/defaults.js.map +0 -1
- package/lib/documents/errors.js +0 -101
- package/lib/documents/errors.js.map +0 -1
- package/lib/documents/index.js +0 -80
- package/lib/documents/index.js.map +0 -1
- package/lib/documents/inspect/facts.js +0 -161
- package/lib/documents/inspect/facts.js.map +0 -1
- package/lib/documents/inspect/zip.js +0 -108
- package/lib/documents/inspect/zip.js.map +0 -1
- package/lib/documents/markdown/directives.js +0 -135
- package/lib/documents/markdown/directives.js.map +0 -1
- package/lib/documents/markdown/frontmatter.js +0 -35
- package/lib/documents/markdown/frontmatter.js.map +0 -1
- package/lib/documents/markdown/normalize.js +0 -113
- package/lib/documents/markdown/normalize.js.map +0 -1
- package/lib/documents/orchestrator/assets.js +0 -243
- package/lib/documents/orchestrator/assets.js.map +0 -1
- package/lib/documents/orchestrator/convert-document.js +0 -186
- package/lib/documents/orchestrator/convert-document.js.map +0 -1
- package/lib/documents/orchestrator/create-document.js +0 -292
- package/lib/documents/orchestrator/create-document.js.map +0 -1
- package/lib/documents/orchestrator/extract-document.js +0 -162
- package/lib/documents/orchestrator/extract-document.js.map +0 -1
- package/lib/documents/orchestrator/inspect-document.js +0 -89
- package/lib/documents/orchestrator/inspect-document.js.map +0 -1
- package/lib/documents/orchestrator/runtime-deps.js +0 -59
- package/lib/documents/orchestrator/runtime-deps.js.map +0 -1
- package/lib/documents/orchestrator/scope.js +0 -132
- package/lib/documents/orchestrator/scope.js.map +0 -1
- package/lib/documents/providers/docling.js +0 -247
- package/lib/documents/providers/docling.js.map +0 -1
- package/lib/documents/providers/libreoffice.js +0 -130
- package/lib/documents/providers/libreoffice.js.map +0 -1
- package/lib/documents/providers/markitdown.js +0 -89
- package/lib/documents/providers/markitdown.js.map +0 -1
- package/lib/documents/providers/pandoc.js +0 -161
- package/lib/documents/providers/pandoc.js.map +0 -1
- package/lib/documents/providers/process.js +0 -164
- package/lib/documents/providers/process.js.map +0 -1
- package/lib/documents/providers/registry.js +0 -152
- package/lib/documents/providers/registry.js.map +0 -1
- package/lib/documents/providers/shared.js +0 -75
- package/lib/documents/providers/shared.js.map +0 -1
- package/lib/documents/runtime.js +0 -114
- package/lib/documents/runtime.js.map +0 -1
- package/lib/documents/security/file-types.js +0 -188
- package/lib/documents/security/file-types.js.map +0 -1
- package/lib/documents/security/limits.js +0 -78
- package/lib/documents/security/limits.js.map +0 -1
- package/lib/documents/security/mime.js +0 -43
- package/lib/documents/security/mime.js.map +0 -1
- package/lib/documents/security/paths.js +0 -133
- package/lib/documents/security/paths.js.map +0 -1
- package/lib/documents/templates/registry.js +0 -147
- package/lib/documents/templates/registry.js.map +0 -1
- package/lib/documents/templates/resolver.js +0 -59
- package/lib/documents/templates/resolver.js.map +0 -1
- package/lib/documents/tools/convert.js +0 -125
- package/lib/documents/tools/convert.js.map +0 -1
- package/lib/documents/tools/create.js +0 -187
- package/lib/documents/tools/create.js.map +0 -1
- package/lib/documents/tools/index.js +0 -41
- package/lib/documents/tools/index.js.map +0 -1
- package/lib/documents/tools/inspect.js +0 -135
- package/lib/documents/tools/inspect.js.map +0 -1
- package/lib/documents/tools/shared.js +0 -88
- package/lib/documents/tools/shared.js.map +0 -1
- package/lib/documents/tools/to-markdown.js +0 -125
- package/lib/documents/tools/to-markdown.js.map +0 -1
- package/lib/documents/types.js +0 -12
- package/lib/documents/types.js.map +0 -1
- package/lib/types/client/settings/sections/documents.d.ts +0 -13
- package/lib/types/documents/artifacts/ids.d.ts +0 -14
- package/lib/types/documents/artifacts/manifest.d.ts +0 -32
- package/lib/types/documents/artifacts/store.d.ts +0 -67
- package/lib/types/documents/capabilities.d.ts +0 -32
- package/lib/types/documents/config.d.ts +0 -27
- package/lib/types/documents/defaults.d.ts +0 -161
- package/lib/types/documents/errors.d.ts +0 -42
- package/lib/types/documents/index.d.ts +0 -63
- package/lib/types/documents/inspect/facts.d.ts +0 -43
- package/lib/types/documents/inspect/zip.d.ts +0 -28
- package/lib/types/documents/markdown/directives.d.ts +0 -39
- package/lib/types/documents/markdown/frontmatter.d.ts +0 -15
- package/lib/types/documents/markdown/normalize.d.ts +0 -30
- package/lib/types/documents/orchestrator/assets.d.ts +0 -55
- package/lib/types/documents/orchestrator/convert-document.d.ts +0 -25
- package/lib/types/documents/orchestrator/create-document.d.ts +0 -18
- package/lib/types/documents/orchestrator/extract-document.d.ts +0 -24
- package/lib/types/documents/orchestrator/inspect-document.d.ts +0 -12
- package/lib/types/documents/orchestrator/runtime-deps.d.ts +0 -43
- package/lib/types/documents/orchestrator/scope.d.ts +0 -52
- package/lib/types/documents/providers/docling.d.ts +0 -54
- package/lib/types/documents/providers/libreoffice.d.ts +0 -40
- package/lib/types/documents/providers/markitdown.d.ts +0 -28
- package/lib/types/documents/providers/pandoc.d.ts +0 -42
- package/lib/types/documents/providers/process.d.ts +0 -54
- package/lib/types/documents/providers/registry.d.ts +0 -68
- package/lib/types/documents/providers/shared.d.ts +0 -27
- package/lib/types/documents/runtime.d.ts +0 -59
- package/lib/types/documents/security/file-types.d.ts +0 -39
- package/lib/types/documents/security/limits.d.ts +0 -24
- package/lib/types/documents/security/mime.d.ts +0 -13
- package/lib/types/documents/security/paths.d.ts +0 -38
- package/lib/types/documents/templates/registry.d.ts +0 -50
- package/lib/types/documents/templates/resolver.d.ts +0 -30
- package/lib/types/documents/tools/convert.d.ts +0 -9
- package/lib/types/documents/tools/create.d.ts +0 -14
- package/lib/types/documents/tools/index.d.ts +0 -33
- package/lib/types/documents/tools/inspect.d.ts +0 -9
- package/lib/types/documents/tools/shared.d.ts +0 -77
- package/lib/types/documents/tools/to-markdown.d.ts +0 -12
- package/lib/types/documents/types.d.ts +0 -294
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Job scope: where an operation reads from and writes to.
|
|
3
|
-
*
|
|
4
|
-
* Artifacts live in the session workspace by default
|
|
5
|
-
* (`<cwd>/.qa/artifacts/documents/<artifact-id>`), which is what makes a QA
|
|
6
|
-
* deployment's per-user workspaces isolate document bundles for free (§40).
|
|
7
|
-
* A deployment may pin `documents.storage.root` to a shared volume instead, in
|
|
8
|
-
* which case the session workspace stays the only place inputs are read from.
|
|
9
|
-
* Inputs may additionally come from explicitly configured roots (§26.2).
|
|
10
|
-
*/
|
|
11
|
-
import { readFile, stat } from "node:fs/promises";
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
import { ArtifactStore } from "../artifacts/store.js";
|
|
14
|
-
import { DocumentError, asDocumentError } from "../errors.js";
|
|
15
|
-
import { assertBytesWithinBudget } from "../security/limits.js";
|
|
16
|
-
import { canonicalizeForContainment, isInsideRoot, resolveInsideRoot, } from "../security/paths.js";
|
|
17
|
-
import { loadTemplateRegistry, } from "../templates/registry.js";
|
|
18
|
-
/** Artifact root of one workspace: configured root, else the workspace itself. */
|
|
19
|
-
export function defaultArtifactRoot(config, workspaceRoot) {
|
|
20
|
-
return (config.storage.root ??
|
|
21
|
-
path.join(workspaceRoot, ".qa", "artifacts", "documents"));
|
|
22
|
-
}
|
|
23
|
-
async function probeManifest(candidate) {
|
|
24
|
-
const details = await stat(path.join(candidate, "manifest.yml")).catch(() => undefined);
|
|
25
|
-
return details?.isFile() === true;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Template roots to probe, in order. An explicitly configured root is
|
|
29
|
-
* authoritative; a deployment that configures none gets the two conventional
|
|
30
|
-
* workspace directories.
|
|
31
|
-
*/
|
|
32
|
-
export function templateCandidateRoots(config, workspaceRoot) {
|
|
33
|
-
if (config.templates.root !== null)
|
|
34
|
-
return [config.templates.root];
|
|
35
|
-
return [
|
|
36
|
-
path.join(workspaceRoot, "document-templates"),
|
|
37
|
-
path.join(workspaceRoot, "templates"),
|
|
38
|
-
];
|
|
39
|
-
}
|
|
40
|
-
/** Load the first candidate root that carries a registry manifest. */
|
|
41
|
-
export async function loadScopeTemplates(config, workspaceRoot) {
|
|
42
|
-
for (const candidate of templateCandidateRoots(config, workspaceRoot)) {
|
|
43
|
-
if (await probeManifest(candidate))
|
|
44
|
-
return await loadTemplateRegistry(candidate);
|
|
45
|
-
}
|
|
46
|
-
return await loadTemplateRegistry(undefined);
|
|
47
|
-
}
|
|
48
|
-
export async function resolveDocumentScope(config, scope) {
|
|
49
|
-
if (typeof scope.workspaceRoot !== "string" ||
|
|
50
|
-
scope.workspaceRoot.trim() === "") {
|
|
51
|
-
// Fail closed: an empty root would silently resolve to the host process's
|
|
52
|
-
// working directory and grant artifacts access to it.
|
|
53
|
-
throw new DocumentError("INVALID_INPUT", "the document scope requires a session working directory");
|
|
54
|
-
}
|
|
55
|
-
const workspaceRoot = await canonicalizeForContainment(scope.workspaceRoot);
|
|
56
|
-
const artifactRoot = await canonicalizeForContainment(defaultArtifactRoot(config, workspaceRoot));
|
|
57
|
-
return {
|
|
58
|
-
workspaceRoot,
|
|
59
|
-
artifactRoot,
|
|
60
|
-
...(scope.sessionId === undefined ? {} : { sessionId: scope.sessionId }),
|
|
61
|
-
...(scope.signal === undefined ? {} : { signal: scope.signal }),
|
|
62
|
-
store: new ArtifactStore({ root: artifactRoot }),
|
|
63
|
-
templates: await loadScopeTemplates(config, workspaceRoot),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
/** Roots an input file may be read from, most specific first. */
|
|
67
|
-
export function allowedInputRoots(config, scope) {
|
|
68
|
-
return [
|
|
69
|
-
scope.workspaceRoot,
|
|
70
|
-
scope.artifactRoot,
|
|
71
|
-
...config.storage.allowedInputRoots,
|
|
72
|
-
];
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Resolve a caller-supplied input path. The file must exist inside one of the
|
|
76
|
-
* allowed roots — traversal, symlinks out of the root and absolute paths to
|
|
77
|
-
* unrelated directories are all refused (§26.2).
|
|
78
|
-
*/
|
|
79
|
-
export async function resolveInputPath(config, scope, requested, label) {
|
|
80
|
-
let lastError;
|
|
81
|
-
for (const root of allowedInputRoots(config, scope)) {
|
|
82
|
-
try {
|
|
83
|
-
const resolved = await resolveInsideRoot(root, requested, label);
|
|
84
|
-
const details = await stat(resolved).catch(() => undefined);
|
|
85
|
-
if (details === undefined || !details.isFile()) {
|
|
86
|
-
throw new DocumentError("FILE_NOT_FOUND", `${label} does not exist`);
|
|
87
|
-
}
|
|
88
|
-
return resolved;
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
lastError = error;
|
|
92
|
-
if (error instanceof DocumentError && error.code === "FILE_NOT_FOUND")
|
|
93
|
-
continue;
|
|
94
|
-
if (error instanceof DocumentError && error.code === "PATH_NOT_ALLOWED")
|
|
95
|
-
continue;
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (lastError instanceof DocumentError) {
|
|
100
|
-
throw new DocumentError("FILE_NOT_FOUND", `${label} is not a file inside the session workspace or a configured document root`, { details: { label } });
|
|
101
|
-
}
|
|
102
|
-
throw asDocumentError(lastError, "FILE_NOT_FOUND");
|
|
103
|
-
}
|
|
104
|
-
/** Read an input file under a byte budget. */
|
|
105
|
-
export async function readInputBytes(filePath, config, label) {
|
|
106
|
-
const details = await stat(filePath).catch(() => undefined);
|
|
107
|
-
if (details === undefined) {
|
|
108
|
-
throw new DocumentError("FILE_NOT_FOUND", `${label} does not exist`);
|
|
109
|
-
}
|
|
110
|
-
assertBytesWithinBudget(details.size, config.limits.maxInputBytes, label);
|
|
111
|
-
const bytes = await readFile(filePath).catch((error) => {
|
|
112
|
-
throw asDocumentError(error, "FILE_NOT_FOUND", label);
|
|
113
|
-
});
|
|
114
|
-
assertBytesWithinBudget(bytes.length, config.limits.maxInputBytes, label);
|
|
115
|
-
return bytes;
|
|
116
|
-
}
|
|
117
|
-
/** Ensure the artifact root exists and is writable, failing with a clear code. */
|
|
118
|
-
export async function ensureArtifactRoot(scope) {
|
|
119
|
-
try {
|
|
120
|
-
await scope.store.ensureDir(".");
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
throw asDocumentError(error, "ARTIFACT_WRITE_FAILED");
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
export function assertInsideArtifactRoot(scope, target, label) {
|
|
127
|
-
if (!isInsideRoot(scope.artifactRoot, path.resolve(target))) {
|
|
128
|
-
throw new DocumentError("PATH_NOT_ALLOWED", `${label} is outside the artifact root`);
|
|
129
|
-
}
|
|
130
|
-
return target;
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=scope.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../../src/documents/orchestrator/scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Docling provider — the default DOCX/PDF → Markdown extractor (§6.1, §15).
|
|
3
|
-
*
|
|
4
|
-
* Docling runs as a separate HTTP service (`docling-serve`) rather than inside
|
|
5
|
-
* the host process: it is the heaviest dependency of the pipeline, it is where
|
|
6
|
-
* OCR happens, and keeping it across a network boundary is what lets the QA
|
|
7
|
-
* image stay small (§21, §39).
|
|
8
|
-
*
|
|
9
|
-
* Two behaviours are deliberate:
|
|
10
|
-
*
|
|
11
|
-
* - images come back inline as base64 data URIs (the only representation that
|
|
12
|
-
* survives an HTTP boundary without a second fetch), and the extractor writes
|
|
13
|
-
* them out as real files under `assets/`, rewriting references to relative
|
|
14
|
-
* paths (§17.2);
|
|
15
|
-
* - nothing about the response shape is assumed beyond "there is Markdown
|
|
16
|
-
* somewhere in it": a deployment upgrades docling-serve independently of
|
|
17
|
-
* this plugin, so both the wrapped (`document.md_content`) and flat
|
|
18
|
-
* (`md_content`) spellings are read.
|
|
19
|
-
*/
|
|
20
|
-
import { mkdir } from "node:fs/promises";
|
|
21
|
-
import path from "node:path";
|
|
22
|
-
import { DocumentError, sanitizeBackendOutput } from "../errors.js";
|
|
23
|
-
import { backendInfo } from "./shared.js";
|
|
24
|
-
const HEALTH_TIMEOUT_MS = 5_000;
|
|
25
|
-
const DATA_URI_PATTERN = /!\[([^\]]*)\]\(data:image\/(png|jpe?g|gif|webp|bmp|tiff);base64,([A-Za-z0-9+/=\s]+)\)/gu;
|
|
26
|
-
const EXTENSION_BY_MIME = {
|
|
27
|
-
png: "png",
|
|
28
|
-
jpg: "jpeg",
|
|
29
|
-
jpeg: "jpeg",
|
|
30
|
-
gif: "gif",
|
|
31
|
-
webp: "webp",
|
|
32
|
-
bmp: "bmp",
|
|
33
|
-
tiff: "tiff",
|
|
34
|
-
};
|
|
35
|
-
function joinUrl(baseUrl, route) {
|
|
36
|
-
const trimmed = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
37
|
-
return `${trimmed}${route}`;
|
|
38
|
-
}
|
|
39
|
-
export class DoclingExtractor {
|
|
40
|
-
options;
|
|
41
|
-
name = "docling";
|
|
42
|
-
constructor(options) {
|
|
43
|
-
this.options = options;
|
|
44
|
-
}
|
|
45
|
-
supports(_format) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
get fetchImpl() {
|
|
49
|
-
return this.options.fetchImpl ?? fetch;
|
|
50
|
-
}
|
|
51
|
-
async health() {
|
|
52
|
-
for (const route of ["/health", "/v1/health"]) {
|
|
53
|
-
try {
|
|
54
|
-
const response = await this.fetchImpl(joinUrl(this.options.baseUrl, route), {
|
|
55
|
-
method: "GET",
|
|
56
|
-
signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS),
|
|
57
|
-
});
|
|
58
|
-
if (response.ok)
|
|
59
|
-
return "ok";
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return "unavailable";
|
|
66
|
-
}
|
|
67
|
-
async extract(input) {
|
|
68
|
-
const warnings = [];
|
|
69
|
-
const body = new FormData();
|
|
70
|
-
const file = await import("node:fs/promises").then((fs) => fs.readFile(input.inputPath));
|
|
71
|
-
body.append("files", new Blob([new Uint8Array(file)], { type: "application/octet-stream" }), path.basename(input.inputPath));
|
|
72
|
-
body.append("to_formats", "md");
|
|
73
|
-
body.append("image_export_mode", input.extractImages ? "embedded" : "placeholder");
|
|
74
|
-
body.append("abort_on_error", "false");
|
|
75
|
-
if (input.extractTables)
|
|
76
|
-
body.append("table_mode", "accurate");
|
|
77
|
-
if (input.ocr === "force") {
|
|
78
|
-
body.append("do_ocr", "true");
|
|
79
|
-
body.append("force_ocr", "true");
|
|
80
|
-
warnings.push({
|
|
81
|
-
code: "OCR_USED",
|
|
82
|
-
message: "Document was processed using OCR.",
|
|
83
|
-
backend: this.name,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
else if (input.ocr === "off") {
|
|
87
|
-
body.append("do_ocr", "false");
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
// Let Docling decide per page; the service turns OCR on for pages that
|
|
91
|
-
// carry no text layer.
|
|
92
|
-
body.append("do_ocr", "true");
|
|
93
|
-
body.append("force_ocr", "false");
|
|
94
|
-
}
|
|
95
|
-
for (const language of input.ocrLanguages ?? []) {
|
|
96
|
-
const clean = language.trim();
|
|
97
|
-
if (clean !== "")
|
|
98
|
-
body.append("ocr_lang", clean);
|
|
99
|
-
}
|
|
100
|
-
let response;
|
|
101
|
-
try {
|
|
102
|
-
response = await this.fetchImpl(joinUrl(this.options.baseUrl, "/v1/convert/file"), {
|
|
103
|
-
method: "POST",
|
|
104
|
-
body,
|
|
105
|
-
signal: input.signal ?? AbortSignal.timeout(this.options.timeoutMs),
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
catch (error) {
|
|
109
|
-
const aborted = input.signal?.aborted === true;
|
|
110
|
-
throw new DocumentError(aborted ? "BACKEND_TIMEOUT" : "BACKEND_UNAVAILABLE", aborted
|
|
111
|
-
? "the document extractor was cancelled"
|
|
112
|
-
: `the document extractor is unreachable: ${sanitizeBackendOutput(error instanceof Error ? error.message : String(error))}`, { backend: this.name, cause: error });
|
|
113
|
-
}
|
|
114
|
-
if (!response.ok) {
|
|
115
|
-
const detail = sanitizeBackendOutput(await response.text().catch(() => ""));
|
|
116
|
-
throw new DocumentError(response.status === 503 ? "BACKEND_UNAVAILABLE" : "EXTRACTION_FAILED", `the document extractor answered ${response.status}${detail === "" ? "" : `: ${detail}`}`, { backend: this.name, details: { status: response.status } });
|
|
117
|
-
}
|
|
118
|
-
const raw = await response.text();
|
|
119
|
-
if (raw.length > this.options.maxResponseBytes) {
|
|
120
|
-
throw new DocumentError("DOCUMENT_TOO_LARGE", "the extracted document exceeds the configured response budget", { backend: this.name, details: { bytes: raw.length } });
|
|
121
|
-
}
|
|
122
|
-
let payload;
|
|
123
|
-
try {
|
|
124
|
-
payload = JSON.parse(raw);
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
throw new DocumentError("EXTRACTION_FAILED", "the document extractor returned a response that is not JSON", { backend: this.name, cause: error });
|
|
128
|
-
}
|
|
129
|
-
const { markdown, pages, serviceVersion } = readDoclingPayload(payload, this.name);
|
|
130
|
-
const { text, assets } = await this.materializeAssets(markdown, input.assetsDir, input.extractImages, warnings);
|
|
131
|
-
if (input.preservePageMarkers && !/\f/u.test(text)) {
|
|
132
|
-
warnings.push({
|
|
133
|
-
code: "METADATA_PARTIALLY_EXTRACTED",
|
|
134
|
-
message: "the extractor reported no page boundaries for this document",
|
|
135
|
-
backend: this.name,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
markdown: text,
|
|
140
|
-
assets,
|
|
141
|
-
...(pages === undefined ? {} : { pages }),
|
|
142
|
-
backend: backendInfo(this.name, serviceVersion),
|
|
143
|
-
warnings,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Write inline images out as files and rewrite the Markdown to reference
|
|
148
|
-
* them relatively. Images beyond the configured cap are dropped with a
|
|
149
|
-
* warning rather than silently inflating the artifact (§25).
|
|
150
|
-
*/
|
|
151
|
-
async materializeAssets(markdown, assetsDir, extractImages, warnings) {
|
|
152
|
-
const matches = [...markdown.matchAll(DATA_URI_PATTERN)];
|
|
153
|
-
if (matches.length === 0) {
|
|
154
|
-
if (extractImages && markdown.includes("data:image/")) {
|
|
155
|
-
warnings.push({
|
|
156
|
-
code: "IMAGE_SKIPPED",
|
|
157
|
-
message: "images reported by the extractor could not be decoded",
|
|
158
|
-
backend: this.name,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
return { text: markdown, assets: [] };
|
|
162
|
-
}
|
|
163
|
-
await mkdir(assetsDir, { recursive: true });
|
|
164
|
-
const assets = [];
|
|
165
|
-
const replacements = new Map();
|
|
166
|
-
let index = 0;
|
|
167
|
-
let skipped = 0;
|
|
168
|
-
const { writeFile } = await import("node:fs/promises");
|
|
169
|
-
for (const match of matches) {
|
|
170
|
-
const [full, alt = "", mime = "png", base64 = ""] = match;
|
|
171
|
-
if (index >= this.options.maxImages) {
|
|
172
|
-
skipped += 1;
|
|
173
|
-
replacements.set(full, alt);
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
const extension = EXTENSION_BY_MIME[mime.toLowerCase()] ?? "bin";
|
|
177
|
-
const fileName = `image-${String(index + 1).padStart(3, "0")}.${extension}`;
|
|
178
|
-
const payload = Buffer.from(base64.replace(/\s+/gu, ""), "base64");
|
|
179
|
-
if (payload.length === 0) {
|
|
180
|
-
skipped += 1;
|
|
181
|
-
replacements.set(full, alt);
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
await writeFile(path.join(assetsDir, fileName), payload);
|
|
185
|
-
assets.push({
|
|
186
|
-
path: fileName,
|
|
187
|
-
mediaType: `image/${extension === "jpg" ? "jpeg" : extension}`,
|
|
188
|
-
});
|
|
189
|
-
replacements.set(full, ``);
|
|
190
|
-
index += 1;
|
|
191
|
-
}
|
|
192
|
-
let text = markdown;
|
|
193
|
-
for (const [from, to] of replacements) {
|
|
194
|
-
text = text.split(from).join(to);
|
|
195
|
-
}
|
|
196
|
-
if (skipped > 0) {
|
|
197
|
-
warnings.push({
|
|
198
|
-
code: "IMAGE_SKIPPED",
|
|
199
|
-
message: `${skipped} image(s) were left out: the configured image budget is ${this.options.maxImages}`,
|
|
200
|
-
backend: this.name,
|
|
201
|
-
details: { skipped },
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
if (!extractImages && assets.length > 0) {
|
|
205
|
-
warnings.push({
|
|
206
|
-
code: "IMAGE_SKIPPED",
|
|
207
|
-
message: "extracted images were written anyway; extraction asked for none",
|
|
208
|
-
backend: this.name,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
return { text, assets };
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
/** Read the Markdown out of a docling-serve response, in either spelling. */
|
|
215
|
-
export function readDoclingPayload(payload, backend) {
|
|
216
|
-
if (payload === null || typeof payload !== "object") {
|
|
217
|
-
throw new DocumentError("EXTRACTION_FAILED", "the extractor returned no document", {
|
|
218
|
-
backend,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
const root = payload;
|
|
222
|
-
const status = root["status"];
|
|
223
|
-
if (typeof status === "string" && status.toLowerCase() !== "success") {
|
|
224
|
-
const errors = Array.isArray(root["errors"])
|
|
225
|
-
? root["errors"]
|
|
226
|
-
.map((entry) => sanitizeBackendOutput(JSON.stringify(entry), 300))
|
|
227
|
-
.join("; ")
|
|
228
|
-
: "";
|
|
229
|
-
throw new DocumentError("EXTRACTION_FAILED", `the extractor reported "${status}"${errors === "" ? "" : `: ${errors}`}`, { backend, details: { status } });
|
|
230
|
-
}
|
|
231
|
-
const document = root["document"] !== null && typeof root["document"] === "object"
|
|
232
|
-
? root["document"]
|
|
233
|
-
: root;
|
|
234
|
-
const markdown = document["md_content"] ?? document["markdown"];
|
|
235
|
-
if (typeof markdown !== "string") {
|
|
236
|
-
throw new DocumentError("EXTRACTION_FAILED", "the extractor returned no Markdown content", { backend });
|
|
237
|
-
}
|
|
238
|
-
const pagesSource = document["page_count"] ?? document["pages"] ?? root["page_count"];
|
|
239
|
-
const pages = typeof pagesSource === "number" ? pagesSource : undefined;
|
|
240
|
-
const version = root["version"] ?? document["version"];
|
|
241
|
-
return {
|
|
242
|
-
markdown,
|
|
243
|
-
...(pages === undefined ? {} : { pages }),
|
|
244
|
-
...(typeof version === "string" ? { serviceVersion: version } : {}),
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
//# sourceMappingURL=docling.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docling.js","sourceRoot":"","sources":["../../../src/documents/providers/docling.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LibreOffice provider — DOCX → PDF (§6.1, §14.1, §46).
|
|
3
|
-
*
|
|
4
|
-
* Two details matter beyond "call the converter":
|
|
5
|
-
*
|
|
6
|
-
* - every invocation gets its own `-env:UserInstallation` profile, because
|
|
7
|
-
* concurrent headless LibreOffice processes sharing one profile corrupt each
|
|
8
|
-
* other's state; the temp profile is removed afterwards on success and on
|
|
9
|
-
* failure alike;
|
|
10
|
-
* - a conversion that produced no file, timed out, or died is reported as a
|
|
11
|
-
* failure of this step only. The orchestrator keeps whatever earlier steps
|
|
12
|
-
* already produced (§45).
|
|
13
|
-
*/
|
|
14
|
-
import { mkdtemp, readdir, rm, stat } from "node:fs/promises";
|
|
15
|
-
import { tmpdir } from "node:os";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import { sha256OfFile } from "../artifacts/store.js";
|
|
18
|
-
import { DocumentError } from "../errors.js";
|
|
19
|
-
import { expectProcessOk, runProcess } from "./process.js";
|
|
20
|
-
import { backendInfo, parseVersionOutput, verifyOutput } from "./shared.js";
|
|
21
|
-
import { toFileUri } from "../security/paths.js";
|
|
22
|
-
const VERSION_TIMEOUT_MS = 20_000;
|
|
23
|
-
const MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
24
|
-
/** Flags that keep a headless conversion from touching shared user state. */
|
|
25
|
-
const HEADLESS_FLAGS = [
|
|
26
|
-
"--headless",
|
|
27
|
-
"--invisible",
|
|
28
|
-
"--norestore",
|
|
29
|
-
"--nolockcheck",
|
|
30
|
-
"--nodefault",
|
|
31
|
-
"--nofirststartwizard",
|
|
32
|
-
"--nologo",
|
|
33
|
-
];
|
|
34
|
-
export class LibreOfficePdfConverter {
|
|
35
|
-
options;
|
|
36
|
-
name = "libreoffice";
|
|
37
|
-
cachedVersion;
|
|
38
|
-
constructor(options) {
|
|
39
|
-
this.options = options;
|
|
40
|
-
}
|
|
41
|
-
supports(source, target) {
|
|
42
|
-
return source === "docx" && target === "pdf";
|
|
43
|
-
}
|
|
44
|
-
async version() {
|
|
45
|
-
this.cachedVersion ??= this.probeVersion();
|
|
46
|
-
return await this.cachedVersion;
|
|
47
|
-
}
|
|
48
|
-
async probeVersion() {
|
|
49
|
-
if (this.options.versionProbe !== undefined)
|
|
50
|
-
return await this.options.versionProbe();
|
|
51
|
-
try {
|
|
52
|
-
const result = await runProcess(this.options.executable, ["--version"], {
|
|
53
|
-
timeoutMs: VERSION_TIMEOUT_MS,
|
|
54
|
-
maxStdoutBytes: 8 * 1024,
|
|
55
|
-
backend: this.name,
|
|
56
|
-
context: "reporting its version",
|
|
57
|
-
...(this.options.programPrefixArgs === undefined
|
|
58
|
-
? {}
|
|
59
|
-
: { programPrefixArgs: this.options.programPrefixArgs }),
|
|
60
|
-
});
|
|
61
|
-
if (result.exitCode !== 0)
|
|
62
|
-
return undefined;
|
|
63
|
-
return parseVersionOutput(result.stdout, this.name);
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async convert(input) {
|
|
70
|
-
const outputDir = path.dirname(input.outputPath);
|
|
71
|
-
const profile = await mkdtemp(path.join(this.options.profileRoot ?? tmpdir(), "qa-libreoffice-"));
|
|
72
|
-
try {
|
|
73
|
-
const argv = [
|
|
74
|
-
...HEADLESS_FLAGS,
|
|
75
|
-
`-env:UserInstallation=${toFileUri(profile)}`,
|
|
76
|
-
"--convert-to",
|
|
77
|
-
"pdf",
|
|
78
|
-
"--outdir",
|
|
79
|
-
outputDir,
|
|
80
|
-
input.inputPath,
|
|
81
|
-
];
|
|
82
|
-
const result = await runProcess(this.options.executable, argv, {
|
|
83
|
-
cwd: input.workDir,
|
|
84
|
-
timeoutMs: this.options.timeoutMs,
|
|
85
|
-
maxStdoutBytes: MAX_OUTPUT_BYTES,
|
|
86
|
-
backend: this.name,
|
|
87
|
-
context: "converting DOCX to PDF",
|
|
88
|
-
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
89
|
-
...(this.options.programPrefixArgs === undefined
|
|
90
|
-
? {}
|
|
91
|
-
: { programPrefixArgs: this.options.programPrefixArgs }),
|
|
92
|
-
});
|
|
93
|
-
expectProcessOk(result, {
|
|
94
|
-
backend: this.name,
|
|
95
|
-
context: "converting DOCX to PDF",
|
|
96
|
-
fallbackCode: "CONVERSION_FAILED",
|
|
97
|
-
});
|
|
98
|
-
const produced = await this.locateOutput(outputDir, input.outputPath);
|
|
99
|
-
const verified = await verifyOutput(produced, this.name, "CONVERSION_FAILED");
|
|
100
|
-
return {
|
|
101
|
-
path: verified.path,
|
|
102
|
-
size: verified.size,
|
|
103
|
-
sha256: await sha256OfFile(verified.path),
|
|
104
|
-
backend: backendInfo(this.name, await this.version()),
|
|
105
|
-
warnings: [],
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
await rm(profile, { recursive: true, force: true }).catch(() => undefined);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* LibreOffice derives the output name from the input, so the expected path
|
|
114
|
-
* is a prediction. When it is absent exactly one PDF in the output directory
|
|
115
|
-
* is accepted; anything else is a failure rather than a guess.
|
|
116
|
-
*/
|
|
117
|
-
async locateOutput(outputDir, expected) {
|
|
118
|
-
const details = await stat(expected).catch(() => undefined);
|
|
119
|
-
if (details?.isFile() === true)
|
|
120
|
-
return expected;
|
|
121
|
-
const entries = await readdir(outputDir).catch(() => []);
|
|
122
|
-
const pdfs = entries.filter((entry) => entry.toLowerCase().endsWith(".pdf"));
|
|
123
|
-
if (pdfs.length === 1)
|
|
124
|
-
return path.join(outputDir, pdfs[0] ?? "");
|
|
125
|
-
throw new DocumentError("CONVERSION_FAILED", pdfs.length === 0
|
|
126
|
-
? "the PDF converter reported success but produced no PDF"
|
|
127
|
-
: "the PDF converter produced an unexpected number of PDF files", { backend: this.name, details: { candidates: pdfs.length } });
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
//# sourceMappingURL=libreoffice.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"libreoffice.js","sourceRoot":"","sources":["../../../src/documents/providers/libreoffice.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MarkItDown provider — the optional fast extractor (§6.2, §9).
|
|
3
|
-
*
|
|
4
|
-
* Kept behind `documents.markitdown.enabled` (off by default): it is a
|
|
5
|
-
* convenient fallback when Docling is unreachable and high-fidelity parsing is
|
|
6
|
-
* not needed, but it is not the extractor a QA report should be built on.
|
|
7
|
-
*/
|
|
8
|
-
import { DocumentError } from "../errors.js";
|
|
9
|
-
import { expectProcessOk, runProcess } from "./process.js";
|
|
10
|
-
import { backendInfo, parseVersionOutput } from "./shared.js";
|
|
11
|
-
const VERSION_TIMEOUT_MS = 10_000;
|
|
12
|
-
export class MarkItDownExtractor {
|
|
13
|
-
options;
|
|
14
|
-
name = "markitdown";
|
|
15
|
-
cachedVersion;
|
|
16
|
-
constructor(options) {
|
|
17
|
-
this.options = options;
|
|
18
|
-
}
|
|
19
|
-
supports(format) {
|
|
20
|
-
return format === "docx" || format === "pdf";
|
|
21
|
-
}
|
|
22
|
-
async version() {
|
|
23
|
-
this.cachedVersion ??= this.probeVersion();
|
|
24
|
-
return await this.cachedVersion;
|
|
25
|
-
}
|
|
26
|
-
async probeVersion() {
|
|
27
|
-
if (this.options.versionProbe !== undefined)
|
|
28
|
-
return await this.options.versionProbe();
|
|
29
|
-
try {
|
|
30
|
-
const result = await runProcess(this.options.executable, ["--version"], {
|
|
31
|
-
timeoutMs: VERSION_TIMEOUT_MS,
|
|
32
|
-
maxStdoutBytes: 8 * 1024,
|
|
33
|
-
backend: this.name,
|
|
34
|
-
context: "reporting its version",
|
|
35
|
-
});
|
|
36
|
-
if (result.exitCode !== 0)
|
|
37
|
-
return undefined;
|
|
38
|
-
return parseVersionOutput(result.stdout, this.name);
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
async health() {
|
|
45
|
-
try {
|
|
46
|
-
return (await this.version()) === undefined ? "unavailable" : "ok";
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
return "unavailable";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async extract(input) {
|
|
53
|
-
const result = await runProcess(this.options.executable, [input.inputPath], {
|
|
54
|
-
cwd: input.workDir,
|
|
55
|
-
timeoutMs: this.options.timeoutMs,
|
|
56
|
-
maxStdoutBytes: this.options.maxStdoutBytes,
|
|
57
|
-
backend: this.name,
|
|
58
|
-
context: "extracting Markdown",
|
|
59
|
-
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
60
|
-
...(this.options.programPrefixArgs === undefined
|
|
61
|
-
? {}
|
|
62
|
-
: { programPrefixArgs: this.options.programPrefixArgs }),
|
|
63
|
-
});
|
|
64
|
-
expectProcessOk(result, {
|
|
65
|
-
backend: this.name,
|
|
66
|
-
context: "extracting Markdown",
|
|
67
|
-
fallbackCode: "EXTRACTION_FAILED",
|
|
68
|
-
});
|
|
69
|
-
const text = result.stdout.trimStart();
|
|
70
|
-
if (text.trim() === "") {
|
|
71
|
-
throw new DocumentError("EXTRACTION_FAILED", "the extractor produced no text for this document", { backend: this.name });
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
markdown: text,
|
|
75
|
-
assets: [],
|
|
76
|
-
backend: backendInfo(this.name, await this.version()),
|
|
77
|
-
warnings: input.extractImages
|
|
78
|
-
? [
|
|
79
|
-
{
|
|
80
|
-
code: "IMAGE_SKIPPED",
|
|
81
|
-
message: "this extractor does not report images; the response carries text only",
|
|
82
|
-
backend: this.name,
|
|
83
|
-
},
|
|
84
|
-
]
|
|
85
|
-
: [],
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=markitdown.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"markitdown.js","sourceRoot":"","sources":["../../../src/documents/providers/markitdown.ts"],"names":[],"mappings":"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"}
|