@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,388 @@
1
+ /**
2
+ * Decimal normalization and validation utilities for financial safety.
3
+ *
4
+ * CRITICAL SAFETY INVARIANT:
5
+ * Money is always represented as exact decimal strings. Floating-point conversions
6
+ * (Number(), parseFloat(), unary +) are strictly forbidden on decimal value paths.
7
+ *
8
+ * All checks are linear scans bounded by MAX_DECIMAL_INPUT_LENGTH to eliminate
9
+ * polynomial ReDoS. No regex with nested quantifiers is used on attacker-controlled
10
+ * strings.
11
+ */
12
+
13
+ const MAX_DECIMAL_INPUT_LENGTH = 8192;
14
+
15
+ const CURRENCY_TOKENS = [
16
+ "USD",
17
+ "EUR",
18
+ "GBP",
19
+ "CAD",
20
+ "AUD",
21
+ "JPY",
22
+ "INR",
23
+ "CNY",
24
+ "CHF",
25
+ "$",
26
+ "€",
27
+ "£",
28
+ "¥",
29
+ "₹",
30
+ "元",
31
+ "₩",
32
+ "₱",
33
+ "฿",
34
+ "₫",
35
+ ] as const;
36
+
37
+ function isDigit(c: string): boolean {
38
+ return c >= "0" && c <= "9";
39
+ }
40
+
41
+ function isWs(c: string): boolean {
42
+ return c === " " || c === "\t" || c === "\n" || c === "\r";
43
+ }
44
+
45
+ function allDigits(s: string): boolean {
46
+ if (s.length === 0) return false;
47
+ for (let i = 0; i < s.length; i++) if (!isDigit(s[i]!)) return false;
48
+ return true;
49
+ }
50
+
51
+ function hasCurrencyPrefix(s: string): boolean {
52
+ const up = s.toUpperCase();
53
+ for (const tok of CURRENCY_TOKENS) {
54
+ if (up.startsWith(tok.toUpperCase())) return true;
55
+ }
56
+ return false;
57
+ }
58
+
59
+ function hasCurrencySuffix(s: string): boolean {
60
+ const up = s.toUpperCase();
61
+ for (const tok of CURRENCY_TOKENS) {
62
+ if (up.endsWith(tok.toUpperCase())) return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ function stripCurrencyPrefix(s: string): { rest: string; stripped: boolean } {
68
+ const up = s.toUpperCase();
69
+ for (const tok of CURRENCY_TOKENS) {
70
+ const tUp = tok.toUpperCase();
71
+ if (up.startsWith(tUp)) {
72
+ let rest = s.slice(tok.length);
73
+ let i = 0;
74
+ while (i < rest.length && isWs(rest[i]!)) i++;
75
+ rest = rest.slice(i);
76
+ return { rest, stripped: true };
77
+ }
78
+ }
79
+ return { rest: s, stripped: false };
80
+ }
81
+
82
+ function stripCurrencySuffix(s: string): { rest: string; stripped: boolean } {
83
+ const up = s.toUpperCase();
84
+ for (const tok of CURRENCY_TOKENS) {
85
+ const tUp = tok.toUpperCase();
86
+ if (up.endsWith(tUp)) {
87
+ let rest = s.slice(0, s.length - tok.length);
88
+ let i = rest.length - 1;
89
+ while (i >= 0 && isWs(rest[i]!)) i--;
90
+ rest = rest.slice(0, i + 1);
91
+ return { rest, stripped: true };
92
+ }
93
+ }
94
+ return { rest: s, stripped: false };
95
+ }
96
+
97
+ // --- canonical / scientific helpers (linear, bounded) ---
98
+
99
+ /**
100
+ * Checks if a string is already in canonical decimal format (e.g. "1234.56", "-0.05", "42").
101
+ */
102
+ export function isCanonicalDecimal(str: string): boolean {
103
+ if (str.length === 0 || str.length > MAX_DECIMAL_INPUT_LENGTH) return false;
104
+ let i = 0;
105
+ if (str[0] === "-") {
106
+ i = 1;
107
+ if (i >= str.length) return false;
108
+ }
109
+ let digits = 0;
110
+ while (i < str.length && isDigit(str[i]!)) {
111
+ digits++;
112
+ i++;
113
+ }
114
+ if (digits === 0) return false;
115
+ if (i === str.length) return true;
116
+ if (str[i] !== ".") return false;
117
+ i++;
118
+ digits = 0;
119
+ while (i < str.length && isDigit(str[i]!)) {
120
+ digits++;
121
+ i++;
122
+ }
123
+ return digits > 0 && i === str.length;
124
+ }
125
+
126
+ /**
127
+ * Checks if a string contains scientific notation (e.g. "1.23e5", "4.56E-3").
128
+ */
129
+ export function isScientificNotation(str: string): boolean {
130
+ const s = str.trim();
131
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
132
+ let i = 0;
133
+ if (s[i] === "+" || s[i] === "-") i++;
134
+ let intDigits = 0;
135
+ while (i < s.length && isDigit(s[i]!)) {
136
+ intDigits++;
137
+ i++;
138
+ }
139
+ if (intDigits === 0) return false;
140
+ if (i < s.length && s[i] === ".") {
141
+ i++;
142
+ let frac = 0;
143
+ while (i < s.length && isDigit(s[i]!)) {
144
+ frac++;
145
+ i++;
146
+ }
147
+ if (frac === 0) return false;
148
+ }
149
+ if (i >= s.length) return false;
150
+ if (s[i] !== "e" && s[i] !== "E") return false;
151
+ i++;
152
+ if (i < s.length && (s[i] === "+" || s[i] === "-")) i++;
153
+ let exp = 0;
154
+ while (i < s.length && isDigit(s[i]!)) {
155
+ exp++;
156
+ i++;
157
+ }
158
+ return exp > 0 && i === s.length;
159
+ }
160
+
161
+ /**
162
+ * Checks if a string contains explicit currency symbols or currency ISO codes.
163
+ */
164
+ export function isCurrencyString(str: string): boolean {
165
+ const trimmed = str.trim();
166
+ if (trimmed.length === 0 || trimmed.length > MAX_DECIMAL_INPUT_LENGTH) return false;
167
+ if (hasCurrencyPrefix(trimmed) || hasCurrencySuffix(trimmed)) return true;
168
+ if (trimmed.startsWith("($") || trimmed.startsWith("(€") || trimmed.startsWith("(£")) return true;
169
+ return false;
170
+ }
171
+
172
+ export interface NormalizedDecimalResult {
173
+ /** Canonical decimal string (e.g. "1234.56", "-1234.56", "42"). */
174
+ readonly value: string;
175
+ /** True if currency symbols, grouping separators, or accounting parentheses were detected. */
176
+ readonly isMoney: boolean;
177
+ }
178
+
179
+ // --- grouping helpers (all linear, bounded via length + split) ---
180
+
181
+ function isPureDigits(s: string): boolean {
182
+ return allDigits(s);
183
+ }
184
+
185
+ function isUSGrouping(s: string): boolean {
186
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
187
+ const dotIdx = s.indexOf(".");
188
+ if (dotIdx !== -1 && s.indexOf(".", dotIdx + 1) !== -1) return false;
189
+ let intPart: string;
190
+ let fracPart: string | null = null;
191
+ if (dotIdx !== -1) {
192
+ intPart = s.slice(0, dotIdx);
193
+ fracPart = s.slice(dotIdx + 1);
194
+ if (fracPart.length === 0 || !allDigits(fracPart)) return false;
195
+ } else {
196
+ intPart = s;
197
+ }
198
+ if (intPart.length === 0 || !intPart.includes(",")) return false;
199
+ const parts = intPart.split(",");
200
+ if (parts.length < 2) return false;
201
+ const first = parts[0]!;
202
+ if (first.length < 1 || first.length > 3 || !allDigits(first)) return false;
203
+ for (let i = 1; i < parts.length; i++) {
204
+ const p = parts[i]!;
205
+ if (p.length !== 3 || !allDigits(p)) return false;
206
+ }
207
+ return true;
208
+ }
209
+
210
+ function isIndianGrouping(s: string): boolean {
211
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
212
+ const dotIdx = s.indexOf(".");
213
+ if (dotIdx !== -1 && s.indexOf(".", dotIdx + 1) !== -1) return false;
214
+ let intPart: string;
215
+ let fracPart: string | null = null;
216
+ if (dotIdx !== -1) {
217
+ intPart = s.slice(0, dotIdx);
218
+ fracPart = s.slice(dotIdx + 1);
219
+ if (fracPart.length === 0 || !allDigits(fracPart)) return false;
220
+ } else {
221
+ intPart = s;
222
+ }
223
+ if (intPart.length === 0 || !intPart.includes(",")) return false;
224
+ const parts = intPart.split(",");
225
+ if (parts.length < 2) return false;
226
+ const first = parts[0]!;
227
+ if (first.length < 1 || first.length > 2 || !allDigits(first)) return false;
228
+ const last = parts[parts.length - 1]!;
229
+ if (last.length !== 3 || !allDigits(last)) return false;
230
+ for (let i = 1; i < parts.length - 1; i++) {
231
+ const p = parts[i]!;
232
+ if (p.length !== 2 || !allDigits(p)) return false;
233
+ }
234
+ return true;
235
+ }
236
+
237
+ function isEUGrouping(s: string): boolean {
238
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
239
+ const commaIdx = s.indexOf(",");
240
+ if (commaIdx !== -1 && s.indexOf(",", commaIdx + 1) !== -1) return false;
241
+ let intPart: string;
242
+ let fracPart: string | null = null;
243
+ if (commaIdx !== -1) {
244
+ intPart = s.slice(0, commaIdx);
245
+ fracPart = s.slice(commaIdx + 1);
246
+ if (fracPart.length === 0 || !allDigits(fracPart)) return false;
247
+ } else {
248
+ intPart = s;
249
+ }
250
+ if (intPart.length === 0 || !intPart.includes(".")) return false;
251
+ const parts = intPart.split(".");
252
+ if (parts.length < 2) return false;
253
+ const first = parts[0]!;
254
+ if (first.length < 1 || first.length > 3 || !allDigits(first)) return false;
255
+ for (let i = 1; i < parts.length; i++) {
256
+ const p = parts[i]!;
257
+ if (p.length !== 3 || !allDigits(p)) return false;
258
+ }
259
+ return true;
260
+ }
261
+
262
+ function isDotDecimal(s: string): boolean {
263
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
264
+ const dotIdx = s.indexOf(".");
265
+ if (dotIdx === -1) return false;
266
+ if (s.indexOf(".", dotIdx + 1) !== -1) return false;
267
+ if (s.includes(",")) return false;
268
+ const before = s.slice(0, dotIdx);
269
+ const after = s.slice(dotIdx + 1);
270
+ if (after.length === 0 || !allDigits(after)) return false;
271
+ if (before.length === 0) return true;
272
+ return allDigits(before);
273
+ }
274
+
275
+ function isCommaDecimal(s: string): boolean {
276
+ if (s.length === 0 || s.length > MAX_DECIMAL_INPUT_LENGTH) return false;
277
+ const commaIdx = s.indexOf(",");
278
+ if (commaIdx === -1) return false;
279
+ if (s.indexOf(",", commaIdx + 1) !== -1) return false;
280
+ if (s.includes(".")) return false;
281
+ const before = s.slice(0, commaIdx);
282
+ const after = s.slice(commaIdx + 1);
283
+ if (after.length === 0 || !allDigits(after)) return false;
284
+ if (before.length === 0) return true;
285
+ return allDigits(before);
286
+ }
287
+
288
+ /**
289
+ * Normalizes a raw string representation of a decimal or currency number into a canonical decimal string.
290
+ * Returns `null` if the string cannot be safely and unambiguously normalized.
291
+ *
292
+ * @param input Raw token or cell text.
293
+ * @returns Canonical decimal string result or `null`.
294
+ */
295
+ export function normalizeDecimal(input: string): NormalizedDecimalResult | null {
296
+ if (input.length > MAX_DECIMAL_INPUT_LENGTH) return null;
297
+ let str = input.trim();
298
+ if (str === "") return null;
299
+ if (str.length > MAX_DECIMAL_INPUT_LENGTH) return null;
300
+
301
+ // Explicitly reject scientific notation from decimal normalization (must be flagged as ambiguous/string)
302
+ if (isScientificNotation(str)) return null;
303
+
304
+ let isNegative = false;
305
+ let isMoney = false;
306
+
307
+ // 1. Accounting-style parenthesis negative: (1,234.56) or ($1,234.56)
308
+ if (str.startsWith("(") && str.endsWith(")")) {
309
+ isNegative = true;
310
+ isMoney = true;
311
+ str = str.slice(1, -1).trim();
312
+ if (str.length === 0 || str.length > MAX_DECIMAL_INPUT_LENGTH) return null;
313
+ }
314
+
315
+ // 2. Standard leading/trailing negative signs
316
+ if (str.startsWith("-") || str.startsWith("−")) {
317
+ isNegative = true;
318
+ str = str.slice(1).trim();
319
+ } else if (str.endsWith("-") || str.endsWith("−")) {
320
+ isNegative = true;
321
+ str = str.slice(0, -1).trim();
322
+ }
323
+ if (str.length === 0) return null;
324
+
325
+ // 3. Strip currency symbols
326
+ {
327
+ const pre = stripCurrencyPrefix(str);
328
+ if (pre.stripped) {
329
+ isMoney = true;
330
+ str = pre.rest.trim();
331
+ }
332
+ }
333
+ {
334
+ const suf = stripCurrencySuffix(str);
335
+ if (suf.stripped) {
336
+ isMoney = true;
337
+ str = suf.rest.trim();
338
+ }
339
+ }
340
+ if (str.length === 0) return null;
341
+
342
+ // Negative sign could have been nested inside currency symbol e.g. $-100
343
+ if (str.startsWith("-") || str.startsWith("−")) {
344
+ isNegative = true;
345
+ str = str.slice(1).trim();
346
+ if (str.length === 0) return null;
347
+ }
348
+
349
+ // 4. Pure integer digits: "12345"
350
+ if (isPureDigits(str)) {
351
+ const val = (isNegative ? "-" : "") + str;
352
+ return { value: val, isMoney };
353
+ }
354
+
355
+ // 5. US/UK thousands grouping: "1,234,567.89" or "1,234"
356
+ if (isUSGrouping(str)) {
357
+ const val = (isNegative ? "-" : "") + str.replaceAll(",", "");
358
+ return { value: val, isMoney: true };
359
+ }
360
+
361
+ // 6. Indian thousands grouping: "1,00,000.50" or "10,00,000"
362
+ if (isIndianGrouping(str)) {
363
+ const val = (isNegative ? "-" : "") + str.replaceAll(",", "");
364
+ return { value: val, isMoney: true };
365
+ }
366
+
367
+ // 7. EU thousands grouping with comma decimal: "1.234.567,89" or "1.234"
368
+ if (isEUGrouping(str)) {
369
+ const val = (isNegative ? "-" : "") + str.replaceAll(".", "").replaceAll(",", ".");
370
+ return { value: val, isMoney: true };
371
+ }
372
+
373
+ // 8. Standard single dot decimal without thousands: "1234.56" or ".56"
374
+ if (isDotDecimal(str)) {
375
+ const canonicalStr = str.startsWith(".") ? `0${str}` : str;
376
+ const val = (isNegative ? "-" : "") + canonicalStr;
377
+ return { value: val, isMoney };
378
+ }
379
+
380
+ // 9. Single comma decimal without thousands: "1234,56" or ",56"
381
+ if (isCommaDecimal(str)) {
382
+ const canonicalStr = str.startsWith(",") ? `0.${str.slice(1)}` : str.replace(",", ".");
383
+ const val = (isNegative ? "-" : "") + canonicalStr;
384
+ return { value: val, isMoney };
385
+ }
386
+
387
+ return null;
388
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Base error class for all sheets and CSV operations.
3
+ */
4
+ export class SheetsError extends Error {
5
+ readonly code: string;
6
+
7
+ constructor(message: string, code = "ERR_PRISM_SHEETS") {
8
+ super(message);
9
+ this.name = "SheetsError";
10
+ this.code = code;
11
+ }
12
+ }
13
+
14
+ /**
15
+ * Thrown when an input buffer or structural element exceeds configured limits/caps.
16
+ */
17
+ export class SheetsCapError extends SheetsError {
18
+ constructor(message: string) {
19
+ super(message, "ERR_PRISM_SHEETS_CAP");
20
+ this.name = "SheetsCapError";
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Thrown when options or configurations violate validation constraints.
26
+ */
27
+ export class SheetsValidationError extends SheetsError {
28
+ constructor(message: string) {
29
+ super(message, "ERR_PRISM_SHEETS_VALIDATION");
30
+ this.name = "SheetsValidationError";
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Thrown when an input format is unsupported (e.g. non-ZIP header on XLSX, unsupported encoding).
36
+ */
37
+ export class SheetsFormatError extends SheetsError {
38
+ constructor(message: string) {
39
+ super(message, "ERR_PRISM_SHEETS_UNSUPPORTED_FORMAT");
40
+ this.name = "SheetsFormatError";
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Thrown when parsing corrupted, malformed, or unrecoverable XML/CSV data fails.
46
+ */
47
+ export class SheetsParseError extends SheetsError {
48
+ constructor(message: string) {
49
+ super(message, "ERR_PRISM_SHEETS_PARSE_FAILED");
50
+ this.name = "SheetsParseError";
51
+ }
52
+ }
@@ -0,0 +1,62 @@
1
+ export {
2
+ DEFAULT_INFERENCE_WINDOW_ROWS,
3
+ DEFAULT_MAX_COLUMNS,
4
+ DEFAULT_MAX_ROWS,
5
+ DEFAULT_MAX_SHEET_BYTES,
6
+ DEFAULT_MAX_SHEETS,
7
+ DEFAULT_MAX_WARNINGS,
8
+ HARD_INFERENCE_WINDOW_ROWS,
9
+ HARD_MAX_COLUMNS,
10
+ HARD_MAX_ROWS,
11
+ HARD_MAX_SHEET_BYTES,
12
+ HARD_MAX_SHEETS,
13
+ HARD_MAX_WARNINGS,
14
+ resolveSheetsCaps,
15
+ validateByteCap,
16
+ validateZipSignature,
17
+ } from "./caps.js";
18
+ export { parseCsv } from "./csv.js";
19
+ export {
20
+ isCanonicalDecimal,
21
+ isCurrencyString,
22
+ isScientificNotation,
23
+ type NormalizedDecimalResult,
24
+ normalizeDecimal,
25
+ } from "./decimal.js";
26
+ export {
27
+ SheetsCapError,
28
+ SheetsError,
29
+ SheetsFormatError,
30
+ SheetsParseError,
31
+ SheetsValidationError,
32
+ } from "./errors.js";
33
+ export {
34
+ type InferAndTransformResult,
35
+ inferAndTransformRows,
36
+ } from "./inference.js";
37
+ export {
38
+ noopSheetsSpan,
39
+ noopSheetsTelemetry,
40
+ type SheetsTelemetry,
41
+ type SheetsTelemetryAttributeValue,
42
+ type SheetsTelemetrySpan,
43
+ } from "./telemetry.js";
44
+ export type {
45
+ CellValue,
46
+ ColumnSchema,
47
+ ColumnType,
48
+ CsvDialect,
49
+ CsvParse,
50
+ DateCellValue,
51
+ DateTimeCellValue,
52
+ DecimalCellValue,
53
+ FormulaCellValue,
54
+ InferenceWarning,
55
+ ParseCsvOptions,
56
+ ParseWorkbookOptions,
57
+ ResolvedSheetsCaps,
58
+ SheetParse,
59
+ SheetsCaps,
60
+ WorkbookParse,
61
+ } from "./types.js";
62
+ export { parseWorkbook } from "./xlsx.js";