@heripo/pdf-parser 0.1.33 → 0.1.34

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.cjs CHANGED
@@ -377,6 +377,29 @@ var LLMCaller = class {
377
377
  function formatTokens(usage) {
378
378
  return `${usage.inputTokens} input, ${usage.outputTokens} output, ${usage.totalTokens} total`;
379
379
  }
380
+ function emptyUsage() {
381
+ return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
382
+ }
383
+ function addInto(target, src) {
384
+ target.inputTokens += src.inputTokens;
385
+ target.outputTokens += src.outputTokens;
386
+ target.totalTokens += src.totalTokens;
387
+ }
388
+ function sumUsage(a, b) {
389
+ return {
390
+ inputTokens: (a?.inputTokens ?? 0) + (b?.inputTokens ?? 0),
391
+ outputTokens: (a?.outputTokens ?? 0) + (b?.outputTokens ?? 0),
392
+ totalTokens: (a?.totalTokens ?? 0) + (b?.totalTokens ?? 0)
393
+ };
394
+ }
395
+ function accumulateModel(bucket, modelName, usage) {
396
+ let entry = bucket.get(modelName);
397
+ if (!entry) {
398
+ entry = emptyUsage();
399
+ bucket.set(modelName, entry);
400
+ }
401
+ addInto(entry, usage);
402
+ }
380
403
  var LLMTokenUsageAggregator = class {
381
404
  usage = {};
382
405
  /**
@@ -389,21 +412,15 @@ var LLMTokenUsageAggregator = class {
389
412
  this.usage[usage.component] = {
390
413
  component: usage.component,
391
414
  phases: {},
392
- total: {
393
- inputTokens: 0,
394
- outputTokens: 0,
395
- totalTokens: 0
396
- }
415
+ total: emptyUsage()
397
416
  };
398
417
  }
399
418
  const component = this.usage[usage.component];
400
419
  if (!component.phases[usage.phase]) {
401
420
  component.phases[usage.phase] = {
402
- total: {
403
- inputTokens: 0,
404
- outputTokens: 0,
405
- totalTokens: 0
406
- },
421
+ primary: /* @__PURE__ */ new Map(),
422
+ fallback: /* @__PURE__ */ new Map(),
423
+ total: emptyUsage(),
407
424
  metadata: []
408
425
  };
409
426
  }
@@ -412,41 +429,17 @@ var LLMTokenUsageAggregator = class {
412
429
  phase.metadata.push(usage.metadata);
413
430
  }
414
431
  if (usage.model === "primary") {
415
- if (!phase.primary) {
416
- phase.primary = {
417
- modelName: usage.modelName,
418
- inputTokens: 0,
419
- outputTokens: 0,
420
- totalTokens: 0
421
- };
422
- }
423
- phase.primary.inputTokens += usage.inputTokens;
424
- phase.primary.outputTokens += usage.outputTokens;
425
- phase.primary.totalTokens += usage.totalTokens;
432
+ accumulateModel(phase.primary, usage.modelName, usage);
426
433
  } else if (usage.model === "fallback") {
427
- if (!phase.fallback) {
428
- phase.fallback = {
429
- modelName: usage.modelName,
430
- inputTokens: 0,
431
- outputTokens: 0,
432
- totalTokens: 0
433
- };
434
- }
435
- phase.fallback.inputTokens += usage.inputTokens;
436
- phase.fallback.outputTokens += usage.outputTokens;
437
- phase.fallback.totalTokens += usage.totalTokens;
434
+ accumulateModel(phase.fallback, usage.modelName, usage);
438
435
  }
439
- phase.total.inputTokens += usage.inputTokens;
440
- phase.total.outputTokens += usage.outputTokens;
441
- phase.total.totalTokens += usage.totalTokens;
442
- component.total.inputTokens += usage.inputTokens;
443
- component.total.outputTokens += usage.outputTokens;
444
- component.total.totalTokens += usage.totalTokens;
436
+ addInto(phase.total, usage);
437
+ addInto(component.total, usage);
445
438
  }
446
439
  /**
447
440
  * Get aggregated usage grouped by component
448
441
  *
449
- * @returns Array of component aggregates with phase breakdown
442
+ * @returns Array of component aggregates with per-model phase breakdown
450
443
  */
