@arnilo/prism-tools 0.0.0-stage → 0.13.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.
Files changed (331) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -2
  4. package/browser/README.md +98 -0
  5. package/browser/skills/browser-automation/SKILL.md +14 -0
  6. package/browser/src/actions/cdp.ts +131 -0
  7. package/browser/src/actions/dialog.ts +25 -0
  8. package/browser/src/actions/download_release.ts +22 -0
  9. package/browser/src/actions/index.ts +37 -0
  10. package/browser/src/actions/locator.ts +70 -0
  11. package/browser/src/actions/navigate.ts +23 -0
  12. package/browser/src/actions/screenshot.ts +27 -0
  13. package/browser/src/actions/scroll.ts +24 -0
  14. package/browser/src/actions/select_page.ts +21 -0
  15. package/browser/src/actions/types.ts +114 -0
  16. package/browser/src/actions/upload.ts +44 -0
  17. package/browser/src/actions/wait.ts +45 -0
  18. package/browser/src/browser.ts +197 -0
  19. package/browser/src/cdp.ts +178 -0
  20. package/browser/src/checkpoint.ts +189 -0
  21. package/browser/src/config.ts +72 -0
  22. package/browser/src/downloads.ts +253 -0
  23. package/browser/src/errors.ts +31 -0
  24. package/browser/src/evaluate.ts +101 -0
  25. package/browser/src/index.ts +129 -0
  26. package/browser/src/limits.ts +271 -0
  27. package/browser/src/manager.ts +730 -0
  28. package/browser/src/network.ts +263 -0
  29. package/browser/src/observe.ts +178 -0
  30. package/browser/src/policy.ts +133 -0
  31. package/browser/src/screenshot.ts +107 -0
  32. package/browser/src/shared-sandbox.ts +53 -0
  33. package/browser/src/snapshot.ts +99 -0
  34. package/browser/src/targets.ts +165 -0
  35. package/browser/src/tools.ts +480 -0
  36. package/browser/src/types.ts +316 -0
  37. package/browser/src/uploads.ts +174 -0
  38. package/coding/README.md +337 -0
  39. package/coding/src/agent/acp-operations.ts +146 -0
  40. package/coding/src/agent/artifacts.ts +38 -0
  41. package/coding/src/agent/ask-user-decision.ts +623 -0
  42. package/coding/src/agent/atomic-write.ts +23 -0
  43. package/coding/src/agent/bounded-file.ts +21 -0
  44. package/coding/src/agent/checks.ts +301 -0
  45. package/coding/src/agent/coding-checkpoint.ts +828 -0
  46. package/coding/src/agent/delete.ts +237 -0
  47. package/coding/src/agent/diagnostics-tool.ts +163 -0
  48. package/coding/src/agent/diagnostics.ts +262 -0
  49. package/coding/src/agent/edit-diff.ts +382 -0
  50. package/coding/src/agent/edit.ts +322 -0
  51. package/coding/src/agent/effects.ts +102 -0
  52. package/coding/src/agent/env.ts +28 -0
  53. package/coding/src/agent/execution-policy.ts +89 -0
  54. package/coding/src/agent/file-mutation-queue.ts +72 -0
  55. package/coding/src/agent/forge/github.ts +603 -0
  56. package/coding/src/agent/forge/index.ts +16 -0
  57. package/coding/src/agent/forge/types.ts +185 -0
  58. package/coding/src/agent/git-aware-repository.ts +305 -0
  59. package/coding/src/agent/git-exec.ts +326 -0
  60. package/coding/src/agent/git-status.ts +177 -0
  61. package/coding/src/agent/git-tools.ts +360 -0
  62. package/coding/src/agent/git.ts +1074 -0
  63. package/coding/src/agent/glob-match.ts +146 -0
  64. package/coding/src/agent/glob.ts +182 -0
  65. package/coding/src/agent/goal-verify.ts +385 -0
  66. package/coding/src/agent/grep-worker.ts +74 -0
  67. package/coding/src/agent/grep.ts +459 -0
  68. package/coding/src/agent/identity.ts +48 -0
  69. package/coding/src/agent/index.ts +676 -0
  70. package/coding/src/agent/language/client.ts +429 -0
  71. package/coding/src/agent/language/framing.ts +190 -0
  72. package/coding/src/agent/language/index.ts +23 -0
  73. package/coding/src/agent/language/intelligence.ts +682 -0
  74. package/coding/src/agent/language/types.ts +187 -0
  75. package/coding/src/agent/lifecycle-events.ts +121 -0
  76. package/coding/src/agent/lifecycle.ts +166 -0
  77. package/coding/src/agent/limits.ts +214 -0
  78. package/coding/src/agent/move.ts +178 -0
  79. package/coding/src/agent/mutation-path.ts +52 -0
  80. package/coding/src/agent/output-accumulator.ts +304 -0
  81. package/coding/src/agent/path-utils.ts +120 -0
  82. package/coding/src/agent/process/index.ts +58 -0
  83. package/coding/src/agent/process/recovery.ts +508 -0
  84. package/coding/src/agent/process/sessions-host.ts +222 -0
  85. package/coding/src/agent/process/sessions-monitor.ts +141 -0
  86. package/coding/src/agent/process/sessions-recovery.ts +241 -0
  87. package/coding/src/agent/process/sessions-spawn.ts +613 -0
  88. package/coding/src/agent/process/sessions-teardown.ts +281 -0
  89. package/coding/src/agent/process/sessions.ts +30 -0
  90. package/coding/src/agent/process/types.ts +358 -0
  91. package/coding/src/agent/read-path-set.ts +126 -0
  92. package/coding/src/agent/read.ts +713 -0
  93. package/coding/src/agent/repository/glob.ts +147 -0
  94. package/coding/src/agent/repository/indexed-search.ts +480 -0
  95. package/coding/src/agent/repository/list.ts +131 -0
  96. package/coding/src/agent/repository/operations.ts +22 -0
  97. package/coding/src/agent/repository/path.ts +98 -0
  98. package/coding/src/agent/repository/search.ts +277 -0
  99. package/coding/src/agent/repository/types.ts +243 -0
  100. package/coding/src/agent/repository/walk.ts +126 -0
  101. package/coding/src/agent/repository.ts +12 -0
  102. package/coding/src/agent/shell-background.ts +264 -0
  103. package/coding/src/agent/shell-output.ts +75 -0
  104. package/coding/src/agent/shell.ts +526 -0
  105. package/coding/src/agent/todo.ts +399 -0
  106. package/coding/src/agent/truncate.ts +251 -0
  107. package/coding/src/agent/write.ts +170 -0
  108. package/coding/src/ask-user-host.ts +48 -0
  109. package/coding/src/config.ts +278 -0
  110. package/coding/src/hard-deny.ts +97 -0
  111. package/coding/src/index.ts +318 -0
  112. package/coding/src/principal-guard.ts +84 -0
  113. package/coding/src/sandbox.ts +92 -0
  114. package/coding/src/security/approval.ts +144 -0
  115. package/coding/src/security/command-rules.ts +57 -0
  116. package/coding/src/security/docker-cli.ts +222 -0
  117. package/coding/src/security/docker-sandbox.ts +1205 -0
  118. package/coding/src/security/e2b-sandbox.ts +853 -0
  119. package/coding/src/security/egress/dns-pin.ts +88 -0
  120. package/coding/src/security/egress/index.ts +32 -0
  121. package/coding/src/security/egress/limits.ts +57 -0
  122. package/coding/src/security/egress/policy.ts +137 -0
  123. package/coding/src/security/egress/proxy.ts +599 -0
  124. package/coding/src/security/egress/types.ts +30 -0
  125. package/coding/src/security/index.ts +199 -0
  126. package/coding/src/security/native-sandbox.ts +639 -0
  127. package/coding/src/security/path-containment.ts +55 -0
  128. package/coding/src/security/sandbox-coding-operations.ts +392 -0
  129. package/coding/src/security/sandbox-fs-operations.ts +644 -0
  130. package/coding/src/security/sandbox-limits.ts +147 -0
  131. package/coding/src/security/sandbox-tar.ts +308 -0
  132. package/coding/src/security/sandbox.ts +179 -0
  133. package/coding/src/security/semaphore.ts +55 -0
  134. package/coding/src/targets.ts +110 -0
  135. package/coding/src/workspace/diff.ts +78 -0
  136. package/coding/src/workspace/errors.ts +28 -0
  137. package/coding/src/workspace/index.ts +5 -0
  138. package/coding/src/workspace/merge.ts +151 -0
  139. package/coding/src/workspace/routing.ts +76 -0
  140. package/coding/src/workspace/service.ts +545 -0
  141. package/computer-use/README.md +105 -0
  142. package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
  143. package/computer-use/src/classify.ts +53 -0
  144. package/computer-use/src/command.ts +29 -0
  145. package/computer-use/src/config.ts +69 -0
  146. package/computer-use/src/create.ts +170 -0
  147. package/computer-use/src/devices.ts +247 -0
  148. package/computer-use/src/env.ts +28 -0
  149. package/computer-use/src/index.ts +157 -0
  150. package/computer-use/src/skill.ts +21 -0
  151. package/openapi/README.md +97 -0
  152. package/openapi/src/compile.ts +386 -0
  153. package/openapi/src/config.ts +73 -0
  154. package/openapi/src/errors.ts +16 -0
  155. package/openapi/src/execute.ts +241 -0
  156. package/openapi/src/index.ts +124 -0
  157. package/openapi/src/limits.ts +63 -0
  158. package/openapi/src/specs.ts +86 -0
  159. package/openapi/src/tools.ts +60 -0
  160. package/openapi/src/types.ts +61 -0
  161. package/package.json +171 -4
  162. package/research/README.md +72 -0
  163. package/research/skills/research-report/SKILL.md +12 -0
  164. package/research/skills/research-scoping/SKILL.md +10 -0
  165. package/research/skills/research-synthesis/SKILL.md +10 -0
  166. package/research/skills/source-triage/SKILL.md +10 -0
  167. package/research/src/check.ts +71 -0
  168. package/research/src/config.ts +41 -0
  169. package/research/src/index.ts +147 -0
  170. package/research/src/ledger.ts +157 -0
  171. package/research/src/urls.ts +21 -0
  172. package/web/README.md +287 -0
  173. package/web/skills/web-research/SKILL.md +17 -0
  174. package/web/src/brave.ts +66 -0
  175. package/web/src/cache.ts +151 -0
  176. package/web/src/config.ts +210 -0
  177. package/web/src/controls.ts +128 -0
  178. package/web/src/domains.ts +114 -0
  179. package/web/src/exa.ts +60 -0
  180. package/web/src/firecrawl.ts +160 -0
  181. package/web/src/index.ts +387 -0
  182. package/web/src/kagi.ts +73 -0
  183. package/web/src/limits.ts +55 -0
  184. package/web/src/native/convert.ts +84 -0
  185. package/web/src/native/fetch.ts +226 -0
  186. package/web/src/normalize.ts +131 -0
  187. package/web/src/obscura/cdp.ts +201 -0
  188. package/web/src/obscura/classify.ts +35 -0
  189. package/web/src/obscura/cli.ts +254 -0
  190. package/web/src/obscura/errors.ts +8 -0
  191. package/web/src/obscura/index.ts +59 -0
  192. package/web/src/obscura/limits.ts +92 -0
  193. package/web/src/obscura/mcp.ts +104 -0
  194. package/web/src/obscura/playwright.ts +133 -0
  195. package/web/src/obscura/process.ts +235 -0
  196. package/web/src/obscura/search-profile.ts +73 -0
  197. package/web/src/obscura/types.ts +48 -0
  198. package/web/src/obscura/web.ts +419 -0
  199. package/web/src/prompt-fetch.ts +88 -0
  200. package/web/src/render.ts +75 -0
  201. package/web/src/searxng.ts +78 -0
  202. package/web/src/slice.ts +139 -0
  203. package/web/src/tavily.ts +77 -0
  204. package/web/src/tools.ts +182 -0
  205. package/web/src/transport.ts +310 -0
  206. package/web/src/types.ts +199 -0
  207. package/work/README.md +77 -0
  208. package/work/THIRD_PARTY_NOTICES +24 -0
  209. package/work/docling/ocr.py +150 -0
  210. package/work/sandbox/Dockerfile +36 -0
  211. package/work/sandbox/soffice.sh +12 -0
  212. package/work/src/command.ts +29 -0
  213. package/work/src/config.ts +138 -0
  214. package/work/src/connectors/cli.ts +343 -0
  215. package/work/src/connectors/drafts.ts +647 -0
  216. package/work/src/connectors/errors.ts +8 -0
  217. package/work/src/connectors/file-bytes.ts +149 -0
  218. package/work/src/connectors/google-workspace-http.ts +399 -0
  219. package/work/src/connectors/google-workspace.ts +465 -0
  220. package/work/src/connectors/gws-tools.ts +378 -0
  221. package/work/src/connectors/http.ts +123 -0
  222. package/work/src/connectors/idempotency.ts +235 -0
  223. package/work/src/connectors/identity.ts +34 -0
  224. package/work/src/connectors/index.ts +93 -0
  225. package/work/src/connectors/limits.ts +50 -0
  226. package/work/src/connectors/m365-tools.ts +308 -0
  227. package/work/src/connectors/microsoft365-http.ts +428 -0
  228. package/work/src/connectors/microsoft365.ts +402 -0
  229. package/work/src/connectors/normalize.ts +120 -0
  230. package/work/src/connectors/tool-helpers.ts +398 -0
  231. package/work/src/connectors/tools.ts +42 -0
  232. package/work/src/connectors/types.ts +399 -0
  233. package/work/src/diagrams/canonicalize.ts +166 -0
  234. package/work/src/diagrams/caps.ts +52 -0
  235. package/work/src/diagrams/embed.ts +340 -0
  236. package/work/src/diagrams/errors.ts +76 -0
  237. package/work/src/diagrams/index.ts +81 -0
  238. package/work/src/diagrams/messages.ts +150 -0
  239. package/work/src/diagrams/origin.ts +52 -0
  240. package/work/src/diagrams/telemetry.ts +34 -0
  241. package/work/src/diagrams/xml.ts +267 -0
  242. package/work/src/document-extraction/index.ts +563 -0
  243. package/work/src/document-reader/ambient.d.ts +2 -0
  244. package/work/src/document-reader/errors.ts +7 -0
  245. package/work/src/document-reader/index.ts +181 -0
  246. package/work/src/document-reader/mistral-ocr.ts +318 -0
  247. package/work/src/document-reader/parsers.ts +171 -0
  248. package/work/src/documents/caps.ts +135 -0
  249. package/work/src/documents/diff.ts +269 -0
  250. package/work/src/documents/errors.ts +44 -0
  251. package/work/src/documents/fidelity.ts +98 -0
  252. package/work/src/documents/generate.ts +96 -0
  253. package/work/src/documents/hash.ts +8 -0
  254. package/work/src/documents/index.ts +14 -0
  255. package/work/src/documents/model-schema.ts +639 -0
  256. package/work/src/documents/parse.ts +252 -0
  257. package/work/src/documents/patch-history.ts +81 -0
  258. package/work/src/documents/patch.ts +476 -0
  259. package/work/src/documents/preview-html.ts +245 -0
  260. package/work/src/documents/preview.ts +227 -0
  261. package/work/src/documents/telemetry.ts +36 -0
  262. package/work/src/documents/translate/docx.ts +292 -0
  263. package/work/src/documents/translate/pptx.ts +304 -0
  264. package/work/src/documents/translate/xlsx.ts +137 -0
  265. package/work/src/documents/types.ts +188 -0
  266. package/work/src/index.ts +311 -0
  267. package/work/src/runtime/worker-pool-entry.ts +102 -0
  268. package/work/src/runtime/worker-pool.ts +267 -0
  269. package/work/src/sandbox/composition.ts +212 -0
  270. package/work/src/sandbox/image.ts +6 -0
  271. package/work/src/sandbox/index.ts +14 -0
  272. package/work/src/sheets/caps.ts +68 -0
  273. package/work/src/sheets/csv.ts +351 -0
  274. package/work/src/sheets/decimal.ts +388 -0
  275. package/work/src/sheets/errors.ts +52 -0
  276. package/work/src/sheets/index.ts +62 -0
  277. package/work/src/sheets/inference.ts +378 -0
  278. package/work/src/sheets/telemetry.ts +34 -0
  279. package/work/src/sheets/types.ts +162 -0
  280. package/work/src/sheets/xlsx.ts +388 -0
  281. package/work/src/skills/index.ts +8 -0
  282. package/work/src/skills/load.ts +43 -0
  283. package/work/src/tools/filesystem.ts +21 -0
  284. package/work/src/tools/index.ts +1 -0
  285. package/work/src/tools/local-filesystem.ts +33 -0
  286. package/work/src/tools/office.ts +311 -0
  287. package/work/vendor/hermes-agent/LICENSE +21 -0
  288. package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
  289. package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
  290. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
  291. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
  292. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
  293. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
  294. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
  295. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
  296. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
  297. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
  298. package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
  299. package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
  300. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
  301. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
  302. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
  303. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
  304. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
  305. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
  306. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
  307. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
  308. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
  309. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
  310. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
  311. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
  312. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
  313. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
  314. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
  315. package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
  316. package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
  317. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
  318. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
  319. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
  320. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
  321. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
  322. package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
  323. package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
  324. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
  325. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
  326. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
  327. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
  328. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
  329. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
  330. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
  331. package/work/vendor-lock.json +11 -0
