brainy/docs/guides/import-progress-examples.md
David Snelling d5576ffb56 feat: comprehensive import progress tracking for all 7 formats
Add real-time progress reporting throughout the entire import pipeline
with a standardized API that works across all supported formats.

Workshop Team Feature Request:
- Eliminates "0% complete" hangs during AI extraction
- Shows continuous progress with entities/sec, throughput, ETA
- Reports contextual messages ("Processing page 5 of 23")
- Standardized progress API for CSV, PDF, Excel, JSON, Markdown, YAML, DOCX

Core Changes:
- Add FormatHandlerProgressHooks interface for extensible progress
- Wire up all 3 binary format handlers (CSV, PDF, Excel) with 7+ progress points
- Wire up all 4 text format importers (JSON, Markdown, YAML, DOCX)
- Add ImportProgress interface with stage, message, counts, throughput, ETA
- ImportCoordinator normalizes all format progress to standard interface

CLI Improvements:
- Import command now uses brain.import() directly with full progress
- Add --include-vfs flag to find command (v4.4.0 compatibility)
- Add --confidence and --weight options to add command

Documentation:
- docs/guides/standard-import-progress.md - Universal API guide
- docs/guides/import-progress-implementation.md - Developer guide
- docs/guides/import-progress-examples.md - Practical examples
- JSDoc on brain.import() with universal handler examples

Result: ONE progress handler works for ALL 7 formats with zero format-specific code!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:45:46 -07:00

9.5 KiB

Import Progress - Usage Examples

How to Use Progress Tracking in Your Applications

Brainy v4.5.0+ provides real-time progress tracking for all 7 supported file formats (CSV, PDF, Excel, JSON, Markdown, YAML, DOCX).

⚠️ KEY FEATURE: The progress API is 100% standardized. Write your progress handler ONCE and it works for ALL formats with zero format-specific code! See Standard Import Progress API for the complete interface documentation.


🚀 Quick Start

Basic Progress Tracking

import { Brainy } from '@soulcraft/brainy'
import * as fs from 'fs'

const brain = await Brainy.create()

// Import with progress tracking
const result = await brain.import(fs.readFileSync('large-file.xlsx'), {
  onProgress: (progress) => {
    console.log(`Progress: ${progress.stage}`)
    console.log(`  Message: ${progress.message}`)
    console.log(`  Entities: ${progress.entities || 0}`)
    console.log(`  Relationships: ${progress.relationships || 0}`)
  }
})

console.log(`Import complete: ${result.entities.length} entities created`)

Expected Output:

Progress: detecting
  Message: Detecting format...
  Entities: 0
  Relationships: 0
Progress: extracting
  Message: Loading Excel workbook...
  Entities: 0
  Relationships: 0
Progress: extracting
  Message: Reading sheet: Sales (1/3)
  Entities: 0
  Relationships: 0
Progress: extracting
  Message: Parsing Excel (33%)
  Entities: 0
  Relationships: 0
Progress: extracting
  Message: Reading sheet: Products (2/3)
  Entities: 0
  Relationships: 0
... (more progress updates)
Progress: complete
  Message: Import complete
  Entities: 1523
  Relationships: 892
Import complete: 1523 entities created

🎯 Universal Progress Handler (Works for ALL Formats)

The examples below show format-specific messages, but you don't need format-specific code! The ImportProgress interface is the same for all formats:

// ONE HANDLER FOR ALL FORMATS!
function universalProgressHandler(progress) {
  console.log(`[${progress.stage}] ${progress.message}`)

  if (progress.processed && progress.total) {
    console.log(`  Progress: ${progress.processed}/${progress.total}`)
  }

  if (progress.entities || progress.relationships) {
    console.log(`  Extracted: ${progress.entities || 0} entities, ${progress.relationships || 0} relationships`)
  }

  if (progress.throughput && progress.eta) {
    console.log(`  Rate: ${progress.throughput.toFixed(1)}/sec, ETA: ${Math.round(progress.eta/1000)}s`)
  }
}

// Use it for ANY format!
await brain.import(csvBuffer, { onProgress: universalProgressHandler })
await brain.import(pdfBuffer, { onProgress: universalProgressHandler })
await brain.import(excelBuffer, { onProgress: universalProgressHandler })
await brain.import(jsonBuffer, { onProgress: universalProgressHandler })
await brain.import(markdownString, { onProgress: universalProgressHandler })
await brain.import(yamlBuffer, { onProgress: universalProgressHandler })
await brain.import(docxBuffer, { onProgress: universalProgressHandler })

📊 What Different Formats Look Like (Same Handler!)

The examples below show what messages look like for different formats using the same universal handler above.

CSV Import (Row-by-Row Progress)

await brain.import(csvBuffer, {
  format: 'csv',
  onProgress: (progress) => {
    if (progress.stage === 'extracting') {
      // CSV reports: "Parsing CSV (45%)", "Extracted 1000 rows", etc.
      console.log(progress.message)
    }
  }
})

CSV Progress Messages:

  • "Detecting CSV encoding and delimiter..."
  • "Parsing CSV rows (delimiter: ",")"
  • "Parsed 75%" (via bytes processed)
  • "Extracted 1000 rows"
  • "Converting types: 5000/10000 rows..."
  • "CSV processing complete: 10000 rows"

PDF Import (Page-by-Page Progress)

await brain.import(pdfBuffer, {
  format: 'pdf',
  onProgress: (progress) => {
    // PDF reports exact page numbers
    console.log(progress.message)
    // Example: "Processing page 5 of 23"
  }
})

