rea-agents 1.7.0 → 2.0.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 (156) hide show
  1. package/README.md +38 -31
  2. package/dist/application/CapabilityInventory.js +18 -0
  3. package/dist/application/CrossVersionInvestigation.js +10 -6
  4. package/dist/application/Doctor.js +56 -6
  5. package/dist/application/ElectronBoundaryAnalysis.js +96 -0
  6. package/dist/application/ElectronBoundaryGraph.js +9 -0
  7. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  8. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  9. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  10. package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
  11. package/dist/application/EnhancedTools.js +38 -13
  12. package/dist/application/InvestigationProviders.js +30 -0
  13. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  14. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  15. package/dist/application/JavaScriptApplicationService.js +74 -0
  16. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  17. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  18. package/dist/application/JavaScriptArtifactAnalysis.js +7 -1
  19. package/dist/application/JavaScriptArtifactGraphBuilder.js +59 -16
  20. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  21. package/dist/application/JavaScriptArtifactReconstruction.js +3 -0
  22. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  23. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  24. package/dist/application/JavaScriptReplayService.js +266 -0
  25. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  26. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  27. package/dist/application/ManagedApplicationGraphService.js +55 -0
  28. package/dist/application/ManagedMemberComparisonService.js +122 -0
  29. package/dist/application/ManagedNativeVerificationService.js +39 -0
  30. package/dist/application/ManagedReconstructionService.js +58 -0
  31. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  32. package/dist/application/PermissionAuthority.js +1 -1
  33. package/dist/application/ProcessSampling.js +15 -11
  34. package/dist/application/ProjectPermissionStore.js +1 -0
  35. package/dist/application/runtime.js +2 -0
  36. package/dist/browser/CdpCaptureEvents.js +49 -0
  37. package/dist/browser/CdpElectronInspection.js +106 -162
  38. package/dist/browser/CdpElectronProvider.js +5 -1
  39. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  40. package/dist/browser/CdpElectronScripts.js +94 -0
  41. package/dist/browser/CdpElectronWorkers.js +56 -0
  42. package/dist/browser/CdpPageCapture.js +8 -4
  43. package/dist/catalogIdentity.js +4 -1
  44. package/dist/cli.js +388 -0
  45. package/dist/cliApplicationCommands.js +62 -0
  46. package/dist/cliCommandNames.js +13 -0
  47. package/dist/cliElectronCommands.js +103 -1
  48. package/dist/cliJsonInput.js +54 -0
  49. package/dist/config.js +83 -0
  50. package/dist/contracts/applicationToolContracts.js +91 -0
  51. package/dist/contracts/artifactToolContracts.js +5 -9
  52. package/dist/contracts/browserToolContracts.js +14 -62
  53. package/dist/contracts/electronToolContracts.js +45 -19
  54. package/dist/contracts/errorSchemas.js +1 -0
  55. package/dist/contracts/investigationExamples.js +0 -6
  56. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  57. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  58. package/dist/contracts/managedToolContracts.js +153 -0
  59. package/dist/contracts/managedWorkflowExamples.js +346 -0
  60. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  61. package/dist/contracts/nativeToolContracts.js +2 -6
  62. package/dist/contracts/promptContracts.js +18 -2
  63. package/dist/contracts/toolContractExamples.js +10 -25
  64. package/dist/contracts/toolContracts.js +47 -45
  65. package/dist/contracts/toolEffects.js +160 -0
  66. package/dist/contracts/toolOutputSchemas.js +46 -31
  67. package/dist/doctorRuntime.js +42 -1
  68. package/dist/domain/artifactComparison.js +3 -4
  69. package/dist/domain/browserObservation.js +3 -0
  70. package/dist/domain/bundleComparison.js +4 -4
  71. package/dist/domain/electronObservation.js +13 -0
  72. package/dist/domain/electronStaticAnalysis.js +9 -0
  73. package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
  74. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  75. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  76. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  77. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  78. package/dist/domain/errors.js +67 -1
  79. package/dist/domain/functionComparisonSchemas.js +3 -8
  80. package/dist/domain/inputIssueProjection.js +52 -0
  81. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  82. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  83. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  84. package/dist/domain/javascriptApplicationGraph.js +2 -1
  85. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  86. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  87. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  88. package/dist/domain/javascriptApplicationVersionItems.js +221 -0
  89. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  90. package/dist/domain/javascriptFeatureSeed.js +140 -0
  91. package/dist/domain/javascriptFeatureTrace.js +232 -0
  92. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  93. package/dist/domain/javascriptFeatureTraversal.js +88 -0
  94. package/dist/domain/javascriptNativeHandoff.js +85 -0
  95. package/dist/domain/javascriptReplay.js +361 -0
  96. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  97. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  98. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  99. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  100. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  101. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  102. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  103. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  104. package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
  105. package/dist/domain/javascriptStaticAnalysis.js +31 -43
  106. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  107. package/dist/domain/javascriptStaticAnalysisHelpers.js +10 -0
  108. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  109. package/dist/domain/managedApplicationGraph.js +556 -0
  110. package/dist/domain/managedArtifact.js +444 -0
  111. package/dist/domain/managedMemberComparison.js +565 -0
  112. package/dist/domain/managedNativeVerification.js +408 -0
  113. package/dist/domain/managedReconstruction.js +183 -0
  114. package/dist/domain/managedRuntimeCorrelation.js +175 -0
  115. package/dist/domain/reconstructionVerificationSchemas.js +1 -3
  116. package/dist/dotnet/ManagedArtifactInspector.js +318 -0
  117. package/dist/dotnet/ManagedMemberInspector.js +887 -0
  118. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  119. package/dist/dotnet/ManagedMetadataInventory.js +368 -0
  120. package/dist/dotnet/ManagedMetadataLayout.js +322 -0
  121. package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
  122. package/dist/dotnet/ManagedPeReader.js +157 -0
  123. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  124. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  125. package/dist/generatedPackageMetadata.js +2 -2
  126. package/dist/ghidra/GhidraProvider.js +6 -0
  127. package/dist/main.js +14 -0
  128. package/dist/replay/JavaScriptReplayWorker.js +286 -0
  129. package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
  130. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  131. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  132. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  133. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  134. package/dist/server/createServer.js +52 -0
  135. package/dist/server/registerApplicationTools.js +115 -0
  136. package/dist/server/registerArtifactComparisonTool.js +16 -9
  137. package/dist/server/registerBrowserTools.js +33 -8
  138. package/dist/server/registerBundleComparisonTool.js +17 -20
  139. package/dist/server/registerElectronTools.js +45 -3
  140. package/dist/server/registerEnhancedTools.js +58 -13
  141. package/dist/server/registerEvidenceTools.js +5 -1
  142. package/dist/server/registerFunctionComparisonTool.js +14 -7
  143. package/dist/server/registerInvestigationTools.js +21 -17
  144. package/dist/server/registerManagedTools.js +6 -0
  145. package/dist/server/registerManagedWorkflowTools.js +277 -0
  146. package/dist/server/registerOfficialTools.js +8 -8
  147. package/dist/server/registerProcessComparisonTool.js +25 -47
  148. package/dist/server/registerSessionStatusTool.js +7 -7
  149. package/dist/server/registerSessionTools.js +51 -86
  150. package/dist/server/sessionEvidence.js +14 -19
  151. package/dist/server/toolInputValidation.js +77 -0
  152. package/dist/server/toolRegistrationOptions.js +79 -2
  153. package/dist/server/toolResult.js +25 -17
  154. package/package.json +12 -4
  155. package/scripts/rea.mjs +1 -1
  156. package/skills/rea-analysis/SKILL.md +59 -3