451
444
  getByComponent() {
452
445
  return Object.values(this.usage);
@@ -455,8 +448,16 @@ var LLMTokenUsageAggregator = class {
455
448
  * Get token usage report in structured JSON format
456
449
  *
457
450
  * Converts internal usage data to external TokenUsageReport format suitable
458
- * for serialization and reporting. The report includes component breakdown,
459
- * phase-level details, and both primary and fallback model usage.
451
+ * for serialization and reporting.
452
+ *
453
+ * Each (phase, model) pair becomes its own PhaseUsageReport entry. A phase
454
+ * that used a single primary (and/or a single fallback) model yields exactly
455
+ * one entry — identical to the legacy shape — while a phase that mixed models
456
+ * yields one entry per model, all sharing the same `phase` name. Every
457
+ * (phase, tier, modelName) combination appears in exactly one entry, so
458
+ * consumers that key by `${component}|${phase}|${tier}|${modelName}`
459
+ * (heripo-web's token-usage emitter / ledger recorder) attribute each model's
460
+ * tokens — and cost — correctly without double counting.
460
461
  *
461
462
  * @returns Structured token usage report with components and total
462
463
  */
@@ -465,34 +466,41 @@ var LLMTokenUsageAggregator = class {
465
466
  for (const component of Object.values(this.usage)) {
466
467
  const phases = [];
467
468
  for (const [phaseName, phaseData] of Object.entries(component.phases)) {
468
- const phaseReport = {
469
- phase: phaseName,
470
- total: {
471
- inputTokens: phaseData.total.inputTokens,
472
- outputTokens: phaseData.total.outputTokens,
473
- totalTokens: phaseData.total.totalTokens
474
- }
475
- };
476
- if (phaseData.metadata.length > 0) {
477
- phaseReport.metadata = [...phaseData.metadata];
478
- }
479
- if (phaseData.primary) {
480
- phaseReport.primary = {
481
- modelName: phaseData.primary.modelName,
482
- inputTokens: phaseData.primary.inputTokens,
483
- outputTokens: phaseData.primary.outputTokens,
484
- totalTokens: phaseData.primary.totalTokens
469
+ const primaryEntries = [...phaseData.primary.entries()];
470
+ const fallbackEntries = [...phaseData.fallback.entries()];
471
+ const entryCount = Math.max(
472
+ primaryEntries.length,
473
+ fallbackEntries.length
474
+ );
475
+ if (entryCount === 0) {
476
+ const phaseReport = {
477
+ phase: phaseName,
478
+ total: { ...phaseData.total }
485
479
  };
480
+ if (phaseData.metadata.length > 0) {
481
+ phaseReport.metadata = [...phaseData.metadata];
482
+ }
483
+ phases.push(phaseReport);
484
+ continue;
486
485
  }
487
- if (phaseData.fallback) {
488
- phaseReport.fallback = {
489
- modelName: phaseData.fallback.modelName,
490
- inputTokens: phaseData.fallback.inputTokens,
491
- outputTokens: phaseData.fallback.outputTokens,
492
- totalTokens: phaseData.fallback.totalTokens
486
+ for (let i = 0; i < entryCount; i++) {
487
+ const primary = primaryEntries[i];
488
+ const fallback = fallbackEntries[i];
489
+ const phaseReport = {
490
+ phase: phaseName,
491
+ total: sumUsage(primary?.[1], fallback?.[1])
493
492
  };
493
+ if (primary) {
494
+ phaseReport.primary = { modelName: primary[0], ...primary[1] };
495
+ }
496
+ if (fallback) {
497
+ phaseReport.fallback = { modelName: fallback[0], ...fallback[1] };
498
+ }
499
+ if (i === 0 && phaseData.metadata.length > 0) {
500
+ phaseReport.metadata = [...phaseData.metadata];
501
+ }
502
+ phases.push(phaseReport);
494
503
  }
495
- phases.push(phaseReport);
496
504
  }
497
505
  components.push({
498
506
  component: component.component,
@@ -537,8 +545,8 @@ var LLMTokenUsageAggregator = class {
537
545
  /**
538
546
  * Log comprehensive token usage summary
539
547
  *
540
- * Outputs usage grouped by component, with phase and model breakdown.
541
- * Shows primary and fallback token usage separately for each phase.
548
+ * Outputs usage grouped by component, with phase and per-model breakdown.
549
+ * Shows each primary and fallback model on its own line for each phase.
542
550
  * Call this once at the end of document processing.
543
551
  *
544
552
  * @param logger - Logger instance for output
@@ -554,31 +562,23 @@ var LLMTokenUsageAggregator = class {
554
562
  let grandInputTokens = 0;
555
563
  let grandOutputTokens = 0;
556
564
  let grandTotalTokens = 0;
557
- let grandPrimaryInputTokens = 0;
558
- let grandPrimaryOutputTokens = 0;
559
- let grandPrimaryTotalTokens = 0;
560
- let grandFallbackInputTokens = 0;
561
- let grandFallbackOutputTokens = 0;
562
- let grandFallbackTotalTokens = 0;
565
+ const grandPrimary = emptyUsage();
566
+ const grandFallback = emptyUsage();
563
567
  for (const component of components) {
564
568
  logger.info(`${component.component}:`);
565
- for (const [phase, phaseData] of Object.entries(component.phases)) {
566
- logger.info(` - ${phase}:`);
567
- if (phaseData.primary) {
569
+ for (const [phaseName, phaseData] of Object.entries(component.phases)) {
570
+ logger.info(` - ${phaseName}:`);
571
+ for (const [modelName, modelUsage] of phaseData.primary) {
568
572
  logger.info(
569
- ` primary (${phaseData.primary.modelName}): ${formatTokens(phaseData.primary)}`
573
+ ` primary (${modelName}): ${formatTokens(modelUsage)}`
570
574
  );
571
- grandPrimaryInputTokens += phaseData.primary.inputTokens;
572
- grandPrimaryOutputTokens += phaseData.primary.outputTokens;
573
- grandPrimaryTotalTokens += phaseData.primary.totalTokens;
575
+ addInto(grandPrimary, modelUsage);
574
576
  }
575
- if (phaseData.fallback) {
577
+ for (const [modelName, modelUsage] of phaseData.fallback) {
576
578
  logger.info(
577
- ` fallback (${phaseData.fallback.modelName}): ${formatTokens(phaseData.fallback)}`
579
+ ` fallback (${modelName}): ${formatTokens(modelUsage)}`
578
580
  );
579
- grandFallbackInputTokens += phaseData.fallback.inputTokens;
580
- grandFallbackOutputTokens += phaseData.fallback.outputTokens;
581
- grandFallbackTotalTokens += phaseData.fallback.totalTokens;
581
+ addInto(grandFallback, modelUsage);
582
582
  }
583
583
  logger.info(` subtotal: ${formatTokens(phaseData.total)}`);
584
584
  }
@@ -591,23 +591,11 @@ var LLMTokenUsageAggregator = class {
591
591
  grandTotalTokens += component.total.totalTokens;
592
592
  }
593
593
  logger.info("--- Summary ---");
594
- if (grandPrimaryTotalTokens > 0) {
595
- logger.info(
596
- `Primary total: ${formatTokens({
597
- inputTokens: grandPrimaryInputTokens,
598
- outputTokens: grandPrimaryOutputTokens,
599
- totalTokens: grandPrimaryTotalTokens
600
- })}`
601
- );
594
+ if (grandPrimary.totalTokens > 0) {
595
+ logger.info(`Primary total: ${formatTokens(grandPrimary)}`);
602
596
  }
603
- if (grandFallbackTotalTokens > 0) {
604
- logger.info(
605
- `Fallback total: ${formatTokens({
606
- inputTokens: grandFallbackInputTokens,
607
- outputTokens: grandFallbackOutputTokens,
608
- totalTokens: grandFallbackTotalTokens
609
- })}`
610
- );
597
+ if (grandFallback.totalTokens > 0) {
598
+ logger.info(`Fallback total: ${formatTokens(grandFallback)}`);
611
599
  }
612
600
  logger.info(
613
601
  `Grand total: ${formatTokens({