PDF Progress Messages:

  • "Loading PDF document..."
  • "Processing 23 pages..."
  • "Processing page 5 of 23"
  • "Parsed 22%" (via bytes processed)
  • "Extracted 156 items from PDF"
  • "PDF complete: 23 pages, 156 items extracted"

Excel Import (Sheet-by-Sheet Progress)

await brain.import(excelBuffer, {
  format: 'excel',
  onProgress: (progress) => {
    // Excel reports sheet names
    console.log(progress.message)
    // Example: "Reading sheet: Q2 Sales (2/5)"
  }
})

Excel Progress Messages:

  • "Loading Excel workbook..."
  • "Processing 3 sheets..."
  • "Reading sheet: Sales (1/3)"
  • "Parsing Excel (33%)" (via bytes processed)
  • "Extracted 5234 rows from Excel"
  • "Excel complete: 3 sheets, 5234 rows"

JSON Import (Node Traversal)

await brain.import(jsonBuffer, {
  format: 'json',
  onProgress: (progress) => {
    // JSON reports every 10 nodes
    console.log(`Processed ${progress.processed} nodes, found ${progress.entities} entities`)
  }
})

Markdown Import (Section-by-Section)

await brain.import(markdownString, {
  format: 'markdown',
  onProgress: (progress) => {
    console.log(`Section ${progress.processed}/${progress.total}`)
  }
})

🎯 Building Progress UI Components

React Progress Bar

function ImportProgress({ file }: { file: File }) {
  const [progress, setProgress] = useState({
    stage: 'idle',
    message: '',
    percent: 0,
    entities: 0,
    relationships: 0
  })

  const handleImport = async () => {
    const buffer = await file.arrayBuffer()

    await brain.import(Buffer.from(buffer), {
      onProgress: (p) => {
        setProgress({
          stage: p.stage,
          message: p.message,
          // Estimate percentage from stage
          percent: {
            detecting: 10,
            extracting: 50,
            'storing-vfs': 80,
            'storing-graph': 90,
            complete: 100
          }[p.stage] || 0,
          entities: p.entities || 0,
          relationships: p.relationships || 0
        })
      }
    })
  }

  return (
    <div>
      <ProgressBar value={progress.percent} />
      <p>{progress.message}</p>
      <p>Entities: {progress.entities} | Relationships: {progress.relationships}</p>
    </div>
  )
}

CLI Progress Spinner

import ora from 'ora'

const spinner = ora('Starting import...').start()

await brain.import(buffer, {
  onProgress: (progress) => {
    spinner.text = progress.message

    if (progress.stage === 'complete') {
      spinner.succeed(`Import complete: ${progress.entities} entities`)
    }
  }
})

CLI Output:

⠋ Detecting format...
⠙ Loading Excel workbook...
⠹ Reading sheet: Sales (1/3)
⠸ Parsing Excel (33%)
⠼ Reading sheet: Products (2/3)
...
✔ Import complete: 1523 entities

Progress Dashboard with ETA

let startTime = Date.now()
let lastUpdate = startTime

await brain.import(buffer, {
  onProgress: (progress) => {
    const elapsed = Date.now() - startTime
    const rate = progress.entities / (elapsed / 1000)  // entities/sec

    console.clear()
    console.log('Import Progress Dashboard')
    console.log('========================')
    console.log(`Stage: ${progress.stage}`)
    console.log(`Status: ${progress.message}`)
    console.log(`Entities: ${progress.entities}`)
    console.log(`Relationships: ${progress.relationships}`)
    console.log(`Rate: ${rate.toFixed(1)} entities/sec`)
    console.log(`Elapsed: ${(elapsed / 1000).toFixed(1)}s`)
  }
})

🔧 Advanced: Format-Specific Optimization

Detecting Format to Show Appropriate Progress

const formatMessages = {
  csv: (p) => `CSV: ${p.message}`,
  pdf: (p) => `PDF: ${p.message}`,
  excel: (p) => `Excel: ${p.message}`,
  json: (p) => `JSON: ${p.processed} nodes, ${p.entities} entities`,
  markdown: (p) => `Markdown: Section ${p.processed}/${p.total}`,
  yaml: (p) => `YAML: ${p.processed} nodes`,
  docx: (p) => `DOCX: ${p.processed} paragraphs`
}

await brain.import(buffer, {
  onProgress: (progress) => {
    // Format is available in progress.stage metadata
    const message = formatMessages[detectedFormat]?.(progress) || progress.message
    console.log(message)
  }
})

Performance Tips

Throttle UI Updates

let lastUIUpdate = 0
const THROTTLE_MS = 100  // Update UI max once per 100ms

await brain.import(buffer, {
  onProgress: (progress) => {
    const now = Date.now()
    if (now - lastUIUpdate < THROTTLE_MS && progress.stage !== 'complete') {
      return  // Skip this update
    }

    lastUIUpdate = now
    updateUI(progress)  // Only update every 100ms
  }
})

Note: Brainy already throttles progress callbacks internally, but additional UI throttling can help with heavy rendering.


📝 Summary

All 7 formats have consistent progress reporting Real-time updates during long imports (no more "0%" hangs) Contextual messages show exactly what's happening Build reliable tools with standardized progress callbacks Workshop team problem SOLVED - users see progress throughout import

Files Modified:

  • 3 handlers: csvHandler.ts, pdfHandler.ts, excelHandler.ts
  • 7 importers: SmartCSVImporter.ts, SmartPDFImporter.ts, SmartExcelImporter.ts, SmartJSONImporter.ts, SmartMarkdownImporter.ts, SmartYAMLImporter.ts, SmartDOCXImporter.ts

Result: Comprehensive, consistent progress tracking across ALL import formats!