bantamkit-mcp 0.26.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 (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +398 -0
  3. package/assets/contracts/default.yaml +90 -0
  4. package/assets/evals/devteam/manifest.yaml +351 -0
  5. package/assets/evals/devteam/repo/HISTORY.md +18 -0
  6. package/assets/evals/devteam/repo/README.md +12 -0
  7. package/assets/evals/devteam/repo/docs/architecture.md +17 -0
  8. package/assets/evals/devteam/repo/docs/runbook.md +10 -0
  9. package/assets/evals/devteam/repo/issues/142-settlement-timeout.md +23 -0
  10. package/assets/evals/devteam/repo/patches/0009-retry-budget.patch +38 -0
  11. package/assets/evals/devteam/repo/src/ledger/__init__.py +3 -0
  12. package/assets/evals/devteam/repo/src/ledger/config.py +35 -0
  13. package/assets/evals/devteam/repo/src/ledger/errors.py +13 -0
  14. package/assets/evals/devteam/repo/src/ledger/posting.py +12 -0
  15. package/assets/evals/devteam/repo/src/ledger/registry.py +7 -0
  16. package/assets/evals/devteam/repo/src/ledger/report.py +9 -0
  17. package/assets/evals/devteam/repo/src/ledger/retry.py +17 -0
  18. package/assets/evals/devteam/repo/src/ledger/settle.py +16 -0
  19. package/assets/evals/devteam/repo/src/ledger/validate.py +14 -0
  20. package/assets/evals/devteam/repo/tests/test_posting.py +13 -0
  21. package/assets/evals/devteam/repo/tests/test_settle.py +9 -0
  22. package/assets/evals/devteam/tasks/dt-error-contract.yaml +186 -0
  23. package/assets/evals/devteam/tasks/dt-handler-map.yaml +183 -0
  24. package/assets/evals/devteam/tasks/dt-patch-before-after.yaml +182 -0
  25. package/assets/evals/devteam/tasks/dt-retry-attempts.yaml +181 -0
  26. package/assets/evals/devteam/tasks/dt-settlement-config.yaml +185 -0
  27. package/assets/evals/devteam/tasks/dt-symbol-home.yaml +181 -0
  28. package/assets/evals/devteam/tasks/dt-trace-blame.yaml +182 -0
  29. package/assets/evals/devteam/tasks/dt-unread-key.yaml +180 -0
  30. package/assets/evals/document/tasks/doc-large-in-137.yaml +38 -0
  31. package/assets/evals/document/tasks/doc-large-in-359.yaml +44 -0
  32. package/assets/evals/document/tasks/doc-large-in-372.yaml +38 -0
  33. package/assets/evals/document/tasks/doc-large-out-11764.yaml +37 -0
  34. package/assets/evals/document/tasks/doc-large-out-4137.yaml +37 -0
  35. package/assets/evals/document/tasks/doc-large-out-8022.yaml +37 -0
  36. package/assets/evals/document/tasks/doc-small-137.yaml +37 -0
  37. package/assets/evals/document/tasks/doc-small-261.yaml +37 -0
  38. package/assets/evals/document/tasks/doc-small-388.yaml +37 -0
  39. package/assets/evals/fixtures/.gitkeep +0 -0
  40. package/assets/evals/fixtures/catalog.json +6 -0
  41. package/assets/evals/perturbations/task-completion.yaml +576 -0
  42. package/assets/evals/tasks/.gitkeep +0 -0
  43. package/assets/evals/tasks/extract-contact.yaml +14 -0
  44. package/assets/evals/tasks/extract-invoice.yaml +14 -0
  45. package/assets/evals/tasks/extract-order.yaml +15 -0
  46. package/assets/evals/tasks/extract-schedule.yaml +14 -0
  47. package/assets/evals/tasks/extract-versions.yaml +17 -0
  48. package/assets/evals/tasks/nav-prod-port.yaml +84 -0
  49. package/assets/evals/tasks/nav-release-bundle.yaml +87 -0
  50. package/assets/evals/tasks/recall-audit-retention.yaml +17 -0
  51. package/assets/evals/tasks/recall-cache-ttl.yaml +13 -0
  52. package/assets/evals/tasks/recall-db-port.yaml +17 -0
  53. package/assets/evals/tasks/recall-deploy.yaml +13 -0
  54. package/assets/evals/tasks/recall-env-endpoint.yaml +18 -0
  55. package/assets/evals/tasks/recall-oncall-rotation.yaml +21 -0
  56. package/assets/evals/tasks/recall-oncall.yaml +13 -0
  57. package/assets/evals/tasks/recall-org-quota.yaml +18 -0
  58. package/assets/evals/tasks/recall-owner.yaml +13 -0
  59. package/assets/evals/tasks/shop-basket-total.yaml +10 -0
  60. package/assets/evals/tasks/shop-cheapest.yaml +9 -0
  61. package/assets/evals/tasks/shop-compare.yaml +9 -0
  62. package/assets/evals/tasks/shop-gadget-value.yaml +9 -0
  63. package/assets/evals/tasks/shop-stock-total.yaml +9 -0
  64. package/assets/evals/tasks/shop-total.yaml +9 -0
  65. package/assets/profiles/default.yaml +31 -0
  66. package/assets/profiles/patient.yaml +31 -0
  67. package/assets/rubrics/.gitkeep +0 -0
  68. package/assets/rubrics/code-quality.yaml +20 -0
  69. package/assets/rubrics/grounded-completion.yaml +37 -0
  70. package/assets/rubrics/task-completion.yaml +28 -0
  71. package/assets/schemas/shiftwork-checkpoint.json +188 -0
  72. package/assets/skills/.gitkeep +0 -0
  73. package/assets/skills/file-graph.md +7 -0
  74. package/assets/skills/memory.md +35 -0
  75. package/assets/tools/.gitkeep +0 -0
  76. package/assets/tools/bantamkit_read.json +48 -0
  77. package/assets/tools/bantamkit_status.json +25 -0
  78. package/assets/tools/build_identity.json +17 -0
  79. package/assets/tools/document_list.json +12 -0
  80. package/assets/tools/document_read.json +31 -0
  81. package/assets/tools/file_graph.json +12 -0
  82. package/assets/tools/memory_compact.json +31 -0
  83. package/assets/tools/memory_recall.json +38 -0
  84. package/assets/tools/memory_save.json +61 -0
  85. package/assets/tools/shiftwork_clock_in.json +25 -0
  86. package/assets/tools/shiftwork_clock_out.json +60 -0
  87. package/assets/tools/shiftwork_status.json +25 -0
  88. package/assets/tools/skill_audit.json +70 -0
  89. package/assets/tools/validate_json.json +31 -0
  90. package/dist/assets.d.ts +48 -0
  91. package/dist/assets.js +109 -0
  92. package/dist/charsets.d.ts +17 -0
  93. package/dist/charsets.js +580 -0
  94. package/dist/cli.d.ts +12 -0
  95. package/dist/cli.js +280 -0
  96. package/dist/contract.d.ts +145 -0
  97. package/dist/contract.js +608 -0
  98. package/dist/docread.d.ts +357 -0
  99. package/dist/docread.js +3315 -0
  100. package/dist/errors.d.ts +11 -0
  101. package/dist/errors.js +14 -0
  102. package/dist/eventlog.d.ts +137 -0
  103. package/dist/eventlog.js +294 -0
  104. package/dist/htmlentities.d.ts +2 -0
  105. package/dist/htmlentities.js +16 -0
  106. package/dist/index.d.ts +23 -0
  107. package/dist/index.js +13 -0
  108. package/dist/mcp/identity.d.ts +25 -0
  109. package/dist/mcp/identity.js +275 -0
  110. package/dist/mcp/pyargs.d.ts +80 -0
  111. package/dist/mcp/pyargs.js +362 -0
  112. package/dist/mcp/sdkjson.d.ts +56 -0
  113. package/dist/mcp/sdkjson.js +91 -0
  114. package/dist/mcp/server.d.ts +45 -0
  115. package/dist/mcp/server.js +740 -0
  116. package/dist/mcp/status.d.ts +210 -0
  117. package/dist/mcp/status.js +357 -0
  118. package/dist/mcp/transport.d.ts +68 -0
  119. package/dist/mcp/transport.js +111 -0
  120. package/dist/mcpreport.d.ts +214 -0
  121. package/dist/mcpreport.js +758 -0
  122. package/dist/memory/cli.d.ts +2 -0
  123. package/dist/memory/cli.js +396 -0
  124. package/dist/memory/component.d.ts +256 -0
  125. package/dist/memory/component.js +497 -0
  126. package/dist/memory/factfile.d.ts +120 -0
  127. package/dist/memory/factfile.js +406 -0
  128. package/dist/memory/layers.d.ts +92 -0
  129. package/dist/memory/layers.js +410 -0
  130. package/dist/memory/pyfs.d.ts +521 -0
  131. package/dist/memory/pyfs.js +1608 -0
  132. package/dist/memory/pyyaml.d.ts +155 -0
  133. package/dist/memory/pyyaml.js +868 -0
  134. package/dist/memory/store.d.ts +478 -0
  135. package/dist/memory/store.js +1034 -0
  136. package/dist/pyargparse.d.ts +141 -0
  137. package/dist/pyargparse.js +813 -0
  138. package/dist/pyjson.d.ts +110 -0
  139. package/dist/pyjson.js +524 -0
  140. package/dist/pyjsonschema.d.ts +50 -0
  141. package/dist/pyjsonschema.js +951 -0
  142. package/dist/shiftwork.d.ts +60 -0
  143. package/dist/shiftwork.js +324 -0
  144. package/dist/skillaudit.d.ts +172 -0
  145. package/dist/skillaudit.js +914 -0
  146. package/dist/statusline.d.ts +106 -0
  147. package/dist/statusline.js +281 -0
  148. package/package.json +45 -0
@@ -0,0 +1,357 @@
1
+ /**
2
+ * The Node half of `runtime-py/src/bantamkit/docread.py`: deterministic text extraction,
3
+ * addressable by part and row, dispatched on what a file IS.
4
+ *
5
+ * The Python module is the reference and this file COPIES it — its rows, its omission
6
+ * records and its sentences, byte for byte, for the kinds it reads: `text`, `xlsx`,
7
+ * `docx`, `html` and `mhtml`. Every constant, token and sentence below is the Python
8
+ * one; where the reference reads something this half does not (`pdf` through
9
+ * `pdfread`, `doc`/`rtf` through `/usr/bin/textutil`), `sniff` still IDENTIFIES the
10
+ * container so the refusal names it, and `extract` refuses with a sentence that is a
11
+ * DELIBERATE divergence recorded in `docs/porting.md`.
12
+ *
13
+ * No third-party dependency. The reference leans on four standard-library modules that
14
+ * Node does not ship, and each is replaced by the smallest hand-written reader that
15
+ * reproduces the reference's answers on the reference's own fixtures:
16
+ *
17
+ * - `zipfile` -> `ZipReader`: central-directory walk, stored + deflate (`node:zlib`
18
+ * `inflateRawSync`), CRC-32 checked the way `ZipFile.read` checks it.
19
+ * - `xml.etree` -> `parseXml`: a namespace-expanding element tree with `.text`,
20
+ * `iter(tag)`, `find(tag)` and direct-child iteration — the four ET
21
+ * operations `docread.py` actually calls.
22
+ * - `html.parser` + `html.unescape` -> `HtmlText` over a line-for-line port of
23
+ * `HTMLParser.goahead` (CPython 3.12.13, `convert_charrefs=True`), so
24
+ * the DATA CHUNKS arrive in the same pieces — the chunking is visible in
25
+ * the rows because `_HtmlText` joins chunks with a space.
26
+ * - `email` -> `parseMime`: multipart boundaries, header unfolding, Content-Type
27
+ * parameters, quoted-printable (`binascii.a2b_qp`) and base64.
28
+ *
29
+ * Python string semantics that JavaScript does not share are ported explicitly rather
30
+ * than approximated: `str.strip()`/`split()`/`splitlines()` use Python's whitespace and
31
+ * line-boundary sets (`PY_WS`, `pySplitlines`), `repr()` of a `str` and of `bytes` is
32
+ * `pyRepr`/`bytesRepr`, `sorted()` compares by code point (`cmpCodepoint`), and a UTF-8
33
+ * decode error reports the same `start` offset and `reason` CPython's decoder does
34
+ * (`utf8Scan`).
35
+ */
36
+ import { BantamError } from './errors.js';
37
+ export declare const NS_S = "{http://schemas.openxmlformats.org/spreadsheetml/2006/main}";
38
+ export declare const NS_W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}";
39
+ export declare const NS_R = "{http://schemas.openxmlformats.org/officeDocument/2006/relationships}";
40
+ export declare const SUPPORTED: readonly ["text", "xlsx", "docx", "pdf", "html", "mhtml"];
41
+ export declare const TEXTUTIL_SUPPORTED: readonly ["doc", "rtf"];
42
+ export declare const TEXTUTIL = "/usr/bin/textutil";
43
+ export declare const DEFAULT_ROW_LIMIT = 50;
44
+ export declare const PAGE_MAX_ROWS = 200;
45
+ export declare const PAGE_MAX_BYTES = 3072;
46
+ export declare const TEXT_MAX_BYTES: number;
47
+ export declare const OMIT_MEDIA = "media";
48
+ export declare const OMIT_BLANK_ROWS = "blank-rows";
49
+ export declare const OMIT_NUMBER_FORMAT = "number-format";
50
+ export declare const OMIT_UNREAD_PAGE = "unread-page";
51
+ export declare const OMIT_UNMAPPED = "unmapped-text";
52
+ export declare const OMIT_UNREAD_TAIL = "unread-tail";
53
+ export declare const OMIT_SIZE_CAP = "size-cap";
54
+ export declare const OMIT_UNPLACED_CELL = "unplaced-cell";
55
+ /** Extraction failed. The message names what was seen, never just the format's own error. */
56
+ export declare class DocumentReadError extends BantamError {
57
+ }
58
+ /** `str.strip()` with no argument. */
59
+ export declare function pyStrip(s: string): string;
60
+ /** `str.split()` with no argument: runs of whitespace, no empty fields. */
61
+ export declare function pySplit(s: string): string[];
62
+ /** `str.splitlines()`: Python's line boundaries, terminators dropped. */
63
+ export declare function pySplitlines(s: string): string[];
64
+ /** `sorted()` on strings: by code point, which is not what `Array.sort` does above U+FFFF. */
65
+ export declare function cmpCodepoint(a: string, b: string): number;
66
+ /** `repr(str)`. */
67
+ export declare function pyRepr(s: string): string;
68
+ /** `repr(bytes)`. */
69
+ export declare function bytesRepr(buf: Uint8Array): string;
70
+ export interface Utf8Scan {
71
+ /** Bytes `[0, end)` decode cleanly. */
72
+ end: number;
73
+ /** Where the first sequence no continuation could complete begins, or -1. */
74
+ invalidAt: number;
75
+ /** CPython's `UnicodeDecodeError.reason` for that sequence. */
76
+ reason: string;
77
+ /** With `final` false: the bytes past `end` are an incomplete trailing character. */
78
+ incomplete: boolean;
79
+ }
80
+ /**
81
+ * CPython's UTF-8 decoder, as a validator: the same `start` and `reason` its
82
+ * `UnicodeDecodeError` carries, and the same tolerance an incremental decoder has for a
83
+ * final character the read cut in half when `final` is false.
84
+ */
85
+ export declare function utf8Scan(buf: Uint8Array, final: boolean): Utf8Scan;
86
+ /**
87
+ * `encodings.normalize_encoding` after `codecs.lookup`'s own lower-casing: runs of anything
88
+ * that is not an ASCII letter, digit or `.` collapse to one `_`, and none leads or trails.
89
+ * `ISO 8859-1`, `ISO--8859--1` and `iso-8859-1;` are all `iso_8859_1`.
90
+ */
91
+ export declare function pyNormalizeEncoding(encoding: string): string;
92
+ /**
93
+ * `encodings.search_function`: the module `codecs.lookup(name)` would import, or `null`
94
+ * where it raises `LookupError`. The alias table is consulted on the normalized name and on
95
+ * the name with `.` as `_`; the module name itself is the fallback, and a name that is not
96
+ * a module — `cp-437` (`cp_437`), `x-mac-roman`, `latin.1` — is the `LookupError`.
97
+ */
98
+ export declare function pyCodecModule(name: string): string | null;
99
+ /**
100
+ * `bytes.decode(charset, errors="replace")`, falling back to UTF-8 on `LookupError`
101
+ * (`docread.py`, `_decoded_body`).
102
+ *
103
+ * Until H2 this was `TextDecoder(charset)` with the WHATWG label table, and review round 3
104
+ * measured that table against the codec registry on bytes `80 D0 E9 A4 FF`
105
+ * (`runtime-py/tests/data/docread/charset-table.json`): cp437, mac_roman and iso-8859-16
106
+ * are labels WHATWG does not have; iso-8859-9's 0x80–0x9F are C1 controls to Python and
107
+ * windows-1254's punctuation to WHATWG; Node 25.2.1's ICU decoder maps windows-1252's
108
+ * 0x80 to U+0080 and prints nothing for a trailing 0xFF under latin-1; us-ascii is
109
+ * windows-1252 there. The single-byte codecs are now `charsets.ts`, 256 characters per
110
+ * module written by the registry itself (79 codecs, 20 of them measured over all 256 bytes
111
+ * against the old path: 13 differed); the CJK codecs go through `TextDecoder` with
112
+ * CPython's replacement policy (`decodeMultiByte`, where the residual is quantified); a
113
+ * module this port has no decoder for (`utf_7`, `hz`, `iso2022_kr`, `johab`, the JIS X
114
+ * 0213 variants) decodes as UTF-8, which is the other remaining divergence.
115
+ *
116
+ * AMENDED at review round 4 (H1). This paragraph used to name `iso2022_*` among the modules
117
+ * with no decoder, and for seven of that family the code did something else and worse: the
118
+ * generator had written them a single-byte table, so they were decoded one byte at a time and
119
+ * their escape sequences became U+FFFD. The six `iso2022_jp*` modules now go through ICU's
120
+ * real decoder (`ESCAPE_LABELS`, where the three arms are scored); `hz`, `iso2022_kr` and
121
+ * `utf_7` are what is left of the no-decoder set, and for them this paragraph is now true.
122
+ */
123
+ export declare function decodeCharset(buf: Uint8Array, charset: string): string;
124
+ export interface OmissionDict {
125
+ subject: string;
126
+ count: number;
127
+ size: number;
128
+ where: string[];
129
+ what: string;
130
+ facts: Record<string, number>;
131
+ }
132
+ /** Something the file holds that the rows do not carry, as a COUNT and the fact behind it. */
133
+ export declare class Omission {
134
+ readonly subject: string;
135
+ readonly count: number;
136
+ readonly size: number;
137
+ readonly where: readonly string[];
138
+ readonly what: string;
139
+ readonly facts: readonly (readonly [string, number])[];
140
+ constructor(subject: string, count: number, size?: number, where?: readonly string[], what?: string, facts?: readonly (readonly [string, number])[]);
141
+ /** The primitive form the contract layer takes, keys in the reference's order. */
142
+ asDict(): OmissionDict;
143
+ }
144
+ /** One addressable unit: a worksheet, or a `.docx` body. `rows` are rendered lines. */
145
+ export declare class Part {
146
+ readonly name: string;
147
+ readonly index: number;
148
+ readonly rows: readonly string[];
149
+ readonly omissions: readonly Omission[];
150
+ constructor(name: string, index: number, rows: readonly string[], omissions?: readonly Omission[]);
151
+ get rowCount(): number;
152
+ /** UTF-8 bytes of this part's full rendering. EXTRACTED size, not file size. */
153
+ get textBytes(): number;
154
+ }
155
+ export declare class Document {
156
+ readonly kind: string;
157
+ readonly parts: readonly Part[];
158
+ readonly omissions: readonly Omission[];
159
+ constructor(kind: string, parts: readonly Part[], omissions?: readonly Omission[]);
160
+ get textBytes(): number;
161
+ /** Resolve by exact sheet name, else by 0-based index. Names win over numeric keys. */
162
+ part(key: string | number): Part;
163
+ }
164
+ /** A row slice of one part. `nextOffset` is null exactly when the part is exhausted. */
165
+ export declare class Page {
166
+ readonly part: string;
167
+ readonly offset: number;
168
+ readonly rows: readonly string[];
169
+ readonly totalRows: number;
170
+ readonly nextOffset: number | null;
171
+ readonly truncatedBytes: number;
172
+ constructor(part: string, offset: number, rows: readonly string[], totalRows: number, nextOffset: number | null, truncatedBytes?: number);
173
+ get text(): string;
174
+ }
175
+ /** The container a file's own bytes declare it to be. `kind` decides; `what` explains. */
176
+ export declare class Container {
177
+ readonly kind: string;
178
+ readonly what: string;
179
+ readonly named: string;
180
+ constructor(kind: string, what: string, named: string);
181
+ /** True when the name promises a container the bytes do not deliver. */
182
+ get suffixLies(): boolean;
183
+ }
184
+ export declare const SUFFIX_KINDS: Readonly<Record<string, string>>;
185
+ export declare const HEAD_BYTES = 4096;
186
+ /** What `path` IS. Magic bytes, then a zip's member list. The suffix is never consulted. */
187
+ export declare function sniff(path: string): Container;
188
+ /** `zipfile.BadZipFile`. Not a `DocumentReadError`: the reference lets it through too. */
189
+ export declare class BadZipFile extends Error {
190
+ constructor(message: string);
191
+ }
192
+ export declare function crc32(buf: Uint8Array): number;
193
+ /** `zipfile.ZipFile` read-only: the central directory, and `read(name)` with a CRC check. */
194
+ export declare class ZipReader {
195
+ private readonly data;
196
+ private readonly entries;
197
+ private readonly concat;
198
+ /** `Path(p).name`, for the one sentence `read` composes itself (the bzip2/lzma ruling). */
199
+ private readonly pathName;
200
+ private readonly byName;
201
+ private constructor();
202
+ static open(path: string): ZipReader;
203
+ static from(data: Buffer, pathName?: string): ZipReader;
204
+ namelist(): string[];
205
+ /** `infolist()` reduced to what `_media_index` reads: name, size, and whether it is a directory. */
206
+ infolist(): {
207
+ filename: string;
208
+ fileSize: number;
209
+ isDir: boolean;
210
+ }[];
211
+ has(name: string): boolean;
212
+ /** `ZipFile.read(name)`; a missing member is a `KeyError` — here `RangeError`, see `readMember`. */
213
+ read(name: string): Buffer;
214
+ }
215
+ /**
216
+ * The ruled bzip2/lzma refusal, as its own class — review round 4 (M1).
217
+ *
218
+ * It IS a `DocumentReadError` and its sentence is unchanged, so `docs/porting.md`'s ruling
219
+ * and every case that pins the wording still hold. What the subclass buys is that
220
+ * `isUnreadableOptional` can name exactly this refusal: on the reference the same members are
221
+ * a `NotImplementedError`, which `_UNREADABLE_OPTIONAL` catches through `RuntimeError`, so a
222
+ * TOLERANT read swallows it there and must swallow it here. Without the class the only way to
223
+ * recognise it would be `instanceof DocumentReadError`, which would also swallow the
224
+ * encrypted-member and shared-string refusals that the same call can raise.
225
+ */
226
+ export declare class ZipMethodUnsupported extends DocumentReadError {
227
+ constructor(message: string);
228
+ }
229
+ /**
230
+ * `ZipFile.read`'s `RuntimeError` family: the member is encrypted (`method` undefined), or
231
+ * (its subclass `NotImplementedError`) compressed by a method zipfile has no decompressor
232
+ * for (`method` is the number). Not a `DocumentReadError` itself, because the reference's
233
+ * `_read` is what words it, and the parts `_rel_targets`/`_date_formats` read swallow it
234
+ * silently instead.
235
+ */
236
+ export declare class ZipMemberUnreadable extends Error {
237
+ readonly member: string;
238
+ readonly method?: number | undefined;
239
+ constructor(member: string, method?: number | undefined);
240
+ }
241
+ /** `xml.etree.ElementTree.ParseError`. Not a `DocumentReadError`: the reference lets it through. */
242
+ export declare class XmlParseError extends Error {
243
+ constructor(message: string);
244
+ }
245
+ /** An element the way ET exposes one: expanded `{ns}tag`, attributes, `.text`, children. */
246
+ export declare class XmlElement {
247
+ readonly tag: string;
248
+ readonly attrs: Map<string, string>;
249
+ text: string;
250
+ readonly children: XmlElement[];
251
+ constructor(tag: string, attrs: Map<string, string>);
252
+ get(name: string): string | undefined;
253
+ /** `Element.find(tag)`: the first DIRECT child with that tag. */
254
+ find(tag: string): XmlElement | undefined;
255
+ /** `Element.iter(tag)`: this element and every descendant, document order. */
256
+ iter(tag?: string): IterableIterator<XmlElement>;
257
+ }
258
+ /**
259
+ * A declared encoding expat has no decoder for. `LookupError("unknown encoding: x")` on the
260
+ * reference — NOT an `ET.ParseError`, so `_parse` does not word it and it escapes to the
261
+ * wire as a raised exception; the same class of thing here, deliberately not `XmlParseError`.
262
+ */
263
+ export declare class XmlEncodingError extends Error {
264
+ constructor(encoding: string);
265
+ }
266
+ /**
267
+ * A strict-enough XML reader: one root, matched tags, declared prefixes, the five
268
+ * predefined entities and the internal subset's own, comments and PIs dropped, CDATA kept,
269
+ * line ends normalised, and attribute values whitespace-normalised — what expat gives ET
270
+ * for an OOXML part.
271
+ *
272
+ * A declared entity is expanded the way expat expands it: in a text run its replacement
273
+ * text is PARSED in place, so `<!ENTITY e "<x>in</x>y">` yields an element, and a
274
+ * replacement that opens what it does not close is "asynchronous entity"; in an attribute
275
+ * value it is expanded as text and may not contain `<`; a reference to the entity being
276
+ * expanded is "recursive entity reference". Measured against `ET.fromstring` (job43 G2).
277
+ */
278
+ export declare function parseXml(data: Uint8Array): XmlElement;
279
+ export declare function isDateFormat(code: string): boolean;
280
+ /** 0 -> `A`. */
281
+ export declare function columnLetter(index: number): string;
282
+ /**
283
+ * ECMA-376 gives a worksheet 16,384 columns, the last of them `XFD`. A reference past that
284
+ * does not name a column of any workbook, so this reader will not build a row wide enough to
285
+ * reach one. THE FORMAT'S NUMBER, not a limit invented here, which is why it is spelled as
286
+ * the last column's name rather than as a round figure someone liked.
287
+ */
288
+ export declare const XLSX_MAX_COLUMNS = 16384;
289
+ /**
290
+ * Why a cell's own reference could not place it. Fixed strings, never the reference itself:
291
+ * `r` is whatever the file says, and an omission that echoed it would carry the file's bytes
292
+ * into the manifest with no bound at all.
293
+ */
294
+ export declare const UNPLACED_SHAPE = "the column of a cell whose reference is not letters then digits";
295
+ export declare const UNPLACED_RANGE = "the column of a cell past XFD, the last column the format has";
296
+ /**
297
+ * `B7` -> `[1, '']`. The cell's own reference decides its column; XML order is a fallback.
298
+ *
299
+ * A reference is ASCII letters then ASCII digits naming a column the format has, or this
300
+ * reader cannot place it and says WHY. The match is on the reference AS WRITTEN and never on
301
+ * its uppercase (`_column`, review round 3): `r="ß1"` was a `TypeError` on the Python side
302
+ * and column 486 (`SS1`, after `toUpperCase`) here, and a column number that depends on a
303
+ * Unicode case table is not a fact about the workbook.
304
+ *
305
+ * AN ANSWER AND NOT A THROW, which is review round 4 (M2), mirroring `runtime-py` `a1acfa7`.
306
+ * Round 3 spelled the refusal as a `DocumentReadError` out of a function `sheetRows` does not
307
+ * catch, so ONE cell the reader could not place refused the entire workbook — measured on a
308
+ * two-sheet fixture where sheet `Good` is clean and sheet `Bad` holds one cell `r="1"`: no
309
+ * manifest, no parts, the clean sheet unreachable. `r="1"`, `r="A"` and `r="B7 "` all read
310
+ * before round 3. The strictness was right and its price was not: the cell keeps its text and
311
+ * takes its XML position, which is where it sat before round 3 and is the same position on
312
+ * both runtimes, and the column it did not get is disclosed as an `Omission` rather than
313
+ * charged to the whole document. The sentence "cell reference {r!r} is not a column-and-row
314
+ * reference like B7, so this reader cannot place it" NO LONGER EXISTS on either runtime.
315
+ *
316
+ * THE CEILING is review round 4 (M5). Round 3 made this function stricter about the SHAPE of
317
+ * a reference and left the resulting index unbounded: measured on the reference, a 1,755-byte
318
+ * xlsx whose one cell is `r="ZZZZZ1"` produced a 12,356,630-byte row, 7,041x the file. Row
319
+ * width is now bounded by the format at `XLSX_MAX_COLUMNS` fields however many bytes the file
320
+ * spends asking for more.
321
+ */
322
+ export declare function columnIndex(ref: string | undefined, fallback: number): [number, string];
323
+ export declare function extractXlsx(path: string): Document;
324
+ export declare function extractDocx(path: string): Document;
325
+ /** `html.unescape`. */
326
+ export declare function unescape(s: string): string;
327
+ /** Rendered rows of one HTML fragment. A pure function of the string: no I/O, no host. */
328
+ export declare function htmlRows(markup: string): string[];
329
+ /** `binascii.a2b_qp(data, header=False)`, i.e. `quopri.decodestring`. */
330
+ export declare function decodeQuotedPrintable(data: Uint8Array): Buffer;
331
+ /**
332
+ * `binascii.a2b_uu(line)`: one uuencoded line to its bytes, in the C module's own steps.
333
+ *
334
+ * The first character is the byte count; each following character carries six bits, a line
335
+ * end or a line that ran out counts as zero ("some spaces got eaten at end-of-line"); a
336
+ * character outside `' '..'\x60'` is "Illegal char"; and whatever is left after the count
337
+ * is satisfied must be space, backtick or a line end, or it is "Trailing garbage".
338
+ */
339
+ export declare function a2bUu(line: Uint8Array): Buffer;
340
+ /**
341
+ * `email.message._decode_uu`: the lines between `begin <octal mode> ...` and `end`, or
342
+ * `ValueError` — which `get_payload` answers with the payload UNDECODED.
343
+ *
344
+ * `begin` must start the line and its mode must parse in base 8; a blank line before `end`
345
+ * is "Truncated input"; `end` is recognised stripped of ` \t\r\n\f`; and a line
346
+ * `a2b_uu` rejects is retried cut to the length its count character implies (the workaround
347
+ * for broken encoders that the stdlib carries by name). Measured against the reference
348
+ * (job43 G2) on seventeen payload shapes, including the Truncated and no-`begin` ones.
349
+ */
350
+ export declare function decodeUu(encoded: Buffer): Buffer;
351
+ export declare function extractMhtml(path: string): Document;
352
+ export declare function extractHtml(path: string): Document;
353
+ export declare function extractText(path: string): Document;
354
+ /** Dispatch on what the file IS. Anything unreadable raises, naming the container. */
355
+ export declare function extract(path: string): Document;
356
+ /** Slice `limit` rows from `part` starting at `offset`, optionally under a byte ceiling. */
357
+ export declare function page(doc: Document, part?: string | number, offset?: number, limit?: number, maxBytes?: number | null): Page;