@yadsh/dsh-qa-surface 0.5.0 → 0.6.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 +194 -9
- package/compatibility.json +10 -1
- package/cordis.patch.yml +9 -0
- package/lib/account-remotes.js +10 -0
- 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 +22 -0
- package/lib/accounts/store.js.map +1 -1
- package/lib/client/QaAccountsController.js +29 -0
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaSessionController.js +168 -48
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +125 -56
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaSurfaceGuard.js +96 -0
- package/lib/client/QaSurfaceGuard.js.map +1 -0
- package/lib/client/QaTranscriptAdapter.js +11 -5
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/components/QaChangelog.js +31 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +1 -1
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaHeader.js +2 -8
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +20 -7
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaModal.js +24 -6
- package/lib/client/components/QaModal.js.map +1 -1
- package/lib/client/components/QaSidebar.js +2 -6
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +6 -5
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaWidthHandle.js +21 -1
- package/lib/client/components/QaWidthHandle.js.map +1 -1
- package/lib/client/components/surface-utils.js +2 -0
- package/lib/client/components/surface-utils.js.map +1 -1
- package/lib/client/index.js +72 -24
- package/lib/client/index.js.map +1 -1
- package/lib/client/panels/PanelHost.js +209 -0
- package/lib/client/panels/PanelHost.js.map +1 -0
- package/lib/client/panels/PanelLauncher.js +39 -0
- package/lib/client/panels/PanelLauncher.js.map +1 -0
- package/lib/client/panels/contract.js +2 -0
- package/lib/client/panels/contract.js.map +1 -0
- package/lib/client/panels/index.js +2 -0
- package/lib/client/panels/index.js.map +1 -0
- package/lib/client/panels/registry.js +171 -0
- package/lib/client/panels/registry.js.map +1 -0
- package/lib/client/project-session-state.js +3 -0
- package/lib/client/project-session-state.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/accounts.js +3 -1
- package/lib/client/settings/sections/accounts.js.map +1 -1
- package/lib/client/settings/sections/documents.js +88 -0
- package/lib/client/settings/sections/documents.js.map +1 -0
- package/lib/client/settings/sections/interface.js +2 -0
- package/lib/client/settings/sections/interface.js.map +1 -1
- package/lib/client/settings/sections.js +1 -0
- package/lib/client/settings/sections.js.map +1 -1
- package/lib/client/settings-extensions/contract.js +2 -0
- package/lib/client/settings-extensions/contract.js.map +1 -0
- package/lib/client/settings-extensions/index.js +2 -0
- package/lib/client/settings-extensions/index.js.map +1 -0
- package/lib/client/settings-extensions/registry.js +63 -0
- package/lib/client/settings-extensions/registry.js.map +1 -0
- package/lib/client/settlement.js +51 -5
- package/lib/client/settlement.js.map +1 -1
- package/lib/client/source-preview.js +24 -0
- package/lib/client/source-preview.js.map +1 -0
- package/lib/client/styles.js +157 -32
- package/lib/client/styles.js.map +1 -1
- package/lib/client/subagent-codenames.js +109 -0
- package/lib/client/subagent-codenames.js.map +1 -0
- package/lib/client/types.js +1 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client/user-settings/GeneralSettingsPage.js +13 -0
- package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -0
- package/lib/client/user-settings/ProfileSettingsPage.js +59 -0
- package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -0
- package/lib/client/user-settings/SkillCatalog.js +23 -0
- package/lib/client/user-settings/SkillCatalog.js.map +1 -0
- package/lib/client/user-settings/SkillEditor.js +89 -0
- package/lib/client/user-settings/SkillEditor.js.map +1 -0
- package/lib/client/user-settings/SkillToolPicker.js +58 -0
- package/lib/client/user-settings/SkillToolPicker.js.map +1 -0
- package/lib/client/user-settings/SkillsSettingsPage.js +171 -0
- package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -0
- package/lib/client/user-settings/StartersSettingsPage.js +78 -0
- package/lib/client/user-settings/StartersSettingsPage.js.map +1 -0
- package/lib/client/user-settings/UserSettingsDialog.js +50 -0
- package/lib/client/user-settings/UserSettingsDialog.js.map +1 -0
- package/lib/client/user-settings/copy.js +84 -0
- package/lib/client/user-settings/copy.js.map +1 -0
- package/lib/client/user-settings/draft.js +127 -0
- package/lib/client/user-settings/draft.js.map +1 -0
- package/lib/client/user-settings/fields.js +24 -0
- package/lib/client/user-settings/fields.js.map +1 -0
- package/lib/client.js +5467 -1379
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +30 -0
- package/lib/config-resolvers/accounts.js.map +1 -1
- package/lib/config-resolvers/defaults.js +23 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/tools.js +37 -0
- package/lib/config-resolvers/tools.js.map +1 -0
- package/lib/config-resolvers/ui.js +2 -0
- package/lib/config-resolvers/ui.js.map +1 -1
- package/lib/config.js +288 -0
- package/lib/config.js.map +1 -1
- package/lib/documents/artifacts/ids.js +43 -0
- package/lib/documents/artifacts/ids.js.map +1 -0
- package/lib/documents/artifacts/manifest.js +66 -0
- package/lib/documents/artifacts/manifest.js.map +1 -0
- package/lib/documents/artifacts/store.js +169 -0
- package/lib/documents/artifacts/store.js.map +1 -0
- package/lib/documents/capabilities.js +93 -0
- package/lib/documents/capabilities.js.map +1 -0
- package/lib/documents/config.js +302 -0
- package/lib/documents/config.js.map +1 -0
- package/lib/documents/defaults.js +78 -0
- package/lib/documents/defaults.js.map +1 -0
- package/lib/documents/errors.js +101 -0
- package/lib/documents/errors.js.map +1 -0
- package/lib/documents/index.js +80 -0
- package/lib/documents/index.js.map +1 -0
- package/lib/documents/inspect/facts.js +161 -0
- package/lib/documents/inspect/facts.js.map +1 -0
- package/lib/documents/inspect/zip.js +108 -0
- package/lib/documents/inspect/zip.js.map +1 -0
- package/lib/documents/markdown/directives.js +135 -0
- package/lib/documents/markdown/directives.js.map +1 -0
- package/lib/documents/markdown/frontmatter.js +35 -0
- package/lib/documents/markdown/frontmatter.js.map +1 -0
- package/lib/documents/markdown/normalize.js +113 -0
- package/lib/documents/markdown/normalize.js.map +1 -0
- package/lib/documents/orchestrator/assets.js +243 -0
- package/lib/documents/orchestrator/assets.js.map +1 -0
- package/lib/documents/orchestrator/convert-document.js +186 -0
- package/lib/documents/orchestrator/convert-document.js.map +1 -0
- package/lib/documents/orchestrator/create-document.js +292 -0
- package/lib/documents/orchestrator/create-document.js.map +1 -0
- package/lib/documents/orchestrator/extract-document.js +162 -0
- package/lib/documents/orchestrator/extract-document.js.map +1 -0
- package/lib/documents/orchestrator/inspect-document.js +89 -0
- package/lib/documents/orchestrator/inspect-document.js.map +1 -0
- package/lib/documents/orchestrator/runtime-deps.js +59 -0
- package/lib/documents/orchestrator/runtime-deps.js.map +1 -0
- package/lib/documents/orchestrator/scope.js +132 -0
- package/lib/documents/orchestrator/scope.js.map +1 -0
- package/lib/documents/providers/docling.js +247 -0
- package/lib/documents/providers/docling.js.map +1 -0
- package/lib/documents/providers/libreoffice.js +130 -0
- package/lib/documents/providers/libreoffice.js.map +1 -0
- package/lib/documents/providers/markitdown.js +89 -0
- package/lib/documents/providers/markitdown.js.map +1 -0
- package/lib/documents/providers/pandoc.js +161 -0
- package/lib/documents/providers/pandoc.js.map +1 -0
- package/lib/documents/providers/process.js +164 -0
- package/lib/documents/providers/process.js.map +1 -0
- package/lib/documents/providers/registry.js +152 -0
- package/lib/documents/providers/registry.js.map +1 -0
- package/lib/documents/providers/shared.js +75 -0
- package/lib/documents/providers/shared.js.map +1 -0
- package/lib/documents/runtime.js +114 -0
- package/lib/documents/runtime.js.map +1 -0
- package/lib/documents/security/file-types.js +188 -0
- package/lib/documents/security/file-types.js.map +1 -0
- package/lib/documents/security/limits.js +78 -0
- package/lib/documents/security/limits.js.map +1 -0
- package/lib/documents/security/mime.js +43 -0
- package/lib/documents/security/mime.js.map +1 -0
- package/lib/documents/security/paths.js +133 -0
- package/lib/documents/security/paths.js.map +1 -0
- package/lib/documents/templates/registry.js +147 -0
- package/lib/documents/templates/registry.js.map +1 -0
- package/lib/documents/templates/resolver.js +59 -0
- package/lib/documents/templates/resolver.js.map +1 -0
- package/lib/documents/tools/convert.js +125 -0
- package/lib/documents/tools/convert.js.map +1 -0
- package/lib/documents/tools/create.js +187 -0
- package/lib/documents/tools/create.js.map +1 -0
- package/lib/documents/tools/index.js +41 -0
- package/lib/documents/tools/index.js.map +1 -0
- package/lib/documents/tools/inspect.js +135 -0
- package/lib/documents/tools/inspect.js.map +1 -0
- package/lib/documents/tools/shared.js +88 -0
- package/lib/documents/tools/shared.js.map +1 -0
- package/lib/documents/tools/to-markdown.js +125 -0
- package/lib/documents/tools/to-markdown.js.map +1 -0
- package/lib/documents/types.js +12 -0
- package/lib/documents/types.js.map +1 -0
- package/lib/index.js +225 -20
- package/lib/index.js.map +1 -1
- package/lib/integration-principals.js +22 -0
- package/lib/integration-principals.js.map +1 -0
- package/lib/lockdown-policy.js +15 -3
- package/lib/lockdown-policy.js.map +1 -1
- package/lib/personal-skills/errors.js +9 -0
- package/lib/personal-skills/errors.js.map +1 -0
- package/lib/personal-skills/host.js +80 -0
- package/lib/personal-skills/host.js.map +1 -0
- package/lib/personal-skills/index.js +10 -0
- package/lib/personal-skills/index.js.map +1 -0
- package/lib/personal-skills/paths.js +127 -0
- package/lib/personal-skills/paths.js.map +1 -0
- package/lib/personal-skills/provider.js +109 -0
- package/lib/personal-skills/provider.js.map +1 -0
- package/lib/personal-skills/remotes.js +40 -0
- package/lib/personal-skills/remotes.js.map +1 -0
- package/lib/personal-skills/service.js +686 -0
- package/lib/personal-skills/service.js.map +1 -0
- package/lib/personal-skills/skill-file.js +278 -0
- package/lib/personal-skills/skill-file.js.map +1 -0
- package/lib/personal-skills/skill-format.js +202 -0
- package/lib/personal-skills/skill-format.js.map +1 -0
- package/lib/personal-skills/watcher.js +96 -0
- package/lib/personal-skills/watcher.js.map +1 -0
- package/lib/profile.js +6 -4
- package/lib/profile.js.map +1 -1
- package/lib/prompt-notes.js +19 -0
- package/lib/prompt-notes.js.map +1 -1
- package/lib/provenance/file-preview.js +68 -21
- package/lib/provenance/file-preview.js.map +1 -1
- package/lib/provenance/host-store.js +44 -11
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/provenance/index.js +1 -0
- package/lib/provenance/index.js.map +1 -1
- package/lib/provenance/normalize.js +3 -1
- package/lib/provenance/normalize.js.map +1 -1
- package/lib/provenance/snapshot-store.js +154 -0
- package/lib/provenance/snapshot-store.js.map +1 -0
- package/lib/qa-tools/activation-detector.js +53 -0
- package/lib/qa-tools/activation-detector.js.map +1 -0
- package/lib/qa-tools/activation-manager.js +111 -0
- package/lib/qa-tools/activation-manager.js.map +1 -0
- package/lib/qa-tools/catalog.js +108 -0
- package/lib/qa-tools/catalog.js.map +1 -0
- package/lib/qa-tools/durable-marker.js +115 -0
- package/lib/qa-tools/durable-marker.js.map +1 -0
- package/lib/qa-tools/index.js +83 -0
- package/lib/qa-tools/index.js.map +1 -0
- package/lib/qa-tools/lifecycle.js +64 -0
- package/lib/qa-tools/lifecycle.js.map +1 -0
- package/lib/qa-tools/types.js +2 -0
- package/lib/qa-tools/types.js.map +1 -0
- package/lib/resolve-config.js +5 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +35 -3
- package/lib/secure-session.js.map +1 -1
- package/lib/starters.js +117 -0
- package/lib/starters.js.map +1 -0
- package/lib/typert.host.js +767 -22
- package/lib/typert.remote-client.d.ts +17 -1
- package/lib/typert.remote-client.js +609 -17
- package/lib/types/account-remotes.d.ts +3 -1
- package/lib/types/accounts/errors.d.ts +1 -1
- package/lib/types/accounts/file.d.ts +10 -0
- package/lib/types/accounts/store.d.ts +7 -1
- package/lib/types/client/QaAccountsController.d.ts +7 -1
- package/lib/types/client/QaSessionController.d.ts +12 -0
- package/lib/types/client/QaSurface.d.ts +14 -4
- package/lib/types/client/QaSurfaceGuard.d.ts +27 -0
- package/lib/types/client/QaTranscriptAdapter.d.ts +7 -0
- package/lib/types/client/components/QaComposer.d.ts +3 -1
- package/lib/types/client/components/QaHeader.d.ts +3 -1
- package/lib/types/client/components/QaModal.d.ts +5 -4
- package/lib/types/client/components/QaSidebar.d.ts +8 -11
- package/lib/types/client/components/QaWidthHandle.d.ts +13 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/panels/PanelHost.d.ts +18 -0
- package/lib/types/client/panels/PanelLauncher.d.ts +5 -0
- package/lib/types/client/panels/contract.d.ts +83 -0
- package/lib/types/client/panels/index.d.ts +3 -0
- package/lib/types/client/panels/registry.d.ts +40 -0
- package/lib/types/client/project-session-state.d.ts +5 -0
- package/lib/types/client/settings/sections/documents.d.ts +13 -0
- package/lib/types/client/settings/sections.d.ts +1 -0
- package/lib/types/client/settings-extensions/contract.d.ts +32 -0
- package/lib/types/client/settings-extensions/index.d.ts +3 -0
- package/lib/types/client/settings-extensions/registry.d.ts +15 -0
- package/lib/types/client/settlement.d.ts +41 -5
- package/lib/types/client/source-preview.d.ts +8 -0
- package/lib/types/client/styles.d.ts +2 -0
- package/lib/types/client/subagent-codenames.d.ts +18 -0
- package/lib/types/client/types.d.ts +35 -3
- package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +14 -0
- package/lib/types/client/user-settings/ProfileSettingsPage.d.ts +18 -0
- package/lib/types/client/user-settings/SkillCatalog.d.ts +16 -0
- package/lib/types/client/user-settings/SkillEditor.d.ts +42 -0
- package/lib/types/client/user-settings/SkillToolPicker.d.ts +17 -0
- package/lib/types/client/user-settings/SkillsSettingsPage.d.ts +15 -0
- package/lib/types/client/user-settings/StartersSettingsPage.d.ts +14 -0
- package/lib/types/client/user-settings/UserSettingsDialog.d.ts +43 -0
- package/lib/types/client/user-settings/copy.d.ts +25 -0
- package/lib/types/client/user-settings/draft.d.ts +51 -0
- package/lib/types/client/user-settings/fields.d.ts +43 -0
- package/lib/types/config-resolvers/tools.d.ts +6 -0
- package/lib/types/documents/artifacts/ids.d.ts +14 -0
- package/lib/types/documents/artifacts/manifest.d.ts +32 -0
- package/lib/types/documents/artifacts/store.d.ts +67 -0
- package/lib/types/documents/capabilities.d.ts +32 -0
- package/lib/types/documents/config.d.ts +27 -0
- package/lib/types/documents/defaults.d.ts +161 -0
- package/lib/types/documents/errors.d.ts +42 -0
- package/lib/types/documents/index.d.ts +63 -0
- package/lib/types/documents/inspect/facts.d.ts +43 -0
- package/lib/types/documents/inspect/zip.d.ts +28 -0
- package/lib/types/documents/markdown/directives.d.ts +39 -0
- package/lib/types/documents/markdown/frontmatter.d.ts +15 -0
- package/lib/types/documents/markdown/normalize.d.ts +30 -0
- package/lib/types/documents/orchestrator/assets.d.ts +55 -0
- package/lib/types/documents/orchestrator/convert-document.d.ts +25 -0
- package/lib/types/documents/orchestrator/create-document.d.ts +18 -0
- package/lib/types/documents/orchestrator/extract-document.d.ts +24 -0
- package/lib/types/documents/orchestrator/inspect-document.d.ts +12 -0
- package/lib/types/documents/orchestrator/runtime-deps.d.ts +43 -0
- package/lib/types/documents/orchestrator/scope.d.ts +52 -0
- package/lib/types/documents/providers/docling.d.ts +54 -0
- package/lib/types/documents/providers/libreoffice.d.ts +40 -0
- package/lib/types/documents/providers/markitdown.d.ts +28 -0
- package/lib/types/documents/providers/pandoc.d.ts +42 -0
- package/lib/types/documents/providers/process.d.ts +54 -0
- package/lib/types/documents/providers/registry.d.ts +68 -0
- package/lib/types/documents/providers/shared.d.ts +27 -0
- package/lib/types/documents/runtime.d.ts +59 -0
- package/lib/types/documents/security/file-types.d.ts +39 -0
- package/lib/types/documents/security/limits.d.ts +24 -0
- package/lib/types/documents/security/mime.d.ts +13 -0
- package/lib/types/documents/security/paths.d.ts +38 -0
- package/lib/types/documents/templates/registry.d.ts +50 -0
- package/lib/types/documents/templates/resolver.d.ts +30 -0
- package/lib/types/documents/tools/convert.d.ts +9 -0
- package/lib/types/documents/tools/create.d.ts +14 -0
- package/lib/types/documents/tools/index.d.ts +33 -0
- package/lib/types/documents/tools/inspect.d.ts +9 -0
- package/lib/types/documents/tools/shared.d.ts +77 -0
- package/lib/types/documents/tools/to-markdown.d.ts +12 -0
- package/lib/types/documents/types.d.ts +294 -0
- package/lib/types/index.d.ts +75 -3
- package/lib/types/integration-principals.d.ts +9 -0
- package/lib/types/lockdown-policy.d.ts +12 -2
- package/lib/types/personal-skills/errors.d.ts +11 -0
- package/lib/types/personal-skills/host.d.ts +42 -0
- package/lib/types/personal-skills/index.d.ts +10 -0
- package/lib/types/personal-skills/paths.d.ts +39 -0
- package/lib/types/personal-skills/provider.d.ts +33 -0
- package/lib/types/personal-skills/remotes.d.ts +35 -0
- package/lib/types/personal-skills/service.d.ts +131 -0
- package/lib/types/personal-skills/skill-file.d.ts +64 -0
- package/lib/types/personal-skills/skill-format.d.ts +100 -0
- package/lib/types/personal-skills/watcher.d.ts +39 -0
- package/lib/types/profile.d.ts +13 -0
- package/lib/types/prompt-notes.d.ts +9 -0
- package/lib/types/provenance/file-preview.d.ts +47 -4
- package/lib/types/provenance/host-store.d.ts +7 -1
- package/lib/types/provenance/index.d.ts +1 -0
- package/lib/types/provenance/snapshot-store.d.ts +23 -0
- package/lib/types/qa-tools/activation-detector.d.ts +29 -0
- package/lib/types/qa-tools/activation-manager.d.ts +47 -0
- package/lib/types/qa-tools/catalog.d.ts +40 -0
- package/lib/types/qa-tools/durable-marker.d.ts +16 -0
- package/lib/types/qa-tools/index.d.ts +40 -0
- package/lib/types/qa-tools/lifecycle.d.ts +44 -0
- package/lib/types/qa-tools/types.d.ts +45 -0
- package/lib/types/secure-session.d.ts +24 -2
- package/lib/types/starters.d.ts +45 -0
- package/lib/types/types.d.ts +202 -3
- package/package.json +24 -11
- package/scripts/repair-session-events.mjs +260 -0
- package/lib/client/components/QaProfile.js +0 -64
- package/lib/client/components/QaProfile.js.map +0 -1
- package/lib/types/client/components/QaProfile.d.ts +0 -25
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.js","sourceRoot":"","sources":["../../../src/documents/artifacts/ids.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,QAAQ,GAAG,cAAc,CAAC;AAEhC,SAAS,UAAU,CAAC,SAAiB;IACnC,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAa,IAAI,KAAK,CAAS,UAAU,CAAC,CAAC;IACvD,KAAK,IAAI,KAAK,GAAG,UAAU,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,SAAS,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC;QAChD,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,GAAG,GAAW,IAAI,CAAC,GAAG,EAAE;IACjD,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,YAAY,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAW,IAAI,CAAC,GAAG,EAAE;IACvD,OAAO,OAAO,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,mBAAmB,GAAG,+BAA+B,CAAC;AAE5D,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest construction and persistence (§19).
|
|
3
|
+
*
|
|
4
|
+
* The manifest is the source of truth about an artifact: which operation,
|
|
5
|
+
* which backends and versions, which template (and its hash), which files came
|
|
6
|
+
* out, which warnings were raised, and which session/workspace the bundle
|
|
7
|
+
* belongs to. Logical reproducibility rests on it, because byte-level
|
|
8
|
+
* reproducibility of DOCX/PDF cannot be promised (§31).
|
|
9
|
+
*/
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { DocumentError, asDocumentError } from "../errors.js";
|
|
12
|
+
export const MANIFEST_FILE = "manifest.json";
|
|
13
|
+
export const MANIFEST_SCHEMA_VERSION = 1;
|
|
14
|
+
export function buildManifest(input) {
|
|
15
|
+
return {
|
|
16
|
+
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
17
|
+
artifactId: input.artifactId,
|
|
18
|
+
operation: input.operation,
|
|
19
|
+
createdAt: input.createdAt,
|
|
20
|
+
input: input.input,
|
|
21
|
+
outputs: input.outputs,
|
|
22
|
+
...(input.template === undefined ? {} : { template: input.template }),
|
|
23
|
+
...(input.templateSha256 === undefined
|
|
24
|
+
? {}
|
|
25
|
+
: { templateSha256: input.templateSha256 }),
|
|
26
|
+
backends: input.backends,
|
|
27
|
+
warnings: input.warnings,
|
|
28
|
+
scope: input.scope,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function writeManifest(store, artifactId, manifest) {
|
|
32
|
+
const written = await store.write(path.join(artifactId, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
33
|
+
return written.path;
|
|
34
|
+
}
|
|
35
|
+
export async function readManifest(store, artifactId) {
|
|
36
|
+
const raw = await store
|
|
37
|
+
.read(path.join(artifactId, MANIFEST_FILE))
|
|
38
|
+
.catch((error) => {
|
|
39
|
+
throw asDocumentError(error, "FILE_NOT_FOUND", "artifact store");
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(raw.toString("utf8"));
|
|
43
|
+
if (parsed.schemaVersion !== MANIFEST_SCHEMA_VERSION) {
|
|
44
|
+
throw new Error(`unsupported manifest schema ${String(parsed.schemaVersion)}`);
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw new DocumentError("INVALID_INPUT", `the artifact manifest of ${artifactId} is unreadable`, { cause: error });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Project a tool-level file result onto the manifest's output record. */
|
|
53
|
+
export function outputRecord(file) {
|
|
54
|
+
return {
|
|
55
|
+
format: file.format,
|
|
56
|
+
path: path.basename(file.path),
|
|
57
|
+
sha256: file.sha256,
|
|
58
|
+
size: file.size,
|
|
59
|
+
status: file.status,
|
|
60
|
+
...(file.error === undefined ? {} : { error: file.error }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function formatOfOperation(operation) {
|
|
64
|
+
return operation === "document_create" ? "md" : "unknown";
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/documents/artifacts/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU9D,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAU,CAAC;AAelD,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,OAAO;QACL,aAAa,EAAE,uBAAuB;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrE,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS;YACpC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC;QAC7C,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAoB,EACpB,UAAkB,EAClB,QAA0B;IAE1B,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,EACpC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACzC,CAAC;IACF,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAoB,EACpB,UAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,KAAK;SACpB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;SAC1C,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACxB,MAAM,eAAe,CAAC,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IACL,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAqB,CAAC;QACpE,IAAI,MAAM,CAAC,aAAa,KAAK,uBAAuB,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACb,+BAA+B,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAC9D,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CACrB,eAAe,EACf,4BAA4B,UAAU,gBAAgB,EACtD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAC1B,IAAwB;IAExB,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,SAAwC;IAExC,OAAO,SAAS,KAAK,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact bundle storage (§18, §47).
|
|
3
|
+
*
|
|
4
|
+
* One directory per operation:
|
|
5
|
+
*
|
|
6
|
+
* ```text
|
|
7
|
+
* <root>/<artifact-id>/
|
|
8
|
+
* manifest.json
|
|
9
|
+
* source.md
|
|
10
|
+
* input/original.pdf
|
|
11
|
+
* assets/
|
|
12
|
+
* output.docx
|
|
13
|
+
* extracted.md
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Everything the store writes goes through a root-relative path that is
|
|
17
|
+
* validated first, and every file lands atomically (temp file + rename) so a
|
|
18
|
+
* crashed host never leaves a half-written artifact that a later read would
|
|
19
|
+
* trust. Job temp directories live under `<root>/.tmp` and are removed on both
|
|
20
|
+
* success and failure (§47).
|
|
21
|
+
*/
|
|
22
|
+
import { randomBytes } from "node:crypto";
|
|
23
|
+
import { createHash } from "node:crypto";
|
|
24
|
+
import { mkdir, readdir, readFile, rename, rm, stat, writeFile, } from "node:fs/promises";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { DocumentError, asDocumentError } from "../errors.js";
|
|
27
|
+
import { assertInsideRoot } from "../security/paths.js";
|
|
28
|
+
import { createArtifactId, isArtifactId } from "./ids.js";
|
|
29
|
+
export function sha256Hex(data) {
|
|
30
|
+
return createHash("sha256").update(data).digest("hex");
|
|
31
|
+
}
|
|
32
|
+
export async function sha256OfFile(filePath) {
|
|
33
|
+
return sha256Hex(await readFile(filePath));
|
|
34
|
+
}
|
|
35
|
+
export class ArtifactStore {
|
|
36
|
+
root;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this.root = path.resolve(options.root);
|
|
39
|
+
}
|
|
40
|
+
/** Absolute path of a root-relative artifact member, containment checked. */
|
|
41
|
+
path(relativePath) {
|
|
42
|
+
return assertInsideRoot(this.root, path.resolve(this.root, relativePath), "artifact path");
|
|
43
|
+
}
|
|
44
|
+
artifactDir(artifactId) {
|
|
45
|
+
if (!isArtifactId(artifactId)) {
|
|
46
|
+
throw new DocumentError("INVALID_INPUT", `"${artifactId}" is not an artifact id`);
|
|
47
|
+
}
|
|
48
|
+
return this.path(artifactId);
|
|
49
|
+
}
|
|
50
|
+
/** Prepare a fresh bundle directory and return its id. */
|
|
51
|
+
async create(now = Date.now()) {
|
|
52
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
53
|
+
const artifactId = createArtifactId(now);
|
|
54
|
+
const dir = this.artifactDir(artifactId);
|
|
55
|
+
try {
|
|
56
|
+
await mkdir(dir, { recursive: false });
|
|
57
|
+
return { artifactId, dir };
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error.code !== "EEXIST") {
|
|
61
|
+
throw asDocumentError(error, "ARTIFACT_WRITE_FAILED");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
throw new DocumentError("ARTIFACT_WRITE_FAILED", "unable to allocate an artifact directory");
|
|
66
|
+
}
|
|
67
|
+
async ensureDir(relativePath) {
|
|
68
|
+
const target = this.path(relativePath);
|
|
69
|
+
await mkdir(target, { recursive: true });
|
|
70
|
+
return target;
|
|
71
|
+
}
|
|
72
|
+
/** Atomically write a root-relative member. */
|
|
73
|
+
async write(relativePath, data) {
|
|
74
|
+
const target = this.path(relativePath);
|
|
75
|
+
const payload = typeof data === "string" ? Buffer.from(data, "utf8") : data;
|
|
76
|
+
const temp = `${target}.tmp-${randomBytes(6).toString("hex")}`;
|
|
77
|
+
try {
|
|
78
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
79
|
+
await writeFile(temp, payload);
|
|
80
|
+
await rename(temp, target);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
await rm(temp, { force: true }).catch(() => undefined);
|
|
84
|
+
throw asDocumentError(error, "ARTIFACT_WRITE_FAILED");
|
|
85
|
+
}
|
|
86
|
+
return { path: target, size: payload.length, sha256: sha256Hex(payload) };
|
|
87
|
+
}
|
|
88
|
+
async read(relativePath) {
|
|
89
|
+
return readFile(this.path(relativePath));
|
|
90
|
+
}
|
|
91
|
+
async fingerprint(relativePath) {
|
|
92
|
+
const target = this.path(relativePath);
|
|
93
|
+
const details = await stat(target);
|
|
94
|
+
return {
|
|
95
|
+
path: target,
|
|
96
|
+
size: details.size,
|
|
97
|
+
sha256: await sha256OfFile(target),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async exists(relativePath) {
|
|
101
|
+
try {
|
|
102
|
+
await stat(this.path(relativePath));
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Job-scoped temp directory: never an artifact, always removed (§47). */
|
|
110
|
+
async createWorkDir(jobId) {
|
|
111
|
+
const dir = this.path(path.join(".tmp", jobId));
|
|
112
|
+
await mkdir(dir, { recursive: true });
|
|
113
|
+
return dir;
|
|
114
|
+
}
|
|
115
|
+
async removeWorkDir(dir) {
|
|
116
|
+
if (!path.resolve(dir).startsWith(this.path(".tmp")))
|
|
117
|
+
return;
|
|
118
|
+
await rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
119
|
+
}
|
|
120
|
+
/** Bundle directories, newest first, with their modification time. */
|
|
121
|
+
async list() {
|
|
122
|
+
let names;
|
|
123
|
+
try {
|
|
124
|
+
names = await readdir(this.root);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
const artifacts = [];
|
|
130
|
+
for (const name of names) {
|
|
131
|
+
if (!isArtifactId(name))
|
|
132
|
+
continue;
|
|
133
|
+
const dir = this.path(name);
|
|
134
|
+
try {
|
|
135
|
+
const details = await stat(dir);
|
|
136
|
+
if (!details.isDirectory())
|
|
137
|
+
continue;
|
|
138
|
+
artifacts.push({ artifactId: name, dir, modifiedAt: details.mtime });
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return artifacts.sort((left, right) => left.modifiedAt < right.modifiedAt ? 1 : -1);
|
|
145
|
+
}
|
|
146
|
+
/** Retention sweep (§41): drop bundles older than `maxAgeDays`. */
|
|
147
|
+
async cleanup(options) {
|
|
148
|
+
const cutoff = (options.now ?? new Date()).getTime() - options.maxAgeDays * 86_400_000;
|
|
149
|
+
const removed = [];
|
|
150
|
+
for (const artifact of await this.list()) {
|
|
151
|
+
if (artifact.modifiedAt.getTime() >= cutoff)
|
|
152
|
+
continue;
|
|
153
|
+
await rm(artifact.dir, { recursive: true, force: true }).catch(() => undefined);
|
|
154
|
+
removed.push(artifact.artifactId);
|
|
155
|
+
}
|
|
156
|
+
const tempRoot = this.path(".tmp");
|
|
157
|
+
const tempNames = await readdir(tempRoot).catch(() => []);
|
|
158
|
+
for (const name of tempNames) {
|
|
159
|
+
const dir = path.join(tempRoot, name);
|
|
160
|
+
const details = await stat(dir).catch(() => undefined);
|
|
161
|
+
if (details === undefined || details.mtime.getTime() >= cutoff)
|
|
162
|
+
continue;
|
|
163
|
+
await rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
164
|
+
}
|
|
165
|
+
await rm(tempRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
166
|
+
return { removed };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/documents/artifacts/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability discovery (§43) and backend health (§42).
|
|
3
|
+
*
|
|
4
|
+
* Health separates required from optional backends on purpose: a deployment
|
|
5
|
+
* without Docling cannot extract PDFs, but it still creates documents, so the
|
|
6
|
+
* subsystem reports `degraded` and names what is missing instead of declaring
|
|
7
|
+
* itself down. An optional backend that was never enabled reports `disabled`,
|
|
8
|
+
* which is not a fault.
|
|
9
|
+
*/
|
|
10
|
+
import { createProviders, } from "./providers/registry.js";
|
|
11
|
+
import { runProcess } from "./providers/process.js";
|
|
12
|
+
import { CONVERSION_ROUTES } from "./orchestrator/convert-document.js";
|
|
13
|
+
import { loadTemplateRegistry, templateNames, } from "./templates/registry.js";
|
|
14
|
+
async function probeExecutable(executable, timeoutMs) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await runProcess(executable, ["--version"], {
|
|
17
|
+
timeoutMs: Math.min(timeoutMs, 10_000),
|
|
18
|
+
maxStdoutBytes: 8 * 1024,
|
|
19
|
+
backend: executable,
|
|
20
|
+
context: "probing backend availability",
|
|
21
|
+
});
|
|
22
|
+
return result.exitCode === 0 ? "ok" : "unavailable";
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return "unavailable";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function documentHealth(options) {
|
|
29
|
+
const { config, providers } = options;
|
|
30
|
+
const required = {};
|
|
31
|
+
const optional = {};
|
|
32
|
+
required["pandoc"] =
|
|
33
|
+
options.probeProcessBackends === false
|
|
34
|
+
? "ok"
|
|
35
|
+
: await probeExecutable(config.pandoc.executable, config.pandoc.timeoutMs);
|
|
36
|
+
required["libreoffice"] =
|
|
37
|
+
options.probeProcessBackends === false
|
|
38
|
+
? "ok"
|
|
39
|
+
: await probeExecutable(config.libreoffice.executable, config.libreoffice.timeoutMs);
|
|
40
|
+
required["docling"] =
|
|
41
|
+
providers.doclingHealth === undefined
|
|
42
|
+
? "disabled"
|
|
43
|
+
: await providers.doclingHealth();
|
|
44
|
+
optional["typst"] = config.typst.enabled ? "ok" : "disabled";
|
|
45
|
+
optional["markitdown"] =
|
|
46
|
+
providers.markitdownHealth === undefined
|
|
47
|
+
? "disabled"
|
|
48
|
+
: await providers.markitdownHealth();
|
|
49
|
+
const requiredValues = Object.values(required);
|
|
50
|
+
const status = requiredValues.every((entry) => entry === "ok")
|
|
51
|
+
? "ok"
|
|
52
|
+
: requiredValues.every((entry) => entry !== "ok")
|
|
53
|
+
? "unavailable"
|
|
54
|
+
: "degraded";
|
|
55
|
+
return { status, required, optional };
|
|
56
|
+
}
|
|
57
|
+
export function documentCapabilities(options) {
|
|
58
|
+
const config = options.config;
|
|
59
|
+
const create = [...config.create.allowFormats];
|
|
60
|
+
const extract = [];
|
|
61
|
+
if (options.providers.docling !== undefined)
|
|
62
|
+
extract.push("docx", "pdf");
|
|
63
|
+
else if (options.providers.markitdown !== undefined)
|
|
64
|
+
extract.push("docx", "pdf");
|
|
65
|
+
const convert = CONVERSION_ROUTES.filter(([from, to]) => {
|
|
66
|
+
if (from === "md")
|
|
67
|
+
return to === "docx" ? create.includes("docx") : create.includes("pdf");
|
|
68
|
+
return extract.includes(from);
|
|
69
|
+
}).map(([from, to]) => [from, to]);
|
|
70
|
+
return {
|
|
71
|
+
enabled: config.enabled,
|
|
72
|
+
create,
|
|
73
|
+
extract,
|
|
74
|
+
convert,
|
|
75
|
+
ocr: config.docling.enabled || options.providers.markitdown !== undefined,
|
|
76
|
+
templates: templateNames(options.templates),
|
|
77
|
+
pdfModes: config.typst.enabled
|
|
78
|
+
? ["auto", "office", "typst"]
|
|
79
|
+
: ["auto", "office"],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Load the template registry of a workspace for capability reporting. */
|
|
83
|
+
export async function capabilitiesForRoot(options) {
|
|
84
|
+
const templates = options.templateRoot === undefined
|
|
85
|
+
? await loadTemplateRegistry(undefined)
|
|
86
|
+
: await loadTemplateRegistry(options.templateRoot);
|
|
87
|
+
return documentCapabilities({
|
|
88
|
+
config: options.config,
|
|
89
|
+
providers: createProviders(options.config, options.seams ?? {}),
|
|
90
|
+
templates,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/documents/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration of the document subsystem (§20).
|
|
3
|
+
*
|
|
4
|
+
* The subsystem is part of the `qa-surface` namespace, so this resolver
|
|
5
|
+
* follows the same shape as the other domains: it normalizes, validates and
|
|
6
|
+
* freezes, and the schema in `src/config.ts` takes every default from
|
|
7
|
+
* {@link DEFAULT_QA_DOCUMENTS_CONFIG} so an untouched deployment sends the
|
|
8
|
+
* resolver nothing at all.
|
|
9
|
+
*
|
|
10
|
+
* Environment overrides are applied in `applyDocumentsEnvOverrides`, on the
|
|
11
|
+
* way into the plugin, and only for the documented variables — a deployment
|
|
12
|
+
* that injects secrets into the process environment does not thereby get to
|
|
13
|
+
* reconfigure the pipeline.
|
|
14
|
+
*/
|
|
15
|
+
import { DEFAULT_QA_DOCUMENTS_CONFIG, } from "./defaults.js";
|
|
16
|
+
import { DocumentError } from "./errors.js";
|
|
17
|
+
export { DEFAULT_QA_DOCUMENTS_CONFIG, } from "./defaults.js";
|
|
18
|
+
const MS_PER_MINUTE = 60_000;
|
|
19
|
+
/**
|
|
20
|
+
* Absolute-path test for the configuration surface.
|
|
21
|
+
*
|
|
22
|
+
* A hand-rolled check rather than `node:path.isAbsolute`: the schema that reads
|
|
23
|
+
* these defaults is bundled into the browser settings page, and the page cannot
|
|
24
|
+
* load a Node builtin. Only absolute paths are accepted, so there is nothing to
|
|
25
|
+
* resolve here — canonicalization happens host-side, when the path is used.
|
|
26
|
+
*/
|
|
27
|
+
function isAbsolutePath(value) {
|
|
28
|
+
return (/^[A-Za-z]:[\\/]/u.test(value) ||
|
|
29
|
+
value.startsWith("/") ||
|
|
30
|
+
value.startsWith("\\\\"));
|
|
31
|
+
}
|
|
32
|
+
function readBoolean(value, fallback) {
|
|
33
|
+
return typeof value === "boolean" ? value : fallback;
|
|
34
|
+
}
|
|
35
|
+
function readInteger(value, fallback, bounds, label) {
|
|
36
|
+
if (value === undefined || value === null)
|
|
37
|
+
return fallback;
|
|
38
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
39
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be a number`);
|
|
40
|
+
}
|
|
41
|
+
const rounded = Math.round(value);
|
|
42
|
+
if (rounded < bounds.min || rounded > bounds.max) {
|
|
43
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be between ${bounds.min} and ${bounds.max}`, { details: { label, value } });
|
|
44
|
+
}
|
|
45
|
+
return rounded;
|
|
46
|
+
}
|
|
47
|
+
function readString(value, fallback, label) {
|
|
48
|
+
if (value === undefined || value === null)
|
|
49
|
+
return fallback;
|
|
50
|
+
if (typeof value !== "string") {
|
|
51
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be a string`);
|
|
52
|
+
}
|
|
53
|
+
const trimmed = value.trim();
|
|
54
|
+
return trimmed === "" ? fallback : trimmed;
|
|
55
|
+
}
|
|
56
|
+
function readNullableAbsolutePath(value, label) {
|
|
57
|
+
if (value === undefined || value === null)
|
|
58
|
+
return null;
|
|
59
|
+
if (typeof value !== "string") {
|
|
60
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be a path`);
|
|
61
|
+
}
|
|
62
|
+
const trimmed = value.trim();
|
|
63
|
+
if (trimmed === "")
|
|
64
|
+
return null;
|
|
65
|
+
if (!isAbsolutePath(trimmed)) {
|
|
66
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be an absolute path (relative and traversal forms are refused)`, { details: { label } });
|
|
67
|
+
}
|
|
68
|
+
return trimmed;
|
|
69
|
+
}
|
|
70
|
+
function readEnum(value, allowed, fallback, label) {
|
|
71
|
+
if (value === undefined || value === null)
|
|
72
|
+
return fallback;
|
|
73
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
74
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be one of: ${allowed.join(", ")}`, { details: { label } });
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function readStringList(value, fallback) {
|
|
79
|
+
if (!Array.isArray(value))
|
|
80
|
+
return [...fallback];
|
|
81
|
+
const entries = value
|
|
82
|
+
.filter((entry) => typeof entry === "string")
|
|
83
|
+
.map((entry) => entry.trim())
|
|
84
|
+
.filter((entry) => entry !== "");
|
|
85
|
+
return [...new Set(entries)];
|
|
86
|
+
}
|
|
87
|
+
function readAbsolutePathList(value, label) {
|
|
88
|
+
if (!Array.isArray(value))
|
|
89
|
+
return [];
|
|
90
|
+
return value.map((entry) => {
|
|
91
|
+
if (typeof entry !== "string" || entry.trim() === "") {
|
|
92
|
+
throw new DocumentError("INVALID_INPUT", `${label} entries must be paths`);
|
|
93
|
+
}
|
|
94
|
+
const entryPath = entry.trim();
|
|
95
|
+
if (!isAbsolutePath(entryPath)) {
|
|
96
|
+
throw new DocumentError("INVALID_INPUT", `${label} entries must be absolute paths`);
|
|
97
|
+
}
|
|
98
|
+
return entryPath;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function assertHttpUrl(value, label) {
|
|
102
|
+
let parsed;
|
|
103
|
+
try {
|
|
104
|
+
parsed = new URL(value);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be an http(s) URL`);
|
|
108
|
+
}
|
|
109
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
110
|
+
throw new DocumentError("INVALID_INPUT", `${label} must be an http(s) URL`);
|
|
111
|
+
}
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
/** Materialize and validate the document configuration. */
|
|
115
|
+
export function resolveDocumentsConfig(input = {}) {
|
|
116
|
+
const D = DEFAULT_QA_DOCUMENTS_CONFIG;
|
|
117
|
+
const storage = input.storage ?? {};
|
|
118
|
+
const templates = input.templates ?? {};
|
|
119
|
+
const create = input.create ?? {};
|
|
120
|
+
const extraction = input.extraction ?? {};
|
|
121
|
+
const docling = input.docling ?? {};
|
|
122
|
+
const pandoc = input.pandoc ?? {};
|
|
123
|
+
const libreoffice = input.libreoffice ?? {};
|
|
124
|
+
const typst = input.typst ?? {};
|
|
125
|
+
const markitdown = input.markitdown ?? {};
|
|
126
|
+
const workers = input.workers ?? {};
|
|
127
|
+
const retention = input.retention ?? {};
|
|
128
|
+
const limits = input.limits ?? {};
|
|
129
|
+
const allowFormats = readStringList(create.allowFormats, D.create.allowFormats).filter((entry) => entry === "docx" || entry === "pdf");
|
|
130
|
+
if (allowFormats.length === 0) {
|
|
131
|
+
throw new DocumentError("INVALID_INPUT", "documents.create.allowFormats must list at least one of: docx, pdf");
|
|
132
|
+
}
|
|
133
|
+
return Object.freeze({
|
|
134
|
+
enabled: readBoolean(input.enabled, D.enabled),
|
|
135
|
+
storage: Object.freeze({
|
|
136
|
+
root: readNullableAbsolutePath(storage.root, "documents.storage.root"),
|
|
137
|
+
retainSource: readBoolean(storage.retainSource, D.storage.retainSource),
|
|
138
|
+
retainInputs: readBoolean(storage.retainInputs, D.storage.retainInputs),
|
|
139
|
+
allowedInputRoots: Object.freeze(readAbsolutePathList(storage.allowedInputRoots, "documents.storage.allowedInputRoots")),
|
|
140
|
+
}),
|
|
141
|
+
templates: Object.freeze({
|
|
142
|
+
root: readNullableAbsolutePath(templates.root, "documents.templates.root"),
|
|
143
|
+
default: readString(templates.default, D.templates.default, "documents.templates.default"),
|
|
144
|
+
}),
|
|
145
|
+
create: Object.freeze({
|
|
146
|
+
defaultPdfMode: readEnum(create.defaultPdfMode, ["auto", "office", "typst"], D.create.defaultPdfMode, "documents.create.defaultPdfMode"),
|
|
147
|
+
allowFormats: Object.freeze(allowFormats),
|
|
148
|
+
allowRawMarkup: readBoolean(create.allowRawMarkup, D.create.allowRawMarkup),
|
|
149
|
+
toc: readBoolean(create.toc, D.create.toc),
|
|
150
|
+
}),
|
|
151
|
+
extraction: Object.freeze({
|
|
152
|
+
defaultMode: readEnum(extraction.defaultMode, ["auto", "fast", "accurate"], D.extraction.defaultMode, "documents.extraction.defaultMode"),
|
|
153
|
+
ocr: readEnum(extraction.ocr, ["auto", "off", "force"], D.extraction.ocr, "documents.extraction.ocr"),
|
|
154
|
+
ocrLanguages: Object.freeze(readStringList(extraction.ocrLanguages, D.extraction.ocrLanguages)),
|
|
155
|
+
extractImages: readBoolean(extraction.extractImages, D.extraction.extractImages),
|
|
156
|
+
extractTables: readBoolean(extraction.extractTables, D.extraction.extractTables),
|
|
157
|
+
preservePageMarkers: readBoolean(extraction.preservePageMarkers, D.extraction.preservePageMarkers),
|
|
158
|
+
allowFallback: readBoolean(extraction.allowFallback, D.extraction.allowFallback),
|
|
159
|
+
maxInlineChars: readInteger(extraction.maxInlineChars, D.extraction.maxInlineChars, { min: 1_000, max: 5_000_000 }, "documents.extraction.maxInlineChars"),
|
|
160
|
+
}),
|
|
161
|
+
docling: Object.freeze({
|
|
162
|
+
enabled: readBoolean(docling.enabled, D.docling.enabled),
|
|
163
|
+
baseUrl: assertHttpUrl(readString(docling.baseUrl, D.docling.baseUrl, "documents.docling.baseUrl").replace(/\/+$/u, ""), "documents.docling.baseUrl"),
|
|
164
|
+
timeoutMs: readInteger(docling.timeoutMs, D.docling.timeoutMs, { min: 1_000, max: 600_000 }, "documents.docling.timeoutMs"),
|
|
165
|
+
}),
|
|
166
|
+
pandoc: Object.freeze({
|
|
167
|
+
executable: readString(pandoc.executable, D.pandoc.executable, "documents.pandoc.executable"),
|
|
168
|
+
timeoutMs: readInteger(pandoc.timeoutMs, D.pandoc.timeoutMs, { min: 1_000, max: 600_000 }, "documents.pandoc.timeoutMs"),
|
|
169
|
+
}),
|
|
170
|
+
libreoffice: Object.freeze({
|
|
171
|
+
executable: readString(libreoffice.executable, D.libreoffice.executable, "documents.libreoffice.executable"),
|
|
172
|
+
timeoutMs: readInteger(libreoffice.timeoutMs, D.libreoffice.timeoutMs, { min: 1_000, max: 600_000 }, "documents.libreoffice.timeoutMs"),
|
|
173
|
+
}),
|
|
174
|
+
typst: Object.freeze({
|
|
175
|
+
enabled: readBoolean(typst.enabled, D.typst.enabled),
|
|
176
|
+
executable: readString(typst.executable, D.typst.executable, "documents.typst.executable"),
|
|
177
|
+
timeoutMs: readInteger(typst.timeoutMs, D.typst.timeoutMs, { min: 1_000, max: 600_000 }, "documents.typst.timeoutMs"),
|
|
178
|
+
}),
|
|
179
|
+
markitdown: Object.freeze({
|
|
180
|
+
enabled: readBoolean(markitdown.enabled, D.markitdown.enabled),
|
|
181
|
+
executable: readString(markitdown.executable, D.markitdown.executable, "documents.markitdown.executable"),
|
|
182
|
+
timeoutMs: readInteger(markitdown.timeoutMs, D.markitdown.timeoutMs, { min: 1_000, max: 600_000 }, "documents.markitdown.timeoutMs"),
|
|
183
|
+
}),
|
|
184
|
+
workers: Object.freeze({
|
|
185
|
+
renderConcurrency: readInteger(workers.renderConcurrency, D.workers.renderConcurrency, { min: 1, max: 16 }, "documents.workers.renderConcurrency"),
|
|
186
|
+
extractionConcurrency: readInteger(workers.extractionConcurrency, D.workers.extractionConcurrency, { min: 1, max: 16 }, "documents.workers.extractionConcurrency"),
|
|
187
|
+
ocrConcurrency: readInteger(workers.ocrConcurrency, D.workers.ocrConcurrency, { min: 1, max: 16 }, "documents.workers.ocrConcurrency"),
|
|
188
|
+
}),
|
|
189
|
+
retention: Object.freeze({
|
|
190
|
+
enabled: readBoolean(retention.enabled, D.retention.enabled),
|
|
191
|
+
maxAgeDays: readInteger(retention.maxAgeDays, D.retention.maxAgeDays, { min: 1, max: 3_650 }, "documents.retention.maxAgeDays"),
|
|
192
|
+
cleanupIntervalHours: readInteger(retention.cleanupIntervalHours, D.retention.cleanupIntervalHours, { min: 1, max: 168 }, "documents.retention.cleanupIntervalHours"),
|
|
193
|
+
}),
|
|
194
|
+
limits: Object.freeze({
|
|
195
|
+
maxInputBytes: readInteger(limits.maxInputBytes, D.limits.maxInputBytes, { min: 1_024, max: 4_294_967_296 }, "documents.limits.maxInputBytes"),
|
|
196
|
+
maxMarkdownChars: readInteger(limits.maxMarkdownChars, D.limits.maxMarkdownChars, { min: 1_000, max: 50_000_000 }, "documents.limits.maxMarkdownChars"),
|
|
197
|
+
maxPages: readInteger(limits.maxPages, D.limits.maxPages, { min: 1, max: 100_000 }, "documents.limits.maxPages"),
|
|
198
|
+
maxExtractedImages: readInteger(limits.maxExtractedImages, D.limits.maxExtractedImages, { min: 0, max: 10_000 }, "documents.limits.maxExtractedImages"),
|
|
199
|
+
maxAssetBytes: readInteger(limits.maxAssetBytes, D.limits.maxAssetBytes, { min: 1_024, max: 1_073_741_824 }, "documents.limits.maxAssetBytes"),
|
|
200
|
+
maxResponseBytes: readInteger(limits.maxResponseBytes, D.limits.maxResponseBytes, { min: 1_024, max: 1_073_741_824 }, "documents.limits.maxResponseBytes"),
|
|
201
|
+
maxExtractedMarkdownBytes: readInteger(limits.maxExtractedMarkdownBytes, D.limits.maxExtractedMarkdownBytes, { min: 1_024, max: 1_073_741_824 }, "documents.limits.maxExtractedMarkdownBytes"),
|
|
202
|
+
allowedAssetMimeTypes: Object.freeze(readStringList(limits.allowedAssetMimeTypes, D.limits.allowedAssetMimeTypes).map((entry) => entry.toLowerCase())),
|
|
203
|
+
}),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/** Parse a boolean env value; unknown text leaves the configured value. */
|
|
207
|
+
function envBoolean(raw, fallback) {
|
|
208
|
+
if (raw === undefined)
|
|
209
|
+
return fallback;
|
|
210
|
+
const normalized = raw.trim().toLowerCase();
|
|
211
|
+
if (["1", "true", "yes", "on"].includes(normalized))
|
|
212
|
+
return true;
|
|
213
|
+
if (["0", "false", "no", "off"].includes(normalized))
|
|
214
|
+
return false;
|
|
215
|
+
return fallback;
|
|
216
|
+
}
|
|
217
|
+
function envInteger(raw, fallback) {
|
|
218
|
+
if (raw === undefined)
|
|
219
|
+
return fallback;
|
|
220
|
+
const parsed = Number.parseInt(raw.trim(), 10);
|
|
221
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Apply the documented environment overrides (§20). Kept out of
|
|
225
|
+
* {@link resolveDocumentsConfig} so the resolver stays a pure function of its
|
|
226
|
+
* input — configuration tests never depend on the ambient environment.
|
|
227
|
+
*/
|
|
228
|
+
export function applyDocumentsEnvOverrides(config, env) {
|
|
229
|
+
const value = (key) => {
|
|
230
|
+
const raw = env[key];
|
|
231
|
+
return raw === undefined || raw.trim() === "" ? undefined : raw.trim();
|
|
232
|
+
};
|
|
233
|
+
const storageRoot = value("QA_DOCUMENTS_STORAGE_ROOT");
|
|
234
|
+
const templatesRoot = value("QA_DOCUMENTS_TEMPLATES_ROOT");
|
|
235
|
+
const doclingBaseUrl = value("QA_DOCLING_BASE_URL");
|
|
236
|
+
const doclingTimeout = value("QA_DOCLING_TIMEOUT_MS");
|
|
237
|
+
const pandocExecutable = value("QA_PANDOC_EXECUTABLE");
|
|
238
|
+
const libreofficeExecutable = value("QA_LIBREOFFICE_EXECUTABLE");
|
|
239
|
+
const markitdownExecutable = value("QA_MARKITDOWN_EXECUTABLE");
|
|
240
|
+
const ocrLanguages = value("QA_DOCUMENTS_OCR_LANGUAGES");
|
|
241
|
+
const maxInputBytes = value("QA_DOCUMENTS_MAX_INPUT_BYTES");
|
|
242
|
+
return {
|
|
243
|
+
...config,
|
|
244
|
+
enabled: envBoolean(value("QA_DOCUMENTS_ENABLED"), config.enabled ?? true),
|
|
245
|
+
storage: {
|
|
246
|
+
...config.storage,
|
|
247
|
+
...(storageRoot === undefined ? {} : { root: storageRoot }),
|
|
248
|
+
},
|
|
249
|
+
templates: {
|
|
250
|
+
...config.templates,
|
|
251
|
+
...(templatesRoot === undefined ? {} : { root: templatesRoot }),
|
|
252
|
+
},
|
|
253
|
+
docling: {
|
|
254
|
+
...config.docling,
|
|
255
|
+
...(doclingBaseUrl === undefined ? {} : { baseUrl: doclingBaseUrl }),
|
|
256
|
+
...(doclingTimeout === undefined
|
|
257
|
+
? {}
|
|
258
|
+
: {
|
|
259
|
+
timeoutMs: envInteger(doclingTimeout, config.docling?.timeoutMs ?? 0),
|
|
260
|
+
}),
|
|
261
|
+
},
|
|
262
|
+
pandoc: {
|
|
263
|
+
...config.pandoc,
|
|
264
|
+
...(pandocExecutable === undefined
|
|
265
|
+
? {}
|
|
266
|
+
: { executable: pandocExecutable }),
|
|
267
|
+
},
|
|
268
|
+
libreoffice: {
|
|
269
|
+
...config.libreoffice,
|
|
270
|
+
...(libreofficeExecutable === undefined
|
|
271
|
+
? {}
|
|
272
|
+
: { executable: libreofficeExecutable }),
|
|
273
|
+
},
|
|
274
|
+
markitdown: {
|
|
275
|
+
...config.markitdown,
|
|
276
|
+
...(markitdownExecutable === undefined
|
|
277
|
+
? {}
|
|
278
|
+
: { executable: markitdownExecutable }),
|
|
279
|
+
},
|
|
280
|
+
extraction: {
|
|
281
|
+
...config.extraction,
|
|
282
|
+
...(ocrLanguages === undefined
|
|
283
|
+
? {}
|
|
284
|
+
: {
|
|
285
|
+
ocrLanguages: ocrLanguages.split(",").map((entry) => entry.trim()),
|
|
286
|
+
}),
|
|
287
|
+
},
|
|
288
|
+
limits: {
|
|
289
|
+
...config.limits,
|
|
290
|
+
...(maxInputBytes === undefined
|
|
291
|
+
? {}
|
|
292
|
+
: {
|
|
293
|
+
maxInputBytes: envInteger(maxInputBytes, config.limits?.maxInputBytes ?? 0),
|
|
294
|
+
}),
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/** Milliseconds a retention sweep interval would wait. */
|
|
299
|
+
export function retentionIntervalMs(config) {
|
|
300
|
+
return config.retention.cleanupIntervalHours * 60 * MS_PER_MINUTE;
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=config.js.map
|