@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,378 @@
1
+ import { isCurrencyString, isScientificNotation, normalizeDecimal } from "./decimal.js";
2
+ import type { CellValue, ColumnSchema, ColumnType, InferenceWarning, ResolvedSheetsCaps } from "./types.js";
3
+
4
+ const MONEY_COLUMN_NAME_PATTERN =
5
+ /(^|_|-|\b)(amount|price|cost|total|revenue|salary|fee|balance|rate|subtotal|tax|discount|payment|deposit|refund|gross|net)($|_|-|\b)/i;
6
+
7
+ const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
8
+ const ISO_DATETIME_REGEX = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/;
9
+
10
+ interface ColumnStats {
11
+ nullCount: number;
12
+ totalCount: number;
13
+ sample?: string;
14
+ hasCurrency: boolean;
15
+ hasScientific: boolean;
16
+ hasMixedDecimalSeparator: boolean;
17
+ typeCounts: Map<ColumnType, number>;
18
+ }
19
+
20
+ export interface InferAndTransformResult {
21
+ readonly schema: readonly ColumnSchema[];
22
+ readonly rows: readonly (readonly CellValue[])[];
23
+ readonly warnings: readonly InferenceWarning[];
24
+ }
25
+
26
+ /**
27
+ * Infers column types across a bounded sampling window and validates all rows against the inferred schema.
28
+ *
29
+ * @param rawRows 2D array of parsed cell values.
30
+ * @param caps Resolved limits and window configuration.
31
+ * @returns Inferred column schemas, typed rows, and validation warnings.
32
+ */
33
+ export function inferAndTransformRows(rawRows: readonly (readonly CellValue[])[], caps: ResolvedSheetsCaps): InferAndTransformResult {
34
+ if (rawRows.length === 0) {
35
+ return { schema: [], rows: [], warnings: [] };
36
+ }
37
+
38
+ const colCount = Math.max(...rawRows.map((r) => r.length), 0);
39
+ if (colCount === 0) {
40
+ return { schema: [], rows: [], warnings: [] };
41
+ }
42
+
43
+ // 1. Check for header row
44
+ const hasHeaderRow =
45
+ rawRows.length > 1 && rawRows[0].length === colCount && rawRows[0].every((cell) => typeof cell === "string" && cell.trim() !== "");
46
+
47
+ const headerNames = hasHeaderRow
48
+ ? rawRows[0].map((cell, idx) => (typeof cell === "string" && cell.trim() ? cell.trim() : `Column ${idx + 1}`))
49
+ : Array.from({ length: colCount }, (_, idx) => `Column ${idx + 1}`);
50
+
51
+ const dataRows = hasHeaderRow ? rawRows.slice(1) : rawRows;
52
+ const sampleWindowRows = dataRows.slice(0, caps.inferenceWindowRows);
53
+
54
+ // 2. Collect statistics over the sampling window
55
+ const stats: ColumnStats[] = Array.from({ length: colCount }, () => ({
56
+ nullCount: 0,
57
+ totalCount: 0,
58
+ hasCurrency: false,
59
+ hasScientific: false,
60
+ hasMixedDecimalSeparator: false,
61
+ typeCounts: new Map<ColumnType, number>(),
62
+ }));
63
+
64
+ for (const row of sampleWindowRows) {
65
+ for (let c = 0; c < colCount; c++) {
66
+ const colStat = stats[c];
67
+ colStat.totalCount += 1;
68
+ const cell = row[c];
69
+
70
+ if (cell === null || cell === undefined || cell === "") {
71
+ colStat.nullCount += 1;
72
+ continue;
73
+ }
74
+
75
+ if (colStat.sample === undefined) {
76
+ if (typeof cell === "object" && cell !== null && "value" in cell) {
77
+ colStat.sample = String(cell.value);
78
+ } else if (typeof cell === "object" && cell !== null && "formula" in cell) {
79
+ colStat.sample = cell.formula;
80
+ } else {
81
+ colStat.sample = String(cell);
82
+ }
83
+ }
84
+
85
+ // Check formula cell
86
+ if (typeof cell === "object" && cell !== null && "formula" in cell) {
87
+ colStat.typeCounts.set("string", (colStat.typeCounts.get("string") ?? 0) + 1);
88
+ continue;
89
+ }
90
+
91
+ // Check existing explicit types
92
+ if (typeof cell === "object" && cell !== null && "type" in cell) {
93
+ if (cell.type === "decimal") {
94
+ colStat.typeCounts.set("decimal", (colStat.typeCounts.get("decimal") ?? 0) + 1);
95
+ } else if (cell.type === "date") {
96
+ colStat.typeCounts.set("date", (colStat.typeCounts.get("date") ?? 0) + 1);
97
+ } else if (cell.type === "datetime") {
98
+ colStat.typeCounts.set("datetime", (colStat.typeCounts.get("datetime") ?? 0) + 1);
99
+ }
100
+ continue;
101
+ }
102
+
103
+ if (typeof cell === "boolean") {
104
+ colStat.typeCounts.set("boolean", (colStat.typeCounts.get("boolean") ?? 0) + 1);
105
+ continue;
106
+ }
107
+
108
+ if (typeof cell === "number") {
109
+ if (Number.isInteger(cell)) {
110
+ colStat.typeCounts.set("integer", (colStat.typeCounts.get("integer") ?? 0) + 1);
111
+ } else {
112
+ colStat.typeCounts.set("decimal", (colStat.typeCounts.get("decimal") ?? 0) + 1);
113
+ }
114
+ continue;
115
+ }
116
+
117
+ // String token analysis
118
+ const strVal = String(cell).trim();
119
+
120
+ if (isScientificNotation(strVal)) {
121
+ colStat.hasScientific = true;
122
+ colStat.typeCounts.set("string", (colStat.typeCounts.get("string") ?? 0) + 1);
123
+ continue;
124
+ }
125
+
126
+ if (isCurrencyString(strVal)) {
127
+ colStat.hasCurrency = true;
128
+ }
129
+
130
+ if (strVal.toLowerCase() === "true" || strVal.toLowerCase() === "false") {
131
+ colStat.typeCounts.set("boolean", (colStat.typeCounts.get("boolean") ?? 0) + 1);
132
+ continue;
133
+ }
134
+
135
+ if (ISO_DATE_REGEX.test(strVal)) {
136
+ colStat.typeCounts.set("date", (colStat.typeCounts.get("date") ?? 0) + 1);
137
+ continue;
138
+ }
139
+
140
+ if (ISO_DATETIME_REGEX.test(strVal)) {
141
+ colStat.typeCounts.set("datetime", (colStat.typeCounts.get("datetime") ?? 0) + 1);
142
+ continue;
143
+ }
144
+
145
+ const normalized = normalizeDecimal(strVal);
146
+ if (normalized !== null) {
147
+ if (normalized.isMoney) {
148
+ colStat.hasCurrency = true;
149
+ }
150
+ if (/^-?\d+$/.test(normalized.value) && !normalized.isMoney) {
151
+ colStat.typeCounts.set("integer", (colStat.typeCounts.get("integer") ?? 0) + 1);
152
+ } else {
153
+ colStat.typeCounts.set("decimal", (colStat.typeCounts.get("decimal") ?? 0) + 1);
154
+ }
155
+ } else {
156
+ colStat.typeCounts.set("string", (colStat.typeCounts.get("string") ?? 0) + 1);
157
+ }
158
+ }
159
+ }
160
+
161
+ // 3. Deduce schemas per column
162
+ const schema: ColumnSchema[] = [];
163
+
164
+ for (let c = 0; c < colCount; c++) {
165
+ const colName = headerNames[c];
166
+ const colStat = stats[c];
167
+ const flags: string[] = [];
168
+ let inferredType: ColumnType = "string";
169
+
170
+ if (colStat.hasScientific) {
171
+ inferredType = "string";
172
+ flags.push("numeric-ambiguous");
173
+ } else {
174
+ const isMoneyNamed = MONEY_COLUMN_NAME_PATTERN.test(colName);
175
+ const decimalCount = colStat.typeCounts.get("decimal") ?? 0;
176
+ const integerCount = colStat.typeCounts.get("integer") ?? 0;
177
+ const numericCount = decimalCount + integerCount;
178
+
179
+ if ((colStat.hasCurrency || isMoneyNamed) && numericCount > 0) {
180
+ inferredType = "decimal";
181
+ } else {
182
+ // Find dominant type
183
+ let highestCount = 0;
184
+ let dominantType: ColumnType = "string";
185
+
186
+ for (const [t, count] of colStat.typeCounts.entries()) {
187
+ if (count > highestCount) {
188
+ highestCount = count;
189
+ dominantType = t;
190
+ }
191
+ }
192
+
193
+ if (dominantType === "integer" && decimalCount > 0) {
194
+ // Mixed integer and decimal in non-money column -> decimal
195
+ inferredType = "decimal";
196
+ } else {
197
+ inferredType = dominantType;
198
+ }
199
+ }
200
+ }
201
+
202
+ const nullRate = Number((colStat.nullCount / Math.max(sampleWindowRows.length, 1)).toFixed(4));
203
+
204
+ schema.push({
205
+ name: colName,
206
+ type: inferredType,
207
+ nullRate,
208
+ sample: colStat.sample,
209
+ flags,
210
+ });
211
+ }
212
+
213
+ // 4. Validate all data rows and transform cell values to match the inferred schema
214
+ const warnings: InferenceWarning[] = [];
215
+ const mismatchCounts = new Map<number, number>();
216
+ const mismatchSamples = new Map<number, string[]>();
217
+
218
+ const transformedDataRows: CellValue[][] = [];
219
+
220
+ for (let r = 0; r < dataRows.length; r++) {
221
+ const rawRow = dataRows[r];
222
+ const transformedRow: CellValue[] = [];
223
+
224
+ for (let c = 0; c < colCount; c++) {
225
+ const colSchema = schema[c];
226
+ const cell = rawRow[c];
227
+
228
+ if (cell === null || cell === undefined || cell === "") {
229
+ transformedRow.push(null);
230
+ continue;
231
+ }
232
+
233
+ // Preserve formula cells intact
234
+ if (typeof cell === "object" && cell !== null && "formula" in cell) {
235
+ transformedRow.push(cell);
236
+ continue;
237
+ }
238
+
239
+ let transformedCell: CellValue = cell;
240
+ let matched = true;
241
+
242
+ switch (colSchema.type) {
243
+ case "decimal": {
244
+ if (typeof cell === "object" && cell !== null && "type" in cell && cell.type === "decimal") {
245
+ transformedCell = cell;
246
+ } else if (typeof cell === "number") {
247
+ transformedCell = { type: "decimal", value: String(cell) };
248
+ } else if (typeof cell === "string") {
249
+ const norm = normalizeDecimal(cell);
250
+ if (norm !== null) {
251
+ transformedCell = { type: "decimal", value: norm.value };
252
+ } else {
253
+ matched = false;
254
+ transformedCell = cell;
255
+ }
256
+ } else {
257
+ matched = false;
258
+ }
259
+ break;
260
+ }
261
+
262
+ case "integer": {
263
+ if (typeof cell === "number" && Number.isInteger(cell)) {
264
+ transformedCell = cell;
265
+ } else if (typeof cell === "string") {
266
+ const norm = normalizeDecimal(cell);
267
+ if (norm !== null && /^-?\d+$/.test(norm.value)) {
268
+ const num = Number(norm.value);
269
+ if (Number.isSafeInteger(num)) {
270
+ transformedCell = num;
271
+ } else {
272
+ transformedCell = { type: "decimal", value: norm.value };
273
+ }
274
+ } else {
275
+ matched = false;
276
+ transformedCell = cell;
277
+ }
278
+ } else {
279
+ matched = false;
280
+ }
281
+ break;
282
+ }
283
+
284
+ case "boolean": {
285
+ if (typeof cell === "boolean") {
286
+ transformedCell = cell;
287
+ } else if (typeof cell === "string") {
288
+ const lower = cell.trim().toLowerCase();
289
+ if (lower === "true" || lower === "1") {
290
+ transformedCell = true;
291
+ } else if (lower === "false" || lower === "0") {
292
+ transformedCell = false;
293
+ } else {
294
+ matched = false;
295
+ transformedCell = cell;
296
+ }
297
+ } else {
298
+ matched = false;
299
+ }
300
+ break;
301
+ }
302
+
303
+ case "date": {
304
+ if (typeof cell === "object" && cell !== null && "type" in cell && cell.type === "date") {
305
+ transformedCell = cell;
306
+ } else if (typeof cell === "string" && ISO_DATE_REGEX.test(cell.trim())) {
307
+ transformedCell = { type: "date", value: cell.trim() };
308
+ } else {
309
+ matched = false;
310
+ transformedCell = cell;
311
+ }
312
+ break;
313
+ }
314
+
315
+ case "datetime": {
316
+ if (typeof cell === "object" && cell !== null && "type" in cell && cell.type === "datetime") {
317
+ transformedCell = cell;
318
+ } else if (typeof cell === "string" && ISO_DATETIME_REGEX.test(cell.trim())) {
319
+ transformedCell = { type: "datetime", value: cell.trim() };
320
+ } else {
321
+ matched = false;
322
+ transformedCell = cell;
323
+ }
324
+ break;
325
+ }
326
+
327
+ default: {
328
+ if (colSchema.flags.includes("numeric-ambiguous")) {
329
+ if (typeof cell === "object" && cell !== null && "value" in cell) {
330
+ transformedCell = String(cell.value);
331
+ } else {
332
+ transformedCell = String(cell);
333
+ }
334
+ } else {
335
+ transformedCell = typeof cell === "object" && cell !== null && "value" in cell ? String(cell.value) : cell;
336
+ }
337
+ break;
338
+ }
339
+ }
340
+
341
+ if (!matched) {
342
+ const curCount = mismatchCounts.get(c) ?? 0;
343
+ mismatchCounts.set(c, curCount + 1);
344
+ const curSamples = mismatchSamples.get(c) ?? [];
345
+ if (curSamples.length < 20) {
346
+ curSamples.push(String(typeof cell === "object" && cell !== null && "value" in cell ? cell.value : cell));
347
+ mismatchSamples.set(c, curSamples);
348
+ }
349
+ }
350
+
351
+ transformedRow.push(transformedCell);
352
+ }
353
+
354
+ transformedDataRows.push(transformedRow);
355
+ }
356
+
357
+ // 5. Construct warning reports for column type mismatches
358
+ for (let c = 0; c < colCount; c++) {
359
+ const count = mismatchCounts.get(c) ?? 0;
360
+ if (count > 0 && warnings.length < caps.maxWarnings) {
361
+ warnings.push({
362
+ kind: "type-mismatch",
363
+ message: `Column "${schema[c].name}" had ${count} value(s) not matching inferred type "${schema[c].type}"`,
364
+ column: schema[c].name,
365
+ mismatchCount: count,
366
+ samples: mismatchSamples.get(c) ?? [],
367
+ });
368
+ }
369
+ }
370
+
371
+ const finalRows = hasHeaderRow ? [rawRows[0], ...transformedDataRows] : transformedDataRows;
372
+
373
+ return {
374
+ schema,
375
+ rows: finalRows,
376
+ warnings,
377
+ };
378
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Dependency-free telemetry seam for Sheets operations.
3
+ * When `telemetry` is omitted, call-sites short-circuit on optional chaining without allocations.
4
+ */
5
+
6
+ export type SheetsTelemetryAttributeValue = string | number | boolean;
7
+
8
+ export interface SheetsTelemetrySpan {
9
+ setAttribute(name: string, value: SheetsTelemetryAttributeValue): void;
10
+ addEvent(name: string, attributes?: Readonly<Record<string, SheetsTelemetryAttributeValue>>): void;
11
+ recordError(): void;
12
+ end(): void;
13
+ }
14
+
15
+ export interface SheetsTelemetry {
16
+ startSpan(
17
+ name: string,
18
+ attributes?: Readonly<Record<string, SheetsTelemetryAttributeValue>>,
19
+ parent?: SheetsTelemetrySpan,
20
+ ): SheetsTelemetrySpan;
21
+ }
22
+
23
+ export const noopSheetsSpan: SheetsTelemetrySpan = {
24
+ setAttribute() {},
25
+ addEvent() {},
26
+ recordError() {},
27
+ end() {},
28
+ };
29
+
30
+ export const noopSheetsTelemetry: SheetsTelemetry = {
31
+ startSpan() {
32
+ return noopSheetsSpan;
33
+ },
34
+ };
@@ -0,0 +1,162 @@
1
+ import type { SheetsTelemetry } from "./telemetry.js";
2
+
3
+ /**
4
+ * Supported data types inferred for sheet and CSV columns.
5
+ */
6
+ export type ColumnType = "string" | "integer" | "number" | "decimal" | "date" | "datetime" | "boolean";
7
+
8
+ /**
9
+ * Explicit decimal value represented as a canonical string to prevent IEEE-754 floating point loss.
10
+ */
11
+ export interface DecimalCellValue {
12
+ readonly type: "decimal";
13
+ /** Canonical decimal string (e.g. "1234.56", "-0.05", "42"). */
14
+ readonly value: string;
15
+ }
16
+
17
+ /**
18
+ * ISO-8601 date string representation (YYYY-MM-DD).
19
+ */
20
+ export interface DateCellValue {
21
+ readonly type: "date";
22
+ readonly value: string;
23
+ }
24
+
25
+ /**
26
+ * ISO-8601 datetime string representation.
27
+ */
28
+ export interface DateTimeCellValue {
29
+ readonly type: "datetime";
30
+ readonly value: string;
31
+ }
32
+
33
+ /**
34
+ * Spreadsheet formula cell with optional cached computation result.
35
+ */
36
+ export interface FormulaCellValue {
37
+ readonly type?: "formula";
38
+ /** Formula expression (e.g. "=SUM(A1:A10)"). */
39
+ readonly formula: string;
40
+ /** Cached or pre-calculated evaluation result (if present in the file). */
41
+ readonly cachedValue?: string | number | boolean | null;
42
+ }
43
+
44
+ /**
45
+ * Cell value in a parsed worksheet or CSV row.
46
+ */
47
+ export type CellValue = string | number | boolean | DecimalCellValue | DateCellValue | DateTimeCellValue | FormulaCellValue | null;
48
+
49
+ /**
50
+ * Inferred schema for a single column.
51
+ */
52
+ export interface ColumnSchema {
53
+ /** Column name / header label. */
54
+ readonly name: string;
55
+ /** Inferred data type. */
56
+ readonly type: ColumnType;
57
+ /** Fraction of rows with null/empty values in (0.0, 1.0]. */
58
+ readonly nullRate: number;
59
+ /** Representative non-null sample value as a string. */
60
+ readonly sample?: string;
61
+ /** Special flags (e.g. "numeric-ambiguous", "date-ambiguous", "mixed-types"). */
62
+ readonly flags: readonly string[];
63
+ }
64
+
65
+ /**
66
+ * Warning produced during parsing or schema inference.
67
+ */
68
+ export interface InferenceWarning {
69
+ readonly kind: string;
70
+ readonly message: string;
71
+ readonly column?: string;
72
+ readonly row?: number;
73
+ readonly mismatchCount?: number;
74
+ readonly samples?: readonly string[];
75
+ }
76
+
77
+ /**
78
+ * Parsed individual worksheet structure.
79
+ */
80
+ export interface SheetParse {
81
+ /** Worksheet name. */
82
+ readonly name: string;
83
+ /** 2D grid of parsed cell values [rowIndex][colIndex]. */
84
+ readonly rows: readonly (readonly CellValue[])[];
85
+ /** Inferred column schema. */
86
+ readonly schema: readonly ColumnSchema[];
87
+ }
88
+
89
+ /**
90
+ * Output of `parseWorkbook` containing all sheets and workbook-level warnings.
91
+ */
92
+ export interface WorkbookParse {
93
+ readonly sheets: readonly SheetParse[];
94
+ readonly warnings: readonly InferenceWarning[];
95
+ }
96
+
97
+ /**
98
+ * Detected CSV dialect attributes.
99
+ */
100
+ export interface CsvDialect {
101
+ readonly delimiter: string;
102
+ readonly quote: string;
103
+ readonly escape?: string;
104
+ readonly hasHeader?: boolean;
105
+ }
106
+
107
+ /**
108
+ * Output of `parseCsv` containing parsed rows, schema, dialect, and warnings.
109
+ */
110
+ export interface CsvParse {
111
+ readonly rows: readonly (readonly CellValue[])[];
112
+ readonly schema: readonly ColumnSchema[];
113
+ readonly dialect: CsvDialect;
114
+ readonly warnings: readonly InferenceWarning[];
115
+ }
116
+
117
+ /**
118
+ * User-configurable limits for sheet and CSV parsing operations.
119
+ */
120
+ export interface SheetsCaps {
121
+ /** Maximum input size in bytes (default 32 MiB, hard ceiling 512 MiB). */
122
+ readonly maxBytes?: number;
123
+ /** Maximum number of sheets in a workbook (default 100, hard ceiling 1,000). */
124
+ readonly maxSheets?: number;
125
+ /** Maximum number of rows per sheet or CSV (default 100,000, hard ceiling 1,000,000). */
126
+ readonly maxRows?: number;
127
+ /** Maximum number of columns per sheet or CSV (default 1,000, hard ceiling 16,384). */
128
+ readonly maxColumns?: number;
129
+ /** Number of rows to sample for schema inference (default 500, hard ceiling 5,000). */
130
+ readonly inferenceWindowRows?: number;
131
+ /** Maximum warnings collected (default 100, hard ceiling 1,000). */
132
+ readonly maxWarnings?: number;
133
+ }
134
+
135
+ /**
136
+ * Fully resolved caps with defaults and hard ceilings applied.
137
+ */
138
+ export interface ResolvedSheetsCaps {
139
+ readonly maxBytes: number;
140
+ readonly maxSheets: number;
141
+ readonly maxRows: number;
142
+ readonly maxColumns: number;
143
+ readonly inferenceWindowRows: number;
144
+ readonly maxWarnings: number;
145
+ }
146
+
147
+ /**
148
+ * Options passed to `parseWorkbook`.
149
+ */
150
+ export interface ParseWorkbookOptions {
151
+ readonly caps?: SheetsCaps;
152
+ readonly telemetry?: SheetsTelemetry;
153
+ }
154
+
155
+ /**
156
+ * Options passed to `parseCsv`.
157
+ */
158
+ export interface ParseCsvOptions {
159
+ readonly caps?: SheetsCaps;
160
+ readonly telemetry?: SheetsTelemetry;
161
+ readonly dialect?: Partial<CsvDialect>;
162
+ }