@@ -0,0 +1,322 @@
1
+ import { managedFailure } from "./ManagedReaderFailure.js";
2
+ export const METADATA_TABLE_NAMES = [
3
+ "Module",
4
+ "TypeRef",
5
+ "TypeDef",
6
+ "FieldPtr",
7
+ "Field",
8
+ "MethodPtr",
9
+ "MethodDef",
10
+ "ParamPtr",
11
+ "Param",
12
+ "InterfaceImpl",
13
+ "MemberRef",
14
+ "Constant",
15
+ "CustomAttribute",
16
+ "FieldMarshal",
17
+ "DeclSecurity",
18
+ "ClassLayout",
19
+ "FieldLayout",
20
+ "StandAloneSig",
21
+ "EventMap",
22
+ "EventPtr",
23
+ "Event",
24
+ "PropertyMap",
25
+ "PropertyPtr",
26
+ "Property",
27
+ "MethodSemantics",
28
+ "MethodImpl",
29
+ "ModuleRef",
30
+ "TypeSpec",
31
+ "ImplMap",
32
+ "FieldRVA",
33
+ "ENCLog",
34
+ "ENCMap",
35
+ "Assembly",
36
+ "AssemblyProcessor",
37
+ "AssemblyOS",
38
+ "AssemblyRef",
39
+ "AssemblyRefProcessor",
40
+ "AssemblyRefOS",
41
+ "File",
42
+ "ExportedType",
43
+ "ManifestResource",
44
+ "NestedClass",
45
+ "GenericParam",
46
+ "MethodSpec",
47
+ "GenericParamConstraint",
48
+ ];
49
+ const CODED_INDEXES = {
50
+ TypeDefOrRef: { bits: 2, tables: [2, 1, 27] },
51
+ HasConstant: { bits: 2, tables: [4, 8, 23] },
52
+ HasCustomAttribute: {
53
+ bits: 5,
54
+ tables: [
55
+ 6, 4, 1, 2, 8, 9, 10, 0, 14, 23, 20, 17, 26, 27, 32, 35, 38, 39, 40, 42,
56
+ 44, 43,
57
+ ],
58
+ },
59
+ HasFieldMarshal: { bits: 1, tables: [4, 8] },
60
+ HasDeclSecurity: { bits: 2, tables: [2, 6, 32] },
61
+ MemberRefParent: { bits: 3, tables: [2, 1, 26, 6, 27] },
62
+ HasSemantics: { bits: 1, tables: [20, 23] },
63
+ MethodDefOrRef: { bits: 1, tables: [6, 10] },
64
+ MemberForwarded: { bits: 1, tables: [4, 6] },
65
+ Implementation: { bits: 2, tables: [38, 35, 39] },
66
+ CustomAttributeType: { bits: 3, tables: [6, 10] },
67
+ ResolutionScope: { bits: 2, tables: [0, 26, 35, 1] },
68
+ TypeOrMethodDef: { bits: 1, tables: [2, 6] },
69
+ };
70
+ const SUPPORTED_TABLE_MASK = (1n << BigInt(METADATA_TABLE_NAMES.length)) - 1n;
71
+ const requireRange = (bytes, offset, length, scope) => {
72
+ if (!Number.isSafeInteger(offset) ||
73
+ !Number.isSafeInteger(length) ||
74
+ offset < 0 ||
75
+ length < 0 ||
76
+ offset > bytes.length - length)
77
+ throw managedFailure("invalid-metadata-root", scope, `${scope} leaves the metadata byte range`, Number.isSafeInteger(offset) && offset >= 0 ? offset : null);
78
+ };
79
+ const align4 = (value) => (value + 3) & ~3;
80
+ const readStreamName = (bytes, offset) => {
81
+ const endLimit = Math.min(bytes.length, offset + 32);
82
+ let end = offset;
83
+ while (end < endLimit && bytes[end] !== 0)
84
+ end += 1;
85
+ if (end === endLimit)
86
+ throw managedFailure("invalid-stream", "metadata.stream-name", "Metadata stream name is missing a bounded terminator", offset);
87
+ const nameBytes = bytes.subarray(offset, end);
88
+ if (nameBytes.some((byte) => byte < 0x20 || byte > 0x7e))
89
+ throw managedFailure("invalid-stream", "metadata.stream-name", "Metadata stream name is not printable ASCII", offset);
90
+ return {
91
+ name: nameBytes.toString("ascii"),
92
+ next: align4(end + 1),
93
+ };
94
+ };
95
+ const streamByName = (streams, names) => {
96
+ for (const name of names) {
97
+ const stream = streams.get(name);
98
+ if (stream !== undefined)
99
+ return stream;
100
+ }
101
+ return undefined;
102
+ };
103
+ const requireStream = (streams, name) => {
104
+ const stream = streams.get(name);
105
+ if (stream === undefined)
106
+ throw managedFailure("missing-stream", `metadata.${name}`, `Required metadata stream ${name} is absent`);
107
+ return stream;
108
+ };
109
+ const codedSize = (name, rowCounts) => {
110
+ const descriptor = CODED_INDEXES[name];
111
+ let maximum = 0;
112
+ for (const table of descriptor.tables)
113
+ maximum = Math.max(maximum, rowCounts[table] ?? 0);
114
+ return maximum < 2 ** (16 - descriptor.bits) ? 2 : 4;
115
+ };
116
+ const tableSize = (index, rows) => (rows[index] ?? 0) < 0x1_0000 ? 2 : 4;
117
+ const rowSize = (table, rowCounts, heaps) => {
118
+ const t = (index) => tableSize(index, rowCounts);
119
+ const c = (name) => codedSize(name, rowCounts);
120
+ const { string: s, guid: g, blob: b } = heaps;
121
+ switch (table) {
122
+ case 0:
123
+ return 2 + s + g * 3;
124
+ case 1:
125
+ return c("ResolutionScope") + s * 2;
126
+ case 2:
127
+ return 4 + s * 2 + c("TypeDefOrRef") + t(4) + t(6);
128
+ case 3:
129
+ return t(4);
130
+ case 4:
131
+ return 2 + s + b;
132
+ case 5:
133
+ return t(6);
134
+ case 6:
135
+ return 8 + s + b + t(8);
136
+ case 7:
137
+ return t(8);
138
+ case 8:
139
+ return 4 + s;
140
+ case 9:
141
+ return t(2) + c("TypeDefOrRef");
142
+ case 10:
143
+ return c("MemberRefParent") + s + b;
144
+ case 11:
145
+ return 2 + c("HasConstant") + b;
146
+ case 12:
147
+ return c("HasCustomAttribute") + c("CustomAttributeType") + b;
148
+ case 13:
149
+ return c("HasFieldMarshal") + b;
150
+ case 14:
151
+ return 2 + c("HasDeclSecurity") + b;
152
+ case 15:
153
+ return 6 + t(2);
154
+ case 16:
155
+ return 4 + t(4);
156
+ case 17:
157
+ return b;
158
+ case 18:
159
+ return t(2) + t(20);
160
+ case 19:
161
+ return t(20);
162
+ case 20:
163
+ return 2 + s + c("TypeDefOrRef");
164
+ case 21:
165
+ return t(2) + t(23);
166
+ case 22:
167
+ return t(23);
168
+ case 23:
169
+ return 2 + s + b;
170
+ case 24:
171
+ return 2 + t(6) + c("HasSemantics");
172
+ case 25:
173
+ return t(2) + c("MethodDefOrRef") * 2;
174
+ case 26:
175
+ return s;
176
+ case 27:
177
+ return b;
178
+ case 28:
179
+ return 2 + c("MemberForwarded") + s + t(26);
180
+ case 29:
181
+ return 4 + t(4);
182
+ case 30:
183
+ return 8;
184
+ case 31:
185
+ return 4;
186
+ case 32:
187
+ return 16 + b + s * 2;
188
+ case 33:
189
+ return 4;
190
+ case 34:
191
+ return 12;
192
+ case 35:
193
+ return 12 + b * 2 + s * 2;
194
+ case 36:
195
+ return 4 + t(35);
196
+ case 37:
197
+ return 12 + t(35);
198
+ case 38:
199
+ return 4 + s + b;
200
+ case 39:
201
+ return 8 + s * 2 + c("Implementation");
202
+ case 40:
203
+ return 8 + s + c("Implementation");
204
+ case 41:
205
+ return t(2) * 2;
206
+ case 42:
207
+ return 4 + c("TypeOrMethodDef") + s;
208
+ case 43:
209
+ return c("MethodDefOrRef") + b;
210
+ case 44:
211
+ return t(42) + c("TypeDefOrRef");
212
+ default:
213
+ throw managedFailure("invalid-tables", "metadata.tables", `Metadata table ${String(table)} is unsupported`);
214
+ }
215
+ };
216
+ /** Parse ECMA-335 stream and table layout with checked byte extents. */
217
+ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRows) => {
218
+ if (size < 20 || rootOffset < 0 || rootOffset > artifact.length - size)
219
+ throw managedFailure("invalid-metadata-root", "metadata.root", "CLI metadata directory leaves the artifact byte range", rootOffset);
220
+ const bytes = artifact.subarray(rootOffset, rootOffset + size);
221
+ if (bytes.readUInt32LE(0) !== 0x424a_5342)
222
+ throw managedFailure("invalid-metadata-root", "metadata.signature", "CLI metadata signature is not BSJB", rootOffset);
223
+ const versionLength = bytes.readUInt32LE(12);
224
+ requireRange(bytes, 16, versionLength, "metadata.version");
225
+ const versionBytes = bytes.subarray(16, 16 + versionLength);
226
+ const zero = versionBytes.indexOf(0);
227
+ const version = versionBytes
228
+ .subarray(0, zero < 0 ? versionBytes.length : zero)
229
+ .toString("utf8");
230
+ let cursor = align4(16 + versionLength);
231
+ requireRange(bytes, cursor, 4, "metadata.stream-count");
232
+ const streamCount = bytes.readUInt16LE(cursor + 2);
233
+ if (streamCount === 0 || streamCount > 64)
234
+ throw managedFailure("invalid-stream", "metadata.stream-count", "Metadata stream count is outside the admitted range", rootOffset + cursor + 2);
235
+ cursor += 4;
236
+ const streams = new Map();
237
+ for (let index = 0; index < streamCount; index += 1) {
238
+ requireRange(bytes, cursor, 8, "metadata.stream-header");
239
+ const relativeOffset = bytes.readUInt32LE(cursor);
240
+ const streamSize = bytes.readUInt32LE(cursor + 4);
241
+ const named = readStreamName(bytes, cursor + 8);
242
+ if (streams.has(named.name))
243
+ throw managedFailure("invalid-stream", "metadata.stream-header", `Duplicate metadata stream ${named.name}`, rootOffset + cursor);
244
+ requireRange(bytes, relativeOffset, streamSize, `metadata.${named.name}`);
245
+ streams.set(named.name, {
246
+ name: named.name,
247
+ offset: rootOffset + relativeOffset,
248
+ size: streamSize,
249
+ });
250
+ cursor = named.next;
251
+ }
252
+ const tablesStream = streamByName(streams, ["#~", "#-"]);
253
+ if (tablesStream === undefined)
254
+ throw managedFailure("missing-stream", "metadata.tables", "Required metadata table stream #~ or #- is absent");
255
+ const tableBytes = artifact.subarray(tablesStream.offset, tablesStream.offset + tablesStream.size);
256
+ requireRange(tableBytes, 0, 24, "metadata.tables-header");
257
+ const heapSizes = tableBytes[6] ?? 0;
258
+ const heaps = {
259
+ string: (heapSizes & 0x01) === 0 ? 2 : 4,
260
+ guid: (heapSizes & 0x02) === 0 ? 2 : 4,
261
+ blob: (heapSizes & 0x04) === 0 ? 2 : 4,
262
+ };
263
+ const valid = tableBytes.readBigUInt64LE(8);
264
+ if ((valid & ~SUPPORTED_TABLE_MASK) !== 0n)
265
+ throw managedFailure("invalid-tables", "metadata.valid-mask", "Metadata valid mask names unsupported tables outside the admitted ECMA-335 range", tablesStream.offset + 8);
266
+ const rowCounts = Array(METADATA_TABLE_NAMES.length).fill(0);
267
+ let tableCursor = 24;
268
+ for (let index = 0; index < METADATA_TABLE_NAMES.length; index += 1) {
269
+ if ((valid & (1n << BigInt(index))) === 0n)
270
+ continue;
271
+ requireRange(tableBytes, tableCursor, 4, "metadata.table-row-count");
272
+ const count = tableBytes.readUInt32LE(tableCursor);
273
+ if (count > maxTableRows)
274
+ throw managedFailure("limit-exceeded", `metadata.${METADATA_TABLE_NAMES[index] ?? String(index)}`, `Metadata table row count ${String(count)} exceeds max_table_rows ${String(maxTableRows)}`, tablesStream.offset + tableCursor);
275
+ rowCounts[index] = count;
276
+ tableCursor += 4;
277
+ }
278
+ const tables = new Map();
279
+ for (let index = 0; index < METADATA_TABLE_NAMES.length; index += 1) {
280
+ const count = rowCounts[index] ?? 0;
281
+ if ((valid & (1n << BigInt(index))) === 0n)
282
+ continue;
283
+ const sizeOfRow = rowSize(index, rowCounts, heaps);
284
+ const byteLength = count * sizeOfRow;
285
+ if (!Number.isSafeInteger(byteLength))
286
+ throw managedFailure("invalid-tables", "metadata.tables", "Metadata table byte size overflowed", tablesStream.offset + tableCursor);
287
+ requireRange(tableBytes, tableCursor, byteLength, "metadata.table-data");
288
+ tables.set(index, {
289
+ index,
290
+ name: METADATA_TABLE_NAMES[index] ?? `Table${String(index)}`,
291
+ rowCount: count,
292
+ rowSize: sizeOfRow,
293
+ offset: tablesStream.offset + tableCursor,
294
+ });
295
+ tableCursor += byteLength;
296
+ }
297
+ const layout = {
298
+ rootOffset,
299
+ size,
300
+ version,
301
+ streamNames: [...streams.keys()].sort(),
302
+ strings: requireStream(streams, "#Strings"),
303
+ guid: requireStream(streams, "#GUID"),
304
+ blob: requireStream(streams, "#Blob"),
305
+ tables,
306
+ rowCounts,
307
+ stringIndexSize: heaps.string,
308
+ guidIndexSize: heaps.guid,
309
+ blobIndexSize: heaps.blob,
310
+ table: (index) => tables.get(index),
311
+ tableIndexSize: (index) => tableSize(index, rowCounts),
312
+ codedIndexSize: (name) => codedSize(name, rowCounts),
313
+ };
314
+ return layout;
315
+ };
316
+ /** Resolve a one-based metadata row to its exact file offset. */
317
+ export const metadataRowOffset = (layout, table, row) => {
318
+ const descriptor = layout.table(table);
319
+ if (descriptor === undefined || row < 1 || row > descriptor.rowCount)
320
+ throw managedFailure("invalid-row", `metadata.${METADATA_TABLE_NAMES[table] ?? String(table)}`, `Metadata row ${String(row)} is outside its table`);
321
+ return descriptor.offset + (row - 1) * descriptor.rowSize;
322
+ };