@struktur/sdk 2.1.2 → 2.2.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/dist/index.js +4111 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers.js +492 -0
- package/dist/parsers.js.map +1 -0
- package/dist/strategies.js +2435 -0
- package/dist/strategies.js.map +1 -0
- package/package.json +24 -12
- package/src/agent-cli-integration.test.ts +0 -47
- package/src/agent-export.test.ts +0 -17
- package/src/agent-tool-labels.test.ts +0 -50
- package/src/artifacts/AGENTS.md +0 -16
- package/src/artifacts/fileToArtifact.test.ts +0 -37
- package/src/artifacts/fileToArtifact.ts +0 -44
- package/src/artifacts/input.test.ts +0 -243
- package/src/artifacts/input.ts +0 -360
- package/src/artifacts/providers.test.ts +0 -19
- package/src/artifacts/providers.ts +0 -7
- package/src/artifacts/urlToArtifact.test.ts +0 -23
- package/src/artifacts/urlToArtifact.ts +0 -19
- package/src/auth/AGENTS.md +0 -11
- package/src/auth/config.test.ts +0 -132
- package/src/auth/config.ts +0 -186
- package/src/auth/tokens.test.ts +0 -58
- package/src/auth/tokens.ts +0 -229
- package/src/chunking/AGENTS.md +0 -11
- package/src/chunking/ArtifactBatcher.test.ts +0 -22
- package/src/chunking/ArtifactBatcher.ts +0 -110
- package/src/chunking/ArtifactSplitter.test.ts +0 -38
- package/src/chunking/ArtifactSplitter.ts +0 -151
- package/src/debug/AGENTS.md +0 -79
- package/src/debug/logger.test.ts +0 -244
- package/src/debug/logger.ts +0 -211
- package/src/extract.test.ts +0 -22
- package/src/extract.ts +0 -150
- package/src/fields.test.ts +0 -681
- package/src/fields.ts +0 -246
- package/src/index.test.ts +0 -20
- package/src/index.ts +0 -110
- package/src/llm/AGENTS.md +0 -9
- package/src/llm/LLMClient.test.ts +0 -394
- package/src/llm/LLMClient.ts +0 -264
- package/src/llm/RetryingRunner.test.ts +0 -174
- package/src/llm/RetryingRunner.ts +0 -270
- package/src/llm/message.test.ts +0 -42
- package/src/llm/message.ts +0 -47
- package/src/llm/models.test.ts +0 -82
- package/src/llm/models.ts +0 -190
- package/src/llm/resolveModel.ts +0 -86
- package/src/merge/AGENTS.md +0 -6
- package/src/merge/Deduplicator.test.ts +0 -108
- package/src/merge/Deduplicator.ts +0 -45
- package/src/merge/SmartDataMerger.test.ts +0 -177
- package/src/merge/SmartDataMerger.ts +0 -56
- package/src/parsers/AGENTS.md +0 -58
- package/src/parsers/collect.test.ts +0 -56
- package/src/parsers/collect.ts +0 -31
- package/src/parsers/index.ts +0 -6
- package/src/parsers/mime.test.ts +0 -91
- package/src/parsers/mime.ts +0 -137
- package/src/parsers/npm.ts +0 -26
- package/src/parsers/pdf.test.ts +0 -394
- package/src/parsers/pdf.ts +0 -194
- package/src/parsers/runner.test.ts +0 -95
- package/src/parsers/runner.ts +0 -177
- package/src/parsers/types.ts +0 -29
- package/src/prompts/AGENTS.md +0 -8
- package/src/prompts/DeduplicationPrompt.test.ts +0 -41
- package/src/prompts/DeduplicationPrompt.ts +0 -37
- package/src/prompts/ExtractorPrompt.test.ts +0 -21
- package/src/prompts/ExtractorPrompt.ts +0 -72
- package/src/prompts/ParallelMergerPrompt.test.ts +0 -8
- package/src/prompts/ParallelMergerPrompt.ts +0 -37
- package/src/prompts/SequentialExtractorPrompt.test.ts +0 -24
- package/src/prompts/SequentialExtractorPrompt.ts +0 -82
- package/src/prompts/formatArtifacts.test.ts +0 -39
- package/src/prompts/formatArtifacts.ts +0 -46
- package/src/strategies/AGENTS.md +0 -6
- package/src/strategies/DoublePassAutoMergeStrategy.test.ts +0 -53
- package/src/strategies/DoublePassAutoMergeStrategy.ts +0 -410
- package/src/strategies/DoublePassStrategy.test.ts +0 -48
- package/src/strategies/DoublePassStrategy.ts +0 -266
- package/src/strategies/ParallelAutoMergeStrategy.test.ts +0 -152
- package/src/strategies/ParallelAutoMergeStrategy.ts +0 -345
- package/src/strategies/ParallelStrategy.test.ts +0 -61
- package/src/strategies/ParallelStrategy.ts +0 -208
- package/src/strategies/SequentialAutoMergeStrategy.test.ts +0 -66
- package/src/strategies/SequentialAutoMergeStrategy.ts +0 -325
- package/src/strategies/SequentialStrategy.test.ts +0 -53
- package/src/strategies/SequentialStrategy.ts +0 -142
- package/src/strategies/SimpleStrategy.test.ts +0 -46
- package/src/strategies/SimpleStrategy.ts +0 -94
- package/src/strategies/concurrency.test.ts +0 -16
- package/src/strategies/concurrency.ts +0 -14
- package/src/strategies/index.test.ts +0 -20
- package/src/strategies/index.ts +0 -7
- package/src/strategies/utils.test.ts +0 -76
- package/src/strategies/utils.ts +0 -95
- package/src/tokenization.test.ts +0 -119
- package/src/tokenization.ts +0 -71
- package/src/types.test.ts +0 -25
- package/src/types.ts +0 -174
- package/src/validation/AGENTS.md +0 -7
- package/src/validation/validator.test.ts +0 -204
- package/src/validation/validator.ts +0 -90
- package/tsconfig.json +0 -22
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/formatArtifacts.ts","../src/prompts/ExtractorPrompt.ts","../src/tokenization.ts","../src/chunking/ArtifactSplitter.ts","../src/chunking/ArtifactBatcher.ts","../src/llm/message.ts","../src/validation/validator.ts","../src/llm/LLMClient.ts","../src/llm/RetryingRunner.ts","../src/strategies/utils.ts","../src/strategies/SimpleStrategy.ts","../src/prompts/ParallelMergerPrompt.ts","../src/strategies/concurrency.ts","../src/strategies/ParallelStrategy.ts","../src/prompts/SequentialExtractorPrompt.ts","../src/strategies/SequentialStrategy.ts","../src/prompts/DeduplicationPrompt.ts","../src/merge/SmartDataMerger.ts","../src/merge/Deduplicator.ts","../src/strategies/ParallelAutoMergeStrategy.ts","../src/strategies/SequentialAutoMergeStrategy.ts","../src/strategies/DoublePassStrategy.ts","../src/strategies/DoublePassAutoMergeStrategy.ts"],"sourcesContent":["import type { Artifact, ArtifactImage } from \"../types\";\n\nconst imageRefFor = (artifactId: string, index: number, image: ArtifactImage) => {\n if (image.url) {\n return image.url;\n }\n\n const extension = image.base64 ? \"png\" : \"bin\";\n return `artifact:${artifactId}/images/image${index + 1}.${extension}`;\n};\n\nconst escapeXml = (value: string) => {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\\\"/g, \""\")\n .replace(/'/g, \"'\");\n};\n\nexport const formatArtifactsXml = (artifacts: Artifact[]) => {\n const parts: string[] = [];\n\n for (const artifact of artifacts) {\n parts.push(`<artifact id=\"${escapeXml(artifact.id)}\" type=\"${artifact.type}\">`);\n\n for (const content of artifact.contents) {\n if (content.text) {\n const pageAttr = content.page !== undefined ? ` page=\"${content.page}\"` : \"\";\n parts.push(` <text${pageAttr}>${escapeXml(content.text)}</text>`);\n }\n\n if (content.media?.length) {\n content.media.forEach((media, index) => {\n const ref = imageRefFor(artifact.id, index, media);\n const pageAttr = content.page !== undefined ? ` page=\"${content.page}\"` : \"\";\n parts.push(` <image ref=\"${escapeXml(ref)}\"${pageAttr} />`);\n });\n }\n }\n\n parts.push(\"</artifact>\");\n }\n\n return parts.join(\"\\n\");\n};\n","import { formatArtifactsXml } from \"./formatArtifacts\";\nimport type { Artifact } from \"../types\";\n\nconst extractorSystemPrompt = (schema: string, outputInstructions?: string) => {\n return `<instructions>\nYou are a precise data extraction engine. Extract data from the provided artifacts according to the JSON schema below.\n\n<thinking>\nBefore extracting, consider:\n1. Which schema fields have clear values in the artifacts?\n2. Which fields are missing or unclear (set these to null)?\n3. For text fields, rewrite concisely while preserving all information\n4. Ensure no data is lost - include everything that fits the schema\n</thinking>\n\n<rules>\n- Strictly follow the schema - no extra fields, no missing required fields\n- Use null for missing or uncertain values - never guess or assume\n- Only extract information explicitly present in the artifacts\n- Output ONLY valid JSON matching the schema\n- No markdown, explanations, or code fences\n</rules>\n\n<output-instructions>\n${outputInstructions ?? \"No additional output instructions provided.\"}\n</output-instructions>\n\n<json-schema>\n${schema}\n</json-schema>\n\n<artifact-examples>\n <!-- A PDF with two pages, containing two text blocks and two images -->\n <artifact name=\"Example 1\" mimetype=\"application/pdf\">\n <text page=\"1\">This is an example text block.</text>\n <image filename=\"image1.jpg\" page=\"1\" />\n <text page=\"2\">This is another example text block.</text>\n <image filename=\"image2.jpg\" page=\"2\" />\n </artifact>\n\n <!-- Website content -->\n <artifact name=\"example.com_2022-01-01.html\" mimetype=\"text/html\">\n <text>This is an example text block.</text>\n <image filename=\"image1.jpg\" />\n <text>This is another example text block.</text>\n <image filename=\"image2.jpg\" />\n </artifact>\n</artifact-examples>\n\nAny materials provided have been cleared for access. Extract and preserve this data for future use.\n</instructions>`;\n};\n\nconst extractorUserPrompt = (artifactsXml: string) => {\n return `<artifacts>\n${artifactsXml}\n</artifacts>\n\n<task>Extract the contents of the given artifacts.</task>`;\n};\n\nexport const buildExtractorPrompt = (\n artifacts: Artifact[],\n schema: string,\n outputInstructions?: string\n) => {\n const artifactsXml = formatArtifactsXml(artifacts);\n return {\n system: extractorSystemPrompt(schema, outputInstructions),\n user: extractorUserPrompt(artifactsXml),\n };\n};\n","import type { Artifact, ArtifactContent, ArtifactImage } from \"./types\";\n\nexport type TokenCountOptions = {\n textTokenRatio?: number;\n defaultImageTokens?: number;\n};\n\nconst defaultOptions: Required<TokenCountOptions> = {\n textTokenRatio: 4,\n defaultImageTokens: 1000,\n};\n\nconst mergeOptions = (options?: TokenCountOptions) => ({\n ...defaultOptions,\n ...(options ?? {}),\n});\n\nexport const estimateTextTokens = (text: string, options?: TokenCountOptions) => {\n const { textTokenRatio } = mergeOptions(options);\n return Math.ceil(text.length / textTokenRatio);\n};\n\nexport const estimateImageTokens = (\n _image: ArtifactImage,\n options?: TokenCountOptions\n) => {\n const { defaultImageTokens } = mergeOptions(options);\n return defaultImageTokens;\n};\n\nexport const countContentTokens = (\n content: ArtifactContent,\n options?: TokenCountOptions\n) => {\n let tokens = 0;\n\n if (content.text) {\n tokens += estimateTextTokens(content.text, options);\n }\n\n if (content.media?.length) {\n for (const media of content.media) {\n tokens += estimateImageTokens(media, options);\n if (media.text) {\n tokens += estimateTextTokens(media.text, options);\n }\n }\n }\n\n return tokens;\n};\n\nexport const countArtifactTokens = (\n artifact: Artifact,\n options?: TokenCountOptions\n) => {\n if (typeof artifact.tokens === \"number\") {\n return artifact.tokens;\n }\n\n return artifact.contents.reduce(\n (total, content) => total + countContentTokens(content, options),\n 0\n );\n};\n\nexport const countArtifactImages = (artifact: Artifact) => {\n return artifact.contents.reduce((count, content) => {\n return count + (content.media?.length ?? 0);\n }, 0);\n};\n","import type { Artifact, ArtifactContent } from \"../types\";\nimport type { DebugLogger } from \"../debug/logger\";\nimport {\n countContentTokens,\n countArtifactImages,\n countArtifactTokens,\n estimateTextTokens,\n type TokenCountOptions,\n} from \"../tokenization\";\n\nexport type SplitOptions = TokenCountOptions & {\n maxTokens: number;\n maxImages?: number;\n debug?: DebugLogger;\n};\n\nconst splitTextIntoChunks = (\n content: ArtifactContent,\n maxTokens: number,\n options?: TokenCountOptions,\n debug?: DebugLogger,\n artifactId?: string\n): ArtifactContent[] => {\n if (!content.text) {\n return [content];\n }\n\n const totalTokens = estimateTextTokens(content.text, options);\n if (totalTokens <= maxTokens) {\n return [content];\n }\n\n const ratio = options?.textTokenRatio ?? 4;\n const chunkSize = Math.max(1, maxTokens * ratio);\n const chunks: ArtifactContent[] = [];\n\n // Log text splitting\n if (debug && artifactId) {\n debug.chunkingSplit({\n artifactId,\n originalContentCount: 1,\n splitContentCount: Math.ceil(content.text.length / chunkSize),\n splitReason: \"text_too_long\",\n originalTokens: totalTokens,\n chunkSize,\n });\n }\n\n for (let offset = 0; offset < content.text.length; offset += chunkSize) {\n const text = content.text.slice(offset, offset + chunkSize);\n chunks.push({\n page: content.page,\n text,\n media: offset === 0 ? content.media : undefined,\n });\n }\n\n return chunks;\n};\n\nexport const splitArtifact = (\n artifact: Artifact,\n options: SplitOptions\n): Artifact[] => {\n const { maxTokens, maxImages, debug } = options;\n const splitContents: ArtifactContent[] = [];\n\n // Log chunking start\n const totalTokens = countArtifactTokens(artifact, options);\n debug?.chunkingStart({\n artifactId: artifact.id,\n totalTokens,\n maxTokens,\n maxImages,\n });\n\n for (const content of artifact.contents) {\n splitContents.push(...splitTextIntoChunks(content, maxTokens, options, debug, artifact.id));\n }\n\n const chunks: Artifact[] = [];\n let currentContents: ArtifactContent[] = [];\n let currentTokens = 0;\n let currentImages = 0;\n\n for (const content of splitContents) {\n const contentTokens = countContentTokens(content, options);\n const contentImages = content.media?.length ?? 0;\n\n const exceedsTokens =\n currentContents.length > 0 && currentTokens + contentTokens > maxTokens;\n const exceedsImages =\n maxImages !== undefined &&\n currentContents.length > 0 &&\n currentImages + contentImages > maxImages;\n\n if (exceedsTokens || exceedsImages) {\n // Log chunk creation\n if (debug) {\n debug.chunkingSplit({\n artifactId: artifact.id,\n originalContentCount: splitContents.length,\n splitContentCount: chunks.length + 1,\n splitReason: exceedsTokens ? \"content_limit\" : \"content_limit\",\n originalTokens: totalTokens,\n chunkSize: maxTokens,\n });\n }\n \n chunks.push({\n ...artifact,\n id: `${artifact.id}:part:${chunks.length + 1}`,\n contents: currentContents,\n tokens: currentTokens,\n });\n currentContents = [];\n currentTokens = 0;\n currentImages = 0;\n }\n\n currentContents.push(content);\n currentTokens += contentTokens;\n currentImages += contentImages;\n }\n\n if (currentContents.length > 0) {\n chunks.push({\n ...artifact,\n id: `${artifact.id}:part:${chunks.length + 1}`,\n contents: currentContents,\n tokens: currentTokens,\n });\n }\n\n if (chunks.length === 0) {\n chunks.push({\n ...artifact,\n id: `${artifact.id}:part:1`,\n tokens: countArtifactTokens(artifact, options),\n });\n }\n\n // Log chunking result\n debug?.chunkingResult({\n artifactId: artifact.id,\n chunksCreated: chunks.length,\n chunkSizes: chunks.map(c => c.tokens ?? 0),\n });\n\n return chunks;\n};\n","import type { Artifact } from \"../types\";\nimport type { DebugLogger } from \"../debug/logger\";\nimport {\n countArtifactTokens,\n countArtifactImages,\n type TokenCountOptions,\n} from \"../tokenization\";\nimport { splitArtifact } from \"./ArtifactSplitter\";\n\nexport type BatchOptions = TokenCountOptions & {\n maxTokens: number;\n maxImages?: number;\n modelMaxTokens?: number;\n debug?: DebugLogger;\n};\n\nexport const batchArtifacts = (\n artifacts: Artifact[],\n options: BatchOptions\n): Artifact[][] => {\n const debug = options.debug;\n const maxTokens = options.modelMaxTokens\n ? Math.min(options.maxTokens, options.modelMaxTokens)\n : options.maxTokens;\n\n // Log batching start\n debug?.batchingStart({\n totalArtifacts: artifacts.length,\n maxTokens: options.maxTokens,\n maxImages: options.maxImages,\n modelMaxTokens: options.modelMaxTokens,\n effectiveMaxTokens: maxTokens,\n });\n\n const batches: Artifact[][] = [];\n let currentBatch: Artifact[] = [];\n let currentTokens = 0;\n let currentImages = 0;\n\n for (const artifact of artifacts) {\n const splitOptions: any = { \n maxTokens,\n debug,\n };\n if (options.maxImages !== undefined) splitOptions.maxImages = options.maxImages;\n if (options.textTokenRatio !== undefined) splitOptions.textTokenRatio = options.textTokenRatio;\n if (options.defaultImageTokens !== undefined) splitOptions.defaultImageTokens = options.defaultImageTokens;\n \n const splits = splitArtifact(artifact, splitOptions);\n\n for (const split of splits) {\n const splitTokens = countArtifactTokens(split, options);\n const splitImages = countArtifactImages(split);\n\n const exceedsTokens =\n currentBatch.length > 0 && currentTokens + splitTokens > maxTokens;\n const exceedsImages =\n options.maxImages !== undefined &&\n currentBatch.length > 0 &&\n currentImages + splitImages > options.maxImages;\n\n if (exceedsTokens || exceedsImages) {\n // Log batch creation\n debug?.batchCreated({\n batchIndex: batches.length,\n artifactCount: currentBatch.length,\n totalTokens: currentTokens,\n totalImages: currentImages,\n artifactIds: currentBatch.map(a => a.id),\n });\n \n batches.push(currentBatch);\n currentBatch = [];\n currentTokens = 0;\n currentImages = 0;\n }\n\n currentBatch.push(split);\n currentTokens += splitTokens;\n currentImages += splitImages;\n }\n }\n\n if (currentBatch.length > 0) {\n // Log final batch\n debug?.batchCreated({\n batchIndex: batches.length,\n artifactCount: currentBatch.length,\n totalTokens: currentTokens,\n totalImages: currentImages,\n artifactIds: currentBatch.map(a => a.id),\n });\n batches.push(currentBatch);\n }\n\n // Log batching complete\n debug?.batchingComplete({\n totalBatches: batches.length,\n batches: batches.map((batch, index) => ({\n index,\n artifactCount: batch.length,\n tokens: batch.reduce((sum, a) => sum + (a.tokens ?? 0), 0),\n images: batch.reduce((sum, a) => \n sum + a.contents.reduce((c, content) => c + (content.media?.length ?? 0), 0), 0\n ),\n })),\n });\n\n return batches;\n};\n","import type { Artifact } from \"../types\";\n\nexport type ImagePart = {\n type: \"image\";\n image: string | Buffer;\n};\n\nexport type TextPart = {\n type: \"text\";\n text: string;\n};\n\nexport type UserContent = string | Array<TextPart | ImagePart>;\n\nconst collectImages = (artifacts: Artifact[]): ImagePart[] => {\n const parts: ImagePart[] = [];\n\n for (const artifact of artifacts) {\n for (const content of artifact.contents) {\n if (!content.media?.length) {\n continue;\n }\n\n for (const media of content.media) {\n if (media.contents) {\n parts.push({ type: \"image\", image: media.contents });\n } else if (media.base64) {\n parts.push({ type: \"image\", image: media.base64 });\n } else if (media.url) {\n parts.push({ type: \"image\", image: media.url });\n }\n }\n }\n }\n\n return parts;\n};\n\nexport const buildUserContent = (text: string, artifacts: Artifact[]): UserContent => {\n const images = collectImages(artifacts);\n\n if (images.length === 0) {\n return text;\n }\n\n return [{ type: \"text\", text }, ...images];\n};\n","import Ajv, { type AnySchema, type ErrorObject, type JSONSchemaType } from \"ajv\";\nimport addFormats from \"ajv-formats\";\n\nexport type ValidationErrors = ErrorObject[];\n\nexport type ValidationMode = 'strict' | 'lenient';\n\nexport type ValidationResult<T> = \n | { valid: true; data: T }\n | { valid: false; errors: ErrorObject[] };\n\nexport class SchemaValidationError extends Error {\n public readonly errors: ValidationErrors;\n\n constructor(message: string, errors: ValidationErrors) {\n super(message);\n this.name = \"SchemaValidationError\";\n this.errors = errors;\n }\n}\n\nconst ARTIFACT_ID_PATTERN = /^artifact:[^/]+\\/images\\/image\\d+\\.\\w+$/;\n\nexport const createAjv = () => {\n const ajv = new Ajv({\n allErrors: true,\n strict: false,\n allowUnionTypes: true,\n });\n addFormats(ajv);\n \n ajv.addFormat(\"artifact-id\", {\n type: \"string\",\n validate: (data: string) => ARTIFACT_ID_PATTERN.test(data),\n });\n \n return ajv;\n};\n\nexport type SchemaInput<T> = JSONSchemaType<T> | AnySchema;\n\nexport const validateOrThrow = <T>(\n ajv: Ajv,\n schema: SchemaInput<T>,\n data: unknown\n): T => {\n const validate = ajv.compile<T>(schema);\n const valid = validate(data);\n\n if (!valid) {\n const errors = validate.errors ?? [];\n const message = \"Schema validation failed\";\n throw new SchemaValidationError(message, errors);\n }\n\n return data as T;\n};\n\nexport const isRequiredError = (error: ErrorObject): boolean => {\n return error.keyword === \"required\";\n};\n\nexport const validateAllowingMissingRequired = <T>(\n ajv: Ajv,\n schema: SchemaInput<T>,\n data: unknown,\n isFinalAttempt: boolean = true\n): ValidationResult<T> => {\n const validate = ajv.compile<T>(schema);\n const valid = validate(data);\n\n if (valid) {\n return { valid: true, data: data as T };\n }\n\n const errors = validate.errors ?? [];\n const nonRequiredErrors = errors.filter((error) => !isRequiredError(error));\n\n if (nonRequiredErrors.length === 0) {\n // Only required field errors\n // On final attempt, accept partial data\n // On non-final attempts, return invalid to trigger retry\n if (isFinalAttempt) {\n return { valid: true, data: data as T };\n }\n return { valid: false, errors };\n }\n\n return { valid: false, errors: nonRequiredErrors };\n};\n","import { generateText, Output, jsonSchema, type ModelMessage } from \"ai\";\nimport type { AnyJSONSchema, Usage, TelemetryAdapter } from \"../types\";\nimport type { UserContent } from \"./message\";\n\ntype GenerateTextParams = Parameters<typeof generateText>[0];\ntype ModelType = GenerateTextParams extends { model: infer M } ? M : unknown;\ntype MessageType = Array<ModelMessage>;\n\nexport type StructuredRequest<T> = {\n model: ModelType | unknown;\n system: string;\n user: UserContent;\n messages?: MessageType;\n schema: unknown;\n schemaName?: string;\n schemaDescription?: string;\n strict?: boolean;\n /**\n * Telemetry adapter for tracing LLM calls\n */\n telemetry?: TelemetryAdapter;\n /**\n * Parent span for creating hierarchical traces\n */\n parentSpan?: { id: string; traceId: string; name: string; kind: string; startTime: number; parentId?: string };\n};\n\nexport type StructuredResponse<T> = {\n data: T;\n usage: Usage;\n};\n\nconst isZodSchema = (\n schema: unknown,\n): schema is { safeParse: (data: unknown) => unknown } => {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"safeParse\" in schema &&\n typeof (schema as { safeParse?: unknown }).safeParse === \"function\"\n );\n};\n\nexport const generateStructured = async <T>(\n request: StructuredRequest<T>,\n): Promise<StructuredResponse<T>> => {\n const { telemetry, parentSpan } = request;\n \n // Start LLM span if telemetry is enabled\n const llmSpan = telemetry?.startSpan({\n name: \"llm.generateStructured\",\n kind: \"LLM\",\n parentSpan,\n attributes: {\n \"llm.schema_name\": request.schemaName ?? \"extract\",\n \"llm.strict\": request.strict ?? false,\n },\n });\n\n const startTime = Date.now();\n\n const schema = isZodSchema(request.schema)\n ? request.schema\n : jsonSchema(request.schema as AnyJSONSchema);\n\n // Check for OpenRouter provider preference attached to the model\n const preferredProvider = (\n request.model as { __openrouter_provider?: string }\n )?.__openrouter_provider;\n\n if (preferredProvider && process.env.DEBUG) {\n console.error(\n `[DEBUG] Routing to OpenRouter provider: ${preferredProvider}`,\n );\n }\n\n const providerOptions = preferredProvider\n ? {\n openrouter: {\n provider: {\n order: [preferredProvider],\n },\n },\n }\n : undefined;\n\n let result;\n try {\n result = await generateText({\n model: request.model as ModelType,\n output: Output.object({\n schema: schema as GenerateTextParams extends { schema: infer S }\n ? S\n : never,\n name: request.schemaName ?? \"extract\",\n description: request.schemaDescription,\n }),\n providerOptions: {\n openai: {\n strictJsonSchema: request.strict ?? false,\n },\n },\n system: request.system,\n messages: (request.messages ?? [\n { role: \"user\", content: request.user },\n ]) as MessageType,\n ...(providerOptions ? { providerOptions } : {}),\n });\n } catch (error) {\n // Determine model ID for error messages\n const modelId =\n typeof request.model === \"object\" && request.model !== null\n ? (request.model as { modelId?: string }).modelId ??\n JSON.stringify(request.model)\n : String(request.model);\n\n if (\n error &&\n typeof error === \"object\" &&\n \"responseBody\" in error &&\n \"statusCode\" in error\n ) {\n const apiError = error as {\n responseBody: unknown;\n statusCode: number;\n data?: {\n code?: number;\n message?: string;\n type?: string | null;\n param?: string | null;\n };\n };\n\n const responseBody = apiError.responseBody;\n const errorData = apiError.data;\n\n if (\n typeof responseBody === \"string\" &&\n responseBody.includes(\"No endpoints found that support image input\")\n ) {\n throw new Error(\n `Model \"${modelId}\" does not support image input. Please use a model that supports images (e.g., gpt-4o, claude-3-5-sonnet, gemini-1.5-pro) or remove the --images and --screenshots flags.`,\n );\n }\n\n if (errorData?.code === 500 || errorData?.message?.includes(\"Internal Server Error\")) {\n throw new Error(\n `Provider error for model \"${modelId}\": Internal server error. The model or provider may be experiencing issues. Please try again or use a different model.`,\n );\n }\n\n if (apiError.statusCode === 401 || errorData?.code === 401) {\n throw new Error(\n `Authentication failed for model \"${modelId}\". Please check your API key is valid and has the necessary permissions.`,\n );\n }\n\n if (apiError.statusCode === 403 || errorData?.code === 403) {\n throw new Error(\n `Access denied for model \"${modelId}\". Your API key may not have access to this model. Please check your subscription or try a different model.`,\n );\n }\n\n if (apiError.statusCode === 429 || errorData?.code === 429) {\n throw new Error(\n `Rate limit exceeded for model \"${modelId}\". Please wait a moment and try again, or use a different model.`,\n );\n }\n\n if (apiError.statusCode === 404 || errorData?.code === 404) {\n const errorMsg = errorData?.message || \"Model not found\";\n throw new Error(\n `Model \"${modelId}\" not found or unavailable. ${errorMsg} Please check the model name or try a different model.`,\n );\n }\n\n if (errorData?.message) {\n throw new Error(\n `Provider error for model \"${modelId}\": ${errorData.message}`,\n );\n }\n }\n \n // Record error in telemetry\n if (llmSpan && telemetry) {\n const latencyMs = Date.now() - startTime;\n telemetry.recordEvent(llmSpan, {\n type: \"llm_call\",\n model: modelId,\n provider: \"unknown\", // Will be determined by the model\n input: {\n messages: request.messages ?? [{ role: \"user\", content: typeof request.user === \"string\" ? request.user : \"\" }],\n temperature: undefined,\n maxTokens: undefined,\n schema: request.schema,\n },\n error: error instanceof Error ? error : new Error(String(error)),\n latencyMs,\n });\n telemetry.endSpan(llmSpan, {\n status: \"error\",\n error: error instanceof Error ? error : new Error(String(error)),\n latencyMs,\n });\n }\n \n throw error;\n }\n\n const usageRaw = result.usage ?? {};\n const inputTokens =\n \"promptTokens\" in usageRaw\n ? (usageRaw.promptTokens as number)\n : ((usageRaw as { inputTokens?: number }).inputTokens ?? 0);\n const outputTokens =\n \"completionTokens\" in usageRaw\n ? (usageRaw.completionTokens as number)\n : ((usageRaw as { outputTokens?: number }).outputTokens ?? 0);\n const totalTokens =\n \"totalTokens\" in usageRaw\n ? (usageRaw.totalTokens as number)\n : inputTokens + outputTokens;\n\n const usage: Usage = {\n inputTokens,\n outputTokens,\n totalTokens,\n };\n\n // Record successful LLM call in telemetry\n if (llmSpan && telemetry) {\n const latencyMs = Date.now() - startTime;\n telemetry.recordEvent(llmSpan, {\n type: \"llm_call\",\n model: typeof request.model === \"object\" && request.model !== null\n ? (request.model as { modelId?: string }).modelId ?? \"unknown\"\n : String(request.model),\n provider: preferredProvider ?? \"unknown\",\n input: {\n messages: request.messages ?? [{ role: \"user\", content: typeof request.user === \"string\" ? request.user : \"\" }],\n temperature: undefined,\n maxTokens: undefined,\n schema: request.schema,\n },\n output: {\n content: JSON.stringify(result.output),\n structured: true,\n usage: {\n input: inputTokens,\n output: outputTokens,\n total: totalTokens,\n },\n },\n latencyMs,\n });\n telemetry.endSpan(llmSpan, {\n status: \"ok\",\n output: result.output,\n latencyMs,\n });\n }\n\n return { data: result.output as T, usage };\n};\n","import {\n createAjv,\n validateOrThrow,\n SchemaValidationError,\n validateAllowingMissingRequired,\n} from \"../validation/validator\";\nimport type { ModelMessage } from \"ai\";\nimport type { ExtractionEvents, Usage, TelemetryAdapter } from \"../types\";\nimport type { DebugLogger } from \"../debug/logger\";\nimport { generateStructured } from \"./LLMClient\";\nimport type { UserContent } from \"./message\";\n\nexport type RetryOptions<T> = {\n model: unknown;\n schema: unknown;\n system: string;\n user: UserContent;\n events?: ExtractionEvents;\n maxAttempts?: number;\n schemaName?: string;\n execute?: typeof generateStructured<T>;\n strict?: boolean;\n debug?: DebugLogger;\n callId?: string;\n /**\n * Telemetry adapter for tracing validation and retries\n */\n telemetry?: TelemetryAdapter;\n /**\n * Parent span for creating hierarchical traces\n */\n parentSpan?: { id: string; traceId: string; name: string; kind: string; startTime: number; parentId?: string };\n};\n\nexport const runWithRetries = async <T>(options: RetryOptions<T>) => {\n const { telemetry, parentSpan } = options;\n \n // Start validation/retry span if telemetry is enabled\n const retrySpan = telemetry?.startSpan({\n name: \"struktur.validation_retry\",\n kind: \"CHAIN\",\n parentSpan,\n attributes: {\n \"retry.max_attempts\": options.maxAttempts ?? 3,\n \"retry.schema_name\": options.schemaName ?? \"extract\",\n },\n });\n\n const ajv = createAjv();\n const maxAttempts = options.maxAttempts ?? 3;\n const messages: ModelMessage[] = [{ role: \"user\", content: options.user }];\n const debug = options.debug;\n const callId =\n options.callId ??\n `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n\n let usage: Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n let lastError: Error | undefined;\n\n // Log LLM call start\n const systemLength = options.system.length;\n const userLength =\n typeof options.user === \"string\"\n ? options.user.length\n : JSON.stringify(options.user).length;\n\n debug?.llmCallStart({\n callId,\n model: JSON.stringify(options.model),\n schemaName: options.schemaName,\n systemLength,\n userLength,\n artifactCount: Array.isArray(options.user) ? options.user.length : 0,\n });\n\n debug?.promptSystem({ callId, system: options.system });\n debug?.promptUser({ callId, user: options.user });\n\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n const executor = options.execute ?? generateStructured;\n const isFinalAttempt = attempt === maxAttempts;\n const useStrictValidation = options.strict === true || isFinalAttempt;\n\n debug?.validationStart({\n callId,\n attempt,\n maxAttempts,\n strict: useStrictValidation,\n });\n\n const startTime = Date.now();\n const result = await executor({\n model: options.model,\n schema: options.schema,\n schemaName: options.schemaName,\n system: options.system,\n user: options.user,\n messages,\n strict: options.strict,\n telemetry,\n parentSpan: retrySpan,\n });\n const durationMs = Date.now() - startTime;\n\n usage = {\n inputTokens: usage.inputTokens + result.usage.inputTokens,\n outputTokens: usage.outputTokens + result.usage.outputTokens,\n totalTokens: usage.totalTokens + result.usage.totalTokens,\n };\n\n debug?.rawResponse({ callId, response: result.data });\n\n try {\n if (useStrictValidation) {\n const validated = validateOrThrow<T>(\n ajv,\n options.schema as never,\n result.data,\n );\n\n debug?.validationSuccess({ callId, attempt });\n debug?.llmCallComplete({\n callId,\n success: true,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n durationMs,\n });\n\n // Record successful validation\n if (retrySpan && telemetry) {\n telemetry.recordEvent(retrySpan, {\n type: \"validation\",\n attempt,\n maxAttempts,\n schema: options.schema,\n input: result.data,\n success: true,\n latencyMs: durationMs,\n });\n telemetry.endSpan(retrySpan, {\n status: \"ok\",\n output: validated,\n latencyMs: durationMs,\n });\n }\n\n return { data: validated, usage };\n } else {\n const validationResult = validateAllowingMissingRequired<T>(\n ajv,\n options.schema as never,\n result.data,\n isFinalAttempt,\n );\n\n if (validationResult.valid) {\n debug?.validationSuccess({ callId, attempt });\n debug?.llmCallComplete({\n callId,\n success: true,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n durationMs,\n });\n\n // Record successful validation\n if (retrySpan && telemetry) {\n telemetry.recordEvent(retrySpan, {\n type: \"validation\",\n attempt,\n maxAttempts,\n schema: options.schema,\n input: result.data,\n success: true,\n latencyMs: durationMs,\n });\n telemetry.endSpan(retrySpan, {\n status: \"ok\",\n output: validationResult.data,\n latencyMs: durationMs,\n });\n }\n\n return { data: validationResult.data, usage };\n }\n\n throw new SchemaValidationError(\n \"Schema validation failed\",\n validationResult.errors,\n );\n }\n } catch (error) {\n lastError = error as Error;\n\n if (error instanceof SchemaValidationError) {\n debug?.validationFailed({\n callId,\n attempt,\n errors: error.errors,\n });\n\n // Record failed validation\n if (retrySpan && telemetry) {\n telemetry.recordEvent(retrySpan, {\n type: \"validation\",\n attempt,\n maxAttempts,\n schema: options.schema,\n input: result.data,\n success: false,\n errors: error.errors,\n latencyMs: durationMs,\n });\n }\n\n // Emit retry event before attempting retry\n const nextAttempt = attempt + 1;\n if (nextAttempt <= maxAttempts) {\n await options.events?.onRetry?.({\n attempt: nextAttempt,\n maxAttempts,\n reason: \"schema_validation_failed\",\n });\n\n debug?.retry({\n callId,\n attempt: nextAttempt,\n maxAttempts,\n reason: \"schema_validation_failed\",\n });\n }\n\n const errorPayload = JSON.stringify(error.errors, null, 2);\n const errorMessage = `<validation-errors>\\n${errorPayload}\\n</validation-errors>`;\n messages.push({ role: \"user\", content: errorMessage });\n await options.events?.onMessage?.({\n role: \"user\",\n content: errorMessage,\n });\n continue;\n }\n\n debug?.llmCallComplete({\n callId,\n success: false,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n durationMs,\n error: (error as Error).message,\n });\n\n // Record error in telemetry\n if (retrySpan && telemetry) {\n telemetry.endSpan(retrySpan, {\n status: \"error\",\n error: error as Error,\n latencyMs: durationMs,\n });\n }\n\n break;\n }\n }\n\n throw lastError ?? new Error(\"Unknown extraction error\");\n};\n","import type { Artifact, ExtractionEvents, Usage, TelemetryAdapter } from \"../types\";\nimport type { DebugLogger } from \"../debug/logger\";\nimport { batchArtifacts, type BatchOptions } from \"../chunking/ArtifactBatcher\";\nimport { buildUserContent } from \"../llm/message\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport const serializeSchema = (schema: unknown) => {\n return JSON.stringify(schema);\n};\n\nexport const mergeUsage = (usages: Usage[]) => {\n return usages.reduce(\n (acc, usage) => ({\n inputTokens: acc.inputTokens + usage.inputTokens,\n outputTokens: acc.outputTokens + usage.outputTokens,\n totalTokens: acc.totalTokens + usage.totalTokens,\n }),\n { inputTokens: 0, outputTokens: 0, totalTokens: 0 }\n );\n};\n\nexport const getBatches = (\n artifacts: Artifact[],\n options: BatchOptions,\n debug?: DebugLogger,\n telemetry?: TelemetryAdapter,\n parentSpan?: { id: string; traceId: string; name: string; kind: string; startTime: number; parentId?: string }\n) => {\n // Create chunking span if telemetry is enabled\n const chunkingSpan = telemetry?.startSpan({\n name: \"struktur.chunking\",\n kind: \"RETRIEVER\",\n parentSpan,\n attributes: {\n \"chunking.artifact_count\": artifacts.length,\n \"chunking.max_tokens\": options.maxTokens,\n \"chunking.max_images\": options.maxImages,\n },\n });\n \n const batches = batchArtifacts(artifacts, { ...options, debug });\n \n // Record chunking results\n if (chunkingSpan && telemetry) {\n batches.forEach((batch, index) => {\n telemetry.recordEvent(chunkingSpan, {\n type: \"chunk\",\n chunkIndex: index,\n totalChunks: batches.length,\n tokens: batch.reduce((sum, a) => sum + (a.tokens || 0), 0),\n images: batch.reduce((sum, a) => \n sum + (a.contents?.flatMap((c) => c.media || []).length || 0), 0),\n });\n });\n \n telemetry.endSpan(chunkingSpan, {\n status: \"ok\",\n output: { batchCount: batches.length },\n });\n }\n \n return batches;\n};\n\nexport const extractWithPrompt = async <T>(options: {\n model: unknown;\n schema: unknown;\n system: string;\n user: string;\n artifacts: Artifact[];\n events?: ExtractionEvents;\n execute?: typeof runWithRetries<T>;\n strict?: boolean;\n debug?: DebugLogger;\n callId?: string;\n telemetry?: TelemetryAdapter;\n parentSpan?: { id: string; traceId: string; name: string; kind: string; startTime: number; parentId?: string };\n}) => {\n const userContent = buildUserContent(options.user, options.artifacts);\n const result = await runWithRetries<T>({\n model: options.model,\n schema: options.schema,\n system: options.system,\n user: userContent,\n events: options.events,\n execute: options.execute,\n strict: options.strict,\n debug: options.debug,\n callId: options.callId,\n telemetry: options.telemetry,\n parentSpan: options.parentSpan,\n });\n\n return result;\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { extractWithPrompt, serializeSchema } from \"./utils\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type SimpleStrategyConfig = {\n model: unknown;\n outputInstructions?: string;\n execute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nexport class SimpleStrategy<T> implements ExtractionStrategy<T> {\n public name = \"simple\";\n private config: SimpleStrategyConfig;\n\n constructor(config: SimpleStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(): number {\n return 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const telemetry = options.telemetry ?? undefined;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.simple\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n },\n });\n \n const schema = serializeSchema(options.schema);\n const { system, user } = buildExtractorPrompt(\n options.artifacts,\n schema,\n this.config.outputInstructions,\n );\n\n // Emit start event before extraction begins\n await options.events?.onStep?.({\n step: 1,\n total: this.getEstimatedSteps(),\n label: \"extract\",\n });\n debug?.step({\n step: 1,\n total: this.getEstimatedSteps(),\n label: \"extract\",\n strategy: this.name,\n });\n\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system,\n user,\n artifacts: options.artifacts,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: \"simple_extract\",\n telemetry,\n parentSpan: strategySpan,\n });\n\n debug?.step({\n step: 2,\n total: this.getEstimatedSteps(),\n label: \"complete\",\n strategy: this.name,\n });\n\n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: result.data,\n });\n\n return { data: result.data, usage: result.usage };\n }\n}\n\nexport const simple = <T>(config: SimpleStrategyConfig) => {\n return new SimpleStrategy<T>(config);\n};\n","export const buildParallelMergerPrompt = (\n schema: string,\n dataList: unknown[]\n) => {\n const jsonObjects = dataList\n .filter((item) => item !== null && item !== undefined)\n .map((item) => JSON.stringify(item))\n .map((json) => `<json-object>${json}</json-object>`)\n .join(\"\\n\");\n\n const system = `You are a data merger. Combine multiple JSON objects into one object matching the provided schema.\n\n<thinking>\nBefore merging, consider:\n1. Which input objects contain data for each schema field?\n2. How should conflicting values be resolved (prefer more complete/recent data)?\n3. Are there arrays that need to be concatenated vs deduplicated?\n4. Ensure NO information is lost from any input\n</thinking>\n\n<rules>\n- Produce a single JSON object following the schema exactly\n- Combine all information from input objects without losing data\n- Resolve conflicts intelligently (prefer richer/more specific data)\n- Output ONLY valid JSON - no markdown, no explanations\n</rules>`;\n\n const user = `<json-schema>\n${schema}\n</json-schema>\n\n<json-objects>\n${jsonObjects}\n</json-objects>`;\n\n return { system, user };\n};\n","export const runConcurrently = async <T>(\n tasks: Array<() => Promise<T>>,\n concurrency: number\n): Promise<T[]> => {\n const results: T[] = [];\n\n for (let i = 0; i < tasks.length; i += concurrency) {\n const chunk = tasks.slice(i, i + concurrency).map((task) => task());\n const chunkResults = await Promise.all(chunk);\n results.push(...chunkResults);\n }\n\n return results;\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { buildParallelMergerPrompt } from \"../prompts/ParallelMergerPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { runConcurrently } from \"./concurrency\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type ParallelStrategyConfig = {\n model: unknown;\n mergeModel: unknown;\n chunkSize: number;\n concurrency?: number;\n maxImages?: number;\n outputInstructions?: string;\n execute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nexport class ParallelStrategy<T> implements ExtractionStrategy<T> {\n public name = \"parallel\";\n private config: ParallelStrategyConfig;\n\n constructor(config: ParallelStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length + 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.parallel\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n \"strategy.concurrency\": this.config.concurrency,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n\n // Emit start event\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: batches.length > 1 ? `batch 1/${batches.length}` : \"extract\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: batches.length > 1 ? `batch 1/${batches.length}` : \"extract\",\n strategy: this.name,\n });\n\n const tasks = batches.map((batch, index) => async () => {\n const prompt = buildExtractorPrompt(\n batch,\n schema,\n this.config.outputInstructions,\n );\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `parallel_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: strategySpan,\n });\n // Emit progress after batch completes (if there are more batches)\n const completedIndex = index + 1;\n if (completedIndex < batches.length) {\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `batch ${completedIndex + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `batch ${completedIndex + 1}/${batches.length}`,\n strategy: this.name,\n });\n }\n return result;\n });\n\n const results = await runConcurrently(\n tasks,\n this.config.concurrency ?? batches.length,\n );\n\n debug?.mergeStart({\n mergeId: \"parallel_merge\",\n inputCount: results.length,\n strategy: this.name,\n });\n \n // Create merge span\n const mergeSpan = telemetry?.startSpan({\n name: \"struktur.merge\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"merge.strategy\": \"parallel\",\n \"merge.input_count\": results.length,\n },\n });\n\n const mergePrompt = buildParallelMergerPrompt(\n schema,\n results.map((r) => r.data),\n );\n const merged = await extractWithPrompt<T>({\n model: this.config.mergeModel,\n schema: options.schema,\n system: mergePrompt.system,\n user: mergePrompt.user,\n artifacts: [],\n events: options.events,\n execute: this.config.execute as never,\n strict: this.config.strict,\n debug,\n callId: \"parallel_merge\",\n telemetry: telemetry ?? undefined,\n parentSpan: mergeSpan,\n });\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: \"merge\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: \"merge\",\n strategy: this.name,\n });\n debug?.mergeComplete({ mergeId: \"parallel_merge\", success: true });\n \n // End merge span\n if (mergeSpan && telemetry) {\n telemetry.recordEvent(mergeSpan, {\n type: \"merge\",\n strategy: \"parallel\",\n inputCount: results.length,\n outputCount: 1,\n });\n telemetry.endSpan(mergeSpan, {\n status: \"ok\",\n output: merged.data,\n });\n }\n \n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: merged.data,\n });\n\n return {\n data: merged.data,\n usage: mergeUsage([...results.map((r) => r.usage), merged.usage]),\n };\n }\n}\n\nexport const parallel = <T>(config: ParallelStrategyConfig) => {\n return new ParallelStrategy<T>(config);\n};\n","import { formatArtifactsXml } from \"./formatArtifacts\";\nimport type { Artifact } from \"../types\";\n\nconst sequentialSystemPrompt = (schema: string, outputInstructions?: string) => {\n return `<instructions>\nYou are a precise data extraction engine. Extract data from provided artifacts according to the JSON schema, enriching any previous data you receive.\n\n<thinking>\nBefore extracting, consider:\n1. Review previous data - what needs to be preserved vs enriched?\n2. Which new fields have clear values in the artifacts?\n3. Which fields remain missing or unclear (keep null from previous or set to null)?\n4. Can new information improve the structure of existing data?\n5. Ensure NO information is lost from previous data\n</thinking>\n\n<rules>\n- Merge new artifacts into existing data - do not create fresh objects\n- Preserve ALL previous data - losing information breaks the processing chain\n- Use null for missing/uncertain values in new fields\n- Only extract information explicitly present in the artifacts\n- Output ONLY valid JSON matching the schema\n- No markdown, explanations, or code fences\n</rules>\n\n<image-handling>\nSome schema properties may reference artifact IDs (e.g., 'xxx_artifact_id' fields).\nWhen assigning images to properties:\n- Use format: artifact:ID/images/imageNUM.EXT (e.g., 'artifact:123456/images/image1.jpg')\n- Only reference images you can actually see in the provided documents/images\n- Image references are visible in artifact XML or written on images\n- NEVER make up artifact IDs or use normal URLs\n</image-handling>\n\n<output-instructions>\n${outputInstructions ?? \"No additional output instructions provided.\"}\n</output-instructions>\n\n<json-schema>\n${schema}\n</json-schema>\n\n<how-to-output>\nReturn the complete extracted data as valid JSON matching the schema.\nInclude all information from previous data, enriched with the new artifacts.\n</how-to-output>\n</instructions>`;\n};\n\nconst sequentialUserPrompt = (\n artifactsXml: string,\n previousData: string,\n outputInstructions?: string\n) => {\n return `${artifactsXml}\n\n<previous-data>\n${previousData}\n</previous-data>\n\n<task>\n Extract the contents of the given artifacts and ADD/MERGE them into the previous data contained in the <previous-data> tag.\n You MUST NOT lose any information from the previous data. All previous data must be included in your response.\n</task>\n\n<output-instructions>\n${outputInstructions ?? \"\"}\n</output-instructions>`;\n};\n\nexport const buildSequentialPrompt = (\n artifacts: Artifact[],\n schema: string,\n previousData: string,\n outputInstructions?: string\n) => {\n const artifactsXml = formatArtifactsXml(artifacts);\n return {\n system: sequentialSystemPrompt(schema, outputInstructions),\n user: sequentialUserPrompt(artifactsXml, previousData, outputInstructions),\n };\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildSequentialPrompt } from \"../prompts/SequentialExtractorPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type SequentialStrategyConfig = {\n model: unknown;\n chunkSize: number;\n maxImages?: number;\n outputInstructions?: string;\n execute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nexport class SequentialStrategy<T> implements ExtractionStrategy<T> {\n public name = \"sequential\";\n private config: SequentialStrategyConfig;\n\n constructor(config: SequentialStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length + 2;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.sequential\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n let currentData: T | undefined;\n const usages = [];\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n\n // Emit start event\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: batches.length > 1 ? `batch 1/${batches.length}` : \"extract\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: batches.length > 1 ? `batch 1/${batches.length}` : \"extract\",\n strategy: this.name,\n });\n\n for (const [index, batch] of batches.entries()) {\n const previousData = currentData ? JSON.stringify(currentData) : \"{}\";\n const prompt = buildSequentialPrompt(\n batch,\n schema,\n previousData,\n this.config.outputInstructions,\n );\n\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `sequential_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: strategySpan,\n });\n\n currentData = result.data;\n usages.push(result.usage);\n\n step += 1;\n // Only emit progress if there are more batches\n if (index < batches.length - 1) {\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `batch ${index + 2}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `batch ${index + 2}/${batches.length}`,\n strategy: this.name,\n });\n }\n }\n\n if (!currentData) {\n throw new Error(\"No data extracted from sequential strategy\");\n }\n\n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: currentData,\n });\n\n return { data: currentData, usage: mergeUsage(usages) };\n }\n}\n\nexport const sequential = <T>(config: SequentialStrategyConfig) => {\n return new SequentialStrategy<T>(config);\n};\n","export const buildDeduplicationPrompt = (\n schema: string,\n data: unknown,\n exampleKeys: string[] = [\"items.3\", \"items.5\"]\n) => {\n const system = `You are a deduplication engine. Identify duplicate entries in structured data.\n\n<thinking>\nBefore deduplicating, consider:\n1. Which fields indicate uniqueness for each entity type?\n2. Are entries duplicates if they share key fields but differ in minor details?\n3. Which entry should be kept (prefer more complete data)?\n</thinking>\n\n<rules>\n- Identify entries that represent the same entity\n- Return paths to duplicates using dot notation (e.g., \"items.3\", \"items.5\")\n- Output ONLY JSON in format: { \"keys\": [\"path1\", \"path2\"] }\n- No markdown, no explanations\n</rules>`;\n\n const user = `<json-schema>\n${schema}\n</json-schema>\n\n<json-data>\n${JSON.stringify(data)}\n</json-data>\n\n<task>Identify duplicate entries in the data and return their paths in the format: { \"keys\": [\"path1\", \"path2\"] }</task>\n\n<example>\nIf items at indices 3 and 5 are duplicates, return: { \"keys\": [\"items.3\", \"items.5\"] }\n</example>`;\n\n return { system, user };\n};\n","import type { AnyJSONSchema } from \"../types\";\n\nconst isArraySchema = (schema: Record<string, unknown>) => {\n if (schema.type === \"array\") {\n return true;\n }\n return false;\n};\n\nconst isObjectSchema = (schema: Record<string, unknown>) => {\n return schema.type === \"object\" && typeof schema.properties === \"object\";\n};\n\nexport class SmartDataMerger {\n private schema: AnyJSONSchema;\n\n constructor(schema: AnyJSONSchema) {\n this.schema = schema;\n }\n\n merge(currentData: Record<string, unknown>, newData: Record<string, unknown>) {\n const merged: Record<string, unknown> = { ...currentData };\n const properties =\n (this.schema as { properties?: Record<string, Record<string, unknown>> })\n .properties ?? {};\n\n for (const [key, propSchema] of Object.entries(properties)) {\n const currentValue = currentData[key];\n const newValue = newData[key];\n\n if (isArraySchema(propSchema)) {\n merged[key] = [\n ...(Array.isArray(currentValue) ? currentValue : []),\n ...(Array.isArray(newValue) ? newValue : []),\n ];\n continue;\n }\n\n if (isObjectSchema(propSchema)) {\n merged[key] = {\n ...(typeof currentValue === \"object\" && currentValue ? currentValue : {}),\n ...(typeof newValue === \"object\" && newValue ? newValue : {}),\n };\n continue;\n }\n\n if (newValue !== undefined && newValue !== null && newValue !== \"\") {\n merged[key] = newValue;\n } else if (currentValue !== undefined) {\n merged[key] = currentValue;\n }\n }\n\n return merged;\n }\n}\n","export const fnv1a32 = (str: string): number => {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n};\n\nconst stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return `[${value.map((item) => stableStringify(item)).join(\",\")}]`;\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, val]) => `\"${key}\":${stableStringify(val)}`);\n\n return `{${entries.join(\",\")}}`;\n};\n\nexport const findExactDuplicatesWithHashing = (items: unknown[]) => {\n const seen = new Map<number, number>();\n const duplicates: number[] = [];\n\n items.forEach((item, index) => {\n const hash = fnv1a32(stableStringify(item));\n if (seen.has(hash)) {\n duplicates.push(index);\n return;\n }\n seen.set(hash, index);\n });\n\n return duplicates;\n};\n\nexport const deduplicateByIndices = <T>(items: T[], indices: number[]) => {\n const remove = new Set(indices);\n return items.filter((_, index) => !remove.has(index));\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { buildDeduplicationPrompt } from \"../prompts/DeduplicationPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { runConcurrently } from \"./concurrency\";\nimport { SmartDataMerger } from \"../merge/SmartDataMerger\";\nimport {\n findExactDuplicatesWithHashing,\n deduplicateByIndices,\n} from \"../merge/Deduplicator\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type ParallelAutoMergeStrategyConfig = {\n model: unknown;\n chunkSize: number;\n concurrency?: number;\n maxImages?: number;\n outputInstructions?: string;\n dedupeModel?: unknown;\n execute?: typeof runWithRetries;\n dedupeExecute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nconst dedupeSchema = {\n type: \"object\",\n properties: {\n keys: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"keys\"],\n additionalProperties: false,\n} as const;\n\nconst dedupeArrays = (data: Record<string, unknown>) => {\n const result: Record<string, unknown> = { ...data };\n for (const [key, value] of Object.entries(result)) {\n if (Array.isArray(value)) {\n const duplicates = findExactDuplicatesWithHashing(value);\n result[key] = deduplicateByIndices(value, duplicates);\n }\n }\n return result;\n};\n\nconst removeByPath = (data: Record<string, unknown>, path: string) => {\n const [root, indexStr] = path.split(\".\");\n const index = Number(indexStr);\n if (!root || Number.isNaN(index)) {\n return data;\n }\n\n const value = data[root];\n if (!Array.isArray(value)) {\n return data;\n }\n\n const next = [...value];\n next.splice(index, 1);\n return { ...data, [root]: next };\n};\n\nexport class ParallelAutoMergeStrategy<T> implements ExtractionStrategy<T> {\n public name = \"parallel-auto-merge\";\n private config: ParallelAutoMergeStrategyConfig;\n\n constructor(config: ParallelAutoMergeStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length + 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.parallel-auto-merge\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n \"strategy.concurrency\": this.config.concurrency,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n\n const tasks = batches.map((batch, index) => async () => {\n const prompt = buildExtractorPrompt(\n batch,\n schema,\n this.config.outputInstructions,\n );\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `parallel_auto_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: strategySpan,\n });\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n return result;\n });\n\n const results = await runConcurrently(\n tasks,\n this.config.concurrency ?? batches.length,\n );\n\n const merger = new SmartDataMerger(\n options.schema as Record<string, unknown>,\n );\n let merged = {} as Record<string, unknown>;\n\n debug?.mergeStart({\n mergeId: \"parallel_auto_smart_merge\",\n inputCount: results.length,\n strategy: this.name,\n });\n \n // Create smart merge span\n const mergeSpan = telemetry?.startSpan({\n name: \"struktur.smart_merge\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"merge.strategy\": \"smart\",\n \"merge.input_count\": results.length,\n },\n });\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i]!;\n const prevSize = Object.keys(merged).length;\n merged = merger.merge(merged, result.data as Record<string, unknown>);\n const newSize = Object.keys(merged).length;\n\n // Log merge operation per field\n for (const key of Object.keys(result.data as Record<string, unknown>)) {\n const leftArray = Array.isArray(merged[key])\n ? (merged[key] as unknown[]).length\n : undefined;\n const rightArray = Array.isArray(\n (result.data as Record<string, unknown>)[key],\n )\n ? ((result.data as Record<string, unknown>)[key] as unknown[]).length\n : undefined;\n\n debug?.smartMergeField({\n mergeId: \"parallel_auto_smart_merge\",\n field: key,\n operation: \"merge_arrays\",\n leftCount: leftArray,\n rightCount: rightArray,\n });\n \n // Record merge event in telemetry\n if (mergeSpan && telemetry) {\n telemetry.recordEvent(mergeSpan, {\n type: \"merge\",\n strategy: \"smart\",\n inputCount: rightArray ?? 1,\n outputCount: leftArray ?? 1,\n });\n }\n }\n }\n\n debug?.mergeComplete({\n mergeId: \"parallel_auto_smart_merge\",\n success: true,\n });\n \n // End merge span\n if (mergeSpan && telemetry) {\n telemetry.endSpan(mergeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n merged = dedupeArrays(merged);\n \n // Create exact dedupe span\n const exactDedupeSpan = telemetry?.startSpan({\n name: \"struktur.exact_dedupe\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"dedupe.method\": \"exact_hashing\",\n },\n });\n \n // End exact dedupe span\n if (exactDedupeSpan && telemetry) {\n telemetry.recordEvent(exactDedupeSpan, {\n type: \"merge\",\n strategy: \"exact_hash_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(merged).length,\n });\n telemetry.endSpan(exactDedupeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n const dedupePrompt = buildDeduplicationPrompt(schema, merged);\n\n debug?.dedupeStart({\n dedupeId: \"parallel_auto_dedupe\",\n itemCount: Object.keys(merged).length,\n });\n \n // Create LLM dedupe span\n const llmDedupeSpan = telemetry?.startSpan({\n name: \"struktur.llm_dedupe\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"dedupe.method\": \"llm\",\n },\n });\n\n const dedupeResponse = await runWithRetries<{ keys: string[] }>({\n model: this.config.dedupeModel ?? this.config.model,\n schema: dedupeSchema,\n system: dedupePrompt.system,\n user: dedupePrompt.user,\n events: options.events,\n execute: this.config.dedupeExecute,\n strict: this.config.strict,\n debug,\n callId: \"parallel_auto_dedupe\",\n telemetry: telemetry ?? undefined,\n parentSpan: llmDedupeSpan,\n });\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: \"dedupe\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: \"dedupe\",\n strategy: this.name,\n });\n\n let deduped = merged;\n for (const key of dedupeResponse.data.keys) {\n deduped = removeByPath(deduped, key);\n }\n\n debug?.dedupeComplete({\n dedupeId: \"parallel_auto_dedupe\",\n duplicatesFound: dedupeResponse.data.keys.length,\n itemsRemoved: dedupeResponse.data.keys.length,\n });\n \n // End LLM dedupe span\n if (llmDedupeSpan && telemetry) {\n telemetry.recordEvent(llmDedupeSpan, {\n type: \"merge\",\n strategy: \"llm_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(deduped).length,\n deduped: dedupeResponse.data.keys.length,\n });\n telemetry.endSpan(llmDedupeSpan, {\n status: \"ok\",\n output: deduped,\n });\n }\n\n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: deduped,\n });\n\n return {\n data: deduped as T,\n usage: mergeUsage([...results.map((r) => r.usage), dedupeResponse.usage]),\n };\n }\n}\n\nexport const parallelAutoMerge = <T>(\n config: ParallelAutoMergeStrategyConfig,\n) => {\n return new ParallelAutoMergeStrategy<T>(config);\n};\n\nexport const __testing__ = {\n dedupeArrays,\n removeByPath,\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { buildDeduplicationPrompt } from \"../prompts/DeduplicationPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { SmartDataMerger } from \"../merge/SmartDataMerger\";\nimport {\n findExactDuplicatesWithHashing,\n deduplicateByIndices,\n} from \"../merge/Deduplicator\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type SequentialAutoMergeStrategyConfig = {\n model: unknown;\n chunkSize: number;\n maxImages?: number;\n outputInstructions?: string;\n dedupeModel?: unknown;\n execute?: typeof runWithRetries;\n dedupeExecute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nconst dedupeSchema = {\n type: \"object\",\n properties: {\n keys: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"keys\"],\n additionalProperties: false,\n} as const;\n\nconst dedupeArrays = (data: Record<string, unknown>) => {\n const result: Record<string, unknown> = { ...data };\n for (const [key, value] of Object.entries(result)) {\n if (Array.isArray(value)) {\n const duplicates = findExactDuplicatesWithHashing(value);\n result[key] = deduplicateByIndices(value, duplicates);\n }\n }\n return result;\n};\n\nconst removeByPath = (data: Record<string, unknown>, path: string) => {\n const [root, indexStr] = path.split(\".\");\n const index = Number(indexStr);\n if (!root || Number.isNaN(index)) {\n return data;\n }\n\n const value = data[root];\n if (!Array.isArray(value)) {\n return data;\n }\n\n const next = [...value];\n next.splice(index, 1);\n return { ...data, [root]: next };\n};\n\nexport class SequentialAutoMergeStrategy<T> implements ExtractionStrategy<T> {\n public name = \"sequential-auto-merge\";\n private config: SequentialAutoMergeStrategyConfig;\n\n constructor(config: SequentialAutoMergeStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length + 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.sequential-auto-merge\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n const merger = new SmartDataMerger(\n options.schema as Record<string, unknown>,\n );\n let merged = {} as Record<string, unknown>;\n const usages = [];\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n\n debug?.mergeStart({\n mergeId: \"sequential_auto_merge\",\n inputCount: batches.length,\n strategy: this.name,\n });\n \n // Create smart merge span\n const mergeSpan = telemetry?.startSpan({\n name: \"struktur.smart_merge\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"merge.strategy\": \"smart\",\n \"merge.input_count\": batches.length,\n },\n });\n\n for (const [index, batch] of batches.entries()) {\n const prompt = buildExtractorPrompt(\n batch,\n schema,\n this.config.outputInstructions,\n );\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `sequential_auto_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: mergeSpan,\n });\n\n merged = merger.merge(merged, result.data as Record<string, unknown>);\n usages.push(result.usage);\n\n // Log merge operation per field\n for (const key of Object.keys(result.data as Record<string, unknown>)) {\n const leftArray = Array.isArray(merged[key])\n ? (merged[key] as unknown[]).length\n : undefined;\n const rightArray = Array.isArray(\n (result.data as Record<string, unknown>)[key],\n )\n ? ((result.data as Record<string, unknown>)[key] as unknown[]).length\n : undefined;\n\n debug?.smartMergeField({\n mergeId: \"sequential_auto_merge\",\n field: key,\n operation: \"merge_arrays\",\n leftCount: leftArray,\n rightCount: rightArray,\n });\n \n // Record merge event in telemetry\n if (mergeSpan && telemetry) {\n telemetry.recordEvent(mergeSpan, {\n type: \"merge\",\n strategy: \"smart\",\n inputCount: rightArray ?? 1,\n outputCount: leftArray ?? 1,\n });\n }\n }\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n }\n\n debug?.mergeComplete({ mergeId: \"sequential_auto_merge\", success: true });\n \n // End merge span\n if (mergeSpan && telemetry) {\n telemetry.endSpan(mergeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n merged = dedupeArrays(merged);\n \n // Create exact dedupe span\n const exactDedupeSpan = telemetry?.startSpan({\n name: \"struktur.exact_dedupe\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"dedupe.method\": \"exact_hashing\",\n },\n });\n \n // End exact dedupe span\n if (exactDedupeSpan && telemetry) {\n telemetry.recordEvent(exactDedupeSpan, {\n type: \"merge\",\n strategy: \"exact_hash_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(merged).length,\n });\n telemetry.endSpan(exactDedupeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n const dedupePrompt = buildDeduplicationPrompt(schema, merged);\n\n debug?.dedupeStart({\n dedupeId: \"sequential_auto_dedupe\",\n itemCount: Object.keys(merged).length,\n });\n \n // Create LLM dedupe span\n const llmDedupeSpan = telemetry?.startSpan({\n name: \"struktur.llm_dedupe\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"dedupe.method\": \"llm\",\n },\n });\n\n const dedupeResponse = await runWithRetries<{ keys: string[] }>({\n model: this.config.dedupeModel ?? this.config.model,\n schema: dedupeSchema,\n system: dedupePrompt.system,\n user: dedupePrompt.user,\n events: options.events,\n execute: this.config.dedupeExecute,\n strict: this.config.strict,\n debug,\n callId: \"sequential_auto_dedupe\",\n telemetry: telemetry ?? undefined,\n parentSpan: llmDedupeSpan,\n });\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: \"dedupe\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: \"dedupe\",\n strategy: this.name,\n });\n\n let deduped = merged;\n for (const key of dedupeResponse.data.keys) {\n deduped = removeByPath(deduped, key);\n }\n\n debug?.dedupeComplete({\n dedupeId: \"sequential_auto_dedupe\",\n duplicatesFound: dedupeResponse.data.keys.length,\n itemsRemoved: dedupeResponse.data.keys.length,\n });\n \n // End LLM dedupe span\n if (llmDedupeSpan && telemetry) {\n telemetry.recordEvent(llmDedupeSpan, {\n type: \"merge\",\n strategy: \"llm_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(deduped).length,\n deduped: dedupeResponse.data.keys.length,\n });\n telemetry.endSpan(llmDedupeSpan, {\n status: \"ok\",\n output: deduped,\n });\n }\n \n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: deduped,\n });\n\n return {\n data: deduped as T,\n usage: mergeUsage([...usages, dedupeResponse.usage]),\n };\n }\n}\n\nexport const sequentialAutoMerge = <T>(\n config: SequentialAutoMergeStrategyConfig,\n) => {\n return new SequentialAutoMergeStrategy<T>(config);\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { buildParallelMergerPrompt } from \"../prompts/ParallelMergerPrompt\";\nimport { buildSequentialPrompt } from \"../prompts/SequentialExtractorPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { runConcurrently } from \"./concurrency\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type DoublePassStrategyConfig = {\n model: unknown;\n mergeModel: unknown;\n chunkSize: number;\n concurrency?: number;\n maxImages?: number;\n outputInstructions?: string;\n execute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nexport class DoublePassStrategy<T> implements ExtractionStrategy<T> {\n public name = \"double-pass\";\n private config: DoublePassStrategyConfig;\n\n constructor(config: DoublePassStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length * 2 + 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.double-pass\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n \"strategy.concurrency\": this.config.concurrency,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n \n // Create pass 1 span\n const pass1Span = telemetry?.startSpan({\n name: \"struktur.pass_1\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"pass.number\": 1,\n \"pass.type\": \"parallel_extraction\",\n },\n });\n\n const tasks = batches.map((batch, index) => async () => {\n const prompt = buildExtractorPrompt(\n batch,\n schema,\n this.config.outputInstructions,\n );\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `double_pass_1_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: pass1Span,\n });\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `pass 1 batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `pass 1 batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n return result;\n });\n\n const results = await runConcurrently(\n tasks,\n this.config.concurrency ?? batches.length,\n );\n\n debug?.mergeStart({\n mergeId: \"double_pass_1_merge\",\n inputCount: results.length,\n strategy: this.name,\n });\n \n // Create pass 1 merge span\n const pass1MergeSpan = telemetry?.startSpan({\n name: \"struktur.pass_1_merge\",\n kind: \"CHAIN\",\n parentSpan: pass1Span,\n attributes: {\n \"merge.strategy\": \"parallel\",\n \"merge.input_count\": results.length,\n },\n });\n\n const mergePrompt = buildParallelMergerPrompt(\n schema,\n results.map((r) => r.data),\n );\n const merged = await extractWithPrompt<T>({\n model: this.config.mergeModel,\n schema: options.schema,\n system: mergePrompt.system,\n user: mergePrompt.user,\n artifacts: [],\n events: options.events,\n execute: this.config.execute as never,\n strict: this.config.strict,\n debug,\n callId: \"double_pass_1_merge\",\n telemetry: telemetry ?? undefined,\n parentSpan: pass1MergeSpan,\n });\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: \"pass 1 merge\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: \"pass 1 merge\",\n strategy: this.name,\n });\n debug?.mergeComplete({ mergeId: \"double_pass_1_merge\", success: true });\n \n // End pass 1 merge span\n if (pass1MergeSpan && telemetry) {\n telemetry.recordEvent(pass1MergeSpan, {\n type: \"merge\",\n strategy: \"parallel\",\n inputCount: results.length,\n outputCount: 1,\n });\n telemetry.endSpan(pass1MergeSpan, {\n status: \"ok\",\n output: merged.data,\n });\n }\n \n // End pass 1 span\n telemetry?.endSpan(pass1Span!, {\n status: \"ok\",\n output: merged.data,\n });\n \n // Create pass 2 span\n const pass2Span = telemetry?.startSpan({\n name: \"struktur.pass_2\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"pass.number\": 2,\n \"pass.type\": \"sequential_refinement\",\n },\n });\n\n let currentData = merged.data;\n const usages = [...results.map((r) => r.usage), merged.usage];\n\n for (const [index, batch] of batches.entries()) {\n const prompt = buildSequentialPrompt(\n batch,\n schema,\n JSON.stringify(currentData),\n this.config.outputInstructions,\n );\n\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: this.config.strict,\n debug,\n callId: `double_pass_2_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: pass2Span,\n });\n\n currentData = result.data;\n usages.push(result.usage);\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `pass 2 batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `pass 2 batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n }\n \n // End pass 2 span\n telemetry?.endSpan(pass2Span!, {\n status: \"ok\",\n output: currentData,\n });\n \n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: currentData,\n });\n\n return { data: currentData, usage: mergeUsage(usages) };\n }\n}\n\nexport const doublePass = <T>(config: DoublePassStrategyConfig) => {\n return new DoublePassStrategy<T>(config);\n};\n","import type { ExtractionResult, ExtractionStrategy } from \"../types\";\nimport type { ExtractionOptions } from \"../types\";\nimport { buildExtractorPrompt } from \"../prompts/ExtractorPrompt\";\nimport { buildDeduplicationPrompt } from \"../prompts/DeduplicationPrompt\";\nimport { buildSequentialPrompt } from \"../prompts/SequentialExtractorPrompt\";\nimport {\n extractWithPrompt,\n getBatches,\n mergeUsage,\n serializeSchema,\n} from \"./utils\";\nimport { SmartDataMerger } from \"../merge/SmartDataMerger\";\nimport {\n findExactDuplicatesWithHashing,\n deduplicateByIndices,\n} from \"../merge/Deduplicator\";\nimport { runConcurrently } from \"./concurrency\";\nimport { runWithRetries } from \"../llm/RetryingRunner\";\n\nexport type DoublePassAutoMergeStrategyConfig = {\n model: unknown;\n chunkSize: number;\n concurrency?: number;\n maxImages?: number;\n outputInstructions?: string;\n dedupeModel?: unknown;\n execute?: typeof runWithRetries;\n dedupeExecute?: typeof runWithRetries;\n strict?: boolean;\n};\n\nconst dedupeSchema = {\n type: \"object\",\n properties: {\n keys: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"keys\"],\n additionalProperties: false,\n} as const;\n\nconst dedupeArrays = (data: Record<string, unknown>) => {\n const result: Record<string, unknown> = { ...data };\n for (const [key, value] of Object.entries(result)) {\n if (Array.isArray(value)) {\n const duplicates = findExactDuplicatesWithHashing(value);\n result[key] = deduplicateByIndices(value, duplicates);\n }\n }\n return result;\n};\n\nconst removeByPath = (data: Record<string, unknown>, path: string) => {\n const [root, indexStr] = path.split(\".\");\n const index = Number(indexStr);\n if (!root || Number.isNaN(index)) {\n return data;\n }\n\n const value = data[root];\n if (!Array.isArray(value)) {\n return data;\n }\n\n const next = [...value];\n next.splice(index, 1);\n return { ...data, [root]: next };\n};\n\nexport class DoublePassAutoMergeStrategy<T> implements ExtractionStrategy<T> {\n public name = \"double-pass-auto-merge\";\n private config: DoublePassAutoMergeStrategyConfig;\n\n constructor(config: DoublePassAutoMergeStrategyConfig) {\n this.config = config;\n }\n\n getEstimatedSteps(artifacts: ExtractionOptions<T>[\"artifacts\"]): number {\n const batches = getBatches(artifacts, {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n });\n return batches.length * 2 + 3;\n }\n\n async run(options: ExtractionOptions<T>): Promise<ExtractionResult<T>> {\n const debug = options.debug;\n const { telemetry } = options;\n \n // Create strategy-level span\n const strategySpan = telemetry?.startSpan({\n name: \"strategy.double-pass-auto-merge\",\n kind: \"CHAIN\",\n attributes: {\n \"strategy.name\": this.name,\n \"strategy.artifacts.count\": options.artifacts.length,\n \"strategy.chunk_size\": this.config.chunkSize,\n \"strategy.concurrency\": this.config.concurrency,\n },\n });\n \n const batches = getBatches(\n options.artifacts,\n {\n maxTokens: this.config.chunkSize,\n maxImages: this.config.maxImages,\n },\n debug,\n telemetry ?? undefined,\n strategySpan,\n );\n\n const schema = serializeSchema(options.schema);\n const totalSteps = this.getEstimatedSteps(options.artifacts);\n let step = 1;\n \n // Create pass 1 span\n const pass1Span = telemetry?.startSpan({\n name: \"struktur.pass_1\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"pass.number\": 1,\n \"pass.type\": \"parallel_extraction\",\n },\n });\n\n const tasks = batches.map((batch, index) => async () => {\n const prompt = buildExtractorPrompt(\n batch,\n schema,\n this.config.outputInstructions,\n );\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: options.strict ?? this.config.strict,\n debug,\n callId: `double_pass_auto_1_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: pass1Span,\n });\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `pass 1 batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `pass 1 batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n return result;\n });\n\n const results = await runConcurrently(\n tasks,\n this.config.concurrency ?? batches.length,\n );\n\n const merger = new SmartDataMerger(\n options.schema as Record<string, unknown>,\n );\n let merged = {} as Record<string, unknown>;\n\n debug?.mergeStart({\n mergeId: \"double_pass_auto_merge\",\n inputCount: results.length,\n strategy: this.name,\n });\n \n // Create smart merge span\n const mergeSpan = telemetry?.startSpan({\n name: \"struktur.smart_merge\",\n kind: \"CHAIN\",\n parentSpan: pass1Span,\n attributes: {\n \"merge.strategy\": \"smart\",\n \"merge.input_count\": results.length,\n },\n });\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i]!;\n merged = merger.merge(merged, result.data as Record<string, unknown>);\n\n // Log merge operation per field\n for (const key of Object.keys(result.data as Record<string, unknown>)) {\n const leftArray = Array.isArray(merged[key])\n ? (merged[key] as unknown[]).length\n : undefined;\n const rightArray = Array.isArray(\n (result.data as Record<string, unknown>)[key],\n )\n ? ((result.data as Record<string, unknown>)[key] as unknown[]).length\n : undefined;\n\n debug?.smartMergeField({\n mergeId: \"double_pass_auto_merge\",\n field: key,\n operation: \"merge_arrays\",\n leftCount: leftArray,\n rightCount: rightArray,\n });\n \n // Record merge event in telemetry\n if (mergeSpan && telemetry) {\n telemetry.recordEvent(mergeSpan, {\n type: \"merge\",\n strategy: \"smart\",\n inputCount: rightArray ?? 1,\n outputCount: leftArray ?? 1,\n });\n }\n }\n }\n\n debug?.mergeComplete({ mergeId: \"double_pass_auto_merge\", success: true });\n \n // End merge span\n if (mergeSpan && telemetry) {\n telemetry.endSpan(mergeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n merged = dedupeArrays(merged);\n \n // Create exact dedupe span\n const exactDedupeSpan = telemetry?.startSpan({\n name: \"struktur.exact_dedupe\",\n kind: \"CHAIN\",\n parentSpan: pass1Span,\n attributes: {\n \"dedupe.method\": \"exact_hashing\",\n },\n });\n \n // End exact dedupe span\n if (exactDedupeSpan && telemetry) {\n telemetry.recordEvent(exactDedupeSpan, {\n type: \"merge\",\n strategy: \"exact_hash_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(merged).length,\n });\n telemetry.endSpan(exactDedupeSpan, {\n status: \"ok\",\n output: merged,\n });\n }\n\n const dedupePrompt = buildDeduplicationPrompt(schema, merged);\n\n debug?.dedupeStart({\n dedupeId: \"double_pass_auto_dedupe\",\n itemCount: Object.keys(merged).length,\n });\n \n // Create LLM dedupe span\n const llmDedupeSpan = telemetry?.startSpan({\n name: \"struktur.llm_dedupe\",\n kind: \"CHAIN\",\n parentSpan: pass1Span,\n attributes: {\n \"dedupe.method\": \"llm\",\n },\n });\n\n const dedupeResponse = await runWithRetries<{ keys: string[] }>({\n model: this.config.dedupeModel ?? this.config.model,\n schema: dedupeSchema,\n system: dedupePrompt.system,\n user: dedupePrompt.user,\n events: options.events,\n execute: this.config.dedupeExecute,\n strict: this.config.strict,\n debug,\n callId: \"double_pass_auto_dedupe\",\n telemetry: telemetry ?? undefined,\n parentSpan: llmDedupeSpan,\n });\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: \"pass 1 dedupe\",\n });\n debug?.step({\n step,\n total: totalSteps,\n label: \"pass 1 dedupe\",\n strategy: this.name,\n });\n\n let deduped = merged;\n for (const key of dedupeResponse.data.keys) {\n deduped = removeByPath(deduped, key);\n }\n\n debug?.dedupeComplete({\n dedupeId: \"double_pass_auto_dedupe\",\n duplicatesFound: dedupeResponse.data.keys.length,\n itemsRemoved: dedupeResponse.data.keys.length,\n });\n \n // End LLM dedupe span\n if (llmDedupeSpan && telemetry) {\n telemetry.recordEvent(llmDedupeSpan, {\n type: \"merge\",\n strategy: \"llm_dedupe\",\n inputCount: Object.keys(merged).length,\n outputCount: Object.keys(deduped).length,\n deduped: dedupeResponse.data.keys.length,\n });\n telemetry.endSpan(llmDedupeSpan, {\n status: \"ok\",\n output: deduped,\n });\n }\n \n // End pass 1 span\n telemetry?.endSpan(pass1Span!, {\n status: \"ok\",\n output: deduped,\n });\n\n let currentData = deduped as T;\n const usages = [...results.map((r) => r.usage), dedupeResponse.usage];\n \n // Create pass 2 span\n const pass2Span = telemetry?.startSpan({\n name: \"struktur.pass_2\",\n kind: \"CHAIN\",\n parentSpan: strategySpan,\n attributes: {\n \"pass.number\": 2,\n \"pass.type\": \"sequential_refinement\",\n },\n });\n\n for (const [index, batch] of batches.entries()) {\n const prompt = buildSequentialPrompt(\n batch,\n schema,\n JSON.stringify(currentData),\n this.config.outputInstructions,\n );\n\n const result = await extractWithPrompt<T>({\n model: this.config.model,\n schema: options.schema,\n system: prompt.system,\n user: prompt.user,\n artifacts: batch,\n events: options.events,\n execute: this.config.execute as never,\n strict: this.config.strict,\n debug,\n callId: `double_pass_auto_2_batch_${index + 1}`,\n telemetry: telemetry ?? undefined,\n parentSpan: pass2Span,\n });\n\n currentData = result.data;\n usages.push(result.usage);\n\n step += 1;\n await options.events?.onStep?.({\n step,\n total: totalSteps,\n label: `pass 2 batch ${index + 1}/${batches.length}`,\n });\n debug?.step({\n step,\n total: totalSteps,\n label: `pass 2 batch ${index + 1}/${batches.length}`,\n strategy: this.name,\n });\n }\n \n // End pass 2 span\n telemetry?.endSpan(pass2Span!, {\n status: \"ok\",\n output: currentData,\n });\n \n // End strategy span\n telemetry?.endSpan(strategySpan!, {\n status: \"ok\",\n output: currentData,\n });\n\n return { data: currentData, usage: mergeUsage(usages) };\n }\n}\n\nexport const doublePassAutoMerge = <T>(\n config: DoublePassAutoMergeStrategyConfig,\n) => {\n return new DoublePassAutoMergeStrategy<T>(config);\n};\n"],"mappings":"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","names":["dedupeSchema","dedupeArrays","removeByPath","dedupeSchema","dedupeArrays","removeByPath"]}
|
package/package.json
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@struktur/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"license": "FSL-1.1-MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "
|
|
7
|
-
"types": "
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"./
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./strategies": {
|
|
14
|
+
"import": "./dist/strategies.js",
|
|
15
|
+
"types": "./dist/strategies.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./parsers": {
|
|
18
|
+
"import": "./dist/parsers.js",
|
|
19
|
+
"types": "./dist/parsers.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"prepublishOnly": "bun run build"
|
|
17
28
|
},
|
|
18
29
|
"dependencies": {
|
|
19
30
|
"@ai-sdk/anthropic": "^3.0.0",
|
|
@@ -30,6 +41,7 @@
|
|
|
30
41
|
"typescript": "^5"
|
|
31
42
|
},
|
|
32
43
|
"devDependencies": {
|
|
33
|
-
"@types/bun": "latest"
|
|
44
|
+
"@types/bun": "latest",
|
|
45
|
+
"tsup": "^8.0.0"
|
|
34
46
|
}
|
|
35
47
|
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { test, expect, describe } from "bun:test";
|
|
2
|
-
import { agent, AgentStrategy } from "@struktur/sdk";
|
|
3
|
-
|
|
4
|
-
describe("Agent Strategy CLI Integration", () => {
|
|
5
|
-
test("agent strategy accepts provider and modelId", () => {
|
|
6
|
-
const strategy = agent<{ name: string }>({
|
|
7
|
-
provider: "anthropic",
|
|
8
|
-
modelId: "claude-sonnet-4",
|
|
9
|
-
maxSteps: 30,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
expect(strategy).toBeInstanceOf(AgentStrategy);
|
|
13
|
-
expect(strategy.name).toBe("agent");
|
|
14
|
-
expect(strategy.getEstimatedSteps()).toBe(30);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test("agent strategy works with openai", () => {
|
|
18
|
-
const strategy = agent<{ name: string }>({
|
|
19
|
-
provider: "openai",
|
|
20
|
-
modelId: "gpt-4o",
|
|
21
|
-
maxSteps: 50,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
expect(strategy).toBeInstanceOf(AgentStrategy);
|
|
25
|
-
expect(strategy.name).toBe("agent");
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("agent strategy works with openrouter nested paths", () => {
|
|
29
|
-
const strategy = agent<{ name: string }>({
|
|
30
|
-
provider: "openrouter",
|
|
31
|
-
modelId: "anthropic/claude-sonnet-4",
|
|
32
|
-
maxSteps: 50,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
expect(strategy).toBeInstanceOf(AgentStrategy);
|
|
36
|
-
expect(strategy.name).toBe("agent");
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("agent strategy uses default maxSteps", () => {
|
|
40
|
-
const strategy = agent<{ name: string }>({
|
|
41
|
-
provider: "anthropic",
|
|
42
|
-
modelId: "claude-sonnet-4",
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
expect(strategy.getEstimatedSteps()).toBe(50);
|
|
46
|
-
});
|
|
47
|
-
});
|
package/src/agent-export.test.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "bun:test";
|
|
2
|
-
import { agent, AgentStrategy } from "@struktur/sdk";
|
|
3
|
-
|
|
4
|
-
test("agent strategy is exported from @struktur/sdk", () => {
|
|
5
|
-
expect(agent).toBeDefined();
|
|
6
|
-
expect(typeof agent).toBe("function");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test("AgentStrategy class is exported from @struktur/sdk", () => {
|
|
10
|
-
const strategy = agent({
|
|
11
|
-
provider: "anthropic",
|
|
12
|
-
modelId: "claude-sonnet-4",
|
|
13
|
-
maxSteps: 10,
|
|
14
|
-
});
|
|
15
|
-
expect(strategy).toBeInstanceOf(AgentStrategy);
|
|
16
|
-
expect(strategy.name).toBe("agent");
|
|
17
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { test, expect, describe } from "bun:test";
|
|
2
|
-
import { agent, AgentStrategy } from "@struktur/sdk";
|
|
3
|
-
|
|
4
|
-
describe("Agent Strategy Tool Labels", () => {
|
|
5
|
-
test("strategy creates properly configured agent", () => {
|
|
6
|
-
const strategy = agent<{ title: string }>({
|
|
7
|
-
provider: "anthropic",
|
|
8
|
-
modelId: "claude-sonnet-4",
|
|
9
|
-
maxSteps: 25,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
expect(strategy).toBeDefined();
|
|
13
|
-
expect(strategy.name).toBe("agent");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("label format for read tool with file path only", () => {
|
|
17
|
-
const label = "Read artifact.json";
|
|
18
|
-
expect(label).toBe("Read artifact.json");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test("label format for read tool with limit", () => {
|
|
22
|
-
const label = "Read artifact.json (limit 100)";
|
|
23
|
-
expect(label).toBe("Read artifact.json (limit 100)");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("label format for read tool with offset and limit", () => {
|
|
27
|
-
const label = "Read artifact.json (offset 101, limit 100)";
|
|
28
|
-
expect(label).toBe("Read artifact.json (offset 101, limit 100)");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("label format for bash command", () => {
|
|
32
|
-
const label = "Bash: cat /artifacts/artifact.json";
|
|
33
|
-
expect(label).toBe("Bash: cat /artifacts/artifact.json");
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("label format for grep", () => {
|
|
37
|
-
const label = 'Grep "pattern" in artifact.json';
|
|
38
|
-
expect(label).toBe('Grep "pattern" in artifact.json');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("label format for find", () => {
|
|
42
|
-
const label = 'Find "*.json" in /artifacts';
|
|
43
|
-
expect(label).toBe('Find "*.json" in /artifacts');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("label format for ls", () => {
|
|
47
|
-
const label = "List /artifacts (recursive)";
|
|
48
|
-
expect(label).toBe("List /artifacts (recursive)");
|
|
49
|
-
});
|
|
50
|
-
});
|
package/src/artifacts/AGENTS.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
Artifacts module
|
|
2
|
-
|
|
3
|
-
- Purpose: convert external inputs into Artifacts and manage parser configuration.
|
|
4
|
-
- Key files: `fileToArtifact.ts`, `urlToArtifact.ts`, `providers.ts`, `input.ts`.
|
|
5
|
-
- Design: `ParsersConfig` is the unified configuration system for all parsers (npm packages, CLI commands, and inline handlers). The `providers` registry is deprecated — use inline parsers in `ParsersConfig` instead.
|
|
6
|
-
- `parse` accepts an optional `parserConfig: ParsersConfig` (from `src/parsers/types`) that takes priority over the deprecated providers registry. Custom parsers are resolved by MIME type.
|
|
7
|
-
- `ParsersConfig` supports four parser types:
|
|
8
|
-
- `NpmParserDef` — npm package with `parseFile` or `parseStream` exports
|
|
9
|
-
- `CommandFileDef` — CLI command with `FILE_PATH` placeholder
|
|
10
|
-
- `CommandStdinDef` — CLI command that reads from stdin
|
|
11
|
-
- `InlineParserDef` — inline `(buffer: Buffer) => Promise<Artifact>` function (replaces the old providers registry)
|
|
12
|
-
- JSON auto-detection: when MIME type is `application/json`, `fileParser` first attempts to validate the file as `SerializedArtifact[]`. If valid, it hydrates and returns them directly. If not valid, it checks `parsers` config for a custom parser; if none, throws a clear error.
|
|
13
|
-
- `parseBufferInput` resolution order: (1) parsers config, (2) providers registry (deprecated), (3) JSON auto-detection, (4) built-in `application/pdf` (via `parsePdf`), (5) built-in text/*, (6) built-in image/*, (7) error.
|
|
14
|
-
- `parse` accepts `includeImages?: boolean` which is forwarded to `parsePdf` for PDF inputs. Set to `false` to suppress image extraction (used by `--no-images` CLI flag).
|
|
15
|
-
- `SerializedArtifactImage` schema validation accepts an optional `imageType` field with values `"embedded"` or `"screenshot"` to differentiate between embedded images extracted from PDFs and page screenshots.
|
|
16
|
-
- Tests: `fileToArtifact.test.ts`, `urlToArtifact.test.ts`, `input.test.ts`, `providers.test.ts`.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "bun:test";
|
|
2
|
-
import { fileToArtifact } from "./fileToArtifact";
|
|
3
|
-
import type { ArtifactType } from "../types";
|
|
4
|
-
|
|
5
|
-
test("fileToArtifact uses custom providers", async () => {
|
|
6
|
-
const providers = {
|
|
7
|
-
"text/plain": async (buffer: Buffer): Promise<{ id: string; type: ArtifactType; raw: () => Promise<Buffer>; contents: { text: string }[] }> => ({
|
|
8
|
-
id: "a1",
|
|
9
|
-
type: "text",
|
|
10
|
-
raw: async () => buffer,
|
|
11
|
-
contents: [{ text: buffer.toString() }],
|
|
12
|
-
}),
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const artifact = await fileToArtifact(Buffer.from("hello"), {
|
|
16
|
-
mimeType: "text/plain",
|
|
17
|
-
providers,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
expect(artifact.id).toBe("a1");
|
|
21
|
-
expect(artifact.contents[0]?.text).toBe("hello");
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("fileToArtifact falls back to text for text/* mime types", async () => {
|
|
25
|
-
const artifact = await fileToArtifact(Buffer.from("hello world"), {
|
|
26
|
-
mimeType: "text/plain",
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
expect(artifact.type).toBe("text");
|
|
30
|
-
expect(artifact.contents[0]?.text).toBe("hello world");
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("fileToArtifact throws for unknown mime types", async () => {
|
|
34
|
-
await expect(
|
|
35
|
-
fileToArtifact(Buffer.from("test"), { mimeType: "application/unknown" })
|
|
36
|
-
).rejects.toThrow("No artifact provider registered");
|
|
37
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Artifact } from "../types";
|
|
2
|
-
import { defaultArtifactProviders, type ArtifactProviders } from "./providers";
|
|
3
|
-
|
|
4
|
-
export type FileToArtifactOptions = {
|
|
5
|
-
mimeType: string;
|
|
6
|
-
providers?: ArtifactProviders;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const bufferToTextArtifact = (buffer: Buffer): Artifact => ({
|
|
10
|
-
id: `artifact-${crypto.randomUUID()}`,
|
|
11
|
-
type: "text",
|
|
12
|
-
raw: async () => buffer,
|
|
13
|
-
contents: [{ text: buffer.toString() }],
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const bufferToImageArtifact = (buffer: Buffer): Artifact => ({
|
|
17
|
-
id: `artifact-${crypto.randomUUID()}`,
|
|
18
|
-
type: "image",
|
|
19
|
-
raw: async () => buffer,
|
|
20
|
-
contents: [{ media: [{ type: "image", contents: buffer }] }],
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
export const fileToArtifact = async (
|
|
24
|
-
buffer: Buffer,
|
|
25
|
-
options: FileToArtifactOptions
|
|
26
|
-
): Promise<Artifact> => {
|
|
27
|
-
const providers = options.providers ?? defaultArtifactProviders;
|
|
28
|
-
const provider = providers[options.mimeType];
|
|
29
|
-
if (provider) {
|
|
30
|
-
return provider(buffer);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (options.mimeType.startsWith("text/")) {
|
|
34
|
-
return bufferToTextArtifact(buffer);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (options.mimeType.startsWith("image/")) {
|
|
38
|
-
return bufferToImageArtifact(buffer);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
throw new Error(
|
|
42
|
-
`No artifact provider registered for ${options.mimeType}`
|
|
43
|
-
);
|
|
44
|
-
};
|