docground 0.1.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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/src/compiler/zod-compiler.d.ts +31 -0
  4. package/dist/src/compiler/zod-compiler.d.ts.map +1 -0
  5. package/dist/src/compiler/zod-compiler.js +150 -0
  6. package/dist/src/compiler/zod-compiler.js.map +1 -0
  7. package/dist/src/core/extractor.d.ts +17 -0
  8. package/dist/src/core/extractor.d.ts.map +1 -0
  9. package/dist/src/core/extractor.js +268 -0
  10. package/dist/src/core/extractor.js.map +1 -0
  11. package/dist/src/core/types.d.ts +102 -0
  12. package/dist/src/core/types.d.ts.map +1 -0
  13. package/dist/src/core/types.js +2 -0
  14. package/dist/src/core/types.js.map +1 -0
  15. package/dist/src/grounding/bbox.d.ts +40 -0
  16. package/dist/src/grounding/bbox.d.ts.map +1 -0
  17. package/dist/src/grounding/bbox.js +98 -0
  18. package/dist/src/grounding/bbox.js.map +1 -0
  19. package/dist/src/index.d.ts +16 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +16 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/normalizers/currency.d.ts +14 -0
  24. package/dist/src/normalizers/currency.d.ts.map +1 -0
  25. package/dist/src/normalizers/currency.js +96 -0
  26. package/dist/src/normalizers/currency.js.map +1 -0
  27. package/dist/src/normalizers/tabular.d.ts +16 -0
  28. package/dist/src/normalizers/tabular.d.ts.map +1 -0
  29. package/dist/src/normalizers/tabular.js +81 -0
  30. package/dist/src/normalizers/tabular.js.map +1 -0
  31. package/dist/src/providers/anthropic-provider.d.ts +13 -0
  32. package/dist/src/providers/anthropic-provider.d.ts.map +1 -0
  33. package/dist/src/providers/anthropic-provider.js +62 -0
  34. package/dist/src/providers/anthropic-provider.js.map +1 -0
  35. package/dist/src/providers/factory.d.ts +11 -0
  36. package/dist/src/providers/factory.d.ts.map +1 -0
  37. package/dist/src/providers/factory.js +32 -0
  38. package/dist/src/providers/factory.js.map +1 -0
  39. package/dist/src/providers/gemini-provider.d.ts +13 -0
  40. package/dist/src/providers/gemini-provider.d.ts.map +1 -0
  41. package/dist/src/providers/gemini-provider.js +48 -0
  42. package/dist/src/providers/gemini-provider.js.map +1 -0
  43. package/dist/src/providers/openai-provider.d.ts +14 -0
  44. package/dist/src/providers/openai-provider.d.ts.map +1 -0
  45. package/dist/src/providers/openai-provider.js +48 -0
  46. package/dist/src/providers/openai-provider.js.map +1 -0
  47. package/dist/src/providers/types.d.ts +45 -0
  48. package/dist/src/providers/types.d.ts.map +1 -0
  49. package/dist/src/providers/types.js +2 -0
  50. package/dist/src/providers/types.js.map +1 -0
  51. package/dist/src/stitcher/table-stitcher.d.ts +19 -0
  52. package/dist/src/stitcher/table-stitcher.d.ts.map +1 -0
  53. package/dist/src/stitcher/table-stitcher.js +129 -0
  54. package/dist/src/stitcher/table-stitcher.js.map +1 -0
  55. package/dist/src/tiling/cutter.d.ts +14 -0
  56. package/dist/src/tiling/cutter.d.ts.map +1 -0
  57. package/dist/src/tiling/cutter.js +46 -0
  58. package/dist/src/tiling/cutter.js.map +1 -0
  59. package/dist/src/tiling/tiler.d.ts +41 -0
  60. package/dist/src/tiling/tiler.d.ts.map +1 -0
  61. package/dist/src/tiling/tiler.js +82 -0
  62. package/dist/src/tiling/tiler.js.map +1 -0
  63. package/dist/src/validators/invariants.d.ts +30 -0
  64. package/dist/src/validators/invariants.d.ts.map +1 -0
  65. package/dist/src/validators/invariants.js +164 -0
  66. package/dist/src/validators/invariants.js.map +1 -0
  67. package/dist/tests/compiler.test.d.ts +2 -0
  68. package/dist/tests/compiler.test.d.ts.map +1 -0
  69. package/dist/tests/compiler.test.js +110 -0
  70. package/dist/tests/compiler.test.js.map +1 -0
  71. package/dist/tests/extractor.test.d.ts +2 -0
  72. package/dist/tests/extractor.test.d.ts.map +1 -0
  73. package/dist/tests/extractor.test.js +195 -0
  74. package/dist/tests/extractor.test.js.map +1 -0
  75. package/dist/tests/fixtures.d.ts +9 -0
  76. package/dist/tests/fixtures.d.ts.map +1 -0
  77. package/dist/tests/fixtures.js +20 -0
  78. package/dist/tests/fixtures.js.map +1 -0
  79. package/dist/tests/grounding.test.d.ts +2 -0
  80. package/dist/tests/grounding.test.d.ts.map +1 -0
  81. package/dist/tests/grounding.test.js +82 -0
  82. package/dist/tests/grounding.test.js.map +1 -0
  83. package/dist/tests/multi-domain.test.d.ts +2 -0
  84. package/dist/tests/multi-domain.test.d.ts.map +1 -0
  85. package/dist/tests/multi-domain.test.js +135 -0
  86. package/dist/tests/multi-domain.test.js.map +1 -0
  87. package/dist/tests/normalizer.test.d.ts +2 -0
  88. package/dist/tests/normalizer.test.d.ts.map +1 -0
  89. package/dist/tests/normalizer.test.js +70 -0
  90. package/dist/tests/normalizer.test.js.map +1 -0
  91. package/dist/tests/providers.test.d.ts +2 -0
  92. package/dist/tests/providers.test.d.ts.map +1 -0
  93. package/dist/tests/providers.test.js +110 -0
  94. package/dist/tests/providers.test.js.map +1 -0
  95. package/dist/tests/stitcher.test.d.ts +2 -0
  96. package/dist/tests/stitcher.test.d.ts.map +1 -0
  97. package/dist/tests/stitcher.test.js +85 -0
  98. package/dist/tests/stitcher.test.js.map +1 -0
  99. package/dist/tests/tiling.test.d.ts +2 -0
  100. package/dist/tests/tiling.test.d.ts.map +1 -0
  101. package/dist/tests/tiling.test.js +85 -0
  102. package/dist/tests/tiling.test.js.map +1 -0
  103. package/dist/tests/validators.test.d.ts +2 -0
  104. package/dist/tests/validators.test.d.ts.map +1 -0
  105. package/dist/tests/validators.test.js +125 -0
  106. package/dist/tests/validators.test.js.map +1 -0
  107. package/dist/vitest.config.d.ts +3 -0
  108. package/dist/vitest.config.d.ts.map +1 -0
  109. package/dist/vitest.config.js +13 -0
  110. package/dist/vitest.config.js.map +1 -0
  111. package/package.json +44 -0
