77 * - Layer-based dependency injection
88 * - Type-safe error handling with Effect
99 * - File processing with the FileParserPlugin
10+ * - Uses shared fixtures module with absolute paths
1011 *
1112 * To run: bun run typescript/effect-ai/src/plugin-file-parser/file-parser-all-sizes.ts
1213 */
@@ -17,54 +18,18 @@ import * as LanguageModel from '@effect/ai/LanguageModel';
1718import * as Prompt from '@effect/ai/Prompt' ;
1819import { FetchHttpClient } from '@effect/platform' ;
1920import * as BunContext from '@effect/platform-bun/BunContext' ;
21+ import {
22+ type PdfSize ,
23+ PDF_SIZES ,
24+ extractCode ,
25+ formatSize ,
26+ getPdfPath ,
27+ getPdfSize ,
28+ readExpectedCode ,
29+ readPdfAsDataUrl ,
30+ } from '@openrouter-examples/shared/fixtures' ;
2031import { Console , Effect , Layer , Redacted } from 'effect' ;
2132
22- const PDF_SIZES = [ 'small' , 'medium' , 'large' , 'xlarge' ] as const ;
23-
24- /**
25- * Expected verification codes from PDFs
26- */
27- const EXPECTED_CODES : Record < string , string > = {
28- small : 'SMALL-7X9Q2' ,
29- medium : 'MEDIUM-K4P8R' ,
30- large : 'LARGE-M9N3T' ,
31- xlarge : 'XLARGE-F6H2V' ,
32- } ;
33-
34- /**
35- * Convert a PDF file to a base64 data URL
36- */
37- const readPdfDataUrl = ( filePath : string ) =>
38- Effect . promise ( async ( ) => {
39- const pdfFile = Bun . file ( filePath ) ;
40- const pdfBuffer = await pdfFile . arrayBuffer ( ) ;
41- const base64PDF = Buffer . from ( pdfBuffer ) . toString ( 'base64' ) ;
42- return `data:application/pdf;base64,${ base64PDF } ` ;
43- } ) ;
44-
45- /**
46- * Get a PDF file's size for logging
47- */
48- const getFileSize = ( filePath : string ) => Effect . sync ( ( ) => Bun . file ( filePath ) . size ) ;
49-
50- /**
51- * Format file size for display
52- */
53- function formatSize ( bytes : number ) : string {
54- if ( bytes < 1024 * 1024 ) {
55- return `${ ( bytes / 1024 ) . toFixed ( 0 ) } KB` ;
56- }
57- return `${ ( bytes / ( 1024 * 1024 ) ) . toFixed ( 1 ) } MB` ;
58- }
59-
60- /**
61- * Extract verification code from response text
62- */
63- function extractCode ( text : string ) : string | null {
64- const match = text . match ( / [ A - Z ] + - [ A - Z 0 - 9 ] { 5 } / ) ;
65- return match ? match [ 0 ] : null ;
66- }
67-
6833/**
6934 * OpenRouter FileParserPlugin configuration
7035 * This plugin enables server-side PDF parsing using OpenRouter's file parser
@@ -84,17 +49,15 @@ const fileParserConfig: OpenRouterLanguageModel.Config.Service = {
8449/**
8550 * Process a single PDF file with logging and error handling
8651 */
87- const processPdf = ( size : string , expectedCode : string ) =>
52+ const processPdf = ( size : PdfSize , expectedCode : string ) =>
8853 Effect . gen ( function * ( ) {
89- const filePath = `./fixtures/pdfs/${ size } .pdf` ;
90-
9154 yield * Console . log ( `\n=== ${ size . toUpperCase ( ) } PDF ===` ) ;
9255
93- const sizeBytes = yield * getFileSize ( filePath ) ;
56+ const sizeBytes = getPdfSize ( size ) ;
9457 yield * Console . log ( `Size: ${ formatSize ( sizeBytes ) } ` ) ;
9558 yield * Console . log ( `Expected: ${ expectedCode } ` ) ;
9659
97- const dataUrl = yield * readPdfDataUrl ( filePath ) ;
60+ const dataUrl = yield * Effect . promise ( ( ) => readPdfAsDataUrl ( size ) ) ;
9861
9962 /**
10063 * Construct prompt with file attachment for file parser plugin
@@ -140,32 +103,33 @@ const processPdf = (size: string, expectedCode: string) =>
140103 * Main program orchestrating all PDF runs
141104 */
142105const program = Effect . gen ( function * ( ) {
143- yield * Console . log (
144- '╔════════════════════════════════════════════════════════════════════════════╗' ,
145- ) ;
146- yield * Console . log (
147- '║ OpenRouter FileParserPlugin - Effect AI ║' ,
148- ) ;
149- yield * Console . log (
150- '╚════════════════════════════════════════════════════════════════════════════╝' ,
151- ) ;
106+ yield * Console . log ( '╔════════════════════════════════════════════════════════════════════════════╗' ) ;
107+ yield * Console . log ( '║ OpenRouter FileParserPlugin - Effect AI ║' ) ;
108+ yield * Console . log ( '╚════════════════════════════════════════════════════════════════════════════╝' ) ;
152109 yield * Console . log ( ) ;
153110 yield * Console . log ( 'Testing PDF processing with verification code extraction' ) ;
154111 yield * Console . log ( ) ;
155112
156- const logFailure = ( label : string ) => ( error : unknown ) =>
157- Effect . gen ( function * ( ) {
158- yield * Console . error ( `Error processing ${ label } :` , error ) ;
159- return {
160- success : false ,
161- extracted : null ,
162- expected : EXPECTED_CODES [ label ] || '' ,
163- } ;
164- } ) ;
113+ const logFailure =
114+ ( label : string ) =>
115+ ( error : unknown ) =>
116+ Effect . gen ( function * ( ) {
117+ yield * Console . error ( `Error processing ${ label } :` , error ) ;
118+ return {
119+ success : false ,
120+ extracted : null ,
121+ expected : '' ,
122+ } ;
123+ } ) ;
165124
166125 const results = yield * Effect . all (
167126 PDF_SIZES . map ( ( size ) =>
168- processPdf ( size , EXPECTED_CODES [ size ] ) . pipe ( Effect . catchAll ( logFailure ( size ) ) ) ,
127+ Effect . gen ( function * ( ) {
128+ const expectedCode = yield * Effect . promise ( ( ) => readExpectedCode ( size ) ) ;
129+ return yield * processPdf ( size , expectedCode ) . pipe (
130+ Effect . catchAll ( logFailure ( size ) ) ,
131+ ) ;
132+ } ) ,
169133 ) ,
170134 { concurrency : 'unbounded' } ,
171135 ) ;
0 commit comments