@@ -0,0 +1,639 @@
1
+ import { Ajv, type ValidateFunction } from "ajv";
2
+ import { DocumentsValidationError } from "./errors.js";
3
+ import type { DocModel, DocumentKind, DocumentModel, SheetModel, TableBlock } from "./types.js";
4
+
5
+ export type JsonSchema = Record<string, unknown>;
6
+
7
+ // --- Draft-07 Shared Block and Cell Definitions ---
8
+
9
+ const SHARED_DEFS: Record<string, JsonSchema> = {
10
+ DocRun: {
11
+ type: "object",
12
+ properties: {
13
+ text: { type: "string" },
14
+ bold: { type: "boolean" },
15
+ italic: { type: "boolean" },
16
+ underline: { type: "boolean" },
17
+ strikethrough: { type: "boolean" },
18
+ code: { type: "boolean" },
19
+ link: { type: "string", maxLength: 2048 },
20
+ },
21
+ required: ["text"],
22
+ additionalProperties: false,
23
+ },
24
+ ListItem: {
25
+ type: "object",
26
+ properties: {
27
+ text: { type: "string" },
28
+ runs: {
29
+ type: "array",
30
+ items: { $ref: "#/$defs/DocRun" },
31
+ maxItems: 1000,
32
+ },
33
+ },
34
+ required: ["text"],
35
+ additionalProperties: false,
36
+ },
37
+ DecimalCellValue: {
38
+ type: "object",
39
+ properties: {
40
+ type: { const: "decimal" },
41
+ value: {
42
+ type: "string",
43
+ pattern: "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
44
+ maxLength: 128,
45
+ },
46
+ },
47
+ required: ["type", "value"],
48
+ additionalProperties: false,
49
+ },
50
+ DateCellValue: {
51
+ type: "object",
52
+ properties: {
53
+ type: { const: "date" },
54
+ value: {
55
+ type: "string",
56
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
57
+ },
58
+ },
59
+ required: ["type", "value"],
60
+ additionalProperties: false,
61
+ },
62
+ DateTimeCellValue: {
63
+ type: "object",
64
+ properties: {
65
+ type: { const: "datetime" },
66
+ value: {
67
+ type: "string",
68
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$",
69
+ },
70
+ },
71
+ required: ["type", "value"],
72
+ additionalProperties: false,
73
+ },
74
+ FormulaCellValue: {
75
+ type: "object",
76
+ properties: {
77
+ formula: { type: "string", pattern: "^=.*$", maxLength: 4096 },
78
+ cachedValue: {
79
+ type: ["string", "number", "boolean", "null"],
80
+ },
81
+ },
82
+ required: ["formula"],
83
+ additionalProperties: false,
84
+ },
85
+ CellValue: {
86
+ anyOf: [
87
+ { type: "string", maxLength: 100000 },
88
+ { type: "number" },
89
+ { type: "boolean" },
90
+ { type: "null" },
91
+ { $ref: "#/$defs/DecimalCellValue" },
92
+ { $ref: "#/$defs/DateCellValue" },
93
+ { $ref: "#/$defs/DateTimeCellValue" },
94
+ { $ref: "#/$defs/FormulaCellValue" },
95
+ ],
96
+ },
97
+ ChartSeries: {
98
+ type: "object",
99
+ properties: {
100
+ name: { type: "string", maxLength: 256 },
101
+ values: {
102
+ type: "array",
103
+ items: { type: "number" },
104
+ maxItems: 10000,
105
+ },
106
+ },
107
+ required: ["name", "values"],
108
+ additionalProperties: false,
109
+ },
110
+ ChartData: {
111
+ type: "object",
112
+ properties: {
113
+ categories: {
114
+ type: "array",
115
+ items: { type: "string", maxLength: 256 },
116
+ maxItems: 10000,
117
+ },
118
+ series: {
119
+ type: "array",
120
+ items: { $ref: "#/$defs/ChartSeries" },
121
+ maxItems: 100,
122
+ },
123
+ },
124
+ required: ["categories", "series"],
125
+ additionalProperties: false,
126
+ },
127
+ HeadingBlock: {
128
+ type: "object",
129
+ properties: {
130
+ type: { const: "heading" },
131
+ level: { type: "integer", minimum: 1, maximum: 6 },
132
+ text: { type: "string", maxLength: 10000 },
133
+ id: { type: "string", maxLength: 256 },
134
+ },
135
+ required: ["type", "level", "text"],
136
+ additionalProperties: false,
137
+ },
138
+ ParagraphBlock: {
139
+ type: "object",
140
+ properties: {
141
+ type: { const: "paragraph" },
142
+ text: { type: "string", maxLength: 100000 },
143
+ runs: {
144
+ type: "array",
145
+ items: { $ref: "#/$defs/DocRun" },
146
+ maxItems: 5000,
147
+ },
148
+ },
149
+ required: ["type"],
150
+ additionalProperties: false,
151
+ },
152
+ ListBlock: {
153
+ type: "object",
154
+ properties: {
155
+ type: { const: "list" },
156
+ ordered: { type: "boolean" },
157
+ items: {
158
+ type: "array",
159
+ items: {
160
+ anyOf: [{ type: "string", maxLength: 10000 }, { $ref: "#/$defs/ListItem" }],
161
+ },
162
+ maxItems: 10000,
163
+ },
164
+ },
165
+ required: ["type", "items"],
166
+ additionalProperties: false,
167
+ },
168
+ TableBlock: {
169
+ type: "object",
170
+ properties: {
171
+ type: { const: "table" },
172
+ rows: { type: "integer", minimum: 0, maximum: 100000 },
173
+ columns: { type: "integer", minimum: 0, maximum: 1000 },
174
+ headers: {
175
+ type: "array",
176
+ items: { type: "string", maxLength: 1000 },
177
+ maxItems: 1000,
178
+ },
179
+ cells: {
180
+ type: "array",
181
+ items: {
182
+ type: "array",
183
+ items: { $ref: "#/$defs/CellValue" },
184
+ maxItems: 1000,
185
+ },
186
+ maxItems: 100000,
187
+ },
188
+ },
189
+ required: ["type", "rows", "columns", "cells"],
190
+ additionalProperties: false,
191
+ },
192
+ ImageBlock: {
193
+ type: "object",
194
+ properties: {
195
+ type: { const: "image" },
196
+ data: { type: "string" },
197
+ mimeType: { type: "string", maxLength: 128 },
198
+ alt: { type: "string", maxLength: 1024 },
199
+ width: { type: "number", minimum: 0 },
200
+ height: { type: "number", minimum: 0 },
201
+ ref: { type: "string", maxLength: 1024 },
202
+ },
203
+ required: ["type"],
204
+ additionalProperties: false,
205
+ },
206
+ PageBreakBlock: {
207
+ type: "object",
208
+ properties: {
209
+ type: { const: "page-break" },
210
+ },
211
+ required: ["type"],
212
+ additionalProperties: false,
213
+ },
214
+ ChartBlock: {
215
+ type: "object",
216
+ properties: {
217
+ type: { const: "chart" },
218
+ chartType: { type: "string", enum: ["bar", "line", "pie", "scatter"] },
219
+ title: { type: "string", maxLength: 512 },
220
+ data: { $ref: "#/$defs/ChartData" },
221
+ alt: { type: "string", maxLength: 1024 },
222
+ width: { type: "number", minimum: 0 },
223
+ height: { type: "number", minimum: 0 },
224
+ },
225
+ required: ["type", "chartType", "data"],
226
+ additionalProperties: false,
227
+ },
228
+ DocBlock: {
229
+ anyOf: [
230
+ { $ref: "#/$defs/HeadingBlock" },
231
+ { $ref: "#/$defs/ParagraphBlock" },
232
+ { $ref: "#/$defs/ListBlock" },
233
+ { $ref: "#/$defs/TableBlock" },
234
+ { $ref: "#/$defs/ImageBlock" },
235
+ { $ref: "#/$defs/PageBreakBlock" },
236
+ { $ref: "#/$defs/ChartBlock" },
237
+ ],
238
+ },
239
+ ColumnWidth: {
240
+ type: "object",
241
+ properties: {
242
+ column: { type: "integer", minimum: 0 },
243
+ width: { type: "number", minimum: 0 },
244
+ },
245
+ required: ["column", "width"],
246
+ additionalProperties: false,
247
+ },
248
+ FrozenPanes: {
249
+ type: "object",
250
+ properties: {
251
+ rows: { type: "integer", minimum: 0 },
252
+ columns: { type: "integer", minimum: 0 },
253
+ },
254
+ additionalProperties: false,
255
+ },
256
+ SheetData: {
257
+ type: "object",
258
+ properties: {
259
+ name: { type: "string", minLength: 1, maxLength: 256 },
260
+ cells: {
261
+ type: "array",
262
+ items: {
263
+ type: "array",
264
+ items: { $ref: "#/$defs/CellValue" },
265
+ maxItems: 16384,
266
+ },
267
+ maxItems: 1048576,
268
+ },
269
+ columnWidths: {
270
+ type: "array",
271
+ items: { $ref: "#/$defs/ColumnWidth" },
272
+ maxItems: 16384,
273
+ },
274
+ frozenPanes: { $ref: "#/$defs/FrozenPanes" },
275
+ numberFormats: {
276
+ type: "object",
277
+ additionalProperties: { type: "string", maxLength: 256 },
278
+ },
279
+ },
280
+ required: ["name", "cells"],
281
+ additionalProperties: false,
282
+ },
283
+ SlideLayout: {
284
+ type: "string",
285
+ enum: ["title", "title-and-content", "section-header", "two-column", "blank"],
286
+ },
287
+ SlideData: {
288
+ type: "object",
289
+ properties: {
290
+ layout: { $ref: "#/$defs/SlideLayout" },
291
+ title: { type: "string", maxLength: 1024 },
292
+ subtitle: { type: "string", maxLength: 1024 },
293
+ bullets: {
294
+ type: "array",
295
+ items: {
296
+ anyOf: [{ type: "string", maxLength: 10000 }, { $ref: "#/$defs/ListItem" }],
297
+ },
298
+ maxItems: 1000,
299
+ },
300
+ notes: { type: "string", maxLength: 100000 },
301
+ image: { $ref: "#/$defs/ImageBlock" },
302
+ chart: { $ref: "#/$defs/ChartBlock" },
303
+ },
304
+ required: ["layout"],
305
+ additionalProperties: false,
306
+ },
307
+ };
308
+
309
+ // --- Per-Kind Schema Definitions ---
310
+
311
+ export const docModelSchema: JsonSchema = {
312
+ $schema: "http://json-schema.org/draft-07/schema#",
313
+ title: "Prism Document Model (doc)",
314
+ type: "object",
315
+ properties: {
316
+ kind: { const: "doc" },
317
+ modelVersion: { type: "integer", minimum: 1 },
318
+ title: { type: "string", maxLength: 1000 },
319
+ metadata: { type: "object", additionalProperties: true },
320
+ blocks: {
321
+ type: "array",
322
+ items: { $ref: "#/$defs/DocBlock" },
323
+ maxItems: 50000,
324
+ },
325
+ },
326
+ required: ["kind", "modelVersion", "blocks"],
327
+ additionalProperties: false,
328
+ $defs: {
329
+ DocRun: SHARED_DEFS.DocRun,
330
+ ListItem: SHARED_DEFS.ListItem,
331
+ DecimalCellValue: SHARED_DEFS.DecimalCellValue,
332
+ DateCellValue: SHARED_DEFS.DateCellValue,
333
+ DateTimeCellValue: SHARED_DEFS.DateTimeCellValue,
334
+ FormulaCellValue: SHARED_DEFS.FormulaCellValue,
335
+ CellValue: SHARED_DEFS.CellValue,
336
+ HeadingBlock: SHARED_DEFS.HeadingBlock,
337
+ ParagraphBlock: SHARED_DEFS.ParagraphBlock,
338
+ ListBlock: SHARED_DEFS.ListBlock,
339
+ TableBlock: SHARED_DEFS.TableBlock,
340
+ ImageBlock: SHARED_DEFS.ImageBlock,
341
+ PageBreakBlock: SHARED_DEFS.PageBreakBlock,
342
+ ChartSeries: SHARED_DEFS.ChartSeries,
343
+ ChartData: SHARED_DEFS.ChartData,
344
+ ChartBlock: SHARED_DEFS.ChartBlock,
345
+ DocBlock: SHARED_DEFS.DocBlock,
346
+ },
347
+ };
348
+
349
+ export const sheetModelSchema: JsonSchema = {
350
+ $schema: "http://json-schema.org/draft-07/schema#",
351
+ title: "Prism Sheet Model (sheet)",
352
+ type: "object",
353
+ properties: {
354
+ kind: { const: "sheet" },
355
+ modelVersion: { type: "integer", minimum: 1 },
356
+ title: { type: "string", maxLength: 1000 },
357
+ metadata: { type: "object", additionalProperties: true },
358
+ sheets: {
359
+ type: "array",
360
+ items: { $ref: "#/$defs/SheetData" },
361
+ maxItems: 1000,
362
+ },
363
+ },
364
+ required: ["kind", "modelVersion", "sheets"],
365
+ additionalProperties: false,
366
+ $defs: {
367
+ DecimalCellValue: SHARED_DEFS.DecimalCellValue,
368
+ DateCellValue: SHARED_DEFS.DateCellValue,
369
+ DateTimeCellValue: SHARED_DEFS.DateTimeCellValue,
370
+ FormulaCellValue: SHARED_DEFS.FormulaCellValue,
371
+ CellValue: SHARED_DEFS.CellValue,
372
+ ColumnWidth: SHARED_DEFS.ColumnWidth,
373
+ FrozenPanes: SHARED_DEFS.FrozenPanes,
374
+ SheetData: SHARED_DEFS.SheetData,
375
+ },
376
+ };
377
+
378
+ export const deckModelSchema: JsonSchema = {
379
+ $schema: "http://json-schema.org/draft-07/schema#",
380
+ title: "Prism Deck Model (deck)",
381
+ type: "object",
382
+ properties: {
383
+ kind: { const: "deck" },
384
+ modelVersion: { type: "integer", minimum: 1 },
385
+ title: { type: "string", maxLength: 1000 },
386
+ metadata: { type: "object", additionalProperties: true },
387
+ slides: {
388
+ type: "array",
389
+ items: { $ref: "#/$defs/SlideData" },
390
+ maxItems: 2000,
391
+ },
392
+ },
393
+ required: ["kind", "modelVersion", "slides"],
394
+ additionalProperties: false,
395
+ $defs: {
396
+ DocRun: SHARED_DEFS.DocRun,
397
+ ListItem: SHARED_DEFS.ListItem,
398
+ ImageBlock: SHARED_DEFS.ImageBlock,
399
+ ChartSeries: SHARED_DEFS.ChartSeries,
400
+ ChartData: SHARED_DEFS.ChartData,
401
+ ChartBlock: SHARED_DEFS.ChartBlock,
402
+ SlideLayout: SHARED_DEFS.SlideLayout,
403
+ SlideData: SHARED_DEFS.SlideData,
404
+ },
405
+ };
406
+
407
+ const SCHEMAS_BY_KIND: Record<DocumentKind, JsonSchema> = {
408
+ doc: docModelSchema,
409
+ sheet: sheetModelSchema,
410
+ deck: deckModelSchema,
411
+ };
412
+
413
+ // --- Ajv Compilation and Caching ---
414
+
415
+ const ajv = new Ajv({
416
+ allErrors: true,
417
+ validateSchema: true,
418
+ allowUnionTypes: true,
419
+ addUsedSchema: false,
420
+ });
421
+
422
+ const compiledValidators = new Map<DocumentKind, ValidateFunction>();
423
+
424
+ function getValidator(kind: DocumentKind): ValidateFunction {
425
+ let validator = compiledValidators.get(kind);
426
+ if (!validator) {
427
+ const schema = SCHEMAS_BY_KIND[kind];
428
+ validator = ajv.compile(schema);
429
+ compiledValidators.set(kind, validator);
430
+ }
431
+ return validator;
432
+ }
433
+
434
+ // --- Slice Key Aliases ---
435
+
436
+ const ALIAS_MAP: Record<string, string> = {
437
+ "doc.heading": "HeadingBlock",
438
+ heading: "HeadingBlock",
439
+ "doc.paragraph": "ParagraphBlock",
440
+ paragraph: "ParagraphBlock",
441
+ "doc.list": "ListBlock",
442
+ list: "ListBlock",
443
+ "doc.table": "TableBlock",
444
+ table: "TableBlock",
445
+ "doc.image": "ImageBlock",
446
+ image: "ImageBlock",
447
+ "doc.page-break": "PageBreakBlock",
448
+ "doc.pagebreak": "PageBreakBlock",
449
+ pagebreak: "PageBreakBlock",
450
+ "page-break": "PageBreakBlock",
451
+ "doc.chart": "ChartBlock",
452
+ chart: "ChartBlock",
453
+ "doc.run": "DocRun",
454
+ run: "DocRun",
455
+ "doc.block": "DocBlock",
456
+ block: "DocBlock",
457
+ "sheet.sheet": "SheetData",
458
+ "sheet.sheetdata": "SheetData",
459
+ sheetdata: "SheetData",
460
+ "sheet.cell": "CellValue",
461
+ cell: "CellValue",
462
+ cellvalue: "CellValue",
463
+ decimal: "DecimalCellValue",
464
+ date: "DateCellValue",
465
+ datetime: "DateTimeCellValue",
466
+ formula: "FormulaCellValue",
467
+ "deck.slide": "SlideData",
468
+ slide: "SlideData",
469
+ slidedata: "SlideData",
470
+ "deck.layout": "SlideLayout",
471
+ layout: "SlideLayout",
472
+ };
473
+
474
+ function resolveDefKey(schemaDefs: Record<string, JsonSchema>, sliceName: string): string {
475
+ if (schemaDefs[sliceName]) return sliceName;
476
+ const alias = ALIAS_MAP[sliceName.toLowerCase()];
477
+ if (alias && schemaDefs[alias]) return alias;
478
+ // Case-insensitive fallback
479
+ const lower = sliceName.toLowerCase();
480
+ for (const key of Object.keys(schemaDefs)) {
481
+ if (key.toLowerCase() === lower) return key;
482
+ }
483
+ throw new DocumentsValidationError(`unknown schema slice "${sliceName}"`);
484
+ }
485
+
486
+ function extractRefKeys(obj: unknown, refs: Set<string>): void {
487
+ if (typeof obj !== "object" || obj === null) return;
488
+ if (Array.isArray(obj)) {
489
+ for (const item of obj) extractRefKeys(item, refs);
490
+ return;
491
+ }
492
+ const record = obj as Record<string, unknown>;
493
+ for (const [key, value] of Object.entries(record)) {
494
+ if (key === "$ref" && typeof value === "string") {
495
+ const match = value.match(/^#\/\$defs\/([A-Za-z0-9_]+)$/);
496
+ if (match) refs.add(match[1]);
497
+ } else {
498
+ extractRefKeys(value, refs);
499
+ }
500
+ }
501
+ }
502
+
503
+ function calculateDefsClosure(allDefs: Record<string, JsonSchema>, rootKeys: readonly string[]): Record<string, JsonSchema> {
504
+ const collected = new Set<string>();
505
+ const queue = [...rootKeys];
506
+
507
+ while (queue.length > 0) {
508
+ const key = queue.pop()!;
509
+ if (collected.has(key)) continue;
510
+ collected.add(key);
511
+ const def = allDefs[key];
512
+ if (!def) continue;
513
+
514
+ const childRefs = new Set<string>();
515
+ extractRefKeys(def, childRefs);
516
+ for (const child of childRefs) {
517
+ if (!collected.has(child) && allDefs[child]) {
518
+ queue.push(child);
519
+ }
520
+ }
521
+ }
522
+
523
+ const result: Record<string, JsonSchema> = {};
524
+ for (const key of collected) {
525
+ result[key] = allDefs[key];
526
+ }
527
+ return result;
528
+ }
529
+
530
+ /**
531
+ * Returns the full Draft-07 JSON Schema for the given document kind, or a
532
+ * minimal dependency-closure schema for the requested slice(s).
533
+ */
534
+ export function documentModelSchema(kind: DocumentKind, slice?: string | readonly string[]): JsonSchema {
535
+ const baseSchema = SCHEMAS_BY_KIND[kind];
536
+ if (!baseSchema) {
537
+ throw new DocumentsValidationError(`unsupported document kind: ${String(kind)}`);
538
+ }
539
+
540
+ const defs = (baseSchema.$defs ?? {}) as Record<string, JsonSchema>;
541
+
542
+ if (!slice || (Array.isArray(slice) && slice.length === 0)) {
543
+ return structuredClone(baseSchema);
544
+ }
545
+
546
+ const sliceList = Array.isArray(slice) ? slice : [slice];
547
+ const rootKeys = sliceList.map((s) => resolveDefKey(defs, s));
548
+ const closureDefs = calculateDefsClosure(defs, rootKeys);
549
+
550
+ const slicedSchema: JsonSchema = {
551
+ $schema: "http://json-schema.org/draft-07/schema#",
552
+ title: `Prism Document Schema Slice (${kind}: ${rootKeys.join(", ")})`,
553
+ $defs: closureDefs,
554
+ };
555
+
556
+ if (rootKeys.length === 1) {
557
+ slicedSchema.$ref = `#/$defs/${rootKeys[0]}`;
558
+ } else {
559
+ slicedSchema.anyOf = rootKeys.map((key) => ({ $ref: `#/$defs/${key}` }));
560
+ }
561
+
562
+ return slicedSchema;
563
+ }
564
+
565
+ const CANONICAL_DECIMAL_REGEX = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
566
+
567
+ function validateInvariants(model: DocumentModel): void {
568
+ if (model.kind === "doc") {
569
+ const doc = model as DocModel;
570
+ for (let index = 0; index < doc.blocks.length; index += 1) {
571
+ const block = doc.blocks[index];
572
+ if (block.type === "table") {
573
+ const table = block as TableBlock;
574
+ if (table.cells.length !== table.rows) {
575
+ throw new DocumentsValidationError(
576
+ `table block at index ${index} declares ${table.rows} rows but contains ${table.cells.length} rows`,
577
+ );
578
+ }
579
+ for (let r = 0; r < table.cells.length; r += 1) {
580
+ const row = table.cells[r];
581
+ if (row.length !== table.columns) {
582
+ throw new DocumentsValidationError(
583
+ `table block at index ${index} row ${r} declares ${table.columns} columns but contains ${row.length} cells`,
584
+ );
585
+ }
586
+ }
587
+ }
588
+ }
589
+ } else if (model.kind === "sheet") {
590
+ const sheetModel = model as SheetModel;
591
+ for (let s = 0; s < sheetModel.sheets.length; s += 1) {
592
+ const sheet = sheetModel.sheets[s];
593
+ for (let r = 0; r < sheet.cells.length; r += 1) {
594
+ const row = sheet.cells[r];
595
+ for (let c = 0; c < row.length; c += 1) {
596
+ const cell = row[c];
597
+ if (cell !== null && typeof cell === "object" && "type" in cell && cell.type === "decimal") {
598
+ if (!CANONICAL_DECIMAL_REGEX.test(cell.value)) {
599
+ throw new DocumentsValidationError(
600
+ `sheet "${sheet.name}" cell at row ${r}, col ${c} has invalid decimal string "${cell.value}"`,
601
+ );
602
+ }
603
+ }
604
+ }
605
+ }
606
+ }
607
+ }
608
+ }
609
+
610
+ /**
611
+ * Validates untrusted input against the Prism Document Model Draft-07 schema
612
+ * and structural invariants. Throws {@link DocumentsValidationError} on failure.
613
+ */
614
+ export function validateDocumentModel(model: unknown): asserts model is DocumentModel {
615
+ if (typeof model !== "object" || model === null || Array.isArray(model)) {
616
+ throw new DocumentsValidationError("model must be a non-null object");
617
+ }
618
+
619
+ const candidate = model as Record<string, unknown>;
620
+ const kind = candidate.kind;
621
+ if (kind !== "doc" && kind !== "sheet" && kind !== "deck") {
622
+ throw new DocumentsValidationError(`unknown document kind: "${String(kind)}" (must be "doc", "sheet", or "deck")`);
623
+ }
624
+
625
+ if (typeof candidate.modelVersion !== "number" || !Number.isSafeInteger(candidate.modelVersion) || candidate.modelVersion <= 0) {
626
+ throw new DocumentsValidationError("modelVersion must be a positive safe integer");
627
+ }
628
+
629
+ const validator = getValidator(kind as DocumentKind);
630
+ const valid = validator(model);
631
+ if (!valid) {
632
+ const firstError = validator.errors?.[0];
633
+ const path = firstError?.instancePath || "root";
634
+ const msg = firstError?.message || "schema validation failed";
635
+ throw new DocumentsValidationError(`model validation failed at ${path}: ${msg}`);
636
+ }
637
+
638
+ validateInvariants(model as DocumentModel);
639
+ }