@@ -0,0 +1,110 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { z } from "zod";
3
+ import { compileZodToGeminiSchema } from "../src/compiler/zod-compiler.js";
4
+ describe("compileZodToGeminiSchema", () => {
5
+ it("compiles a primitive schema", () => {
6
+ const schema = z.object({
7
+ name: z.string(),
8
+ age: z.number(),
9
+ active: z.boolean(),
10
+ });
11
+ const geminiSchema = compileZodToGeminiSchema(schema);
12
+ expect(geminiSchema.type).toBe("object");
13
+ expect(geminiSchema.properties).toMatchObject({
14
+ name: { type: "string" },
15
+ age: { type: "number" },
16
+ active: { type: "boolean" },
17
+ });
18
+ expect(geminiSchema.required).toContain("name");
19
+ expect(geminiSchema.required).toContain("age");
20
+ expect(geminiSchema.required).toContain("active");
21
+ });
22
+ it("compiles nested objects", () => {
23
+ const schema = z.object({
24
+ user: z.object({
25
+ id: z.number(),
26
+ email: z.string(),
27
+ }),
28
+ });
29
+ const geminiSchema = compileZodToGeminiSchema(schema);
30
+ expect(geminiSchema.type).toBe("object");
31
+ expect(geminiSchema.properties).toHaveProperty("user");
32
+ expect(geminiSchema.properties).toMatchObject({
33
+ user: {
34
+ type: "object",
35
+ properties: {
36
+ id: { type: "number" },
37
+ email: { type: "string" },
38
+ },
39
+ required: ["id", "email"],
40
+ },
41
+ });
42
+ });
43
+ it("compiles arrays", () => {
44
+ const schema = z.object({
45
+ tags: z.array(z.string()),
46
+ });
47
+ const geminiSchema = compileZodToGeminiSchema(schema);
48
+ expect(geminiSchema.properties).toMatchObject({
49
+ tags: {
50
+ type: "array",
51
+ items: { type: "string" },
52
+ },
53
+ });
54
+ });
55
+ it("compiles optional fields", () => {
56
+ const schema = z.object({
57
+ title: z.string(),
58
+ subtitle: z.string().optional(),
59
+ });
60
+ const geminiSchema = compileZodToGeminiSchema(schema);
61
+ expect(geminiSchema.properties).toHaveProperty("subtitle");
62
+ expect(geminiSchema.required).toContain("title");
63
+ expect(geminiSchema.required).not.toContain("subtitle");
64
+ });
65
+ it("compiles enums", () => {
66
+ const schema = z.object({
67
+ status: z.enum(["pending", "paid", "overdue"]),
68
+ });
69
+ const geminiSchema = compileZodToGeminiSchema(schema);
70
+ expect(geminiSchema.properties).toMatchObject({
71
+ status: {
72
+ type: "string",
73
+ enum: ["pending", "paid", "overdue"],
74
+ },
75
+ });
76
+ });
77
+ it("compiles complex nested schemas with arrays of objects", () => {
78
+ const schema = z.object({
79
+ invoice: z.object({
80
+ lines: z.array(z.object({
81
+ description: z.string(),
82
+ amount: z.number(),
83
+ })),
84
+ total: z.number(),
85
+ }),
86
+ });
87
+ const geminiSchema = compileZodToGeminiSchema(schema);
88
+ expect(geminiSchema.properties).toMatchObject({
89
+ invoice: {
90
+ type: "object",
91
+ properties: {
92
+ lines: {
93
+ type: "array",
94
+ items: {
95
+ type: "object",
96
+ properties: {
97
+ description: { type: "string" },
98
+ amount: { type: "number" },
99
+ },
100
+ required: ["description", "amount"],
101
+ },
102
+ },
103
+ total: { type: "number" },
104
+ },
105
+ required: ["lines", "total"],
106
+ },
107
+ });
108
+ });
109
+ });
110
+ //# sourceMappingURL=compiler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.test.js","sourceRoot":"","sources":["../../tests/compiler.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=extractor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.test.d.ts","sourceRoot":"","sources":["../../tests/extractor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,195 @@
1
+ import { describe, it, expect, vi, beforeAll } from "vitest";
2
+ import { z } from "zod";
3
+ import { DocumentExtractor } from "../src/core/extractor.js";
4
+ import { createBlankImage } from "./fixtures.js";
5
+ const Invoice = z.object({
6
+ invoiceNumber: z.string(),
7
+ subtotal: z.number(),
8
+ tax: z.number(),
9
+ total: z.number(),
10
+ items: z.array(z.object({
11
+ description: z.string(),
12
+ amount: z.number(),
13
+ })),
14
+ });
15
+ describe("DocumentExtractor", () => {
16
+ let image;
17
+ beforeAll(async () => {
18
+ image = await createBlankImage(800, 600);
19
+ });
20
+ it("extracts typed data and groundings using a custom VLM", async () => {
21
+ const mockProvider = {
22
+ name: "mock",
23
+ extract: vi.fn().mockResolvedValue({
24
+ text: JSON.stringify({
25
+ data: {
26
+ invoiceNumber: "INV-001",
27
+ subtotal: 100,
28
+ tax: 21,
29
+ total: 121,
30
+ items: [{ description: "A", amount: 100 }],
31
+ },
32
+ groundings: [
33
+ {
34
+ pageIndex: 0,
35
+ field: "invoiceNumber",
36
+ value: "INV-001",
37
+ bbox: [0.1, 0.1, 0.2, 0.4],
38
+ confidence: 0.98,
39
+ },
40
+ ],
41
+ }),
42
+ raw: null,
43
+ }),
44
+ };
45
+ const extractor = new DocumentExtractor({ customVLM: mockProvider });
46
+ const result = await extractor.extract(image.buffer, Invoice, { tiling: "off" });
47
+ expect(result.data.invoiceNumber).toBe("INV-001");
48
+ expect(result.data.total).toBe(121);
49
+ expect(result.groundings).toHaveLength(1);
50
+ expect(result.fields.invoiceNumber.bbox).toEqual([0.1, 0.1, 0.2, 0.4]);
51
+ expect(result.confidence).toBeGreaterThan(0);
52
+ expect(result.provenance.provider).toBe("mock");
53
+ expect(result.provenance.tilesUsed).toBe(1);
54
+ });
55
+ it("runs invariants and returns a report", async () => {
56
+ const mockProvider = {
57
+ name: "mock",
58
+ extract: vi.fn().mockResolvedValue({
59
+ text: JSON.stringify({
60
+ data: {
61
+ invoiceNumber: "INV-002",
62
+ subtotal: 100,
63
+ tax: 21,
64
+ total: 121,
65
+ items: [{ description: "A", amount: 100 }],
66
+ },
67
+ }),
68
+ raw: null,
69
+ }),
70
+ };
71
+ const extractor = new DocumentExtractor({ customVLM: mockProvider });
72
+ const result = await extractor.extract(image.buffer, Invoice, {
73
+ tiling: "off",
74
+ prove: true,
75
+ invariants: [
76
+ { id: "balance", expression: "subtotal + tax === total" },
77
+ { id: "items-total", expression: "sum(items.amount) === subtotal" },
78
+ ],
79
+ });
80
+ expect(result.invariants?.ok).toBe(true);
81
+ expect(result.invariants?.checks).toHaveLength(2);
82
+ });
83
+ it("auto-repairs when invariants fail", async () => {
84
+ const responses = [
85
+ {
86
+ text: JSON.stringify({
87
+ data: {
88
+ invoiceNumber: "INV-003",
89
+ subtotal: 100,
90
+ tax: 21,
91
+ total: 120, // wrong
92
+ items: [{ description: "A", amount: 100 }],
93
+ },
94
+ }),
95
+ raw: null,
96
+ },
97
+ {
98
+ text: JSON.stringify({
99
+ data: {
100
+ invoiceNumber: "INV-003",
101
+ subtotal: 100,
102
+ tax: 21,
103
+ total: 121, // corrected
104
+ items: [{ description: "A", amount: 100 }],
105
+ },
106
+ }),
107
+ raw: null,
108
+ },
109
+ ];
110
+ const mockProvider = {
111
+ name: "mock",
112
+ extract: vi
113
+ .fn()
114
+ .mockImplementation(() => Promise.resolve(responses.shift())),
115
+ };
116
+ const extractor = new DocumentExtractor({ customVLM: mockProvider });
117
+ const result = await extractor.extract(image.buffer, Invoice, {
118
+ tiling: "off",
119
+ prove: true,
120
+ autoRepair: true,
121
+ invariants: [{ id: "balance", expression: "subtotal + tax === total" }],
122
+ });
123
+ expect(mockProvider.extract).toHaveBeenCalledTimes(2);
124
+ expect(result.data.total).toBe(121);
125
+ expect(result.invariants?.ok).toBe(true);
126
+ expect(result.provenance.repairs).toBe(1);
127
+ });
128
+ it("stitches multi-page tables returned by the VLM", async () => {
129
+ const mockProvider = {
130
+ name: "mock",
131
+ extract: vi.fn().mockResolvedValue({
132
+ text: JSON.stringify({
133
+ data: {
134
+ invoiceNumber: "INV-004",
135
+ subtotal: 200,
136
+ tax: 42,
137
+ total: 242,
138
+ items: [{ description: "A", amount: 200 }],
139
+ },
140
+ tables: [
141
+ {
142
+ pageIndex: 1,
143
+ header: ["Item", "Qty"],
144
+ rows: [["A", 1]],
145
+ bbox: [0, 0, 0.4, 0.9],
146
+ },
147
+ {
148
+ pageIndex: 2,
149
+ header: ["Item", "Qty"],
150
+ rows: [
151
+ ["Item", "Qty"],
152
+ ["B", 2],
153
+ ],
154
+ bbox: [0, 0, 0.4, 0.9],
155
+ },
156
+ ],
157
+ }),
158
+ raw: null,
159
+ }),
160
+ };
161
+ const extractor = new DocumentExtractor({ customVLM: mockProvider });
162
+ const result = await extractor.extract(image.buffer, Invoice, { tiling: "off" });
163
+ expect(result.tables).toHaveLength(1);
164
+ expect(result.tables[0].rows).toEqual([
165
+ ["A", 1],
166
+ ["B", 2],
167
+ ]);
168
+ });
169
+ it("supports tiling when the image exceeds tile limits", async () => {
170
+ const largeImage = await createBlankImage(2000, 2000);
171
+ const mockProvider = {
172
+ name: "mock",
173
+ extract: vi.fn().mockResolvedValue({
174
+ text: JSON.stringify({
175
+ data: {
176
+ invoiceNumber: "INV-005",
177
+ subtotal: 50,
178
+ tax: 10.5,
179
+ total: 60.5,
180
+ items: [{ description: "A", amount: 50 }],
181
+ },
182
+ }),
183
+ raw: null,
184
+ }),
185
+ };
186
+ const extractor = new DocumentExtractor({ customVLM: mockProvider });
187
+ const result = await extractor.extract(largeImage.buffer, Invoice, {
188
+ tiling: { maxTileWidth: 1024, maxTileHeight: 1024, overlap: 0.2 },
189
+ });
190
+ expect(result.provenance.tilesUsed).toBeGreaterThan(1);
191
+ const call = mockProvider.extract.mock.calls[0];
192
+ expect(call[0].images.length).toBeGreaterThan(1);
193
+ });
194
+ });
195
+ //# sourceMappingURL=extractor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.test.js","sourceRoot":"","sources":["../../tests/extractor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface TestImage {
2
+ mimeType: string;
3
+ base64: string;
4
+ width: number;
5
+ height: number;
6
+ buffer: Buffer;
7
+ }
8
+ export declare function createBlankImage(width: number, height: number, mimeType?: "image/png" | "image/jpeg"): Promise<TestImage>;
9
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../tests/fixtures.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,WAAW,GAAG,YAA0B,GACjD,OAAO,CAAC,SAAS,CAAC,CAiBpB"}
@@ -0,0 +1,20 @@
1
+ import sharp from "sharp";
2
+ export async function createBlankImage(width, height, mimeType = "image/png") {
3
+ const pipeline = sharp({
4
+ create: {
5
+ width,
6
+ height,
7
+ channels: 3,
8
+ background: "white",
9
+ },
10
+ });
11
+ const buf = mimeType === "image/jpeg" ? await pipeline.jpeg().toBuffer() : await pipeline.png().toBuffer();
12
+ return {
13
+ mimeType,
14
+ base64: buf.toString("base64"),
15
+ width,
16
+ height,
17
+ buffer: buf,
18
+ };
19
+ }
20
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../tests/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,MAAc,EACd,WAAuC,WAAW;IAElD,MAAM,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,EAAE;YACN,KAAK;YACL,MAAM;YACN,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,OAAO;SACpB;KACF,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC3G,OAAO;QACL,QAAQ;QACR,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC9B,KAAK;QACL,MAAM;QACN,MAAM,EAAE,GAAG;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=grounding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grounding.test.d.ts","sourceRoot":"","sources":["../../tests/grounding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { normalizeBBox, denormalizeBBox, iou, mergeBoxes, } from "../src/grounding/bbox.js";
3
+ describe("bbox grounding", () => {
4
+ const pageSize = { width: 800, height: 1200 };
5
+ describe("normalizeBBox / denormalizeBBox", () => {
6
+ it("normalizes absolute pixel coordinates to [ymin, xmin, ymax, xmax]", () => {
7
+ const box = { x1: 200, y1: 300, x2: 400, y2: 600 };
8
+ const normalized = normalizeBBox(box, pageSize);
9
+ expect(normalized).toEqual([
10
+ 300 / 1200,
11
+ 200 / 800,
12
+ 600 / 1200,
13
+ 400 / 800,
14
+ ]);
15
+ });
16
+ it("round-trips through denormalize", () => {
17
+ const box = { x1: 100, y1: 150, x2: 300, y2: 450 };
18
+ const normalized = normalizeBBox(box, pageSize);
19
+ const denormalized = denormalizeBBox(normalized, pageSize);
20
+ expect(denormalized.x1).toBeCloseTo(box.x1);
21
+ expect(denormalized.y1).toBeCloseTo(box.y1);
22
+ expect(denormalized.x2).toBeCloseTo(box.x2);
23
+ expect(denormalized.y2).toBeCloseTo(box.y2);
24
+ });
25
+ it("normalizes inverted absolute boxes", () => {
26
+ const box = { x1: 400, y1: 600, x2: 200, y2: 300 };
27
+ const normalized = normalizeBBox(box, pageSize);
28
+ expect(normalized).toEqual([
29
+ 300 / 1200,
30
+ 200 / 800,
31
+ 600 / 1200,
32
+ 400 / 800,
33
+ ]);
34
+ });
35
+ });
36
+ describe("iou", () => {
37
+ it("returns 1.0 for identical boxes", () => {
38
+ const a = [0.1, 0.1, 0.5, 0.5];
39
+ const b = [0.1, 0.1, 0.5, 0.5];
40
+ expect(iou(a, b)).toBe(1);
41
+ });
42
+ it("returns 0.0 for non-overlapping boxes", () => {
43
+ const a = [0, 0, 0.2, 0.2];
44
+ const b = [0.3, 0.3, 0.5, 0.5];
45
+ expect(iou(a, b)).toBe(0);
46
+ });
47
+ it("returns the correct overlap ratio for partial overlap", () => {
48
+ const a = [0, 0, 0.5, 0.5];
49
+ const b = [0.25, 0.25, 0.75, 0.75];
50
+ // Intersection area: 0.25 * 0.25 = 0.0625
51
+ // Union area: 0.25 + 0.25 - 0.0625 = 0.4375
52
+ // IoU: 0.0625 / 0.4375 ≈ 0.1428
53
+ expect(iou(a, b)).toBeCloseTo(0.0625 / 0.4375, 4);
54
+ });
55
+ });
56
+ describe("mergeBoxes", () => {
57
+ it("merges two overlapping boxes", () => {
58
+ // Box b is almost fully inside a, producing a high IoU (>0.5).
59
+ const a = [0, 0, 0.5, 0.5];
60
+ const b = [0.1, 0.1, 0.5, 0.5];
61
+ const merged = mergeBoxes([a, b], 0.5);
62
+ expect(merged).toHaveLength(1);
63
+ expect(merged[0]).toEqual([0, 0, 0.5, 0.5]);
64
+ });
65
+ it("does not merge boxes below the IoU threshold", () => {
66
+ const a = [0, 0, 0.1, 0.1];
67
+ const b = [0.2, 0.2, 0.3, 0.3];
68
+ const merged = mergeBoxes([a, b], 0.5);
69
+ expect(merged).toHaveLength(2);
70
+ });
71
+ it("chains merges across multiple boxes", () => {
72
+ // Three boxes with high mutual overlap (>0.5 IoU) that should collapse into one.
73
+ const a = [0, 0, 0.5, 0.5];
74
+ const b = [0, 0, 0.45, 0.45];
75
+ const c = [0.05, 0.05, 0.5, 0.5];
76
+ const merged = mergeBoxes([a, b, c], 0.5);
77
+ expect(merged).toHaveLength(1);
78
+ expect(merged[0]).toEqual([0, 0, 0.5, 0.5]);
79
+ });
80
+ });
81
+ });
82
+ //# sourceMappingURL=grounding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grounding.test.js","sourceRoot":"","sources":["../../tests/grounding.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=multi-domain.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-domain.test.d.ts","sourceRoot":"","sources":["../../tests/multi-domain.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,135 @@
1
+ import { describe, it, expect, vi, beforeAll } from "vitest";
2
+ import { z } from "zod";
3
+ import { DocumentExtractor } from "../src/core/extractor.js";
4
+ import { compileZodToJsonSchema } from "../src/compiler/zod-compiler.js";
5
+ import { createBlankImage } from "./fixtures.js";
6
+ const LegalContractSchema = z.object({
7
+ contractNumber: z.string(),
8
+ parties: z.object({
9
+ client: z.string(),
10
+ contractor: z.string(),
11
+ }),
12
+ effectiveDate: z.string(),
13
+ termYears: z.number(),
14
+ clauseCount: z.number(),
15
+ penaltyAmount: z.number(),
16
+ });
17
+ const EngineeringSpecSchema = z.object({
18
+ project: z.string(),
19
+ revision: z.string(),
20
+ material: z.string(),
21
+ dimensions: z.object({
22
+ length: z.number(),
23
+ width: z.number(),
24
+ height: z.number(),
25
+ }),
26
+ tolerances: z.object({
27
+ linear: z.number(),
28
+ angular: z.number(),
29
+ }),
30
+ testResults: z.array(z.object({
31
+ test: z.string(),
32
+ passed: z.boolean(),
33
+ value: z.number(),
34
+ })),
35
+ });
36
+ const ClinicalReportSchema = z.object({
37
+ patient: z.object({
38
+ name: z.string(),
39
+ id: z.string(),
40
+ dob: z.string(),
41
+ }),
42
+ reportDate: z.string(),
43
+ biomarkers: z.array(z.object({
44
+ marker: z.string(),
45
+ value: z.number(),
46
+ unit: z.string(),
47
+ referenceRange: z.string(),
48
+ })),
49
+ });
50
+ function mockProvider(responseData) {
51
+ return {
52
+ name: "mock",
53
+ extract: vi.fn().mockResolvedValue({
54
+ text: JSON.stringify({ data: responseData, groundings: [] }),
55
+ raw: null,
56
+ }),
57
+ };
58
+ }
59
+ describe("Multi-Domain Extraction", () => {
60
+ let image;
61
+ beforeAll(async () => {
62
+ image = await createBlankImage(800, 600);
63
+ });
64
+ it("compiles heterogeneous Zod schemas to valid JSON Schema", () => {
65
+ expect(compileZodToJsonSchema(LegalContractSchema)).toMatchObject({ type: "object" });
66
+ expect(compileZodToJsonSchema(EngineeringSpecSchema)).toMatchObject({ type: "object" });
67
+ expect(compileZodToJsonSchema(ClinicalReportSchema)).toMatchObject({ type: "object" });
68
+ });
69
+ it("extracts a Legal Contract", async () => {
70
+ const data = {
71
+ contractNumber: "CNT-2026-001",
72
+ parties: { client: "Acme Corp", contractor: "BuildRight LLC" },
73
+ effectiveDate: "2026-01-15",
74
+ termYears: 3,
75
+ clauseCount: 12,
76
+ penaltyAmount: 50000,
77
+ };
78
+ const extractor = new DocumentExtractor({ customVLM: mockProvider(data) });
79
+ const result = await extractor.extract(image.buffer, LegalContractSchema, { tiling: "off" });
80
+ expect(result.data).toEqual(data);
81
+ expect(result.data.parties.client).toBe("Acme Corp");
82
+ expect(result.confidence).toBeGreaterThan(0);
83
+ });
84
+ it("extracts an Engineering Spec", async () => {
85
+ const data = {
86
+ project: "Brigde-Alpha",
87
+ revision: "Rev-C",
88
+ material: "Steel S355",
89
+ dimensions: { length: 1200, width: 400, height: 80 },
90
+ tolerances: { linear: 0.5, angular: 0.25 },
91
+ testResults: [
92
+ { test: "Tensile", passed: true, value: 520 },
93
+ { test: "Compression", passed: true, value: 410 },
94
+ ],
95
+ };
96
+ const extractor = new DocumentExtractor({ customVLM: mockProvider(data) });
97
+ const result = await extractor.extract(image.buffer, EngineeringSpecSchema, { tiling: "off" });
98
+ expect(result.data.project).toBe("Brigde-Alpha");
99
+ expect(result.data.dimensions.height).toBe(80);
100
+ expect(result.data.testResults).toHaveLength(2);
101
+ });
102
+ it("extracts a Clinical Report with biomarkers", async () => {
103
+ const data = {
104
+ patient: { name: "John Doe", id: "PAT-987654", dob: "1985-03-15" },
105
+ reportDate: "2026-08-30",
106
+ biomarkers: [
107
+ { marker: "Glucose", value: 95, unit: "mg/dL", referenceRange: "70 - 100" },
108
+ { marker: "LDL", value: 110, unit: "mg/dL", referenceRange: "< 130" },
109
+ ],
110
+ };
111
+ const extractor = new DocumentExtractor({ customVLM: mockProvider(data) });
112
+ const result = await extractor.extract(image.buffer, ClinicalReportSchema, { tiling: "off" });
113
+ expect(result.data.patient.name).toBe("John Doe");
114
+ expect(result.data.biomarkers[0].marker).toBe("Glucose");
115
+ expect(result.data.biomarkers).toHaveLength(2);
116
+ });
117
+ it("runs invariants across domains", async () => {
118
+ const data = {
119
+ contractNumber: "CNT-2026-002",
120
+ parties: { client: "Client A", contractor: "Contractor B" },
121
+ effectiveDate: "2026-02-01",
122
+ termYears: 2,
123
+ clauseCount: 8,
124
+ penaltyAmount: 10000,
125
+ };
126
+ const extractor = new DocumentExtractor({ customVLM: mockProvider(data) });
127
+ const result = await extractor.extract(image.buffer, LegalContractSchema, {
128
+ tiling: "off",
129
+ prove: true,
130
+ invariants: [{ id: "min-clauses", expression: "clauseCount >= 5" }],
131
+ });
132
+ expect(result.invariants?.ok).toBe(true);
133
+ });
134
+ });
135
+ //# sourceMappingURL=multi-domain.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-domain.test.js","sourceRoot":"","sources":["../../tests/multi-domain.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC;IACF,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;KACnB,CAAC;IACF,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC;IACF,WAAW,EAAE,CAAC,CAAC,KAAK,CAClB,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;QACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;KAClB,CAAC,CACH;CACF,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;KAChB,CAAC;IACF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,UAAU,EAAE,CAAC,CAAC,KAAK,CACjB,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;KAC3B,CAAC,CACH;CACF,CAAC,CAAC;AAEH,SAAS,YAAY,CAAC,YAAqB;IACzC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACjC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;YAC5D,GAAG,EAAE,IAAI;SACQ,CAAC;KACrB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,IAAI,KAAmD,CAAC;IAExD,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,KAAK,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxF,MAAM,CAAC,sBAAsB,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,IAAI,GAAG;YACX,cAAc,EAAE,cAAc;YAC9B,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE;YAC9D,aAAa,EAAE,YAAY;YAC3B,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,EAAE;YACf,aAAa,EAAE,KAAK;SACrB,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,YAAY;YACtB,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;YACpD,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;YAC1C,WAAW,EAAE;gBACX,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC7C,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;aAClD;SACF,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,qBAAqB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAE/F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE;YAClE,UAAU,EAAE,YAAY;YACxB,UAAU,EAAE;gBACV,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE;gBAC3E,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE;aACtE;SACF,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAE9F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,IAAI,GAAG;YACX,cAAc,EAAE,cAAc;YAC9B,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE;YAC3D,aAAa,EAAE,YAAY;YAC3B,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;YACd,aAAa,EAAE,KAAK;SACrB,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB,EAAE;YACxE,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC;SACpE,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=normalizer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.test.d.ts","sourceRoot":"","sources":["../../tests/normalizer.test.ts"],"names":[],"mappings":""}