@okf/ootils 1.32.5 → 1.32.7

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.
@@ -1308,6 +1308,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1308
1308
  scope?: string;
1309
1309
  }) => string | undefined;
1310
1310
 
1311
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1312
+ interface AnnoValueLike {
1313
+ parentThemeId?: string | null;
1314
+ parentSubThemeId?: string | null;
1315
+ }
1316
+ /**
1317
+ * Why annoFilterBucketKey exists
1318
+ * ------------------------------
1319
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1320
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1321
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1322
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1323
+ * trickle across blocks and AND/OR every value across every group together.
1324
+ *
1325
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1326
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1327
+ * bucketKey, so each block has its own independent operator. The frontend
1328
+ * grouping uses this for visual blocks; the backend uses it to build the
1329
+ * per-bucket Mongo query.
1330
+ *
1331
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1332
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1333
+ *
1334
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1335
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1336
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1337
+ */
1338
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1339
+
1311
1340
  /**
1312
1341
  * Automatically generates filter configurations from template structures.
1313
1342
  *
@@ -1802,4 +1831,4 @@ declare class BlockRegistry {
1802
1831
  /** Singleton instance — the one registry shared across the app. */
1803
1832
  declare const blockRegistry: BlockRegistry;
1804
1833
 
1805
- 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 };
1834
+ 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, getAnnoFilterBucketKey, 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
@@ -1308,6 +1308,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1308
1308
  scope?: string;
1309
1309
  }) => string | undefined;
1310
1310
 
1311
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1312
+ interface AnnoValueLike {
1313
+ parentThemeId?: string | null;
1314
+ parentSubThemeId?: string | null;
1315
+ }
1316
+ /**
1317
+ * Why annoFilterBucketKey exists
1318
+ * ------------------------------
1319
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1320
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1321
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1322
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1323
+ * trickle across blocks and AND/OR every value across every group together.
1324
+ *
1325
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1326
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1327
+ * bucketKey, so each block has its own independent operator. The frontend
1328
+ * grouping uses this for visual blocks; the backend uses it to build the
1329
+ * per-bucket Mongo query.
1330
+ *
1331
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1332
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1333
+ *
1334
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1335
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1336
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1337
+ */
1338
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1339
+
1311
1340
  /**
1312
1341
  * Automatically generates filter configurations from template structures.
1313
1342
  *
@@ -1802,4 +1831,4 @@ declare class BlockRegistry {
1802
1831
  /** Singleton instance — the one registry shared across the app. */
1803
1832
  declare const blockRegistry: BlockRegistry;
1804
1833
 
