@okf/ootils 1.31.5 → 1.32.1

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.
@@ -1418,6 +1418,15 @@ declare const UI_CONTENT: {
1418
1418
  */
1419
1419
  declare const genCleanCamelCaseId: (id: string) => string;
1420
1420
 
1421
+ /**
1422
+ * Convert a plain text string into the standard Lexical value shape
1423
+ * used across the platform: { allText, isLexical, editorState }.
1424
+ *
1425
+ * If the value is already Lexical (has `isLexical: true`), returns it as-is.
1426
+ * Each line in the text becomes its own paragraph node.
1427
+ */
1428
+ declare const plainTextToLexical: (value: string | number | any) => any;
1429
+
1421
1430
  /**
1422
1431
  * BlockDef — single source of truth for a tplBlock's cross-cutting configuration.
1423
1432
  *
@@ -1429,6 +1438,18 @@ interface BlockDef {
1429
1438
  compName: string;
1430
1439
  category: 'text' | 'selection' | 'tags' | 'date' | 'number' | 'media' | 'structural' | 'special';
1431
1440
  qualQuant: 'qual' | 'quant' | null;
1441
+ /**
1442
+ * Optional gate that downgrades a block instance from its declared qualQuant unless
1443
+ * ALL conditions match. Used for blocks whose qual-ness depends on a per-instance prop
1444
+ * (e.g. AudioInput is only qual when `props.transcription.enable === true`).
1445
+ *
1446
+ * Each condition is a dotted path into `block.props` with a required value.
1447
+ * No conditions / undefined → block's qualQuant applies unconditionally.
1448
+ */
1449
+ qualConditions?: Array<{
1450
+ propPath: string;
1451
+ equals: any;
1452
+ }>;
1432
1453
  /** Mongoose schema type — the actual value returned to compToTypeMap (e.g. { type: Object }) */
1433
1454
  mongoSchemaType: Record<string, any>;
1434
1455
  /** Elasticsearch mapping shape — used directly by generateMappingsFromTpl */
@@ -1440,8 +1461,6 @@ interface BlockDef {
1440
1461
  plainTextString?: string | null;
1441
1462
  /** Path appended to valuePath for ES/listing search (e.g. 'allText'). null = valuePath used directly. */
1442
1463
  searchField?: string | null;
1443
- /** Path to get display value for table/card rendering (e.g. 'allText'). null = value itself. */
1444
- displayValue?: string | null;
1445
1464
  };
1446
1465
  validation: {
1447
1466
  /** Name of the "is populated" validator fn (resolved by consumer) */
@@ -1559,6 +1578,9 @@ declare const MONGO_SCHEMA_PRESETS: {
1559
1578
  readonly string: {
1560
1579
  readonly type: StringConstructor;
1561
1580
  };
1581
+ readonly array: {
1582
+ readonly type: ArrayConstructor;
1583
+ };
1562
1584
  };
1563
1585
  declare const ELASTIC_MAPPING_PRESETS: {
1564
1586
  readonly largeText: {
@@ -1569,6 +1591,26 @@ declare const ELASTIC_MAPPING_PRESETS: {
1569
1591
  };
1570
1592
  };
1571
1593
  };
1594
+ readonly audioTranscription: {
1595
+ readonly properties: {
1596
+ readonly transcription: {
1597
+ readonly properties: {
1598
+ readonly result: {
1599
+ readonly properties: {
1600
+ readonly finalText: {
1601
+ readonly properties: {
1602
+ readonly allText: {
1603
+ readonly type: "text";
1604
+ readonly analyzer: "LargeTextAnalyzer";
1605
+ };
1606
+ };
1607
+ };
1608
+ };
1609
+ };
1610
+ };
1611
+ };
1612
+ };
1613
+ };
1572
1614
  };
1573
1615
  declare const CHUNKING_PRESETS: {
1574
1616
  readonly lexicalSemantic: {
@@ -1609,8 +1651,24 @@ declare class BlockRegistry {
1609
1651
  getQualBlocks(): string[];
1610
1652
  /** Get compType strings for all quant blocks. */
1611
1653
  getQuantBlocks(): string[];
1654
+ /**
1655
+ * Returns true if a specific block instance should be treated as qualitative.
1656
+ * Combines the static `qualQuant` flag with any per-instance `qualConditions`
1657
+ * — e.g. AudioInput is only qual when `props.transcription.enable === true`.
1658
+ */
1659
+ isQualBlock(block: {
1660
+ comp: string;
1661
+ props?: any;
1662
+ }): boolean;
1612
1663
  /** Check if a specific block has a specific capability. */
1613
1664
  hasCapability(compType: string, capability: keyof BlockCapabilities): boolean;
1665
+ /**
1666
+ * Returns true if the block stores its value as an array (Mongo schema type is Array).
1667
+ * Useful for callers that need to know whether to query `valuePath.0` for existence
1668
+ * vs just `valuePath` — empty arrays still pass `$exists: true` on the field itself.
1669
+ * Returns false for unregistered blocks.
1670
+ */
1671
+ isArrayShaped(compType: string): boolean;
1614
1672
  /** Get all registered block descriptors. */
1615
1673
  getAll(): BlockDef[];
1616
1674
  /**
@@ -1657,4 +1715,4 @@ declare class BlockRegistry {
1657
1715
  /** Singleton instance — the one registry shared across the app. */
1658
1716
  declare const blockRegistry: BlockRegistry;
1659
1717
 
1660
- export { BASE_BULLMQ_CONFIG, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ELASTIC_MAPPING_PRESETS, FILTER_IDS, MONGO_SCHEMA_PRESETS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1718
+ export { BASE_BULLMQ_CONFIG, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ELASTIC_MAPPING_PRESETS, FILTER_IDS, MONGO_SCHEMA_PRESETS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.d.ts CHANGED
@@ -1418,6 +1418,15 @@ declare const UI_CONTENT: {
1418
1418
  */
1419
1419
  declare const genCleanCamelCaseId: (id: string) => string;
1420
1420
 
1421
+ /**
1422
+ * Convert a plain text string into the standard Lexical value shape
1423
+ * used across the platform: { allText, isLexical, editorState }.
1424
+ *
1425
+ * If the value is already Lexical (has `isLexical: true`), returns it as-is.
1426
+ * Each line in the text becomes its own paragraph node.
1427
+ */
1428
+ declare const plainTextToLexical: (value: string | number | any) => any;
1429
+
1421
1430
  /**
1422
1431
  * BlockDef — single source of truth for a tplBlock's cross-cutting configuration.
1423
1432
  *
@@ -1429,6 +1438,18 @@ interface BlockDef {
1429
1438
  compName: string;
1430
1439
  category: 'text' | 'selection' | 'tags' | 'date' | 'number' | 'media' | 'structural' | 'special';
1431
1440
  qualQuant: 'qual' | 'quant' | null;
1441
+ /**
1442
+ * Optional gate that downgrades a block instance from its declared qualQuant unless
1443
+ * ALL conditions match. Used for blocks whose qual-ness depends on a per-instance prop
1444
+ * (e.g. AudioInput is only qual when `props.transcription.enable === true`).
1445
+ *
1446
+ * Each condition is a dotted path into `block.props` with a required value.
1447
+ * No conditions / undefined → block's qualQuant applies unconditionally.
1448
+ */
1449
+ qualConditions?: Array<{
1450
+ propPath: string;
1451
+ equals: any;
1452
+ }>;
1432
1453
  /** Mongoose schema type — the actual value returned to compToTypeMap (e.g. { type: Object }) */
1433
1454
  mongoSchemaType: Record<string, any>;
1434
1455
  /** Elasticsearch mapping shape — used directly by generateMappingsFromTpl */
@@ -1440,8 +1461,6 @@ interface BlockDef {
1440
1461
  plainTextString?: string | null;
1441
1462
  /** Path appended to valuePath for ES/listing search (e.g. 'allText'). null = valuePath used directly. */
1442
1463
  searchField?: string | null;
1443
- /** Path to get display value for table/card rendering (e.g. 'allText'). null = value itself. */
1444
- displayValue?: string | null;
1445
1464
  };
1446
1465
  validation: {
1447
1466
  /** Name of the "is populated" validator fn (resolved by consumer) */
@@ -1559,6 +1578,9 @@ declare const MONGO_SCHEMA_PRESETS: {
1559
1578
  readonly string: {
1560
1579
  readonly type: StringConstructor;
1561
1580
  };
1581
+ readonly array: {
1582
+ readonly type: ArrayConstructor;
1583
+ };
1562
1584
  };
1563
1585
  declare const ELASTIC_MAPPING_PRESETS: {
1564
1586
  readonly largeText: {
@@ -1569,6 +1591,26 @@ declare const ELASTIC_MAPPING_PRESETS: {
1569
1591
  };
1570
1592
  };
1571
1593
  };
1594
+ readonly audioTranscription: {
1595
+ readonly properties: {
1596
+ readonly transcription: {
1597
+ readonly properties: {
1598
+ readonly result: {
1599
+ readonly properties: {
1600
+ readonly finalText: {
1601
+ readonly properties: {
1602
+ readonly allText: {
1603
+ readonly type: "text";
1604
+ readonly analyzer: "LargeTextAnalyzer";
1605
+ };
1606
+ };
1607
+ };
1608
+ };
1609
+ };
1610
+ };
1611
+ };
1612
+ };
1613
+ };
1572
1614
  };
1573
1615
  declare const CHUNKING_PRESETS: {
1574
1616
  readonly lexicalSemantic: {
@@ -1609,8 +1651,24 @@ declare class BlockRegistry {
1609
1651
  getQualBlocks(): string[];
1610
1652
  /** Get compType strings for all quant blocks. */
1611
1653
  getQuantBlocks(): string[];
1654
+ /**
1655
+ * Returns true if a specific block instance should be treated as qualitative.
1656
+ * Combines the static `qualQuant` flag with any per-instance `qualConditions`
1657
+ * — e.g. AudioInput is only qual when `props.transcription.enable === true`.
1658
+ */
1659
+ isQualBlock(block: {
1660
+ comp: string;
1661
+ props?: any;
1662
+ }): boolean;
1612
1663
  /** Check if a specific block has a specific capability. */
1613
1664
  hasCapability(compType: string, capability: keyof BlockCapabilities): boolean;
1665
+ /**
1666
+ * Returns true if the block stores its value as an array (Mongo schema type is Array).
1667
+ * Useful for callers that need to know whether to query `valuePath.0` for existence
1668
+ * vs just `valuePath` — empty arrays still pass `$exists: true` on the field itself.
1669
+ * Returns false for unregistered blocks.
1670
+ */
1671
+ isArrayShaped(compType: string): boolean;
1614
1672
  /** Get all registered block descriptors. */
1615
1673
  getAll(): BlockDef[];
1616
1674
  /**
@@ -1657,4 +1715,4 @@ declare class BlockRegistry {
1657
1715
  /** Singleton instance — the one registry shared across the app. */
1658
1716
  declare const blockRegistry: BlockRegistry;
1659
1717
 
1660
- export { BASE_BULLMQ_CONFIG, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ELASTIC_MAPPING_PRESETS, FILTER_IDS, MONGO_SCHEMA_PRESETS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1718
+ export { BASE_BULLMQ_CONFIG, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ELASTIC_MAPPING_PRESETS, FILTER_IDS, MONGO_SCHEMA_PRESETS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.js CHANGED
@@ -57,6 +57,7 @@ __export(browser_exports, {
57
57
  isTplAnnotationEnabled: () => isTplAnnotationEnabled,
58
58
  mergeAnnoDataIntoAnnotationsTags: () => mergeAnnoDataIntoAnnotationsTags,
59
59
  parseSpecialConfigSyntax: () => parseSpecialConfigSyntax,
60
+ plainTextToLexical: () => plainTextToLexical,
60
61
  processAuthorAndCommonFilters: () => processAuthorAndCommonFilters,
61
62
  recursivelyExtractBlocks: () => _recursExtractBlocks,
62
63
  segrigateDocs: () => segrigateDocs,
@@ -379,7 +380,8 @@ var _extractBlocksFromSomeBuilders = ({
379
380
  // src/blockRegistry/schemaPresets.ts
380
381
  var MONGO_SCHEMA_PRESETS = {
381
382
  object: { type: Object },
382
- string: { type: String }
383
+ string: { type: String },
384
+ array: { type: Array }
383
385
  };
384
386
  var ELASTIC_MAPPING_PRESETS = {
385
387
  largeText: {
@@ -389,6 +391,29 @@ var ELASTIC_MAPPING_PRESETS = {
389
391
  analyzer: "LargeTextAnalyzer"
390
392
  }
391
393
  }
394
+ },
395
+ // Audio file value (array of one object) — only the transcription.result.finalText.allText
396
+ // is indexed as searchable text. finalText is stored in Lexical shape; allText is the
397
+ // plain text within it. Everything else on the audio object is ignored by ES.
398
+ audioTranscription: {
399
+ properties: {
400
+ transcription: {
401
+ properties: {
402
+ result: {
403
+ properties: {
404
+ finalText: {
405
+ properties: {
406
+ allText: {
407
+ type: "text",
408
+ analyzer: "LargeTextAnalyzer"
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
392
417
  }
393
418
  };
394
419
  var CHUNKING_PRESETS = {
@@ -430,8 +455,7 @@ var LexicalTextEditor = {
430
455
  // Field paths
431
456
  fieldPaths: {
432
457
  plainTextString: "allText",
433
- searchField: "allText",
434
- displayValue: "allText"
458
+ searchField: "allText"
435
459
  },
436
460
  // Validation
437
461
  validation: {
@@ -469,11 +493,72 @@ var LexicalTextEditor = {
469
493
  chunkingConfig: CHUNKING_PRESETS.lexicalSemantic
470
494
  };
471
495
 
496
+ // src/blockRegistry/blocks/AudioInput.ts
497
+ var AudioInput = {
498
+ compName: "AudioInput",
499
+ // Identity
500
+ category: "media",
501
+ qualQuant: "qual",
502
+ // Only qualitative when the tpl block has transcription turned on.
503
+ // A non-transcribed audio input has no text to analyze, so downstream
504
+ // qual widgets / search tools should skip it.
505
+ qualConditions: [
506
+ { propPath: "transcription.enable", equals: true }
507
+ ],
508
+ // Schema
509
+ mongoSchemaType: MONGO_SCHEMA_PRESETS.array,
510
+ esMapping: ELASTIC_MAPPING_PRESETS.audioTranscription,
511
+ // Capabilities
512
+ capabilities: {
513
+ // Text lives at transcription.result.finalText on the first (and only) audio item,
514
+ // derived by the Sarvam adapter into a single canonical field.
515
+ hasPlainText: true,
516
+ annotation: true,
517
+ aiAnnotation: true,
518
+ aiEnrichment: true,
519
+ searchable: true,
520
+ directDataImport: false,
521
+ csvExport: true,
522
+ // Translation already happens at the Sarvam level via translateToEnglish flag,
523
+ // so the autoTranslate pipeline doesn't need to touch this block.
524
+ translatable: false,
525
+ documentSummarizer: true,
526
+ // Transcription payloads can be large — strip from chunk/anno main snapshots
527
+ // and listing projections.
528
+ stripFromMainOnAnnoChunkSync: true,
529
+ excludeFromListingProjection: true
530
+ },
531
+ // Field paths
532
+ // `plainTextString` is the Mongo path consumed by getVal (supports the leading
533
+ // array index). `searchField` is the ES path — ES flattens arrays of objects
534
+ // so no index is needed there.
535
+ fieldPaths: {
536
+ plainTextString: "0.transcription.result.finalText.allText",
537
+ searchField: "transcription.result.finalText.allText"
538
+ },
539
+ // Validation
540
+ validation: {
541
+ populatedCheckFn: "valueArrayIsNotEmpty"
542
+ },
543
+ // CSV export — existing transformStructureComp switch routes AudioInput to
544
+ // formatMediaLinks (outputs audio URLs).
545
+ csvExport: {
546
+ transformFn: "formatMediaLinks"
547
+ },
548
+ // Chunking — finalText is long free-form speech, so semantic chunking applies.
549
+ chunkingConfig: CHUNKING_PRESETS.lexicalSemantic,
550
+ // Content block option — matches the current static entry exactly
551
+ contentBlockOption: {
552
+ display: "Audio Input"
553
+ }
554
+ };
555
+
472
556
  // src/blockRegistry/registry.ts
473
557
  var BlockRegistry = class {
474
558
  constructor() {
475
559
  this.blocks = /* @__PURE__ */ new Map();
476
560
  this.register(LexicalTextEditor);
561
+ this.register(AudioInput);
477
562
  }
478
563
  /** Register a block descriptor. */
479
564
  register(descriptor) {
@@ -520,12 +605,36 @@ var BlockRegistry = class {
520
605
  getQuantBlocks() {
521
606
  return Array.from(this.blocks.values()).filter((b) => b.qualQuant === "quant").map((b) => b.compName);
522
607
  }
608
+ /**
609
+ * Returns true if a specific block instance should be treated as qualitative.
610
+ * Combines the static `qualQuant` flag with any per-instance `qualConditions`
611
+ * — e.g. AudioInput is only qual when `props.transcription.enable === true`.
612
+ */
613
+ isQualBlock(block) {
614
+ const def = this.blocks.get(block.comp);
615
+ if (!def || def.qualQuant !== "qual") return false;
616
+ if (!def.qualConditions?.length) return true;
617
+ return def.qualConditions.every((cond) => {
618
+ const value = cond.propPath.split(".").reduce((obj, key) => obj?.[key], block.props);
619
+ return value === cond.equals;
620
+ });
621
+ }
523
622
  /** Check if a specific block has a specific capability. */
524
623
  hasCapability(compType, capability) {
525
624
  const block = this.blocks.get(compType);
526
625
  if (!block) return false;
527
626
  return !!block.capabilities[capability];
528
627
  }
628
+ /**
629
+ * Returns true if the block stores its value as an array (Mongo schema type is Array).
630
+ * Useful for callers that need to know whether to query `valuePath.0` for existence
631
+ * vs just `valuePath` — empty arrays still pass `$exists: true` on the field itself.
632
+ * Returns false for unregistered blocks.
633
+ */
634
+ isArrayShaped(compType) {
635
+ const def = this.blocks.get(compType);
636
+ return def?.mongoSchemaType?.type === Array;
637
+ }
529
638
  /** Get all registered block descriptors. */
530
639
  getAll() {
531
640
  return Array.from(this.blocks.values());
@@ -2466,6 +2575,38 @@ var genCleanCamelCaseId = (id) => {
2466
2575
  if (/^\d/.test(result)) result = "a" + result;
2467
2576
  return result.slice(0, MAX_LENGTH);
2468
2577
  };
2578
+
2579
+ // src/utils/plainTextToLexical.ts
2580
+ var plainTextToLexical = (value) => {
2581
+ if (!value && value !== 0) return void 0;
2582
+ if (value?.isLexical === true) return value;
2583
+ if (typeof value !== "string" && typeof value !== "number") return void 0;
2584
+ const text = String(value);
2585
+ const lines = text.split(/\r?\n/);
2586
+ const paragraphNodes = lines.map((line) => ({
2587
+ type: "paragraph",
2588
+ children: [
2589
+ {
2590
+ type: "text",
2591
+ text: line
2592
+ }
2593
+ ]
2594
+ }));
2595
+ return {
2596
+ allText: text,
2597
+ isLexical: true,
2598
+ editorState: {
2599
+ root: {
2600
+ children: paragraphNodes,
2601
+ direction: "ltr",
2602
+ format: "",
2603
+ indent: 0,
2604
+ type: "root",
2605
+ version: 1
2606
+ }
2607
+ }
2608
+ };
2609
+ };
2469
2610
  // Annotate the CommonJS export names for ESM import in node:
2470
2611
  0 && (module.exports = {
2471
2612
  BASE_BULLMQ_CONFIG,
@@ -2505,6 +2646,7 @@ var genCleanCamelCaseId = (id) => {
2505
2646
  isTplAnnotationEnabled,
2506
2647
  mergeAnnoDataIntoAnnotationsTags,
2507
2648
  parseSpecialConfigSyntax,
2649
+ plainTextToLexical,
2508
2650
  processAuthorAndCommonFilters,
2509
2651
  recursivelyExtractBlocks,
2510
2652
  segrigateDocs,
package/dist/browser.mjs CHANGED
@@ -312,7 +312,8 @@ var _extractBlocksFromSomeBuilders = ({
312
312
  // src/blockRegistry/schemaPresets.ts
313
313
  var MONGO_SCHEMA_PRESETS = {
314
314
  object: { type: Object },
315
- string: { type: String }
315
+ string: { type: String },
316
+ array: { type: Array }
316
317
  };
317
318
  var ELASTIC_MAPPING_PRESETS = {
318
319
  largeText: {
@@ -322,6 +323,29 @@ var ELASTIC_MAPPING_PRESETS = {
322
323
  analyzer: "LargeTextAnalyzer"
323
324
  }
324
325
  }
326
+ },
327
+ // Audio file value (array of one object) — only the transcription.result.finalText.allText
328
+ // is indexed as searchable text. finalText is stored in Lexical shape; allText is the
329
+ // plain text within it. Everything else on the audio object is ignored by ES.
330
+ audioTranscription: {
331
+ properties: {
332
+ transcription: {
333
+ properties: {
334
+ result: {
335
+ properties: {
336
+ finalText: {
337
+ properties: {
338
+ allText: {
339
+ type: "text",
340
+ analyzer: "LargeTextAnalyzer"
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
325
349
  }
326
350
  };
327
351
  var CHUNKING_PRESETS = {
@@ -363,8 +387,7 @@ var LexicalTextEditor = {
363
387
  // Field paths
364
388
  fieldPaths: {
365
389
  plainTextString: "allText",
366
- searchField: "allText",
367
- displayValue: "allText"
390
+ searchField: "allText"
368
391
  },
369
392
  // Validation
370
393
  validation: {
@@ -402,11 +425,72 @@ var LexicalTextEditor = {
402
425
  chunkingConfig: CHUNKING_PRESETS.lexicalSemantic
403
426
  };
404
427
 
428
+ // src/blockRegistry/blocks/AudioInput.ts
429
+ var AudioInput = {
430
+ compName: "AudioInput",
431
+ // Identity
432
+ category: "media",
433
+ qualQuant: "qual",
434
+ // Only qualitative when the tpl block has transcription turned on.
435
+ // A non-transcribed audio input has no text to analyze, so downstream
436
+ // qual widgets / search tools should skip it.
437
+ qualConditions: [
438
+ { propPath: "transcription.enable", equals: true }
439
+ ],
440
+ // Schema
441
+ mongoSchemaType: MONGO_SCHEMA_PRESETS.array,
442
+ esMapping: ELASTIC_MAPPING_PRESETS.audioTranscription,
443
+ // Capabilities
444
+ capabilities: {
445
+ // Text lives at transcription.result.finalText on the first (and only) audio item,
446
+ // derived by the Sarvam adapter into a single canonical field.
447
+ hasPlainText: true,
448
+ annotation: true,
449
+ aiAnnotation: true,
450
+ aiEnrichment: true,
451
+ searchable: true,
452
+ directDataImport: false,
453
+ csvExport: true,
454
+ // Translation already happens at the Sarvam level via translateToEnglish flag,
455
+ // so the autoTranslate pipeline doesn't need to touch this block.
456
+ translatable: false,
457
+ documentSummarizer: true,
458
+ // Transcription payloads can be large — strip from chunk/anno main snapshots
459
+ // and listing projections.
460
+ stripFromMainOnAnnoChunkSync: true,
461
+ excludeFromListingProjection: true
462
+ },
463
+ // Field paths
464
+ // `plainTextString` is the Mongo path consumed by getVal (supports the leading
465
+ // array index). `searchField` is the ES path — ES flattens arrays of objects
466
+ // so no index is needed there.
467
+ fieldPaths: {
468
+ plainTextString: "0.transcription.result.finalText.allText",
469
+ searchField: "transcription.result.finalText.allText"
470
+ },
471
+ // Validation
472
+ validation: {
473
+ populatedCheckFn: "valueArrayIsNotEmpty"
474
+ },
475
+ // CSV export — existing transformStructureComp switch routes AudioInput to
476
+ // formatMediaLinks (outputs audio URLs).
477
+ csvExport: {
478
+ transformFn: "formatMediaLinks"
479
+ },
480
+ // Chunking — finalText is long free-form speech, so semantic chunking applies.
481
+ chunkingConfig: CHUNKING_PRESETS.lexicalSemantic,
482
+ // Content block option — matches the current static entry exactly
483
+ contentBlockOption: {
484
+ display: "Audio Input"
485
+ }
486
+ };
487
+
405
488
  // src/blockRegistry/registry.ts
406
489
  var BlockRegistry = class {
407
490
  constructor() {
408
491
  this.blocks = /* @__PURE__ */ new Map();
409
492
  this.register(LexicalTextEditor);
493
+ this.register(AudioInput);
410
494
  }
411
495
  /** Register a block descriptor. */
412
496
  register(descriptor) {
@@ -453,12 +537,36 @@ var BlockRegistry = class {
453
537
  getQuantBlocks() {
454
538
  return Array.from(this.blocks.values()).filter((b) => b.qualQuant === "quant").map((b) => b.compName);
455
539
  }
540
+ /**
541
+ * Returns true if a specific block instance should be treated as qualitative.
542
+ * Combines the static `qualQuant` flag with any per-instance `qualConditions`
543
+ * — e.g. AudioInput is only qual when `props.transcription.enable === true`.
544
+ */
545
+ isQualBlock(block) {
546
+ const def = this.blocks.get(block.comp);
547
+ if (!def || def.qualQuant !== "qual") return false;
548
+ if (!def.qualConditions?.length) return true;
549
+ return def.qualConditions.every((cond) => {
550
+ const value = cond.propPath.split(".").reduce((obj, key) => obj?.[key], block.props);
551
+ return value === cond.equals;
552
+ });
553
+ }
456
554
  /** Check if a specific block has a specific capability. */
457
555
  hasCapability(compType, capability) {
458
556
  const block = this.blocks.get(compType);
459
557
  if (!block) return false;
460
558
  return !!block.capabilities[capability];
461
559
  }
560
+ /**
561
+ * Returns true if the block stores its value as an array (Mongo schema type is Array).
562
+ * Useful for callers that need to know whether to query `valuePath.0` for existence
563
+ * vs just `valuePath` — empty arrays still pass `$exists: true` on the field itself.
564
+ * Returns false for unregistered blocks.
565
+ */
566
+ isArrayShaped(compType) {
567
+ const def = this.blocks.get(compType);
568
+ return def?.mongoSchemaType?.type === Array;
569
+ }
462
570
  /** Get all registered block descriptors. */
463
571
  getAll() {
464
572
  return Array.from(this.blocks.values());
@@ -2399,6 +2507,38 @@ var genCleanCamelCaseId = (id) => {
2399
2507
  if (/^\d/.test(result)) result = "a" + result;
2400
2508
  return result.slice(0, MAX_LENGTH);
2401
2509
  };
2510
+
2511
+ // src/utils/plainTextToLexical.ts
2512
+ var plainTextToLexical = (value) => {
2513
+ if (!value && value !== 0) return void 0;
2514
+ if (value?.isLexical === true) return value;
2515
+ if (typeof value !== "string" && typeof value !== "number") return void 0;
2516
+ const text = String(value);
2517
+ const lines = text.split(/\r?\n/);
2518
+ const paragraphNodes = lines.map((line) => ({
2519
+ type: "paragraph",
2520
+ children: [
2521
+ {
2522
+ type: "text",
2523
+ text: line
2524
+ }
2525
+ ]
2526
+ }));
2527
+ return {
2528
+ allText: text,
2529
+ isLexical: true,
2530
+ editorState: {
2531
+ root: {
2532
+ children: paragraphNodes,
2533
+ direction: "ltr",
2534
+ format: "",
2535
+ indent: 0,
2536
+ type: "root",
2537
+ version: 1
2538
+ }
2539
+ }
2540
+ };
2541
+ };
2402
2542
  export {
2403
2543
  BASE_BULLMQ_CONFIG,
2404
2544
  BlockRegistry,
@@ -2437,6 +2577,7 @@ export {
2437
2577
  isTplAnnotationEnabled,
2438
2578
  mergeAnnoDataIntoAnnotationsTags,
2439
2579
  parseSpecialConfigSyntax,
2580
+ plainTextToLexical,
2440
2581
  processAuthorAndCommonFilters,
2441
2582
  _recursExtractBlocks as recursivelyExtractBlocks,
2442
2583
  segrigateDocs,