From cf75029b180f54a36e51caba132fa7db76eac84e Mon Sep 17 00:00:00 2001 From: Addison-Huff Date: Wed, 11 Feb 2026 14:56:03 -0500 Subject: [PATCH 1/2] fix(extend-browserbase): use ExtractConfigJson type instead of casting - Type receiptExtractionConfig as Extend.ExtractConfigJson for type safety and autocomplete per SDK contract - Remove 'as Parameters<...>' cast so invalid config would surface as type errors instead of allowing invalid payloads Co-authored-by: Cursor --- typescript/extend-browserbase/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/typescript/extend-browserbase/index.ts b/typescript/extend-browserbase/index.ts index 94321b19..4e9e809b 100644 --- a/typescript/extend-browserbase/index.ts +++ b/typescript/extend-browserbase/index.ts @@ -6,6 +6,7 @@ import { Stagehand } from "@browserbasehq/stagehand"; import fs from "fs"; import path from "path"; import AdmZip from "adm-zip"; +import type { Extend } from "extend-ai"; import { ExtendClient } from "extend-ai"; import open from "open"; @@ -92,7 +93,8 @@ function extractFilesFromZip(zipPath: string, outputDir: string = "output/docume // Receipt extraction config for Extend AI // Uses extraction_light base extractor with parse_performance engine for low latency -const receiptExtractionConfig = { +// Typed as ExtractConfigJson for type safety and autocomplete (no type casting) +const receiptExtractionConfig: Extend.ExtractConfigJson = { baseProcessor: "extraction_light", baseVersion: "3.4.0", parseConfig: { @@ -266,7 +268,7 @@ async function parseReceiptsWithExtend(filePaths: string[]): Promise { // Run extraction using inline config — no need to pre-create an extractor resource const result = await client.extract( { - config: receiptExtractionConfig as Parameters[0]["config"], + config: receiptExtractionConfig, file: { id: fileId }, }, { maxRetries: 4 }, From 001a0bfa3422de9b9ba670a872dd62502157567f Mon Sep 17 00:00:00 2001 From: Addison-Huff Date: Wed, 11 Feb 2026 15:07:22 -0500 Subject: [PATCH 2/2] fix(extend-browserbase): use ReadStream for upload, minimal asserts for API-only fields - Use fs.createReadStream(filePath) for client.files.upload (SDK type, no cast) - Add narrow type assertions only where API accepts fields not in SDK types (parseConfig.advancedOptions, advancedOptions, parseConfig for engineVersion) Co-authored-by: Cursor --- typescript/extend-browserbase/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/typescript/extend-browserbase/index.ts b/typescript/extend-browserbase/index.ts index 4e9e809b..2ada7c58 100644 --- a/typescript/extend-browserbase/index.ts +++ b/typescript/extend-browserbase/index.ts @@ -117,15 +117,16 @@ const receiptExtractionConfig: Extend.ExtractConfigJson = { }, }, engineVersion: "1.0.1", + // API accepts more options than SDK types; assert for known-valid extras (engine, agenticOcrEnabled, pageBreaksEnabled) advancedOptions: { engine: "parse_performance", agenticOcrEnabled: false, pageBreaksEnabled: true, pageRotationEnabled: false, verticalGroupingThreshold: 1, - }, + } as Extend.ParseConfigAdvancedOptions, chunkingStrategy: { type: "document" }, - }, + } as Extend.ParseConfig, // engineVersion and other API-accepted fields not in SDK type schema: { type: "object", required: [ @@ -219,6 +220,7 @@ const receiptExtractionConfig: Extend.ExtractConfigJson = { }, additionalProperties: false, }, + // API accepts advancedFigureParsingEnabled; SDK type is narrower advancedOptions: { advancedMultimodalEnabled: false, citationsEnabled: true, @@ -226,7 +228,7 @@ const receiptExtractionConfig: Extend.ExtractConfigJson = { pageRanges: [], chunkingOptions: {}, advancedFigureParsingEnabled: true, - }, + } as Extend.ExtractAdvancedOptions, }; // Uploads receipt files to Extend AI, runs extraction, and saves results as JSON and CSV @@ -256,11 +258,9 @@ async function parseReceiptsWithExtend(filePaths: string[]): Promise { batch.map(async (filePath) => { const fileName = path.basename(filePath); try { - // Upload the file to Extend - const fileBuffer = fs.readFileSync(filePath); - const blob = new Blob([fileBuffer]); + // Upload the file to Extend (ReadStream is accepted by SDK, no cast needed) const uploadResponse = await client.files.upload( - blob as Parameters[0], + fs.createReadStream(filePath), { maxRetries: 4 }, ); const fileId = uploadResponse.id;