1805
- 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 };
1834
+ 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, getAnnoFilterBucketKey, 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
@@ -42,6 +42,7 @@ __export(browser_exports, {
42
42
  genCleanCamelCaseId: () => genCleanCamelCaseId,
43
43
  genTagId: () => genTagId,
44
44
  generateFilterKey: () => generateFilterKey,
45
+ getAnnoFilterBucketKey: () => getAnnoFilterBucketKey,
45
46
  getFilterKeyForBlock: () => getFilterKeyForBlock,
46
47
  getPlatformContextContent: () => getPlatformContextContent,
47
48
  getRollupPossibilities: () => getRollupPossibilities,
@@ -1007,10 +1008,11 @@ var BASE_BULLMQ_CONFIG = {
1007
1008
  }
1008
1009
  },
1009
1010
  workerConfig: {
1010
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
1011
- // across parallel jobs. Each job already processes 50 docs sequentially, and
1012
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
1013
- concurrency: 1,
1011
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
1012
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
1013
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
1014
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
1015
+ concurrency: 10,
1014
1016
  lockDuration: 3e5,
1015
1017
  // 5 minutes lock duration since annotation can be slow
1016
1018
  maxStalledCount: 3
@@ -2502,6 +2504,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
2502
2504
  return void 0;
2503
2505
  };
2504
2506
 
2507
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
2508
+ var getAnnoFilterBucketKey = (level, value = {}) => {
2509
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
2510
+ if (level === "tags") {
2511
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
2512
+ }
2513
+ return null;
2514
+ };
2515
+
2505
2516
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
2506
2517
  var autoGenFilterConfigsFromTpl = ({
2507
2518
  selectedTpls,
@@ -2688,6 +2699,7 @@ var plainTextToLexical = (value) => {
2688
2699
  genCleanCamelCaseId,
2689
2700
  genTagId,
2690
2701
  generateFilterKey,
2702
+ getAnnoFilterBucketKey,
2691
2703
  getFilterKeyForBlock,
2692
2704
  getPlatformContextContent,
2693
2705
  getRollupPossibilities,
package/dist/browser.mjs CHANGED
@@ -939,10 +939,11 @@ var BASE_BULLMQ_CONFIG = {
939
939
  }
940
940
  },
941
941
  workerConfig: {
942
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
943
- // across parallel jobs. Each job already processes 50 docs sequentially, and
944
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
945
- concurrency: 1,
942
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
943
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
944
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
945
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
946
+ concurrency: 10,
946
947
  lockDuration: 3e5,
947
948
  // 5 minutes lock duration since annotation can be slow
948
949
  maxStalledCount: 3
@@ -2434,6 +2435,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
2434
2435
  return void 0;
2435
2436
  };
2436
2437
 
2438
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
2439
+ var getAnnoFilterBucketKey = (level, value = {}) => {
2440
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
2441
+ if (level === "tags") {
2442
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
2443
+ }
2444
+ return null;
2445
+ };
2446
+
2437
2447
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
2438
2448
  var autoGenFilterConfigsFromTpl = ({
2439
2449
  selectedTpls,
@@ -2619,6 +2629,7 @@ export {
2619
2629
  genCleanCamelCaseId,
2620
2630
  genTagId,
2621
2631
  generateFilterKey,
2632
+ getAnnoFilterBucketKey,
2622
2633
  getFilterKeyForBlock,
2623
2634
  getPlatformContextContent,
2624
2635
  getRollupPossibilities,
package/dist/node.d.mts CHANGED
@@ -1315,6 +1315,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1315
1315
  scope?: string;
1316
1316
  }) => string | undefined;
1317
1317
 
1318
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1319
+ interface AnnoValueLike {
1320
+ parentThemeId?: string | null;
1321
+ parentSubThemeId?: string | null;
1322
+ }
1323
+ /**
1324
+ * Why annoFilterBucketKey exists
1325
+ * ------------------------------
1326
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1327
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1328
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1329
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1330
+ * trickle across blocks and AND/OR every value across every group together.
1331
+ *
1332
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1333
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1334
+ * bucketKey, so each block has its own independent operator. The frontend
1335
+ * grouping uses this for visual blocks; the backend uses it to build the
1336
+ * per-bucket Mongo query.
1337
+ *
1338
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1339
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1340
+ *
1341
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1342
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1343
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1344
+ */
1345
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1346
+
1318
1347
  /**
1319
1348
  * Automatically generates filter configurations from template structures.
1320
1349
  *
@@ -2543,4 +2572,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
2543
2572
  };
2544
2573
  }): Object;
2545
2574
 
2546
- export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ChunksElasticSyncProducer, ELASTIC_MAPPING_PRESETS, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MONGO_SCHEMA_PRESETS, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getTplModelByTenant, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
2575
+ export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ChunksElasticSyncProducer, ELASTIC_MAPPING_PRESETS, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MONGO_SCHEMA_PRESETS, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnoFilterBucketKey, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getTplModelByTenant, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/node.d.ts CHANGED
@@ -1315,6 +1315,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1315
1315
  scope?: string;
1316
1316
  }) => string | undefined;
1317
1317
 
1318
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1319
+ interface AnnoValueLike {
1320
+ parentThemeId?: string | null;
1321
+ parentSubThemeId?: string | null;
1322
+ }
1323
+ /**
1324
+ * Why annoFilterBucketKey exists
1325
+ * ------------------------------
1326
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1327
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1328
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1329
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1330
+ * trickle across blocks and AND/OR every value across every group together.
1331
+ *
1332
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1333
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1334
+ * bucketKey, so each block has its own independent operator. The frontend
1335
+ * grouping uses this for visual blocks; the backend uses it to build the
1336
+ * per-bucket Mongo query.
1337
+ *
1338
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1339
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1340
+ *
1341
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1342
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1343
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1344
+ */
1345
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1346
+
1318
1347
  /**
1319
1348
  * Automatically generates filter configurations from template structures.
1320
1349
  *
@@ -2543,4 +2572,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
2543
2572
  };
2544
2573
  }): Object;
2545
2574
 
2546
- export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ChunksElasticSyncProducer, ELASTIC_MAPPING_PRESETS, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MONGO_SCHEMA_PRESETS, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getTplModelByTenant, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
2575
+ export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, type BlockCapabilities, type BlockDef, BlockRegistry, CHUNKING_PRESETS, ChunksElasticSyncProducer, ELASTIC_MAPPING_PRESETS, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MONGO_SCHEMA_PRESETS, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, blockRegistry, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnoFilterBucketKey, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getTplModelByTenant, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/node.js CHANGED
@@ -265,10 +265,11 @@ var init_GLOBAL_BULLMQ_CONFIG = __esm({
265
265
  }
266
266
  },
267
267
  workerConfig: {
268
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
269
- // across parallel jobs. Each job already processes 50 docs sequentially, and
270
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
271
- concurrency: 1,
268
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
269
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
270
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
271
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
272
+ concurrency: 10,
272
273
  lockDuration: 3e5,
273
274
  // 5 minutes lock duration since annotation can be slow
274
275
  maxStalledCount: 3
@@ -2068,6 +2069,7 @@ __export(node_exports, {
2068
2069
  genTagId: () => genTagId,
2069
2070
  generateFilterKey: () => generateFilterKey,
2070
2071
  getAIChatModelByTenant: () => import_getModelByTenant2.getAIChatModelByTenant,
2072
+ getAnnoFilterBucketKey: () => getAnnoFilterBucketKey,
2071
2073
  getAnnotationsModelByTenant: () => import_getModelByTenant2.getAnnotationsModelByTenant,
2072
2074
  getDbByTenant: () => getDbByTenant,
2073
2075
  getFilterKeyForBlock: () => getFilterKeyForBlock,
@@ -4100,6 +4102,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
4100
4102
  return void 0;
4101
4103
  };
4102
4104
 
4105
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
4106
+ var getAnnoFilterBucketKey = (level, value = {}) => {
4107
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
4108
+ if (level === "tags") {
4109
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
4110
+ }
4111
+ return null;
4112
+ };
4113
+
4103
4114
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
4104
4115
  var autoGenFilterConfigsFromTpl = ({
4105
4116
  selectedTpls,
@@ -4688,6 +4699,7 @@ var import_GET_GLOBAL_BULLMQ_CONFIG = __toESM(require_GET_GLOBAL_BULLMQ_CONFIG()
4688
4699
  genTagId,
4689
4700
  generateFilterKey,
4690
4701
  getAIChatModelByTenant,
4702
+ getAnnoFilterBucketKey,
4691
4703
  getAnnotationsModelByTenant,
4692
4704
  getDbByTenant,
4693
4705
  getFilterKeyForBlock,
package/dist/node.mjs CHANGED
@@ -270,10 +270,11 @@ var init_GLOBAL_BULLMQ_CONFIG = __esm({
270
270
  }
271
271
  },
272
272
  workerConfig: {
273
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
274
- // across parallel jobs. Each job already processes 50 docs sequentially, and
275
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
276
- concurrency: 1,
273
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
274
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
275
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
276
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
277
+ concurrency: 10,
277
278
  lockDuration: 3e5,
278
279
  // 5 minutes lock duration since annotation can be slow
279
280
  maxStalledCount: 3
@@ -4031,6 +4032,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
4031
4032
  return void 0;
4032
4033
  };
4033
4034
 
4035
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
4036
+ var getAnnoFilterBucketKey = (level, value = {}) => {
4037
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
4038
+ if (level === "tags") {
4039
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
4040
+ }
4041
+ return null;
4042
+ };
4043
+
4034
4044
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
4035
4045
  var autoGenFilterConfigsFromTpl = ({
4036
4046
  selectedTpls,
@@ -4634,6 +4644,7 @@ export {
4634
4644
  genTagId,
4635
4645
  generateFilterKey,
4636
4646
  export_getAIChatModelByTenant as getAIChatModelByTenant,
4647
+ getAnnoFilterBucketKey,
4637
4648
  export_getAnnotationsModelByTenant as getAnnotationsModelByTenant,
4638
4649
  getDbByTenant,
4639
4650
  getFilterKeyForBlock,
@@ -1308,6 +1308,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1308
1308
  scope?: string;
1309
1309
  }) => string | undefined;
1310
1310
 
1311
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1312
+ interface AnnoValueLike {
1313
+ parentThemeId?: string | null;
1314
+ parentSubThemeId?: string | null;
1315
+ }
1316
+ /**
1317
+ * Why annoFilterBucketKey exists
1318
+ * ------------------------------
1319
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1320
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1321
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1322
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1323
+ * trickle across blocks and AND/OR every value across every group together.
1324
+ *
1325
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1326
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1327
+ * bucketKey, so each block has its own independent operator. The frontend
1328
+ * grouping uses this for visual blocks; the backend uses it to build the
1329
+ * per-bucket Mongo query.
1330
+ *
1331
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1332
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1333
+ *
1334
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1335
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1336
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1337
+ */
1338
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1339
+
1311
1340
  /**
1312
1341
  * Automatically generates filter configurations from template structures.
1313
1342
  *
@@ -1802,4 +1831,4 @@ declare class BlockRegistry {
1802
1831
  /** Singleton instance — the one registry shared across the app. */
1803
1832
  declare const blockRegistry: BlockRegistry;
1804
1833
 
1805
- 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 };
1834
+ 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, getAnnoFilterBucketKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToContentTypeLanding, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToMyContent, getRoutePathToPublishedContent, getRoutePathToReviewDashboard, getRoutePathToTCI, getRoutePathToTagCategoryLanding, getVal, isTplAnnotationEnabled, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, plainTextToLexical, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
@@ -1308,6 +1308,35 @@ declare const getFilterKeyForBlock: ({ block, scope }?: {
1308
1308
  scope?: string;
1309
1309
  }) => string | undefined;
1310
1310
 
1311
+ type AnnoFilterLevel = "themes" | "subThemes" | "tags";
1312
+ interface AnnoValueLike {
1313
+ parentThemeId?: string | null;
1314
+ parentSubThemeId?: string | null;
1315
+ }
1316
+ /**
1317
+ * Why annoFilterBucketKey exists
1318
+ * ------------------------------
1319
+ * In sub-themes/tags annotation filters, one activeFilter holds values that
1320
+ * span multiple ancestor groups (e.g. tags under different themes/sub-themes).
1321
+ * Each ancestor group is rendered as its own sidebar block. Without per-bucket
1322
+ * state, a single shared `intraFilterOperator` makes Match Any/All toggles
1323
+ * trickle across blocks and AND/OR every value across every group together.
1324
+ *
1325
+ * The bucketKey identifies which ancestor group a value belongs to. Sub-themes
1326
+ * and tags activeFilters carry `intraFilterOperator` as a map keyed by
1327
+ * bucketKey, so each block has its own independent operator. The frontend
1328
+ * grouping uses this for visual blocks; the backend uses it to build the
1329
+ * per-bucket Mongo query.
1330
+ *
1331
+ * Themes are exempt — there's only one themes block per activeFilter, so they
1332
+ * keep the simpler string `intraFilterOperator` (matching doc-filter behaviour).
1333
+ *
1334
+ * Pass the anno-hierarchy level name ("themes" / "subThemes" / "tags"). On the
1335
+ * frontend this comes from LEVEL_META.level on each block. On the backend this
1336
+ * is target.tagType / the leaf of rollupPath. Both carry it as that literal.
1337
+ */
1338
+ declare const getAnnoFilterBucketKey: (level: AnnoFilterLevel | string, value?: AnnoValueLike) => string | null;
1339
+
1311
1340
  /**
1312
1341
  * Automatically generates filter configurations from template structures.
1313
1342
  *
@@ -1802,4 +1831,4 @@ declare class BlockRegistry {
1802
1831
  /** Singleton instance — the one registry shared across the app. */
1803
1832
  declare const blockRegistry: BlockRegistry;
1804
1833
 
1805
- 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 };
1834
+ 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, getAnnoFilterBucketKey, 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/universal.js CHANGED
@@ -42,6 +42,7 @@ __export(universal_exports, {
42
42
  genCleanCamelCaseId: () => genCleanCamelCaseId,
43
43
  genTagId: () => genTagId,
44
44
  generateFilterKey: () => generateFilterKey,
45
+ getAnnoFilterBucketKey: () => getAnnoFilterBucketKey,
45
46
  getFilterKeyForBlock: () => getFilterKeyForBlock,
46
47
  getPlatformContextContent: () => getPlatformContextContent,
47
48
  getRollupPossibilities: () => getRollupPossibilities,
@@ -1007,10 +1008,11 @@ var BASE_BULLMQ_CONFIG = {
1007
1008
  }
1008
1009
  },
1009
1010
  workerConfig: {
1010
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
1011
- // across parallel jobs. Each job already processes 50 docs sequentially, and
1012
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
1013
- concurrency: 1,
1011
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
1012
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
1013
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
1014
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
1015
+ concurrency: 10,
1014
1016
  lockDuration: 3e5,
1015
1017
  // 5 minutes lock duration since annotation can be slow
1016
1018
  maxStalledCount: 3
@@ -2502,6 +2504,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
2502
2504
  return void 0;
2503
2505
  };
2504
2506
 
2507
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
2508
+ var getAnnoFilterBucketKey = (level, value = {}) => {
2509
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
2510
+ if (level === "tags") {
2511
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
2512
+ }
2513
+ return null;
2514
+ };
2515
+
2505
2516
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
2506
2517
  var autoGenFilterConfigsFromTpl = ({
2507
2518
  selectedTpls,
@@ -2688,6 +2699,7 @@ var plainTextToLexical = (value) => {
2688
2699
  genCleanCamelCaseId,
2689
2700
  genTagId,
2690
2701
  generateFilterKey,
2702
+ getAnnoFilterBucketKey,
2691
2703
  getFilterKeyForBlock,
2692
2704
  getPlatformContextContent,
2693
2705
  getRollupPossibilities,
@@ -939,10 +939,11 @@ var BASE_BULLMQ_CONFIG = {
939
939
  }
940
940
  },
941
941
  workerConfig: {
942
- // Concurrency is 1 we process one job at a time to avoid duplicate tag creation
943
- // across parallel jobs. Each job already processes 50 docs sequentially, and
944
- // inductive tag creation benefits from each doc seeing prior docs' new tags.
945
- concurrency: 1,
942
+ // Parallel-safe: createTag/createSubTheme catch E11000 on the unique tagId
943
+ // index and re-fetch the existing doc, so concurrent jobs proposing the
944
+ // same tag converge to one. See ai/dualAgentAnnotation/tools/createTaxonomyItem.js.
945
+ // Starting at 10; real ceiling is the LLM provider's rate limit.
946
+ concurrency: 10,
946
947
  lockDuration: 3e5,
947
948
  // 5 minutes lock duration since annotation can be slow
948
949
  maxStalledCount: 3
@@ -2434,6 +2435,15 @@ var getFilterKeyForBlock = ({ block, scope = "tags" } = {}) => {
2434
2435
  return void 0;
2435
2436
  };
2436
2437
 
2438
+ // src/utils/autoGenFilterConfigsFromTpl/utils/getAnnoFilterBucketKey.ts
2439
+ var getAnnoFilterBucketKey = (level, value = {}) => {
2440
+ if (level === "subThemes") return value.parentThemeId || "__independent__";
2441
+ if (level === "tags") {
2442
+ return `${value.parentThemeId || "_"}::${value.parentSubThemeId || "_"}`;
2443
+ }
2444
+ return null;
2445
+ };
2446
+
2437
2447
  // src/utils/autoGenFilterConfigsFromTpl/index.ts
2438
2448
  var autoGenFilterConfigsFromTpl = ({
2439
2449
  selectedTpls,
@@ -2619,6 +2629,7 @@ export {
2619
2629
  genCleanCamelCaseId,
2620
2630
  genTagId,
2621
2631
  generateFilterKey,
2632
+ getAnnoFilterBucketKey,
2622
2633
  getFilterKeyForBlock,
2623
2634
  getPlatformContextContent,
2624
2635
  getRollupPossibilities,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.32.5",
6
+ "version": "1.32.7",
7
7
  "description": "Utility functions for both browser and Node.js",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.mjs",