@arnilo/prism-tools 0.0.0-stage → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +418 -0
- package/LICENSE +21 -0
- package/README.md +44 -2
- package/browser/README.md +98 -0
- package/browser/skills/browser-automation/SKILL.md +14 -0
- package/browser/src/actions/cdp.ts +131 -0
- package/browser/src/actions/dialog.ts +25 -0
- package/browser/src/actions/download_release.ts +22 -0
- package/browser/src/actions/index.ts +37 -0
- package/browser/src/actions/locator.ts +70 -0
- package/browser/src/actions/navigate.ts +23 -0
- package/browser/src/actions/screenshot.ts +27 -0
- package/browser/src/actions/scroll.ts +24 -0
- package/browser/src/actions/select_page.ts +21 -0
- package/browser/src/actions/types.ts +114 -0
- package/browser/src/actions/upload.ts +44 -0
- package/browser/src/actions/wait.ts +45 -0
- package/browser/src/browser.ts +197 -0
- package/browser/src/cdp.ts +178 -0
- package/browser/src/checkpoint.ts +189 -0
- package/browser/src/config.ts +72 -0
- package/browser/src/downloads.ts +253 -0
- package/browser/src/errors.ts +31 -0
- package/browser/src/evaluate.ts +101 -0
- package/browser/src/index.ts +129 -0
- package/browser/src/limits.ts +271 -0
- package/browser/src/manager.ts +730 -0
- package/browser/src/network.ts +263 -0
- package/browser/src/observe.ts +178 -0
- package/browser/src/policy.ts +133 -0
- package/browser/src/screenshot.ts +107 -0
- package/browser/src/shared-sandbox.ts +53 -0
- package/browser/src/snapshot.ts +99 -0
- package/browser/src/targets.ts +165 -0
- package/browser/src/tools.ts +480 -0
- package/browser/src/types.ts +316 -0
- package/browser/src/uploads.ts +174 -0
- package/coding/README.md +337 -0
- package/coding/src/agent/acp-operations.ts +146 -0
- package/coding/src/agent/artifacts.ts +38 -0
- package/coding/src/agent/ask-user-decision.ts +623 -0
- package/coding/src/agent/atomic-write.ts +23 -0
- package/coding/src/agent/bounded-file.ts +21 -0
- package/coding/src/agent/checks.ts +301 -0
- package/coding/src/agent/coding-checkpoint.ts +828 -0
- package/coding/src/agent/delete.ts +237 -0
- package/coding/src/agent/diagnostics-tool.ts +163 -0
- package/coding/src/agent/diagnostics.ts +262 -0
- package/coding/src/agent/edit-diff.ts +382 -0
- package/coding/src/agent/edit.ts +322 -0
- package/coding/src/agent/effects.ts +102 -0
- package/coding/src/agent/env.ts +28 -0
- package/coding/src/agent/execution-policy.ts +89 -0
- package/coding/src/agent/file-mutation-queue.ts +72 -0
- package/coding/src/agent/forge/github.ts +603 -0
- package/coding/src/agent/forge/index.ts +16 -0
- package/coding/src/agent/forge/types.ts +185 -0
- package/coding/src/agent/git-aware-repository.ts +305 -0
- package/coding/src/agent/git-exec.ts +326 -0
- package/coding/src/agent/git-status.ts +177 -0
- package/coding/src/agent/git-tools.ts +360 -0
- package/coding/src/agent/git.ts +1074 -0
- package/coding/src/agent/glob-match.ts +146 -0
- package/coding/src/agent/glob.ts +182 -0
- package/coding/src/agent/goal-verify.ts +385 -0
- package/coding/src/agent/grep-worker.ts +74 -0
- package/coding/src/agent/grep.ts +459 -0
- package/coding/src/agent/identity.ts +48 -0
- package/coding/src/agent/index.ts +676 -0
- package/coding/src/agent/language/client.ts +429 -0
- package/coding/src/agent/language/framing.ts +190 -0
- package/coding/src/agent/language/index.ts +23 -0
- package/coding/src/agent/language/intelligence.ts +682 -0
- package/coding/src/agent/language/types.ts +187 -0
- package/coding/src/agent/lifecycle-events.ts +121 -0
- package/coding/src/agent/lifecycle.ts +166 -0
- package/coding/src/agent/limits.ts +214 -0
- package/coding/src/agent/move.ts +178 -0
- package/coding/src/agent/mutation-path.ts +52 -0
- package/coding/src/agent/output-accumulator.ts +304 -0
- package/coding/src/agent/path-utils.ts +120 -0
- package/coding/src/agent/process/index.ts +58 -0
- package/coding/src/agent/process/recovery.ts +508 -0
- package/coding/src/agent/process/sessions-host.ts +222 -0
- package/coding/src/agent/process/sessions-monitor.ts +141 -0
- package/coding/src/agent/process/sessions-recovery.ts +241 -0
- package/coding/src/agent/process/sessions-spawn.ts +613 -0
- package/coding/src/agent/process/sessions-teardown.ts +281 -0
- package/coding/src/agent/process/sessions.ts +30 -0
- package/coding/src/agent/process/types.ts +358 -0
- package/coding/src/agent/read-path-set.ts +126 -0
- package/coding/src/agent/read.ts +713 -0
- package/coding/src/agent/repository/glob.ts +147 -0
- package/coding/src/agent/repository/indexed-search.ts +480 -0
- package/coding/src/agent/repository/list.ts +131 -0
- package/coding/src/agent/repository/operations.ts +22 -0
- package/coding/src/agent/repository/path.ts +98 -0
- package/coding/src/agent/repository/search.ts +277 -0
- package/coding/src/agent/repository/types.ts +243 -0
- package/coding/src/agent/repository/walk.ts +126 -0
- package/coding/src/agent/repository.ts +12 -0
- package/coding/src/agent/shell-background.ts +264 -0
- package/coding/src/agent/shell-output.ts +75 -0
- package/coding/src/agent/shell.ts +526 -0
- package/coding/src/agent/todo.ts +399 -0
- package/coding/src/agent/truncate.ts +251 -0
- package/coding/src/agent/write.ts +170 -0
- package/coding/src/ask-user-host.ts +48 -0
- package/coding/src/config.ts +278 -0
- package/coding/src/hard-deny.ts +97 -0
- package/coding/src/index.ts +318 -0
- package/coding/src/principal-guard.ts +84 -0
- package/coding/src/sandbox.ts +92 -0
- package/coding/src/security/approval.ts +144 -0
- package/coding/src/security/command-rules.ts +57 -0
- package/coding/src/security/docker-cli.ts +222 -0
- package/coding/src/security/docker-sandbox.ts +1205 -0
- package/coding/src/security/e2b-sandbox.ts +853 -0
- package/coding/src/security/egress/dns-pin.ts +88 -0
- package/coding/src/security/egress/index.ts +32 -0
- package/coding/src/security/egress/limits.ts +57 -0
- package/coding/src/security/egress/policy.ts +137 -0
- package/coding/src/security/egress/proxy.ts +599 -0
- package/coding/src/security/egress/types.ts +30 -0
- package/coding/src/security/index.ts +199 -0
- package/coding/src/security/native-sandbox.ts +639 -0
- package/coding/src/security/path-containment.ts +55 -0
- package/coding/src/security/sandbox-coding-operations.ts +392 -0
- package/coding/src/security/sandbox-fs-operations.ts +644 -0
- package/coding/src/security/sandbox-limits.ts +147 -0
- package/coding/src/security/sandbox-tar.ts +308 -0
- package/coding/src/security/sandbox.ts +179 -0
- package/coding/src/security/semaphore.ts +55 -0
- package/coding/src/targets.ts +110 -0
- package/coding/src/workspace/diff.ts +78 -0
- package/coding/src/workspace/errors.ts +29 -0
- package/coding/src/workspace/index.ts +5 -0
- package/coding/src/workspace/merge.ts +151 -0
- package/coding/src/workspace/routing.ts +76 -0
- package/coding/src/workspace/service.ts +584 -0
- package/computer-use/README.md +105 -0
- package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
- package/computer-use/src/classify.ts +53 -0
- package/computer-use/src/command.ts +29 -0
- package/computer-use/src/config.ts +69 -0
- package/computer-use/src/create.ts +170 -0
- package/computer-use/src/devices.ts +247 -0
- package/computer-use/src/env.ts +28 -0
- package/computer-use/src/index.ts +157 -0
- package/computer-use/src/skill.ts +21 -0
- package/openapi/README.md +97 -0
- package/openapi/src/compile.ts +386 -0
- package/openapi/src/config.ts +73 -0
- package/openapi/src/errors.ts +16 -0
- package/openapi/src/execute.ts +241 -0
- package/openapi/src/index.ts +124 -0
- package/openapi/src/limits.ts +63 -0
- package/openapi/src/specs.ts +86 -0
- package/openapi/src/tools.ts +60 -0
- package/openapi/src/types.ts +61 -0
- package/package.json +171 -4
- package/research/README.md +72 -0
- package/research/skills/research-report/SKILL.md +12 -0
- package/research/skills/research-scoping/SKILL.md +10 -0
- package/research/skills/research-synthesis/SKILL.md +10 -0
- package/research/skills/source-triage/SKILL.md +10 -0
- package/research/src/check.ts +71 -0
- package/research/src/config.ts +41 -0
- package/research/src/index.ts +147 -0
- package/research/src/ledger.ts +157 -0
- package/research/src/urls.ts +21 -0
- package/web/README.md +287 -0
- package/web/skills/web-research/SKILL.md +17 -0
- package/web/src/brave.ts +66 -0
- package/web/src/cache.ts +151 -0
- package/web/src/config.ts +210 -0
- package/web/src/controls.ts +128 -0
- package/web/src/domains.ts +114 -0
- package/web/src/exa.ts +60 -0
- package/web/src/firecrawl.ts +160 -0
- package/web/src/index.ts +387 -0
- package/web/src/kagi.ts +73 -0
- package/web/src/limits.ts +55 -0
- package/web/src/native/convert.ts +84 -0
- package/web/src/native/fetch.ts +226 -0
- package/web/src/normalize.ts +131 -0
- package/web/src/obscura/cdp.ts +201 -0
- package/web/src/obscura/classify.ts +35 -0
- package/web/src/obscura/cli.ts +254 -0
- package/web/src/obscura/errors.ts +8 -0
- package/web/src/obscura/index.ts +59 -0
- package/web/src/obscura/limits.ts +92 -0
- package/web/src/obscura/mcp.ts +104 -0
- package/web/src/obscura/playwright.ts +133 -0
- package/web/src/obscura/process.ts +235 -0
- package/web/src/obscura/search-profile.ts +73 -0
- package/web/src/obscura/types.ts +48 -0
- package/web/src/obscura/web.ts +419 -0
- package/web/src/prompt-fetch.ts +88 -0
- package/web/src/render.ts +75 -0
- package/web/src/searxng.ts +78 -0
- package/web/src/slice.ts +139 -0
- package/web/src/tavily.ts +77 -0
- package/web/src/tools.ts +182 -0
- package/web/src/transport.ts +310 -0
- package/web/src/types.ts +199 -0
- package/work/README.md +77 -0
- package/work/THIRD_PARTY_NOTICES +24 -0
- package/work/docling/ocr.py +150 -0
- package/work/sandbox/Dockerfile +36 -0
- package/work/sandbox/soffice.sh +12 -0
- package/work/src/command.ts +29 -0
- package/work/src/config.ts +138 -0
- package/work/src/connectors/cli.ts +343 -0
- package/work/src/connectors/drafts.ts +647 -0
- package/work/src/connectors/errors.ts +8 -0
- package/work/src/connectors/file-bytes.ts +149 -0
- package/work/src/connectors/google-workspace-http.ts +399 -0
- package/work/src/connectors/google-workspace.ts +465 -0
- package/work/src/connectors/gws-tools.ts +378 -0
- package/work/src/connectors/http.ts +123 -0
- package/work/src/connectors/idempotency.ts +235 -0
- package/work/src/connectors/identity.ts +34 -0
- package/work/src/connectors/index.ts +93 -0
- package/work/src/connectors/limits.ts +50 -0
- package/work/src/connectors/m365-tools.ts +308 -0
- package/work/src/connectors/microsoft365-http.ts +428 -0
- package/work/src/connectors/microsoft365.ts +402 -0
- package/work/src/connectors/normalize.ts +120 -0
- package/work/src/connectors/tool-helpers.ts +398 -0
- package/work/src/connectors/tools.ts +42 -0
- package/work/src/connectors/types.ts +399 -0
- package/work/src/diagrams/canonicalize.ts +166 -0
- package/work/src/diagrams/caps.ts +52 -0
- package/work/src/diagrams/embed.ts +340 -0
- package/work/src/diagrams/errors.ts +76 -0
- package/work/src/diagrams/index.ts +81 -0
- package/work/src/diagrams/messages.ts +150 -0
- package/work/src/diagrams/origin.ts +52 -0
- package/work/src/diagrams/telemetry.ts +34 -0
- package/work/src/diagrams/xml.ts +267 -0
- package/work/src/document-extraction/index.ts +563 -0
- package/work/src/document-reader/ambient.d.ts +2 -0
- package/work/src/document-reader/errors.ts +7 -0
- package/work/src/document-reader/index.ts +181 -0
- package/work/src/document-reader/mistral-ocr.ts +318 -0
- package/work/src/document-reader/parsers.ts +171 -0
- package/work/src/documents/caps.ts +135 -0
- package/work/src/documents/diff.ts +269 -0
- package/work/src/documents/errors.ts +44 -0
- package/work/src/documents/fidelity.ts +98 -0
- package/work/src/documents/generate.ts +96 -0
- package/work/src/documents/hash.ts +8 -0
- package/work/src/documents/index.ts +14 -0
- package/work/src/documents/model-schema.ts +639 -0
- package/work/src/documents/parse.ts +252 -0
- package/work/src/documents/patch-history.ts +81 -0
- package/work/src/documents/patch.ts +476 -0
- package/work/src/documents/preview-html.ts +245 -0
- package/work/src/documents/preview.ts +227 -0
- package/work/src/documents/telemetry.ts +36 -0
- package/work/src/documents/translate/docx.ts +292 -0
- package/work/src/documents/translate/pptx.ts +304 -0
- package/work/src/documents/translate/xlsx.ts +137 -0
- package/work/src/documents/types.ts +188 -0
- package/work/src/index.ts +311 -0
- package/work/src/runtime/worker-pool-entry.ts +102 -0
- package/work/src/runtime/worker-pool.ts +267 -0
- package/work/src/sandbox/composition.ts +212 -0
- package/work/src/sandbox/image.ts +6 -0
- package/work/src/sandbox/index.ts +14 -0
- package/work/src/sheets/caps.ts +68 -0
- package/work/src/sheets/csv.ts +351 -0
- package/work/src/sheets/decimal.ts +388 -0
- package/work/src/sheets/errors.ts +52 -0
- package/work/src/sheets/index.ts +62 -0
- package/work/src/sheets/inference.ts +378 -0
- package/work/src/sheets/telemetry.ts +34 -0
- package/work/src/sheets/types.ts +162 -0
- package/work/src/sheets/xlsx.ts +388 -0
- package/work/src/skills/index.ts +8 -0
- package/work/src/skills/load.ts +43 -0
- package/work/src/tools/filesystem.ts +21 -0
- package/work/src/tools/index.ts +1 -0
- package/work/src/tools/local-filesystem.ts +33 -0
- package/work/src/tools/office.ts +311 -0
- package/work/vendor/hermes-agent/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
- package/work/vendor-lock.json +11 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency-free telemetry seam for Diagrams operations.
|
|
3
|
+
* When `telemetry` is omitted, call-sites short-circuit on optional chaining without allocations.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type DiagramsTelemetryAttributeValue = string | number | boolean;
|
|
7
|
+
|
|
8
|
+
export interface DiagramsTelemetrySpan {
|
|
9
|
+
setAttribute(name: string, value: DiagramsTelemetryAttributeValue): void;
|
|
10
|
+
addEvent(name: string, attributes?: Readonly<Record<string, DiagramsTelemetryAttributeValue>>): void;
|
|
11
|
+
recordError(): void;
|
|
12
|
+
end(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DiagramsTelemetry {
|
|
16
|
+
startSpan(
|
|
17
|
+
name: string,
|
|
18
|
+
attributes?: Readonly<Record<string, DiagramsTelemetryAttributeValue>>,
|
|
19
|
+
parent?: DiagramsTelemetrySpan,
|
|
20
|
+
): DiagramsTelemetrySpan;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const noopDiagramsSpan: DiagramsTelemetrySpan = {
|
|
24
|
+
setAttribute() {},
|
|
25
|
+
addEvent() {},
|
|
26
|
+
recordError() {},
|
|
27
|
+
end() {},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const noopDiagramsTelemetry: DiagramsTelemetry = {
|
|
31
|
+
startSpan() {
|
|
32
|
+
return noopDiagramsSpan;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { XMLParser, XMLValidator } from "fast-xml-parser";
|
|
2
|
+
import { type DrawioXmlCaps, type ResolvedDrawioXmlCaps, resolveDiagramsCaps, validateByteCap } from "./caps.js";
|
|
3
|
+
import { DiagramsCapError, DiagramsFormatError, DiagramsModelInvalidError, DiagramsXmlMalformedError, DiagramsXxeError } from "./errors.js";
|
|
4
|
+
import type { DiagramsTelemetry } from "./telemetry.js";
|
|
5
|
+
|
|
6
|
+
export const UNSAFE_XML_DECLARATION_PATTERN = /<!\s*(?:DOCTYPE|ENTITY)/i;
|
|
7
|
+
|
|
8
|
+
const VISIO_OLE_SIGNATURE = new Uint8Array([0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1]);
|
|
9
|
+
|
|
10
|
+
export interface DrawioXmlOptions {
|
|
11
|
+
readonly caps?: DrawioXmlCaps;
|
|
12
|
+
readonly telemetry?: DiagramsTelemetry;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DrawioModelSummary {
|
|
16
|
+
readonly pages: number;
|
|
17
|
+
readonly cells: number;
|
|
18
|
+
readonly edges: number;
|
|
19
|
+
readonly width?: number;
|
|
20
|
+
readonly height?: number;
|
|
21
|
+
readonly compressed?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Asserts that the input is not a Microsoft Visio (.vsd / .vsdx) binary or XML file.
|
|
26
|
+
* Throws {@link DiagramsFormatError} if Visio indicators are detected (P12 guard).
|
|
27
|
+
*/
|
|
28
|
+
export function assertNotVisio(input: string | Uint8Array): void {
|
|
29
|
+
if (input instanceof Uint8Array) {
|
|
30
|
+
if (input.length >= 8) {
|
|
31
|
+
let isOle = true;
|
|
32
|
+
for (let i = 0; i < 8; i++) {
|
|
33
|
+
if (input[i] !== VISIO_OLE_SIGNATURE[i]) {
|
|
34
|
+
isOle = false;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (isOle) {
|
|
39
|
+
throw new DiagramsFormatError("Visio binary format (.vsd) is excluded and unsupported in @arnilo/prism-tools/work (P12)");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Check for ZIP container containing Visio markers (.vsdx)
|
|
43
|
+
if (input.length >= 4 && input[0] === 0x50 && input[1] === 0x4b && input[2] === 0x03 && input[3] === 0x04) {
|
|
44
|
+
const headerSample = Buffer.from(input.subarray(0, Math.min(input.length, 4096))).toString("utf8");
|
|
45
|
+
if (headerSample.includes("visio/") || headerSample.includes("Visio") || headerSample.includes("drawing.xml")) {
|
|
46
|
+
throw new DiagramsFormatError("Visio OpenXML format (.vsdx) is excluded and unsupported in @arnilo/prism-tools/work (P12)");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const text = typeof input === "string" ? input : Buffer.from(input).toString("utf8");
|
|
52
|
+
if (
|
|
53
|
+
text.includes("http://schemas.microsoft.com/office/visio") ||
|
|
54
|
+
text.includes("http://schemas.microsoft.com/visio") ||
|
|
55
|
+
text.includes("<VisioDocument") ||
|
|
56
|
+
text.includes("Visio.Drawing") ||
|
|
57
|
+
text.includes("application/vnd.ms-visio")
|
|
58
|
+
) {
|
|
59
|
+
throw new DiagramsFormatError("Visio format (.vsd/.vsdx) is excluded and unsupported in @arnilo/prism-tools/work (P12)");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Validates draw.io / diagrams.net mxGraph XML for well-formedness, caps, and required element structure.
|
|
65
|
+
*
|
|
66
|
+
* Security guarantees:
|
|
67
|
+
* - DOCTYPE and ENTITY declarations are rejected up-front (XXE defense).
|
|
68
|
+
* - Parser entity processing is disabled.
|
|
69
|
+
* - Caps on bytes, total elements, and total attributes are strictly enforced.
|
|
70
|
+
* - Visio (.vsd/.vsdx) inputs are rejected (P12).
|
|
71
|
+
*/
|
|
72
|
+
export function validateDrawioXml(xml: string | Uint8Array, options?: DrawioXmlOptions): DrawioModelSummary {
|
|
73
|
+
const startTime = Date.now();
|
|
74
|
+
const span = options?.telemetry?.startSpan("diagrams.validate");
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
assertNotVisio(xml);
|
|
78
|
+
|
|
79
|
+
const caps: ResolvedDrawioXmlCaps = resolveDiagramsCaps(options?.caps);
|
|
80
|
+
const xmlString = typeof xml === "string" ? xml : Buffer.from(xml).toString("utf8");
|
|
81
|
+
const byteLength = Buffer.byteLength(xmlString, "utf8");
|
|
82
|
+
|
|
83
|
+
validateByteCap(byteLength, caps);
|
|
84
|
+
|
|
85
|
+
// Up-front DOCTYPE/ENTITY rejection (XXE & Billion Laughs prevention)
|
|
86
|
+
if (UNSAFE_XML_DECLARATION_PATTERN.test(xmlString)) {
|
|
87
|
+
throw new DiagramsXxeError("XML contains forbidden DOCTYPE or ENTITY declaration (XXE security policy)");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Well-formedness check
|
|
91
|
+
const validationResult = XMLValidator.validate(xmlString, {
|
|
92
|
+
allowBooleanAttributes: false,
|
|
93
|
+
});
|
|
94
|
+
if (validationResult !== true) {
|
|
95
|
+
throw new DiagramsXmlMalformedError(
|
|
96
|
+
`Malformed XML: ${validationResult.err.msg} (line ${validationResult.err.line}, col ${validationResult.err.col})`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Parse XML tree
|
|
101
|
+
const parser = new XMLParser({
|
|
102
|
+
ignoreAttributes: false,
|
|
103
|
+
attributeNamePrefix: "@_",
|
|
104
|
+
allowBooleanAttributes: false,
|
|
105
|
+
processEntities: false,
|
|
106
|
+
htmlEntities: false,
|
|
107
|
+
stopNodes: [],
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const parsed: unknown = parser.parse(xmlString);
|
|
111
|
+
if (!parsed || typeof parsed !== "object") {
|
|
112
|
+
throw new DiagramsModelInvalidError("Parsed XML does not produce an object model");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Enforce element and attribute caps
|
|
116
|
+
const counts = { elements: 0, attributes: 0 };
|
|
117
|
+
countTree(parsed, counts, caps);
|
|
118
|
+
|
|
119
|
+
const summary = extractModelSummary(parsed as Record<string, unknown>);
|
|
120
|
+
|
|
121
|
+
span?.setAttribute("diagrams.bytes", byteLength);
|
|
122
|
+
span?.setAttribute("diagrams.pages", summary.pages);
|
|
123
|
+
span?.setAttribute("diagrams.cells", summary.cells);
|
|
124
|
+
span?.setAttribute("diagrams.edges", summary.edges);
|
|
125
|
+
span?.setAttribute("diagrams.durationMs", Date.now() - startTime);
|
|
126
|
+
|
|
127
|
+
return summary;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
span?.recordError();
|
|
130
|
+
throw error;
|
|
131
|
+
} finally {
|
|
132
|
+
span?.end();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function countTree(node: unknown, counts: { elements: number; attributes: number }, caps: ResolvedDrawioXmlCaps): void {
|
|
137
|
+
if (!node || typeof node !== "object") return;
|
|
138
|
+
|
|
139
|
+
if (Array.isArray(node)) {
|
|
140
|
+
for (const item of node) {
|
|
141
|
+
countTree(item, counts, caps);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const record = node as Record<string, unknown>;
|
|
147
|
+
for (const [key, value] of Object.entries(record)) {
|
|
148
|
+
if (key.startsWith("@_")) {
|
|
149
|
+
counts.attributes++;
|
|
150
|
+
if (counts.attributes > caps.maxAttributes) {
|
|
151
|
+
throw new DiagramsCapError(`XML total attributes count exceeds maxAttributes cap (${caps.maxAttributes})`);
|
|
152
|
+
}
|
|
153
|
+
} else if (key !== "#text" && key !== ":@") {
|
|
154
|
+
counts.elements++;
|
|
155
|
+
if (counts.elements > caps.maxElements) {
|
|
156
|
+
throw new DiagramsCapError(`XML total element count exceeds maxElements cap (${caps.maxElements})`);
|
|
157
|
+
}
|
|
158
|
+
countTree(value, counts, caps);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function extractModelSummary(root: Record<string, unknown>): DrawioModelSummary {
|
|
164
|
+
if ("mxfile" in root && root.mxfile && typeof root.mxfile === "object") {
|
|
165
|
+
const mxfile = root.mxfile as Record<string, unknown>;
|
|
166
|
+
const diagrams = mxfile.diagram;
|
|
167
|
+
|
|
168
|
+
if (!diagrams) {
|
|
169
|
+
return { pages: 1, cells: 0, edges: 0 };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const diagramList = Array.isArray(diagrams) ? diagrams : [diagrams];
|
|
173
|
+
let totalCells = 0;
|
|
174
|
+
let totalEdges = 0;
|
|
175
|
+
let width: number | undefined;
|
|
176
|
+
let height: number | undefined;
|
|
177
|
+
let anyCompressed = false;
|
|
178
|
+
|
|
179
|
+
for (const diag of diagramList) {
|
|
180
|
+
if (typeof diag === "string") {
|
|
181
|
+
// Plain string diagram content = compressed/deflated base64 payload
|
|
182
|
+
anyCompressed = true;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (typeof diag === "object" && diag !== null) {
|
|
186
|
+
const diagObj = diag as Record<string, unknown>;
|
|
187
|
+
if (diagObj["@_compressed"] === "true" || diagObj["@_compressed"] === true || (diagObj["#text"] && !diagObj.mxGraphModel)) {
|
|
188
|
+
anyCompressed = true;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (diagObj.mxGraphModel && typeof diagObj.mxGraphModel === "object") {
|
|
193
|
+
const modelMetrics = extractGraphModelMetrics(diagObj.mxGraphModel as Record<string, unknown>);
|
|
194
|
+
totalCells += modelMetrics.cells;
|
|
195
|
+
totalEdges += modelMetrics.edges;
|
|
196
|
+
if (width === undefined && modelMetrics.width !== undefined) width = modelMetrics.width;
|
|
197
|
+
if (height === undefined && modelMetrics.height !== undefined) height = modelMetrics.height;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
pages: diagramList.length,
|
|
204
|
+
cells: totalCells,
|
|
205
|
+
edges: totalEdges,
|
|
206
|
+
...(width !== undefined ? { width } : {}),
|
|
207
|
+
...(height !== undefined ? { height } : {}),
|
|
208
|
+
...(anyCompressed ? { compressed: true } : {}),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if ("mxGraphModel" in root && root.mxGraphModel && typeof root.mxGraphModel === "object") {
|
|
213
|
+
const metrics = extractGraphModelMetrics(root.mxGraphModel as Record<string, unknown>);
|
|
214
|
+
return {
|
|
215
|
+
pages: 1,
|
|
216
|
+
cells: metrics.cells,
|
|
217
|
+
edges: metrics.edges,
|
|
218
|
+
...(metrics.width !== undefined ? { width: metrics.width } : {}),
|
|
219
|
+
...(metrics.height !== undefined ? { height: metrics.height } : {}),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
throw new DiagramsModelInvalidError("Invalid draw.io XML structure: root element must be <mxfile> or <mxGraphModel>");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function extractGraphModelMetrics(model: Record<string, unknown>): {
|
|
227
|
+
cells: number;
|
|
228
|
+
edges: number;
|
|
229
|
+
width?: number;
|
|
230
|
+
height?: number;
|
|
231
|
+
} {
|
|
232
|
+
let cells = 0;
|
|
233
|
+
let edges = 0;
|
|
234
|
+
|
|
235
|
+
const width = parsePositiveNumber(model["@_pageWidth"]) ?? parsePositiveNumber(model["@_dx"]) ?? undefined;
|
|
236
|
+
const height = parsePositiveNumber(model["@_pageHeight"]) ?? parsePositiveNumber(model["@_dy"]) ?? undefined;
|
|
237
|
+
|
|
238
|
+
const root = model.root;
|
|
239
|
+
if (root && typeof root === "object") {
|
|
240
|
+
const rootRecord = root as Record<string, unknown>;
|
|
241
|
+
for (const [key, val] of Object.entries(rootRecord)) {
|
|
242
|
+
if (key.startsWith("@_")) continue;
|
|
243
|
+
const cellList = Array.isArray(val) ? val : [val];
|
|
244
|
+
for (const item of cellList) {
|
|
245
|
+
if (item && typeof item === "object") {
|
|
246
|
+
const itemRecord = item as Record<string, unknown>;
|
|
247
|
+
if (itemRecord["@_edge"] === "1" || itemRecord["@_edge"] === 1 || itemRecord["@_edge"] === "true") {
|
|
248
|
+
edges++;
|
|
249
|
+
} else if (itemRecord["@_id"] !== undefined || itemRecord["@_vertex"] === "1") {
|
|
250
|
+
cells++;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { cells, edges, width, height };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function parsePositiveNumber(value: unknown): number | undefined {
|
|
261
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
262
|
+
if (typeof value === "string") {
|
|
263
|
+
const num = Number.parseFloat(value);
|
|
264
|
+
if (Number.isFinite(num) && num > 0) return num;
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|