Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions typescript/extend-browserbase/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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: {
Expand All @@ -115,15 +117,16 @@ const receiptExtractionConfig = {
},
},
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: [
Expand Down Expand Up @@ -217,14 +220,15 @@ const receiptExtractionConfig = {
},
additionalProperties: false,
},
// API accepts advancedFigureParsingEnabled; SDK type is narrower
advancedOptions: {
advancedMultimodalEnabled: false,
citationsEnabled: true,
arrayCitationStrategy: "item",
pageRanges: [],
chunkingOptions: {},
advancedFigureParsingEnabled: true,
},
} as Extend.ExtractAdvancedOptions,
};

// Uploads receipt files to Extend AI, runs extraction, and saves results as JSON and CSV
Expand Down Expand Up @@ -254,19 +258,17 @@ async function parseReceiptsWithExtend(filePaths: string[]): Promise<void> {
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<typeof client.files.upload>[0],
fs.createReadStream(filePath),
{ maxRetries: 4 },
);
const fileId = uploadResponse.id;

// Run extraction using inline config — no need to pre-create an extractor resource
const result = await client.extract(
{
config: receiptExtractionConfig as Parameters<typeof client.extract>[0]["config"],
config: receiptExtractionConfig,
file: { id: fileId },
},
{ maxRetries: 4 },
Expand Down