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,70 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { parseAccountingNumber } from "../src/normalizers/currency.js";
3
+ import { parseISODate } from "../src/normalizers/tabular.js";
4
+ describe("parseAccountingNumber", () => {
5
+ it("parses US formatted currency", () => {
6
+ expect(parseAccountingNumber("$1,250.50")).toBe(1250.5);
7
+ expect(parseAccountingNumber("1,250.50")).toBe(1250.5);
8
+ });
9
+ it("parses European formatted currency", () => {
10
+ expect(parseAccountingNumber("1.250,50 €")).toBe(1250.5);
11
+ expect(parseAccountingNumber("1.250,50")).toBe(1250.5);
12
+ expect(parseAccountingNumber("1,50")).toBe(1.5);
13
+ });
14
+ it("parses plain integers and floats", () => {
15
+ expect(parseAccountingNumber("1250")).toBe(1250);
16
+ expect(parseAccountingNumber("1250.50")).toBe(1250.5);
17
+ expect(parseAccountingNumber(1250.5)).toBe(1250.5);
18
+ });
19
+ it("strips currency symbols and whitespace", () => {
20
+ expect(parseAccountingNumber(" $ 1,250.50 ")).toBe(1250.5);
21
+ expect(parseAccountingNumber("€1.250,50")).toBe(1250.5);
22
+ expect(parseAccountingNumber("£ 1,000.00")).toBe(1000);
23
+ });
24
+ it("handles accounting negative numbers in parentheses", () => {
25
+ expect(parseAccountingNumber("(450.00)")).toBe(-450);
26
+ expect(parseAccountingNumber("(450,50)")).toBe(-450.5);
27
+ });
28
+ it("handles explicit negative signs", () => {
29
+ expect(parseAccountingNumber("-1,250.50")).toBe(-1250.5);
30
+ expect(parseAccountingNumber("1,250.50-")).toBe(-1250.5);
31
+ });
32
+ it("returns null for non-numeric values", () => {
33
+ expect(parseAccountingNumber("abc")).toBeNull();
34
+ expect(parseAccountingNumber("")).toBeNull();
35
+ expect(parseAccountingNumber(NaN)).toBeNull();
36
+ });
37
+ });
38
+ describe("parseISODate", () => {
39
+ it("keeps already ISO dates", () => {
40
+ expect(parseISODate("2024-03-15")).toBe("2024-03-15");
41
+ });
42
+ it("parses year-first dates", () => {
43
+ expect(parseISODate("2024/03/15")).toBe("2024-03-15");
44
+ expect(parseISODate("2024.03.15")).toBe("2024-03-15");
45
+ });
46
+ it("parses international DD/MM/YYYY dates", () => {
47
+ expect(parseISODate("15/03/2024")).toBe("2024-03-15");
48
+ expect(parseISODate("15-03-2024")).toBe("2024-03-15");
49
+ expect(parseISODate("15.03.2024")).toBe("2024-03-15");
50
+ });
51
+ it("parses US MM/DD/YYYY dates", () => {
52
+ expect(parseISODate("03/15/2024", "us")).toBe("2024-03-15");
53
+ });
54
+ it("resolves ambiguous dates with the default international locale", () => {
55
+ // 05/03/2024 is ambiguous; international means DD/MM.
56
+ expect(parseISODate("05/03/2024")).toBe("2024-03-05");
57
+ // With US locale it should be interpreted as MM/DD.
58
+ expect(parseISODate("05/03/2024", "us")).toBe("2024-05-03");
59
+ });
60
+ it("disambiguates by out-of-range values", () => {
61
+ expect(parseISODate("25/03/2024")).toBe("2024-03-25");
62
+ expect(parseISODate("03/25/2024")).toBe("2024-03-25");
63
+ });
64
+ it("returns null for invalid dates", () => {
65
+ expect(parseISODate("2024-13-15")).toBeNull();
66
+ expect(parseISODate("not a date")).toBeNull();
67
+ expect(parseISODate("")).toBeNull();
68
+ });
69
+ });
70
+ //# sourceMappingURL=normalizer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.test.js","sourceRoot":"","sources":["../../tests/normalizer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=providers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.test.d.ts","sourceRoot":"","sources":["../../tests/providers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { GeminiProvider } from "../src/providers/gemini-provider.js";
3
+ import { OpenAIProvider } from "../src/providers/openai-provider.js";
4
+ import { AnthropicProvider } from "../src/providers/anthropic-provider.js";
5
+ import { resolveProvider } from "../src/providers/factory.js";
6
+ const expectedSchema = {
7
+ type: "object",
8
+ properties: {
9
+ invoiceNumber: { type: "string" },
10
+ total: { type: "number" },
11
+ },
12
+ required: ["invoiceNumber", "total"],
13
+ };
14
+ function firstCall(spy) {
15
+ const call = spy.mock.calls[0];
16
+ return (call[0] ?? {});
17
+ }
18
+ describe("providers", () => {
19
+ describe("GeminiProvider", () => {
20
+ it("sends the correct responseMimeType and native schema", async () => {
21
+ const provider = new GeminiProvider({ apiKey: "test", model: "gemini-2.5-flash" });
22
+ const client = provider.client;
23
+ const spy = vi.spyOn(client.models, "generateContent").mockResolvedValue({
24
+ text: JSON.stringify({ invoiceNumber: "001", total: 100 }),
25
+ });
26
+ await provider.extract({
27
+ images: [{ mimeType: "image/png", base64: "iVBORw0KGgo=", width: 100, height: 100 }],
28
+ prompt: "Extract",
29
+ schema: expectedSchema,
30
+ responseMimeType: "application/json",
31
+ });
32
+ const params = firstCall(spy);
33
+ expect(params.model).toBe("gemini-2.5-flash");
34
+ const config = params.config ?? {};
35
+ expect(config.responseMimeType).toBe("application/json");
36
+ const schema = config.responseSchema ?? {};
37
+ expect(schema.type).toBe("OBJECT");
38
+ expect(schema.properties).toBeDefined();
39
+ });
40
+ });
41
+ describe("OpenAIProvider", () => {
42
+ it("sends strict json_schema response_format with image_url content", async () => {
43
+ const provider = new OpenAIProvider({ apiKey: "test", model: "gpt-4o" });
44
+ const client = provider.client;
45
+ const spy = vi.spyOn(client.chat.completions, "create").mockResolvedValue({
46
+ choices: [{ message: { content: JSON.stringify({ invoiceNumber: "002", total: 200 }) } }],
47
+ });
48
+ await provider.extract({
49
+ images: [{ mimeType: "image/png", base64: "iVBORw0KGgo=", width: 100, height: 100 }],
50
+ prompt: "Extract",
51
+ schema: expectedSchema,
52
+ });
53
+ const body = firstCall(spy);
54
+ const responseFormat = body.response_format ?? {};
55
+ expect(responseFormat.type).toBe("json_schema");
56
+ const messages = body.messages ?? [];
57
+ const content = messages[0]?.content;
58
+ const imagePart = content?.find((c) => c.type === "image_url");
59
+ expect(imagePart?.image_url?.url).toMatch(/^data:image\/png;base64,/);
60
+ });
61
+ });
62
+ describe("AnthropicProvider", () => {
63
+ it("sends a single extract_document tool with the schema as input_schema", async () => {
64
+ const provider = new AnthropicProvider({ apiKey: "test", model: "claude-sonnet-4-20250514" });
65
+ const client = provider.client;
66
+ const spy = vi.spyOn(client.messages, "create").mockResolvedValue({
67
+ content: [
68
+ {
69
+ type: "tool_use",
70
+ id: "tu_1",
71
+ name: "extract_document",
72
+ input: { invoiceNumber: "003", total: 300 },
73
+ },
74
+ ],
75
+ });
76
+ await provider.extract({
77
+ images: [{ mimeType: "image/png", base64: "iVBORw0KGgo=", width: 100, height: 100 }],
78
+ prompt: "Extract",
79
+ schema: expectedSchema,
80
+ });
81
+ const body = firstCall(spy);
82
+ expect(body.tool_choice).toEqual({ type: "tool", name: "extract_document" });
83
+ const tools = body.tools ?? [];
84
+ expect(tools).toHaveLength(1);
85
+ expect(tools[0].name).toBe("extract_document");
86
+ expect(tools[0].input_schema).toEqual(expectedSchema);
87
+ });
88
+ });
89
+ describe("factory", () => {
90
+ const OLD_ENV = process.env;
91
+ beforeEach(() => {
92
+ vi.resetModules();
93
+ process.env = { ...OLD_ENV };
94
+ delete process.env.GEMINI_API_KEY;
95
+ delete process.env.OPENAI_API_KEY;
96
+ delete process.env.ANTHROPIC_API_KEY;
97
+ });
98
+ it("selects the provider based on env variables", () => {
99
+ process.env.OPENAI_API_KEY = "sk-test";
100
+ const provider = resolveProvider();
101
+ expect(provider.name).toBe("openai");
102
+ });
103
+ it("uses an explicit custom provider", () => {
104
+ const custom = { name: "custom", extract: vi.fn() };
105
+ const provider = resolveProvider({ customVLM: custom });
106
+ expect(provider.name).toBe("custom");
107
+ });
108
+ });
109
+ });
110
+ //# sourceMappingURL=providers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.test.js","sourceRoot":"","sources":["../../tests/providers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,MAAM,cAAc,GAAG;IACrB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACjC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC1B;IACD,QAAQ,EAAE,CAAC,eAAe,EAAE,OAAO,CAAC;CACrC,CAAC;AAEF,SAAS,SAAS,CAAC,GAAmC;IACpD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAc,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAA4B,CAAC;AACpD,CAAC;AAED,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;YACpE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACnF,MAAM,MAAM,GAAI,QAA6G,CAAC,MAAM,CAAC;YACrI,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,iBAAiB,CAAC;gBACvE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aAC3D,CAAC,CAAC;YAEH,MAAM,QAAQ,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBACpF,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,cAAc;gBACtB,gBAAgB,EAAE,kBAAkB;aACrC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAI,MAAM,CAAC,MAAkC,IAAI,EAAE,CAAC;YAChE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACzD,MAAM,MAAM,GAAI,MAAM,CAAC,cAA0C,IAAI,EAAE,CAAC;YACxE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;YAC/E,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzE,MAAM,MAAM,GAAI,QAAmH,CAAC,MAAM,CAAC;YAC3I,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,iBAAiB,CAAC;gBACxE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;aAC1F,CAAC,CAAC;YAEH,MAAM,QAAQ,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBACpF,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,cAAc,GAAI,IAAI,CAAC,eAA2C,IAAI,EAAE,CAAC;YAC/E,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAI,IAAI,CAAC,QAA2C,IAAI,EAAE,CAAC;YACzE,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAA+D,CAAC;YAC7F,MAAM,SAAS,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YAC/D,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;YAC9F,MAAM,MAAM,GAAI,QAAsG,CAAC,MAAM,CAAC;YAC9H,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,iBAAiB,CAAC;gBAChE,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,UAAU;wBAChB,EAAE,EAAE,MAAM;wBACV,IAAI,EAAE,kBAAkB;wBACxB,KAAK,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE;qBAC5C;iBACF;aACF,CAAC,CAAC;YAEH,MAAM,QAAQ,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBACpF,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC7E,MAAM,KAAK,GAAI,IAAI,CAAC,KAAwC,IAAI,EAAE,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC;QAE5B,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAClC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAClC,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;YACvC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAW,CAAC;YAC7D,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;YACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stitcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stitcher.test.d.ts","sourceRoot":"","sources":["../../tests/stitcher.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { TableStitcher } from "../src/stitcher/table-stitcher.js";
3
+ describe("TableStitcher", () => {
4
+ it("merges tables that continue across pages", () => {
5
+ const t1 = {
6
+ pageIndex: 1,
7
+ header: ["Item", "Qty", "Price"],
8
+ rows: [
9
+ ["A", 1, 100],
10
+ ["B", 2, 200],
11
+ ],
12
+ bbox: [0.1, 0.1, 0.5, 0.9],
13
+ };
14
+ const t2 = {
15
+ pageIndex: 2,
16
+ header: ["Item", "Qty", "Price"],
17
+ rows: [
18
+ ["Item", "Qty", "Price"], // repeated header
19
+ ["C", 1, 150],
20
+ ["D", 3, 300],
21
+ ],
22
+ bbox: [0.1, 0.1, 0.5, 0.9],
23
+ };
24
+ const stitcher = new TableStitcher();
25
+ const merged = stitcher.stitch([t1, t2]);
26
+ expect(merged).toHaveLength(1);
27
+ expect(merged[0].rows).toHaveLength(4);
28
+ expect(merged[0].header).toEqual(["Item", "Qty", "Price"]);
29
+ expect(merged[0].rows[2]).toEqual(["C", 1, 150]);
30
+ });
31
+ it("does not merge tables with different column counts", () => {
32
+ const t1 = {
33
+ pageIndex: 1,
34
+ header: ["A", "B"],
35
+ rows: [[1, 2]],
36
+ bbox: [0, 0, 0.5, 1],
37
+ };
38
+ const t2 = {
39
+ pageIndex: 2,
40
+ header: ["A", "B", "C"],
41
+ rows: [[3, 4, 5]],
42
+ bbox: [0, 0, 0.5, 1],
43
+ };
44
+ const stitcher = new TableStitcher();
45
+ const merged = stitcher.stitch([t1, t2]);
46
+ expect(merged).toHaveLength(2);
47
+ });
48
+ it("does not merge tables with low horizontal overlap", () => {
49
+ const t1 = {
50
+ pageIndex: 1,
51
+ header: ["A", "B"],
52
+ rows: [[1, 2]],
53
+ bbox: [0, 0, 0.5, 0.4],
54
+ };
55
+ const t2 = {
56
+ pageIndex: 2,
57
+ header: ["A", "B"],
58
+ rows: [[3, 4]],
59
+ bbox: [0.6, 0, 0.5, 1],
60
+ };
61
+ const stitcher = new TableStitcher();
62
+ const merged = stitcher.stitch([t1, t2]);
63
+ expect(merged).toHaveLength(2);
64
+ });
65
+ it("preserves rowspan/colspan metadata when present", () => {
66
+ const t1 = {
67
+ pageIndex: 1,
68
+ header: ["A", "B"],
69
+ rows: [[1, 2]],
70
+ bbox: [0, 0, 0.5, 1],
71
+ spans: [[{ rowspan: 2 }, undefined]],
72
+ };
73
+ const t2 = {
74
+ pageIndex: 2,
75
+ header: ["A", "B"],
76
+ rows: [[3, 4]],
77
+ bbox: [0, 0, 0.5, 1],
78
+ spans: [[undefined, { colspan: 2 }]],
79
+ };
80
+ const stitcher = new TableStitcher();
81
+ const merged = stitcher.stitch([t1, t2]);
82
+ expect(merged[0].spans).toHaveLength(2);
83
+ });
84
+ });
85
+ //# sourceMappingURL=stitcher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stitcher.test.js","sourceRoot":"","sources":["../../tests/stitcher.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC;YAChC,IAAI,EAAE;gBACJ,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC;gBACb,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC;aACd;YACD,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;SAC3B,CAAC;QACF,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC;YAChC,IAAI,EAAE;gBACJ,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB;gBAC5C,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC;gBACb,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC;aACd;YACD,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;SAC3B,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEzC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YAClB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;SACrB,CAAC;QACF,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;YACvB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACjB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;SACrB,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEzC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YAClB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC;SACvB,CAAC;QACF,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YAClB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;SACvB,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEzC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YAClB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;SACrC,CAAC;QACF,MAAM,EAAE,GAAmB;YACzB,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YAClB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;SACrC,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEzC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tiling.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiling.test.d.ts","sourceRoot":"","sources":["../../tests/tiling.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect, beforeAll } from "vitest";
2
+ import { planTiling, remapTileBoxes } from "../src/tiling/tiler.js";
3
+ import { cropTile, getImageMetadata } from "../src/tiling/cutter.js";
4
+ import { createBlankImage } from "./fixtures.js";
5
+ describe("tiling", () => {
6
+ let largeImage;
7
+ beforeAll(async () => {
8
+ largeImage = await createBlankImage(2000, 2000);
9
+ });
10
+ describe("planTiling", () => {
11
+ it("returns a single tile when the page fits within limits", () => {
12
+ const plan = planTiling(0, { width: 800, height: 600 }, { maxTileWidth: 1024, maxTileHeight: 1024, overlap: 0.15 });
13
+ expect(plan.tiles).toHaveLength(1);
14
+ expect(plan.tiles[0].bbox).toEqual([0, 0, 1, 1]);
15
+ });
16
+ it("produces a grid with overlap when the page exceeds tile limits", () => {
17
+ const plan = planTiling(0, { width: 2000, height: 2000 }, {
18
+ maxTileWidth: 1024,
19
+ maxTileHeight: 1024,
20
+ overlap: 0.2,
21
+ });
22
+ expect(plan.tiles.length).toBeGreaterThan(1);
23
+ expect(plan.tiles.every((t) => t.bbox[0] >= 0 && t.bbox[3] <= 1)).toBe(true);
24
+ });
25
+ it("tiles overlap by the configured ratio", () => {
26
+ const plan = planTiling(0, { width: 2000, height: 1000 }, {
27
+ maxTileWidth: 1200,
28
+ maxTileHeight: 1200,
29
+ overlap: 0.25,
30
+ });
31
+ expect(plan.tiles.length).toBeGreaterThanOrEqual(2);
32
+ const first = plan.tiles[0];
33
+ const second = plan.tiles.find((t) => t.col === 1 && t.row === 0);
34
+ expect(second).toBeDefined();
35
+ // The second tile should start before the first tile ends.
36
+ expect(second.bbox[1]).toBeLessThan(first.bbox[3]);
37
+ });
38
+ });
39
+ describe("remapTileBoxes", () => {
40
+ it("remaps local bboxes back to page-normalized space", () => {
41
+ const tile = {
42
+ pageIndex: 0,
43
+ bbox: [0.1, 0.1, 0.6, 0.6],
44
+ localBox: [0, 0, 1, 1],
45
+ row: 0,
46
+ col: 0,
47
+ rows: 1,
48
+ cols: 1,
49
+ };
50
+ const localBoxes = [
51
+ [0, 0, 0.5, 0.5],
52
+ ];
53
+ const remapped = remapTileBoxes(localBoxes, tile);
54
+ expect(remapped[0]).toEqual([
55
+ 0.1,
56
+ 0.1,
57
+ 0.35,
58
+ 0.35,
59
+ ]);
60
+ });
61
+ });
62
+ describe("cropTile", () => {
63
+ it("crops a tile from the full image with correct dimensions", async () => {
64
+ const metadata = await getImageMetadata(largeImage);
65
+ expect(metadata.width).toBe(2000);
66
+ expect(metadata.height).toBe(2000);
67
+ const plan = planTiling(0, { width: 2000, height: 2000 }, {
68
+ maxTileWidth: 1024,
69
+ maxTileHeight: 1024,
70
+ overlap: 0.2,
71
+ });
72
+ const firstTile = plan.tiles[0];
73
+ const cropped = await cropTile({
74
+ mimeType: largeImage.mimeType,
75
+ base64: largeImage.base64,
76
+ width: 2000,
77
+ height: 2000,
78
+ }, firstTile);
79
+ expect(cropped.width).toBeLessThanOrEqual(1024);
80
+ expect(cropped.height).toBeLessThanOrEqual(1024);
81
+ expect(cropped.base64).toBeTruthy();
82
+ });
83
+ });
84
+ });
85
+ //# sourceMappingURL=tiling.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiling.test.js","sourceRoot":"","sources":["../../tests/tiling.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.test.d.ts","sourceRoot":"","sources":["../../tests/validators.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { InvariantEngine } from "../src/validators/invariants.js";
3
+ describe("InvariantEngine", () => {
4
+ it("passes a simple balance check", () => {
5
+ const engine = new InvariantEngine();
6
+ engine.addCheck({ id: "balance", expression: "subtotal + tax === total" });
7
+ const report = engine.check({
8
+ subtotal: 1000,
9
+ tax: 210,
10
+ total: 1210,
11
+ });
12
+ expect(report.ok).toBe(true);
13
+ expect(report.checks[0].passed).toBe(true);
14
+ expect(report.confidenceScore).toBe(1);
15
+ expect(report.discrepancies).toHaveLength(0);
16
+ });
17
+ it("flags an incorrect balance with exact diff", () => {
18
+ const engine = new InvariantEngine();
19
+ engine.addCheck({ id: "balance", expression: "subtotal + tax === total" });
20
+ const report = engine.check({
21
+ subtotal: 1000,
22
+ tax: 210,
23
+ total: 1200,
24
+ });
25
+ expect(report.ok).toBe(false);
26
+ expect(report.checks[0].passed).toBe(false);
27
+ expect(report.checks[0].diff).toBeCloseTo(10);
28
+ expect(report.discrepancies[0]).toEqual({
29
+ id: "balance",
30
+ actual: 1210,
31
+ expected: 1200,
32
+ diff: 10,
33
+ });
34
+ expect(report.confidenceScore).toBeLessThan(1);
35
+ });
36
+ it("validates sum of table items", () => {
37
+ const engine = new InvariantEngine();
38
+ engine.addCheck({
39
+ id: "items-total",
40
+ expression: "sum(items.amount) === total",
41
+ });
42
+ const report = engine.check({
43
+ items: [{ amount: 100 }, { amount: 250 }, { amount: 50 }],
44
+ total: 400,
45
+ });
46
+ expect(report.ok).toBe(true);
47
+ expect(report.checks[0].passed).toBe(true);
48
+ });
49
+ it("flags a mismatch between sum of items and total", () => {
50
+ const engine = new InvariantEngine();
51
+ engine.addCheck({
52
+ id: "items-total",
53
+ expression: "sum(items.amount) === total",
54
+ });
55
+ const report = engine.check({
56
+ items: [{ amount: 100 }, { amount: 250 }, { amount: 50 }],
57
+ total: 350,
58
+ });
59
+ expect(report.ok).toBe(false);
60
+ expect(report.checks[0].passed).toBe(false);
61
+ expect(report.checks[0].actual).toBe(400);
62
+ expect(report.checks[0].expected).toBe(350);
63
+ expect(report.checks[0].diff).toBe(50);
64
+ });
65
+ it("computes a confidence score with multiple checks", () => {
66
+ const engine = new InvariantEngine();
67
+ engine.addCheck({ id: "a", expression: "x === y" });
68
+ engine.addCheck({ id: "b", expression: "total >= 0" });
69
+ const report = engine.check({
70
+ x: 10,
71
+ y: 10,
72
+ total: 100,
73
+ });
74
+ expect(report.ok).toBe(true);
75
+ expect(report.confidenceScore).toBe(1);
76
+ });
77
+ it("computes a lower confidence score when some checks fail", () => {
78
+ const engine = new InvariantEngine();
79
+ engine.addCheck({ id: "a", expression: "x === y" });
80
+ engine.addCheck({ id: "b", expression: "total === 0" });
81
+ const report = engine.check({
82
+ x: 10,
83
+ y: 9,
84
+ total: 100,
85
+ });
86
+ expect(report.ok).toBe(false);
87
+ expect(report.confidenceScore).toBeGreaterThanOrEqual(0);
88
+ expect(report.confidenceScore).toBeLessThan(1);
89
+ expect(report.checks).toHaveLength(2);
90
+ expect(report.checks[0].passed).toBe(false);
91
+ expect(report.checks[1].passed).toBe(false);
92
+ });
93
+ it("supports count and avg aggregations", () => {
94
+ const engine = new InvariantEngine();
95
+ engine.addCheck({
96
+ id: "avg-equals",
97
+ expression: "avg(items.score) === 50",
98
+ });
99
+ engine.addCheck({
100
+ id: "count-equals",
101
+ expression: "count(items) === 3",
102
+ });
103
+ const report = engine.check({
104
+ items: [{ score: 40 }, { score: 50 }, { score: 60 }],
105
+ });
106
+ expect(report.ok).toBe(true);
107
+ expect(report.checks[0].passed).toBe(true);
108
+ expect(report.checks[1].passed).toBe(true);
109
+ });
110
+ it("respects a custom numeric tolerance", () => {
111
+ const engine = new InvariantEngine();
112
+ engine.addCheck({
113
+ id: "float-balance",
114
+ expression: "a + b === c",
115
+ tolerance: 0.001,
116
+ });
117
+ const report = engine.check({
118
+ a: 0.1,
119
+ b: 0.2,
120
+ c: 0.3000001,
121
+ });
122
+ expect(report.ok).toBe(true);
123
+ });
124
+ });
125
+ //# sourceMappingURL=validators.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.test.js","sourceRoot":"","sources":["../../tests/validators.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":";AAEA,wBAUG"}
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from "vitest/config";
2
+ export default defineConfig({
3
+ test: {
4
+ globals: true,
5
+ environment: "node",
6
+ include: ["tests/**/*.test.ts"],
7
+ coverage: {
8
+ reporter: ["text", "json", "html"],
9
+ exclude: ["node_modules/", "dist/", "vitest.config.ts"],
10
+ },
11
+ },
12
+ });
13
+ //# sourceMappingURL=vitest.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.js","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,MAAM;QACnB,OAAO,EAAE,CAAC,oBAAoB,CAAC;QAC/B,QAAQ,EAAE;YACR,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAClC,OAAO,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,kBAAkB,CAAC;SACxD;KACF;CACF,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "docground",
3
+ "version": "0.1.0",
4
+ "description": "Extract with sight. Prove with math.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "typecheck": "tsc --noEmit",
16
+ "generate:fixtures": "tsx scripts/generate_fixtures.ts"
17
+ },
18
+ "keywords": [
19
+ "document-extraction",
20
+ "visual-grounding",
21
+ "zod",
22
+ "structured-output",
23
+ "multimodal",
24
+ "pdf",
25
+ "typescript"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@anthropic-ai/sdk": "^0.39.0",
31
+ "@google/genai": "^0.14.0",
32
+ "openai": "^4.80.0",
33
+ "sharp": "^0.35.4",
34
+ "zod": "^3.24.0",
35
+ "zod-to-json-schema": "^3.24.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^22.0.0",
39
+ "pdf-lib": "^1.17.1",
40
+ "tsx": "^4.19.0",
41
+ "typescript": "^5.7.0",
42
+ "vitest": "^3.0.0"
43
+ }
44
+ }