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.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/src/compiler/zod-compiler.d.ts +31 -0
- package/dist/src/compiler/zod-compiler.d.ts.map +1 -0
- package/dist/src/compiler/zod-compiler.js +150 -0
- package/dist/src/compiler/zod-compiler.js.map +1 -0
- package/dist/src/core/extractor.d.ts +17 -0
- package/dist/src/core/extractor.d.ts.map +1 -0
- package/dist/src/core/extractor.js +268 -0
- package/dist/src/core/extractor.js.map +1 -0
- package/dist/src/core/types.d.ts +102 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/grounding/bbox.d.ts +40 -0
- package/dist/src/grounding/bbox.d.ts.map +1 -0
- package/dist/src/grounding/bbox.js +98 -0
- package/dist/src/grounding/bbox.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/normalizers/currency.d.ts +14 -0
- package/dist/src/normalizers/currency.d.ts.map +1 -0
- package/dist/src/normalizers/currency.js +96 -0
- package/dist/src/normalizers/currency.js.map +1 -0
- package/dist/src/normalizers/tabular.d.ts +16 -0
- package/dist/src/normalizers/tabular.d.ts.map +1 -0
- package/dist/src/normalizers/tabular.js +81 -0
- package/dist/src/normalizers/tabular.js.map +1 -0
- package/dist/src/providers/anthropic-provider.d.ts +13 -0
- package/dist/src/providers/anthropic-provider.d.ts.map +1 -0
- package/dist/src/providers/anthropic-provider.js +62 -0
- package/dist/src/providers/anthropic-provider.js.map +1 -0
- package/dist/src/providers/factory.d.ts +11 -0
- package/dist/src/providers/factory.d.ts.map +1 -0
- package/dist/src/providers/factory.js +32 -0
- package/dist/src/providers/factory.js.map +1 -0
- package/dist/src/providers/gemini-provider.d.ts +13 -0
- package/dist/src/providers/gemini-provider.d.ts.map +1 -0
- package/dist/src/providers/gemini-provider.js +48 -0
- package/dist/src/providers/gemini-provider.js.map +1 -0
- package/dist/src/providers/openai-provider.d.ts +14 -0
- package/dist/src/providers/openai-provider.d.ts.map +1 -0
- package/dist/src/providers/openai-provider.js +48 -0
- package/dist/src/providers/openai-provider.js.map +1 -0
- package/dist/src/providers/types.d.ts +45 -0
- package/dist/src/providers/types.d.ts.map +1 -0
- package/dist/src/providers/types.js +2 -0
- package/dist/src/providers/types.js.map +1 -0
- package/dist/src/stitcher/table-stitcher.d.ts +19 -0
- package/dist/src/stitcher/table-stitcher.d.ts.map +1 -0
- package/dist/src/stitcher/table-stitcher.js +129 -0
- package/dist/src/stitcher/table-stitcher.js.map +1 -0
- package/dist/src/tiling/cutter.d.ts +14 -0
- package/dist/src/tiling/cutter.d.ts.map +1 -0
- package/dist/src/tiling/cutter.js +46 -0
- package/dist/src/tiling/cutter.js.map +1 -0
- package/dist/src/tiling/tiler.d.ts +41 -0
- package/dist/src/tiling/tiler.d.ts.map +1 -0
- package/dist/src/tiling/tiler.js +82 -0
- package/dist/src/tiling/tiler.js.map +1 -0
- package/dist/src/validators/invariants.d.ts +30 -0
- package/dist/src/validators/invariants.d.ts.map +1 -0
- package/dist/src/validators/invariants.js +164 -0
- package/dist/src/validators/invariants.js.map +1 -0
- package/dist/tests/compiler.test.d.ts +2 -0
- package/dist/tests/compiler.test.d.ts.map +1 -0
- package/dist/tests/compiler.test.js +110 -0
- package/dist/tests/compiler.test.js.map +1 -0
- package/dist/tests/extractor.test.d.ts +2 -0
- package/dist/tests/extractor.test.d.ts.map +1 -0
- package/dist/tests/extractor.test.js +195 -0
- package/dist/tests/extractor.test.js.map +1 -0
- package/dist/tests/fixtures.d.ts +9 -0
- package/dist/tests/fixtures.d.ts.map +1 -0
- package/dist/tests/fixtures.js +20 -0
- package/dist/tests/fixtures.js.map +1 -0
- package/dist/tests/grounding.test.d.ts +2 -0
- package/dist/tests/grounding.test.d.ts.map +1 -0
- package/dist/tests/grounding.test.js +82 -0
- package/dist/tests/grounding.test.js.map +1 -0
- package/dist/tests/multi-domain.test.d.ts +2 -0
- package/dist/tests/multi-domain.test.d.ts.map +1 -0
- package/dist/tests/multi-domain.test.js +135 -0
- package/dist/tests/multi-domain.test.js.map +1 -0
- package/dist/tests/normalizer.test.d.ts +2 -0
- package/dist/tests/normalizer.test.d.ts.map +1 -0
- package/dist/tests/normalizer.test.js +70 -0
- package/dist/tests/normalizer.test.js.map +1 -0
- package/dist/tests/providers.test.d.ts +2 -0
- package/dist/tests/providers.test.d.ts.map +1 -0
- package/dist/tests/providers.test.js +110 -0
- package/dist/tests/providers.test.js.map +1 -0
- package/dist/tests/stitcher.test.d.ts +2 -0
- package/dist/tests/stitcher.test.d.ts.map +1 -0
- package/dist/tests/stitcher.test.js +85 -0
- package/dist/tests/stitcher.test.js.map +1 -0
- package/dist/tests/tiling.test.d.ts +2 -0
- package/dist/tests/tiling.test.d.ts.map +1 -0
- package/dist/tests/tiling.test.js +85 -0
- package/dist/tests/tiling.test.js.map +1 -0
- package/dist/tests/validators.test.d.ts +2 -0
- package/dist/tests/validators.test.d.ts.map +1 -0
- package/dist/tests/validators.test.js +125 -0
- package/dist/tests/validators.test.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +13 -0
- package/dist/vitest.config.js.map +1 -0
- 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 @@
|
|
|
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":"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"}
|
|
@@ -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":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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
|
+
}
|