@memberjunction/ng-dashboards 5.38.0 → 5.40.0

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.
Files changed (321) hide show
  1. package/README.md +14 -7
  2. package/dist/AI/components/agents/agent-configuration.component.js +199 -198
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  4. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
  8. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
  9. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
  10. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
  11. package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
  13. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
  14. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
  15. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
  16. package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
  17. package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
  18. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
  19. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
  20. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
  21. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
  22. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
  23. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
  24. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
  25. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
  27. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
  29. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  30. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
  31. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
  32. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
  33. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
  34. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
  35. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
  36. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
  37. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
  38. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
  39. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
  40. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
  41. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
  42. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
  43. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
  44. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
  45. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
  46. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
  47. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
  48. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
  49. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
  50. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
  51. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
  52. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
  53. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
  54. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
  55. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
  56. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
  57. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
  58. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
  59. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
  60. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
  61. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
  62. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
  63. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
  64. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
  65. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
  66. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
  67. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
  68. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
  69. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
  70. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
  71. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
  72. package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
  73. package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
  74. package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
  75. package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
  76. package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
  77. package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
  78. package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
  79. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
  80. package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
  81. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
  82. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
  83. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
  84. package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
  85. package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
  86. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
  87. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
  88. package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
  89. package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
  90. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
  91. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
  92. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
  93. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
  94. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
  95. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
  96. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
  97. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
  98. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
  99. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
  100. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
  101. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
  102. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
  103. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
  104. package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
  105. package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
  106. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
  107. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
  108. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
  109. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
  110. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
  111. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
  112. package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
  113. package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
  114. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
  115. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  116. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
  117. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  118. package/dist/AI/components/execution-monitoring.component.js +1 -1
  119. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  120. package/dist/AI/components/models/model-management.component.js +209 -208
  121. package/dist/AI/components/models/model-management.component.js.map +1 -1
  122. package/dist/AI/components/prompts/prompt-management.component.js +130 -128
  123. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  124. package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
  125. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
  126. package/dist/AI/components/system/system-configuration.component.js +17 -17
  127. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  128. package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
  129. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  130. package/dist/AI/components/tags/tags-resource.component.js +578 -538
  131. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  132. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
  133. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  134. package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
  135. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  136. package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
  137. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  138. package/dist/AI/services/ai-instrumentation.service.js +14 -2
  139. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  140. package/dist/AI/services/cache-metrics.d.ts +50 -0
  141. package/dist/AI/services/cache-metrics.d.ts.map +1 -0
  142. package/dist/AI/services/cache-metrics.js +43 -0
  143. package/dist/AI/services/cache-metrics.js.map +1 -0
  144. package/dist/APIKeys/api-applications-panel.component.js +2 -2
  145. package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
  146. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  147. package/dist/APIKeys/api-keys-resource.component.js +132 -131
  148. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  149. package/dist/Actions/components/actions-overview.component.js +141 -141
  150. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  151. package/dist/Actions/components/execution-monitoring.component.js +15 -15
  152. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  153. package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
  154. package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
  155. package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
  156. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  157. package/dist/Admin/admin-data-schema.component.js +2 -2
  158. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  159. package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
  160. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  161. package/dist/Admin/admin-identity-access.component.js +2 -2
  162. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  163. package/dist/Admin/admin-monitoring.component.js +2 -2
  164. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  165. package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
  166. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  167. package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
  168. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  169. package/dist/Communication/communication-logs-resource.component.js +72 -50
  170. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  171. package/dist/Communication/communication-monitor-resource.component.js +103 -102
  172. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  173. package/dist/Communication/communication-providers-resource.component.js +52 -51
  174. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  175. package/dist/Communication/communication-runs-resource.component.js +39 -38
  176. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  177. package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
  178. package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
  179. package/dist/Communication/communication-templates-resource.component.js +92 -89
  180. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  181. package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
  182. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  183. package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
  184. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  185. package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
  186. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  187. package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
  188. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  189. package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
  190. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  191. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
  192. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  193. package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
  194. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  195. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  196. package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
  197. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  198. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
  199. package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
  200. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  201. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
  202. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  203. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
  204. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  205. package/dist/DevTools/app-state-inspector.component.js +18 -17
  206. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  207. package/dist/DevTools/class-registry.component.js +88 -85
  208. package/dist/DevTools/class-registry.component.js.map +1 -1
  209. package/dist/DevTools/event-monitor.component.js +155 -150
  210. package/dist/DevTools/event-monitor.component.js.map +1 -1
  211. package/dist/DevTools/graphql-console.component.js +245 -243
  212. package/dist/DevTools/graphql-console.component.js.map +1 -1
  213. package/dist/DevTools/layout-inspector.component.js +18 -17
  214. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  215. package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
  216. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  217. package/dist/Home/home-dashboard.component.js +2 -2
  218. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  219. package/dist/Integration/components/activity/activity.component.js +236 -229
  220. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  221. package/dist/Integration/components/connections/connections.component.js +390 -389
  222. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  223. package/dist/Integration/components/overview/overview.component.js +2 -2
  224. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  225. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
  226. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  227. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
  228. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
  229. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
  230. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  231. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
  232. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  233. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
  234. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
  235. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
  236. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
  237. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
  238. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
  239. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
  240. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
  241. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
  242. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
  243. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
  244. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
  245. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
  246. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
  247. package/dist/KnowledgeHub/index.d.ts +3 -0
  248. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  249. package/dist/KnowledgeHub/index.js +3 -0
  250. package/dist/KnowledgeHub/index.js.map +1 -1
  251. package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
  252. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  253. package/dist/Lists/components/lists-browse-resource.component.js +525 -566
  254. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  255. package/dist/Lists/components/lists-categories-resource.component.js +135 -134
  256. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  257. package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
  258. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  259. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  260. package/dist/MCP/mcp-dashboard.component.js +443 -438
  261. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  262. package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
  263. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  264. package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
  265. package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
  266. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  267. package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
  268. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  269. package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
  270. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  271. package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
  272. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  273. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
  274. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
  275. package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
  276. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  277. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
  278. package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
  279. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  280. package/dist/Testing/components/testing-explorer.component.js +436 -427
  281. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  282. package/dist/Testing/components/testing-runs-resource.component.js +1 -1
  283. package/dist/Testing/components/testing-runs.component.js +116 -115
  284. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  285. package/dist/Testing/testing-dashboard.component.js +6 -7
  286. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  287. package/dist/VersionHistory/components/labels-resource.component.js +173 -172
  288. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  289. package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
  290. package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
  291. package/dist/VersionHistory/components/restore-resource.component.js +116 -92
  292. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  293. package/dist/ai-dashboards.module.d.ts +57 -35
  294. package/dist/ai-dashboards.module.d.ts.map +1 -1
  295. package/dist/ai-dashboards.module.js +80 -1
  296. package/dist/ai-dashboards.module.js.map +1 -1
  297. package/dist/communication-dashboards.module.d.ts +1 -1
  298. package/dist/communication-dashboards.module.d.ts.map +1 -1
  299. package/dist/communication-dashboards.module.js +7 -1
  300. package/dist/communication-dashboards.module.js.map +1 -1
  301. package/dist/data-explorer-dashboards.module.d.ts +12 -14
  302. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  303. package/dist/data-explorer-dashboards.module.js +5 -14
  304. package/dist/data-explorer-dashboards.module.js.map +1 -1
  305. package/dist/public-api.d.ts +3 -0
  306. package/dist/public-api.d.ts.map +1 -1
  307. package/dist/public-api.js +3 -0
  308. package/dist/public-api.js.map +1 -1
  309. package/dist/testing-dashboards.module.d.ts +4 -5
  310. package/dist/testing-dashboards.module.d.ts.map +1 -1
  311. package/dist/testing-dashboards.module.js +7 -5
  312. package/dist/testing-dashboards.module.js.map +1 -1
  313. package/package.json +57 -54
  314. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
  315. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
  316. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
  317. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
  318. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
  319. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
  320. package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
  321. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
@@ -0,0 +1,475 @@
1
+ /**
2
+ * @fileoverview Classify · Dry-run / disposition PREVIEW dialog.
3
+ *
4
+ * Honest, client-side, in-memory preview of how a source's EXISTING extracted
5
+ * ContentItemTags would be dispositioned under its current taxonomy mode +
6
+ * thresholds. This is NOT a fresh LLM run and NOTHING is persisted — it samples
7
+ * up to N existing tags, resolves each against the cached taxonomy
8
+ * (Tags / TagSynonyms) client-side, and replays the deterministic routing via the
9
+ * pure `previewDispositions` helper.
10
+ *
11
+ * It is hosted by the Sources tab (which already hosts its own dialogs): data
12
+ * DOWN via `[SourceCard]` / `[Show]`, intent UP via `(Closed)`. On open it loads
13
+ * the sample itself (read-only RunView, `ResultType: 'simple'`).
14
+ *
15
+ * NOTE: the server also has a semantic/embedding match tier not reproducible
16
+ * client-side, so borderline rows may resolve differently in a real run. The
17
+ * template states this explicitly.
18
+ */
19
+ import { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';
20
+ import { RunView } from '@memberjunction/core';
21
+ import { UUIDsEqual } from '@memberjunction/global';
22
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
23
+ import { TagEngineBase } from '@memberjunction/tag-engine-base';
24
+ import { KnowledgeHubMetadataEngine } from '@memberjunction/core-entities';
25
+ import { previewDispositions, } from '../shared/classify.dryrun';
26
+ import * as i0 from "@angular/core";
27
+ import * as i1 from "@memberjunction/ng-shared-generic";
28
+ import * as i2 from "@memberjunction/ng-ui-components";
29
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelementStart(0, "div", 7);
31
+ i0.ɵɵelement(1, "i");
32
+ i0.ɵɵelementStart(2, "span", 17);
33
+ i0.ɵɵtext(3);
34
+ i0.ɵɵelementEnd()();
35
+ } if (rf & 2) {
36
+ const ctx_r1 = i0.ɵɵnextContext(2);
37
+ i0.ɵɵadvance();
38
+ i0.ɵɵclassMap(ctx_r1.SourceCard.Icon);
39
+ i0.ɵɵadvance(2);
40
+ i0.ɵɵtextInterpolate(ctx_r1.SourceCard.Name);
41
+ } }
42
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_36_Template(rf, ctx) { if (rf & 1) {
43
+ i0.ɵɵelement(0, "mj-loading", 13);
44
+ } }
45
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_37_Template(rf, ctx) { if (rf & 1) {
46
+ i0.ɵɵelementStart(0, "div", 14);
47
+ i0.ɵɵelement(1, "i", 18);
48
+ i0.ɵɵelementStart(2, "p");
49
+ i0.ɵɵtext(3, "No extracted tags found for this source yet. Run the pipeline first, then preview how its tags would be dispositioned.");
50
+ i0.ɵɵelementEnd()();
51
+ } }
52
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_Conditional_13_Template(rf, ctx) { if (rf & 1) {
53
+ i0.ɵɵelementStart(0, "span", 26);
54
+ i0.ɵɵtext(1);
55
+ i0.ɵɵelementEnd();
56
+ } if (rf & 2) {
57
+ const ctx_r1 = i0.ɵɵnextContext(3);
58
+ i0.ɵɵadvance();
59
+ i0.ɵɵtextInterpolate1("", ctx_r1.Counts.Reject, " reject");
60
+ } }
61
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_For_27_Template(rf, ctx) { if (rf & 1) {
62
+ i0.ɵɵelementStart(0, "tr")(1, "td", 31);
63
+ i0.ɵɵtext(2);
64
+ i0.ɵɵelementEnd();
65
+ i0.ɵɵelementStart(3, "td", 32);
66
+ i0.ɵɵtext(4);
67
+ i0.ɵɵelementEnd();
68
+ i0.ɵɵelementStart(5, "td", 33);
69
+ i0.ɵɵtext(6);
70
+ i0.ɵɵelementEnd();
71
+ i0.ɵɵelementStart(7, "td")(8, "span", 34);
72
+ i0.ɵɵtext(9);
73
+ i0.ɵɵelementEnd()()();
74
+ } if (rf & 2) {
75
+ const row_r3 = ctx.$implicit;
76
+ const ctx_r1 = i0.ɵɵnextContext(3);
77
+ i0.ɵɵadvance(2);
78
+ i0.ɵɵtextInterpolate(row_r3.tag);
79
+ i0.ɵɵadvance(2);
80
+ i0.ɵɵtextInterpolate(row_r3.matchedTag ?? "\u2014");
81
+ i0.ɵɵadvance(2);
82
+ i0.ɵɵtextInterpolate(ctx_r1.FormatScore(row_r3.score));
83
+ i0.ɵɵadvance(2);
84
+ i0.ɵɵclassMap(ctx_r1.DispositionClass(row_r3.disposition));
85
+ i0.ɵɵproperty("title", row_r3.reason);
86
+ i0.ɵɵadvance();
87
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.DispositionLabel(row_r3.disposition), " ");
88
+ } }
89
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_Template(rf, ctx) { if (rf & 1) {
90
+ i0.ɵɵelementStart(0, "div", 19);
91
+ i0.ɵɵelement(1, "i", 20);
92
+ i0.ɵɵelementStart(2, "span");
93
+ i0.ɵɵtext(3);
94
+ i0.ɵɵelementStart(4, "span", 21);
95
+ i0.ɵɵtext(5, "(rough estimate)");
96
+ i0.ɵɵelementEnd()()();
97
+ i0.ɵɵelementStart(6, "div", 22)(7, "span", 23);
98
+ i0.ɵɵtext(8);
99
+ i0.ɵɵelementEnd();
100
+ i0.ɵɵelementStart(9, "span", 24);
101
+ i0.ɵɵtext(10);
102
+ i0.ɵɵelementEnd();
103
+ i0.ɵɵelementStart(11, "span", 25);
104
+ i0.ɵɵtext(12);
105
+ i0.ɵɵelementEnd();
106
+ i0.ɵɵconditionalCreate(13, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_Conditional_13_Template, 2, 1, "span", 26);
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵelementStart(14, "table", 27)(15, "thead")(16, "tr")(17, "th");
109
+ i0.ɵɵtext(18, "Tag");
110
+ i0.ɵɵelementEnd();
111
+ i0.ɵɵelementStart(19, "th");
112
+ i0.ɵɵtext(20, "Matched");
113
+ i0.ɵɵelementEnd();
114
+ i0.ɵɵelementStart(21, "th", 28);
115
+ i0.ɵɵtext(22, "Score");
116
+ i0.ɵɵelementEnd();
117
+ i0.ɵɵelementStart(23, "th");
118
+ i0.ɵɵtext(24, "What would happen");
119
+ i0.ɵɵelementEnd()()();
120
+ i0.ɵɵelementStart(25, "tbody");
121
+ i0.ɵɵrepeaterCreate(26, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_For_27_Template, 10, 7, "tr", null, i0.ɵɵrepeaterTrackByIndex);
122
+ i0.ɵɵelementEnd()();
123
+ i0.ɵɵelementStart(28, "div", 29);
124
+ i0.ɵɵelement(29, "i", 30);
125
+ i0.ɵɵtext(30, " A real run also uses a semantic / embedding match tier not reproducible here, so borderline rows may resolve differently. ");
126
+ i0.ɵɵelementEnd();
127
+ } if (rf & 2) {
128
+ const ctx_r1 = i0.ɵɵnextContext(2);
129
+ i0.ɵɵadvance(3);
130
+ i0.ɵɵtextInterpolate4(" ", ctx_r1.Estimate.ItemsSampled, " sampled tag", ctx_r1.Estimate.ItemsSampled === 1 ? "" : "s", " \u00B7 est. ", ctx_r1.FormatTokens(ctx_r1.Estimate.EstimatedTokens), " tokens \u00B7 ~", ctx_r1.FormatCost(ctx_r1.Estimate.EstimatedCost), " ");
131
+ i0.ɵɵadvance(5);
132
+ i0.ɵɵtextInterpolate1("", ctx_r1.Counts.AutoApply, " auto-apply");
133
+ i0.ɵɵadvance(2);
134
+ i0.ɵɵtextInterpolate1("", ctx_r1.Counts.RouteToInbox, " \u2192 inbox");
135
+ i0.ɵɵadvance(2);
136
+ i0.ɵɵtextInterpolate1("", ctx_r1.Counts.CreateNew, " create");
137
+ i0.ɵɵadvance();
138
+ i0.ɵɵconditional(ctx_r1.Counts.Reject > 0 ? 13 : -1);
139
+ i0.ɵɵadvance(13);
140
+ i0.ɵɵrepeater(ctx_r1.Rows);
141
+ } }
142
+ function ClassifyDryRunPreviewDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
143
+ const _r1 = i0.ɵɵgetCurrentView();
144
+ i0.ɵɵelementStart(0, "div", 0);
145
+ i0.ɵɵlistener("click", function ClassifyDryRunPreviewDialogComponent_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
146
+ i0.ɵɵelementEnd();
147
+ i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "h3");
148
+ i0.ɵɵelement(4, "i", 3);
149
+ i0.ɵɵtext(5, " Dry-run preview");
150
+ i0.ɵɵelementEnd();
151
+ i0.ɵɵelementStart(6, "button", 4);
152
+ i0.ɵɵlistener("click", function ClassifyDryRunPreviewDialogComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
153
+ i0.ɵɵelement(7, "i", 5);
154
+ i0.ɵɵelementEnd()();
155
+ i0.ɵɵelementStart(8, "div", 6);
156
+ i0.ɵɵconditionalCreate(9, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_9_Template, 4, 3, "div", 7);
157
+ i0.ɵɵelementStart(10, "div", 8);
158
+ i0.ɵɵelement(11, "i", 9);
159
+ i0.ɵɵelementStart(12, "span");
160
+ i0.ɵɵtext(13, " Preview of how this source's sampled tags resolve under the current ");
161
+ i0.ɵɵelementStart(14, "b");
162
+ i0.ɵɵtext(15, "mode & thresholds");
163
+ i0.ɵɵelementEnd();
164
+ i0.ɵɵtext(16, " \u2014 ");
165
+ i0.ɵɵelementStart(17, "b");
166
+ i0.ɵɵtext(18, "no LLM call, nothing persisted");
167
+ i0.ɵɵelementEnd();
168
+ i0.ɵɵtext(19, ". ");
169
+ i0.ɵɵelementEnd()();
170
+ i0.ɵɵelementStart(20, "div", 10)(21, "span", 11);
171
+ i0.ɵɵelement(22, "i", 3);
172
+ i0.ɵɵtext(23, " PREVIEW");
173
+ i0.ɵɵelementEnd();
174
+ i0.ɵɵelementStart(24, "span", 12);
175
+ i0.ɵɵtext(25, "Mode ");
176
+ i0.ɵɵelementStart(26, "b");
177
+ i0.ɵɵtext(27);
178
+ i0.ɵɵelementEnd()();
179
+ i0.ɵɵelementStart(28, "span", 12);
180
+ i0.ɵɵtext(29, "Match ");
181
+ i0.ɵɵelementStart(30, "b");
182
+ i0.ɵɵtext(31);
183
+ i0.ɵɵelementEnd()();
184
+ i0.ɵɵelementStart(32, "span", 12);
185
+ i0.ɵɵtext(33, "Suggest ");
186
+ i0.ɵɵelementStart(34, "b");
187
+ i0.ɵɵtext(35);
188
+ i0.ɵɵelementEnd()()();
189
+ i0.ɵɵconditionalCreate(36, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_36_Template, 1, 0, "mj-loading", 13)(37, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_37_Template, 4, 0, "div", 14)(38, ClassifyDryRunPreviewDialogComponent_Conditional_0_Conditional_38_Template, 31, 8);
190
+ i0.ɵɵelementStart(39, "div", 15)(40, "button", 16);
191
+ i0.ɵɵlistener("click", function ClassifyDryRunPreviewDialogComponent_Conditional_0_Template_button_click_40_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
192
+ i0.ɵɵtext(41, "Close");
193
+ i0.ɵɵelementEnd()()()();
194
+ } if (rf & 2) {
195
+ const ctx_r1 = i0.ɵɵnextContext();
196
+ i0.ɵɵadvance(9);
197
+ i0.ɵɵconditional(ctx_r1.SourceCard ? 9 : -1);
198
+ i0.ɵɵadvance(18);
199
+ i0.ɵɵtextInterpolate(ctx_r1.ModeLabel(ctx_r1.EffectiveMode));
200
+ i0.ɵɵadvance(4);
201
+ i0.ɵɵtextInterpolate(ctx_r1.FormatScore(ctx_r1.EffectiveMatchThreshold));
202
+ i0.ɵɵadvance(4);
203
+ i0.ɵɵtextInterpolate(ctx_r1.FormatScore(ctx_r1.EffectiveSuggestThreshold));
204
+ i0.ɵɵadvance();
205
+ i0.ɵɵconditional(ctx_r1.Loading ? 36 : ctx_r1.NoTagsSampled ? 37 : 38);
206
+ } }
207
+ /** Default routing config when a source has no explicit Configuration blob. */
208
+ const DEFAULT_MODE = 'auto-grow';
209
+ const DEFAULT_MATCH_THRESHOLD = 0.85;
210
+ /** Illustrative per-item token estimate for the (non-binding) cost line. */
211
+ const EST_TOKENS_PER_ITEM = 840;
212
+ /** Illustrative blended $/1K-token rate for the cost estimate. */
213
+ const EST_COST_PER_1K_TOKENS = 0.01;
214
+ /** Max existing tags to sample for the preview. */
215
+ const SAMPLE_SIZE = 15;
216
+ export class ClassifyDryRunPreviewDialogComponent extends BaseAngularComponent {
217
+ cdr = inject(ChangeDetectorRef);
218
+ /** Whether the dialog is visible. */
219
+ _show = false;
220
+ set Show(value) {
221
+ const opening = value && !this._show;
222
+ this._show = value;
223
+ if (opening && this._sourceCard) {
224
+ void this.runPreview(this._sourceCard);
225
+ }
226
+ }
227
+ get Show() {
228
+ return this._show;
229
+ }
230
+ /** The source being previewed; supplied by the Sources tab when opening. */
231
+ _sourceCard = null;
232
+ set SourceCard(value) {
233
+ this._sourceCard = value;
234
+ if (value && this._show) {
235
+ void this.runPreview(value);
236
+ }
237
+ }
238
+ get SourceCard() {
239
+ return this._sourceCard;
240
+ }
241
+ /** Emitted when the user dismisses the dialog. */
242
+ Closed = new EventEmitter();
243
+ // ── View state ──
244
+ Loading = false;
245
+ Rows = [];
246
+ Counts = { AutoApply: 0, RouteToInbox: 0, CreateNew: 0, Reject: 0 };
247
+ Estimate = { ItemsSampled: 0, EstimatedTokens: 0, EstimatedCost: 0 };
248
+ /** Effective config used for this preview (mirrored for the "effective values" line). */
249
+ EffectiveMode = DEFAULT_MODE;
250
+ EffectiveMatchThreshold = DEFAULT_MATCH_THRESHOLD;
251
+ EffectiveSuggestThreshold = DEFAULT_MATCH_THRESHOLD - 0.05;
252
+ /** True when the sampled source has no extracted tags yet. */
253
+ NoTagsSampled = false;
254
+ close() {
255
+ this.Closed.emit();
256
+ }
257
+ /**
258
+ * Load a sample of the source's existing extracted tags, resolve each against
259
+ * the cached taxonomy, and produce the preview rows + summary. Read-only —
260
+ * nothing is written.
261
+ */
262
+ async runPreview(card) {
263
+ this.Loading = true;
264
+ this.Rows = [];
265
+ this.NoTagsSampled = false;
266
+ this.cdr.detectChanges();
267
+ try {
268
+ const p = this.ProviderToUse;
269
+ await TagEngineBase.Instance.Config(false, p.CurrentUser, p);
270
+ await KnowledgeHubMetadataEngine.Instance.Config(false, p.CurrentUser, p);
271
+ const cfg = this.resolveSourceConfig(card.ID);
272
+ this.EffectiveMode = cfg.mode;
273
+ this.EffectiveMatchThreshold = cfg.matchThreshold;
274
+ this.EffectiveSuggestThreshold = cfg.suggestThreshold;
275
+ const inputs = await this.loadSampleTags(card.ID);
276
+ if (inputs.length === 0) {
277
+ this.NoTagsSampled = true;
278
+ this.Estimate = { ItemsSampled: 0, EstimatedTokens: 0, EstimatedCost: 0 };
279
+ return;
280
+ }
281
+ const resolve = this.buildResolver();
282
+ this.Rows = previewDispositions(inputs, cfg, resolve);
283
+ this.Counts = this.tally(this.Rows);
284
+ this.Estimate = this.estimate(inputs.length);
285
+ }
286
+ catch (error) {
287
+ console.error('[Classify] Dry-run preview error:', error);
288
+ }
289
+ finally {
290
+ this.Loading = false;
291
+ this.cdr.detectChanges();
292
+ }
293
+ }
294
+ /**
295
+ * Sample up to SAMPLE_SIZE existing ContentItemTags for the source. We first
296
+ * pull a handful of the source's items, then their tags — the simplest path
297
+ * that avoids depending on a direct source-level filter on ContentItemTags.
298
+ */
299
+ async loadSampleTags(sourceID) {
300
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
301
+ const itemResult = await rv.RunView({
302
+ EntityName: 'MJ: Content Items',
303
+ ExtraFilter: `ContentSourceID='${sourceID}'`,
304
+ OrderBy: '__mj_UpdatedAt DESC',
305
+ Fields: ['ID'],
306
+ MaxRows: SAMPLE_SIZE,
307
+ ResultType: 'simple',
308
+ });
309
+ if (!itemResult.Success || itemResult.Results.length === 0)
310
+ return [];
311
+ const itemIds = itemResult.Results.map(i => i.ID);
312
+ const inClause = itemIds.map(id => `'${id}'`).join(',');
313
+ const tagResult = await rv.RunView({
314
+ EntityName: 'MJ: Content Item Tags',
315
+ ExtraFilter: `ItemID IN (${inClause})`,
316
+ Fields: ['Tag', 'TagID', 'Weight'],
317
+ MaxRows: SAMPLE_SIZE,
318
+ ResultType: 'simple',
319
+ });
320
+ if (!tagResult.Success)
321
+ return [];
322
+ return tagResult.Results
323
+ .filter(t => !!t.Tag)
324
+ .map(t => ({
325
+ tag: t.Tag,
326
+ resolvedTagId: t.TagID ?? null,
327
+ weight: Number(t.Weight ?? 1),
328
+ }));
329
+ }
330
+ /**
331
+ * Read the source's effective taxonomy config from its ConfigurationObject,
332
+ * falling back to documented runtime defaults. SuggestThreshold defaults to
333
+ * matchThreshold − 0.05 (matches the server's runtime default).
334
+ */
335
+ resolveSourceConfig(sourceID) {
336
+ const source = KnowledgeHubMetadataEngine.Instance.ContentSources.find(cs => UUIDsEqual(cs.ID, sourceID));
337
+ const config = source?.ConfigurationObject ?? null;
338
+ const mode = config?.TagTaxonomyMode ?? DEFAULT_MODE;
339
+ const matchThreshold = config?.TagMatchThreshold ?? DEFAULT_MATCH_THRESHOLD;
340
+ const suggestThreshold = config?.SuggestThreshold ?? matchThreshold - 0.05;
341
+ return { mode, matchThreshold, suggestThreshold };
342
+ }
343
+ /**
344
+ * Build the client-side resolver closure over the cached taxonomy.
345
+ * tier 'synonym' if the tag matches a TagSynonym (case-insensitive),
346
+ * 'exact' if it matches a Tag Name (case-insensitive), 'fuzzy' if a
347
+ * normalized match (lowercase, strip plurals/hyphens) hits, else 'none'.
348
+ */
349
+ buildResolver() {
350
+ const engine = TagEngineBase.Instance;
351
+ const activeTags = engine.Tags.filter(t => t.Status === 'Active');
352
+ // synonym text (lower) → owning Tag
353
+ const synonymMap = new Map();
354
+ const tagById = new Map();
355
+ for (const t of activeTags) {
356
+ tagById.set(t.ID.toLowerCase(), { id: t.ID, name: t.Name });
357
+ }
358
+ for (const syn of engine.TagSynonyms) {
359
+ // Only Active synonyms resolve — Pending (proposed, unapproved) and
360
+ // Rejected ones are not live, matching the server-side resolver.
361
+ if (syn.Status !== 'Active')
362
+ continue;
363
+ const owner = tagById.get((syn.TagID ?? '').toLowerCase());
364
+ if (owner && syn.Synonym) {
365
+ synonymMap.set(syn.Synonym.trim().toLowerCase(), owner);
366
+ }
367
+ }
368
+ // exact name (lower) → Tag; normalized name (lower) → Tag (for fuzzy tier)
369
+ const exactMap = new Map();
370
+ const normalizedMap = new Map();
371
+ for (const t of activeTags) {
372
+ const entry = { id: t.ID, name: t.Name };
373
+ exactMap.set(t.Name.trim().toLowerCase(), entry);
374
+ normalizedMap.set(this.normalize(t.Name), entry);
375
+ }
376
+ return (tag) => {
377
+ const lower = tag.trim().toLowerCase();
378
+ const syn = synonymMap.get(lower);
379
+ if (syn)
380
+ return { tagId: syn.id, tagName: syn.name, score: 1.0, tier: 'synonym' };
381
+ const exact = exactMap.get(lower);
382
+ if (exact)
383
+ return { tagId: exact.id, tagName: exact.name, score: 1.0, tier: 'exact' };
384
+ const fuzzy = normalizedMap.get(this.normalize(tag));
385
+ if (fuzzy)
386
+ return { tagId: fuzzy.id, tagName: fuzzy.name, score: 0.8, tier: 'fuzzy' };
387
+ return { tagId: null, tagName: null, score: null, tier: 'none' };
388
+ };
389
+ }
390
+ /** Lowercase, strip hyphens/underscores/whitespace and a trailing plural 's'. */
391
+ normalize(value) {
392
+ let v = value.trim().toLowerCase().replace(/[-_\s]+/g, '');
393
+ if (v.endsWith('s') && v.length > 3)
394
+ v = v.slice(0, -1);
395
+ return v;
396
+ }
397
+ tally(rows) {
398
+ const counts = { AutoApply: 0, RouteToInbox: 0, CreateNew: 0, Reject: 0 };
399
+ for (const r of rows) {
400
+ switch (r.disposition) {
401
+ case 'auto-apply':
402
+ counts.AutoApply++;
403
+ break;
404
+ case 'route-to-inbox':
405
+ counts.RouteToInbox++;
406
+ break;
407
+ case 'create-new':
408
+ counts.CreateNew++;
409
+ break;
410
+ case 'reject':
411
+ counts.Reject++;
412
+ break;
413
+ }
414
+ }
415
+ return counts;
416
+ }
417
+ estimate(itemsSampled) {
418
+ const tokens = itemsSampled * EST_TOKENS_PER_ITEM;
419
+ const cost = (tokens / 1000) * EST_COST_PER_1K_TOKENS;
420
+ return { ItemsSampled: itemsSampled, EstimatedTokens: tokens, EstimatedCost: cost };
421
+ }
422
+ // ── Template helpers ──
423
+ /** Status-token-backed CSS class for a disposition pill. */
424
+ DispositionClass(d) {
425
+ switch (d) {
426
+ case 'auto-apply': return 'disp disp-apply';
427
+ case 'route-to-inbox': return 'disp disp-inbox';
428
+ case 'create-new': return 'disp disp-create';
429
+ case 'reject': return 'disp disp-reject';
430
+ }
431
+ }
432
+ /** Human label for a disposition pill. */
433
+ DispositionLabel(d) {
434
+ switch (d) {
435
+ case 'auto-apply': return 'AUTO-APPLY';
436
+ case 'route-to-inbox': return '→ INBOX';
437
+ case 'create-new': return this.EffectiveMode === 'free-flow' ? 'CREATE (free-flow)' : 'CREATE (auto-grow)';
438
+ case 'reject': return 'REJECT';
439
+ }
440
+ }
441
+ FormatScore(score) {
442
+ return score == null ? '—' : score.toFixed(2);
443
+ }
444
+ FormatTokens(tokens) {
445
+ return tokens.toLocaleString();
446
+ }
447
+ FormatCost(cost) {
448
+ return `$${cost.toFixed(2)}`;
449
+ }
450
+ ModeLabel(mode) {
451
+ switch (mode) {
452
+ case 'constrained': return 'Constrained';
453
+ case 'auto-grow': return 'Auto-grow';
454
+ case 'free-flow': return 'Free-flow';
455
+ }
456
+ }
457
+ static ɵfac = /*@__PURE__*/ (() => { let ɵClassifyDryRunPreviewDialogComponent_BaseFactory; return function ClassifyDryRunPreviewDialogComponent_Factory(__ngFactoryType__) { return (ɵClassifyDryRunPreviewDialogComponent_BaseFactory || (ɵClassifyDryRunPreviewDialogComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifyDryRunPreviewDialogComponent)))(__ngFactoryType__ || ClassifyDryRunPreviewDialogComponent); }; })();
458
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifyDryRunPreviewDialogComponent, selectors: [["classify-dry-run-preview"]], inputs: { Show: "Show", SourceCard: "SourceCard" }, outputs: { Closed: "Closed" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel", "dry-run-panel"], [1, "at-slide-header"], [1, "fa-solid", "fa-flask"], ["aria-label", "Close dry-run preview", 1, "at-slide-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-slide-body"], [1, "dry-source-line"], [1, "dry-banner"], [1, "fa-solid", "fa-circle-info"], [1, "dry-effective"], [1, "pill", "purple"], [1, "dry-eff-item"], ["text", "Sampling existing tags\u2026"], [1, "dry-empty"], [1, "dry-footer"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "dry-source-name"], [1, "fa-solid", "fa-tags"], [1, "dry-estimate"], [1, "fa-solid", "fa-calculator"], [1, "dry-est-note"], [1, "dry-summary"], [1, "disp", "disp-apply"], [1, "disp", "disp-inbox"], [1, "disp", "disp-create"], [1, "disp", "disp-reject"], [1, "dry-table"], [1, "dry-col-score"], [1, "dry-disclaimer"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "dry-cell-tag"], [1, "dry-cell-matched"], [1, "dry-col-score", "dry-mono"], [3, "title"]], template: function ClassifyDryRunPreviewDialogComponent_Template(rf, ctx) { if (rf & 1) {
459
+ i0.ɵɵconditionalCreate(0, ClassifyDryRunPreviewDialogComponent_Conditional_0_Template, 42, 5);
460
+ } if (rf & 2) {
461
+ i0.ɵɵconditional(ctx.Show ? 0 : -1);
462
+ } }, dependencies: [i1.LoadingComponent, i2.MJButtonDirective], styles: ["\n\n\n\n\n\n\n.dry-run-panel[_ngcontent-%COMP%] {\n width: 640px;\n max-width: 92vw;\n}\n\n.dry-source-line[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.95rem;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n.dry-source-line[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n.dry-source-name[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.dry-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border);\n color: var(--mj-status-info-text);\n font-size: 0.85rem;\n line-height: 1.4;\n margin-bottom: 14px;\n}\n.dry-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-top: 2px;\n}\n\n\n\n.dry-effective[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n}\n.dry-eff-item[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n}\n.dry-eff-item[_ngcontent-%COMP%] b[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n}\n\n.pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.03em;\n}\n.pill.purple[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.dry-estimate[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.82rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n}\n.dry-est-note[_ngcontent-%COMP%] {\n font-style: italic;\n color: var(--mj-text-muted);\n}\n\n\n\n.dry-summary[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 14px;\n}\n\n\n\n.disp[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 9px;\n border-radius: 6px;\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.02em;\n white-space: nowrap;\n}\n.disp-apply[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n.disp-inbox[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n.disp-create[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n.disp-reject[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n\n\n.dry-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.84rem;\n margin-bottom: 14px;\n}\n.dry-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding: 6px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.dry-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 7px 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n vertical-align: middle;\n}\n.dry-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.dry-cell-tag[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n.dry-cell-matched[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n.dry-col-score[_ngcontent-%COMP%] {\n text-align: right;\n width: 64px;\n}\n.dry-mono[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, monospace);\n color: var(--mj-text-secondary);\n}\n\n.dry-disclaimer[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n margin-bottom: 16px;\n}\n.dry-disclaimer[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-top: 2px;\n color: var(--mj-status-warning);\n}\n\n.dry-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n}\n.dry-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.8rem;\n margin-bottom: 10px;\n color: var(--mj-text-disabled);\n}\n.dry-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 0.88rem;\n line-height: 1.5;\n max-width: 420px;\n margin: 0 auto;\n}\n\n.dry-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}"] });
463
+ }
464
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifyDryRunPreviewDialogComponent, [{
465
+ type: Component,
466
+ args: [{ standalone: false, selector: 'classify-dry-run-preview', template: "<!-- \u2550\u2550\u2550\u2550\u2550\u2550 DRY-RUN / DISPOSITION PREVIEW SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (Show) {\n <div class=\"at-slide-overlay\" (click)=\"close()\"></div>\n <div class=\"at-slide-panel dry-run-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-flask\"></i> Dry-run preview</h3>\n <button class=\"at-slide-close\" aria-label=\"Close dry-run preview\" (click)=\"close()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n\n <div class=\"at-slide-body\">\n <!-- Source + intent line -->\n @if (SourceCard) {\n <div class=\"dry-source-line\">\n <i [class]=\"SourceCard.Icon\"></i>\n <span class=\"dry-source-name\">{{ SourceCard.Name }}</span>\n </div>\n }\n\n <!-- \"nothing persisted\" banner -->\n <div class=\"dry-banner\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <span>\n Preview of how this source's sampled tags resolve under the current\n <b>mode &amp; thresholds</b> \u2014 <b>no LLM call, nothing persisted</b>.\n </span>\n </div>\n\n <!-- Effective config -->\n <div class=\"dry-effective\">\n <span class=\"pill purple\"><i class=\"fa-solid fa-flask\"></i> PREVIEW</span>\n <span class=\"dry-eff-item\">Mode <b>{{ ModeLabel(EffectiveMode) }}</b></span>\n <span class=\"dry-eff-item\">Match <b>{{ FormatScore(EffectiveMatchThreshold) }}</b></span>\n <span class=\"dry-eff-item\">Suggest <b>{{ FormatScore(EffectiveSuggestThreshold) }}</b></span>\n </div>\n\n @if (Loading) {\n <mj-loading text=\"Sampling existing tags\u2026\"></mj-loading>\n } @else if (NoTagsSampled) {\n <div class=\"dry-empty\">\n <i class=\"fa-solid fa-tags\"></i>\n <p>No extracted tags found for this source yet. Run the pipeline first, then preview how its tags would be dispositioned.</p>\n </div>\n } @else {\n <!-- Estimate line (illustrative) -->\n <div class=\"dry-estimate\">\n <i class=\"fa-solid fa-calculator\"></i>\n <span>\n {{ Estimate.ItemsSampled }} sampled tag{{ Estimate.ItemsSampled === 1 ? '' : 's' }} \u00B7\n est. {{ FormatTokens(Estimate.EstimatedTokens) }} tokens \u00B7\n ~{{ FormatCost(Estimate.EstimatedCost) }}\n <span class=\"dry-est-note\">(rough estimate)</span>\n </span>\n </div>\n\n <!-- Summary counts -->\n <div class=\"dry-summary\">\n <span class=\"disp disp-apply\">{{ Counts.AutoApply }} auto-apply</span>\n <span class=\"disp disp-inbox\">{{ Counts.RouteToInbox }} \u2192 inbox</span>\n <span class=\"disp disp-create\">{{ Counts.CreateNew }} create</span>\n @if (Counts.Reject > 0) {\n <span class=\"disp disp-reject\">{{ Counts.Reject }} reject</span>\n }\n </div>\n\n <!-- Disposition table -->\n <table class=\"dry-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Matched</th>\n <th class=\"dry-col-score\">Score</th>\n <th>What would happen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of Rows; track $index) {\n <tr>\n <td class=\"dry-cell-tag\">{{ row.tag }}</td>\n <td class=\"dry-cell-matched\">{{ row.matchedTag ?? '\u2014' }}</td>\n <td class=\"dry-col-score dry-mono\">{{ FormatScore(row.score) }}</td>\n <td>\n <span [class]=\"DispositionClass(row.disposition)\" [title]=\"row.reason\">\n {{ DispositionLabel(row.disposition) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <div class=\"dry-disclaimer\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n A real run also uses a semantic / embedding match tier not reproducible here,\n so borderline rows may resolve differently.\n </div>\n }\n\n <!-- Footer -->\n <div class=\"dry-footer\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"close()\">Close</button>\n </div>\n </div>\n </div>\n}\n", styles: ["/**\n * Dry-run preview dialog \u2014 net-new rules only. The slide-in shell (.at-slide-*)\n * is owned by the host (ViewEncapsulation.None) and already styles the panel.\n * Disposition pills use semantic status tokens so they adapt to dark mode.\n */\n\n.dry-run-panel {\n width: 640px;\n max-width: 92vw;\n}\n\n.dry-source-line {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.95rem;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n.dry-source-line i {\n color: var(--mj-text-secondary);\n}\n.dry-source-name {\n font-weight: 600;\n}\n\n/* \"nothing persisted\" banner */\n.dry-banner {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border);\n color: var(--mj-status-info-text);\n font-size: 0.85rem;\n line-height: 1.4;\n margin-bottom: 14px;\n}\n.dry-banner i {\n margin-top: 2px;\n}\n\n/* effective config row */\n.dry-effective {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n}\n.dry-eff-item {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n}\n.dry-eff-item b {\n color: var(--mj-text-primary);\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.03em;\n}\n.pill.purple {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* estimate line */\n.dry-estimate {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.82rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n}\n.dry-est-note {\n font-style: italic;\n color: var(--mj-text-muted);\n}\n\n/* summary counts */\n.dry-summary {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 14px;\n}\n\n/* disposition pills (status-token backed) */\n.disp {\n display: inline-flex;\n align-items: center;\n padding: 3px 9px;\n border-radius: 6px;\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.02em;\n white-space: nowrap;\n}\n.disp-apply {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n.disp-inbox {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n.disp-create {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n.disp-reject {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n/* table */\n.dry-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.84rem;\n margin-bottom: 14px;\n}\n.dry-table thead th {\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding: 6px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.dry-table tbody td {\n padding: 7px 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n vertical-align: middle;\n}\n.dry-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n}\n.dry-cell-tag {\n font-weight: 500;\n}\n.dry-cell-matched {\n color: var(--mj-text-secondary);\n}\n.dry-col-score {\n text-align: right;\n width: 64px;\n}\n.dry-mono {\n font-family: var(--mj-font-mono, monospace);\n color: var(--mj-text-secondary);\n}\n\n.dry-disclaimer {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n margin-bottom: 16px;\n}\n.dry-disclaimer i {\n margin-top: 2px;\n color: var(--mj-status-warning);\n}\n\n.dry-empty {\n text-align: center;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n}\n.dry-empty i {\n font-size: 1.8rem;\n margin-bottom: 10px;\n color: var(--mj-text-disabled);\n}\n.dry-empty p {\n font-size: 0.88rem;\n line-height: 1.5;\n max-width: 420px;\n margin: 0 auto;\n}\n\n.dry-footer {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}\n"] }]
467
+ }], null, { Show: [{
468
+ type: Input
469
+ }], SourceCard: [{
470
+ type: Input
471
+ }], Closed: [{
472
+ type: Output
473
+ }] }); })();
474
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifyDryRunPreviewDialogComponent, { className: "ClassifyDryRunPreviewDialogComponent", filePath: "src/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.ts", lineNumber: 46 }); })();
475
+ //# sourceMappingURL=dry-run-preview.dialog.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run-preview.dialog.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.ts","../../../../../src/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Classify · Dry-run / disposition PREVIEW dialog.\n *\n * Honest, client-side, in-memory preview of how a source's EXISTING extracted\n * ContentItemTags would be dispositioned under its current taxonomy mode +\n * thresholds. This is NOT a fresh LLM run and NOTHING is persisted — it samples\n * up to N existing tags, resolves each against the cached taxonomy\n * (Tags / TagSynonyms) client-side, and replays the deterministic routing via the\n * pure `previewDispositions` helper.\n *\n * It is hosted by the Sources tab (which already hosts its own dialogs): data\n * DOWN via `[SourceCard]` / `[Show]`, intent UP via `(Closed)`. On open it loads\n * the sample itself (read-only RunView, `ResultType: 'simple'`).\n *\n * NOTE: the server also has a semantic/embedding match tier not reproducible\n * client-side, so borderline rows may resolve differently in a real run. The\n * template states this explicitly.\n */\nimport { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';\nimport { RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { TagEngineBase } from '@memberjunction/tag-engine-base';\nimport { KnowledgeHubMetadataEngine } from '@memberjunction/core-entities';\nimport { SourceCard, DryRunDispositionCount, DryRunEstimate } from '../shared/classify.types';\nimport {\n previewDispositions, DryRunInput, DryRunConfig, DryRunRow, ResolveResult, Disposition,\n} from '../shared/classify.dryrun';\n\n/** Default routing config when a source has no explicit Configuration blob. */\nconst DEFAULT_MODE: DryRunConfig['mode'] = 'auto-grow';\nconst DEFAULT_MATCH_THRESHOLD = 0.85;\n/** Illustrative per-item token estimate for the (non-binding) cost line. */\nconst EST_TOKENS_PER_ITEM = 840;\n/** Illustrative blended $/1K-token rate for the cost estimate. */\nconst EST_COST_PER_1K_TOKENS = 0.01;\n/** Max existing tags to sample for the preview. */\nconst SAMPLE_SIZE = 15;\n\n@Component({\n standalone: false,\n selector: 'classify-dry-run-preview',\n templateUrl: './dry-run-preview.dialog.component.html',\n styleUrls: ['./dry-run-preview.dialog.component.css'],\n})\nexport class ClassifyDryRunPreviewDialogComponent extends BaseAngularComponent {\n private cdr = inject(ChangeDetectorRef);\n\n /** Whether the dialog is visible. */\n private _show = false;\n @Input()\n set Show(value: boolean) {\n const opening = value && !this._show;\n this._show = value;\n if (opening && this._sourceCard) {\n void this.runPreview(this._sourceCard);\n }\n }\n get Show(): boolean {\n return this._show;\n }\n\n /** The source being previewed; supplied by the Sources tab when opening. */\n private _sourceCard: SourceCard | null = null;\n @Input()\n set SourceCard(value: SourceCard | null) {\n this._sourceCard = value;\n if (value && this._show) {\n void this.runPreview(value);\n }\n }\n get SourceCard(): SourceCard | null {\n return this._sourceCard;\n }\n\n /** Emitted when the user dismisses the dialog. */\n @Output() Closed = new EventEmitter<void>();\n\n // ── View state ──\n\n public Loading = false;\n public Rows: DryRunRow[] = [];\n public Counts: DryRunDispositionCount = { AutoApply: 0, RouteToInbox: 0, CreateNew: 0, Reject: 0 };\n public Estimate: DryRunEstimate = { ItemsSampled: 0, EstimatedTokens: 0, EstimatedCost: 0 };\n /** Effective config used for this preview (mirrored for the \"effective values\" line). */\n public EffectiveMode: DryRunConfig['mode'] = DEFAULT_MODE;\n public EffectiveMatchThreshold = DEFAULT_MATCH_THRESHOLD;\n public EffectiveSuggestThreshold = DEFAULT_MATCH_THRESHOLD - 0.05;\n /** True when the sampled source has no extracted tags yet. */\n public NoTagsSampled = false;\n\n public close(): void {\n this.Closed.emit();\n }\n\n /**\n * Load a sample of the source's existing extracted tags, resolve each against\n * the cached taxonomy, and produce the preview rows + summary. Read-only —\n * nothing is written.\n */\n private async runPreview(card: SourceCard): Promise<void> {\n this.Loading = true;\n this.Rows = [];\n this.NoTagsSampled = false;\n this.cdr.detectChanges();\n\n try {\n const p = this.ProviderToUse;\n await TagEngineBase.Instance.Config(false, p.CurrentUser, p);\n await KnowledgeHubMetadataEngine.Instance.Config(false, p.CurrentUser, p);\n\n const cfg = this.resolveSourceConfig(card.ID);\n this.EffectiveMode = cfg.mode;\n this.EffectiveMatchThreshold = cfg.matchThreshold;\n this.EffectiveSuggestThreshold = cfg.suggestThreshold;\n\n const inputs = await this.loadSampleTags(card.ID);\n if (inputs.length === 0) {\n this.NoTagsSampled = true;\n this.Estimate = { ItemsSampled: 0, EstimatedTokens: 0, EstimatedCost: 0 };\n return;\n }\n\n const resolve = this.buildResolver();\n this.Rows = previewDispositions(inputs, cfg, resolve);\n this.Counts = this.tally(this.Rows);\n this.Estimate = this.estimate(inputs.length);\n } catch (error) {\n console.error('[Classify] Dry-run preview error:', error);\n } finally {\n this.Loading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Sample up to SAMPLE_SIZE existing ContentItemTags for the source. We first\n * pull a handful of the source's items, then their tags — the simplest path\n * that avoids depending on a direct source-level filter on ContentItemTags.\n */\n private async loadSampleTags(sourceID: string): Promise<DryRunInput[]> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n const itemResult = await rv.RunView<{ ID: string }>({\n EntityName: 'MJ: Content Items',\n ExtraFilter: `ContentSourceID='${sourceID}'`,\n OrderBy: '__mj_UpdatedAt DESC',\n Fields: ['ID'],\n MaxRows: SAMPLE_SIZE,\n ResultType: 'simple',\n });\n if (!itemResult.Success || itemResult.Results.length === 0) return [];\n\n const itemIds = itemResult.Results.map(i => i.ID);\n const inClause = itemIds.map(id => `'${id}'`).join(',');\n\n const tagResult = await rv.RunView<{ Tag: string; TagID: string | null; Weight: number | null }>({\n EntityName: 'MJ: Content Item Tags',\n ExtraFilter: `ItemID IN (${inClause})`,\n Fields: ['Tag', 'TagID', 'Weight'],\n MaxRows: SAMPLE_SIZE,\n ResultType: 'simple',\n });\n if (!tagResult.Success) return [];\n\n return tagResult.Results\n .filter(t => !!t.Tag)\n .map(t => ({\n tag: t.Tag,\n resolvedTagId: t.TagID ?? null,\n weight: Number(t.Weight ?? 1),\n }));\n }\n\n /**\n * Read the source's effective taxonomy config from its ConfigurationObject,\n * falling back to documented runtime defaults. SuggestThreshold defaults to\n * matchThreshold − 0.05 (matches the server's runtime default).\n */\n private resolveSourceConfig(sourceID: string): DryRunConfig {\n const source = KnowledgeHubMetadataEngine.Instance.ContentSources.find(cs => UUIDsEqual(cs.ID, sourceID));\n const config = source?.ConfigurationObject ?? null;\n\n const mode = config?.TagTaxonomyMode ?? DEFAULT_MODE;\n const matchThreshold = config?.TagMatchThreshold ?? DEFAULT_MATCH_THRESHOLD;\n const suggestThreshold = config?.SuggestThreshold ?? matchThreshold - 0.05;\n\n return { mode, matchThreshold, suggestThreshold };\n }\n\n /**\n * Build the client-side resolver closure over the cached taxonomy.\n * tier 'synonym' if the tag matches a TagSynonym (case-insensitive),\n * 'exact' if it matches a Tag Name (case-insensitive), 'fuzzy' if a\n * normalized match (lowercase, strip plurals/hyphens) hits, else 'none'.\n */\n private buildResolver(): (tag: string) => ResolveResult {\n const engine = TagEngineBase.Instance;\n const activeTags = engine.Tags.filter(t => t.Status === 'Active');\n\n // synonym text (lower) → owning Tag\n const synonymMap = new Map<string, { id: string; name: string }>();\n const tagById = new Map<string, { id: string; name: string }>();\n for (const t of activeTags) {\n tagById.set(t.ID.toLowerCase(), { id: t.ID, name: t.Name });\n }\n for (const syn of engine.TagSynonyms) {\n // Only Active synonyms resolve — Pending (proposed, unapproved) and\n // Rejected ones are not live, matching the server-side resolver.\n if (syn.Status !== 'Active') continue;\n const owner = tagById.get((syn.TagID ?? '').toLowerCase());\n if (owner && syn.Synonym) {\n synonymMap.set(syn.Synonym.trim().toLowerCase(), owner);\n }\n }\n\n // exact name (lower) → Tag; normalized name (lower) → Tag (for fuzzy tier)\n const exactMap = new Map<string, { id: string; name: string }>();\n const normalizedMap = new Map<string, { id: string; name: string }>();\n for (const t of activeTags) {\n const entry = { id: t.ID, name: t.Name };\n exactMap.set(t.Name.trim().toLowerCase(), entry);\n normalizedMap.set(this.normalize(t.Name), entry);\n }\n\n return (tag: string): ResolveResult => {\n const lower = tag.trim().toLowerCase();\n\n const syn = synonymMap.get(lower);\n if (syn) return { tagId: syn.id, tagName: syn.name, score: 1.0, tier: 'synonym' };\n\n const exact = exactMap.get(lower);\n if (exact) return { tagId: exact.id, tagName: exact.name, score: 1.0, tier: 'exact' };\n\n const fuzzy = normalizedMap.get(this.normalize(tag));\n if (fuzzy) return { tagId: fuzzy.id, tagName: fuzzy.name, score: 0.8, tier: 'fuzzy' };\n\n return { tagId: null, tagName: null, score: null, tier: 'none' };\n };\n }\n\n /** Lowercase, strip hyphens/underscores/whitespace and a trailing plural 's'. */\n private normalize(value: string): string {\n let v = value.trim().toLowerCase().replace(/[-_\\s]+/g, '');\n if (v.endsWith('s') && v.length > 3) v = v.slice(0, -1);\n return v;\n }\n\n private tally(rows: DryRunRow[]): DryRunDispositionCount {\n const counts: DryRunDispositionCount = { AutoApply: 0, RouteToInbox: 0, CreateNew: 0, Reject: 0 };\n for (const r of rows) {\n switch (r.disposition) {\n case 'auto-apply': counts.AutoApply++; break;\n case 'route-to-inbox': counts.RouteToInbox++; break;\n case 'create-new': counts.CreateNew++; break;\n case 'reject': counts.Reject++; break;\n }\n }\n return counts;\n }\n\n private estimate(itemsSampled: number): DryRunEstimate {\n const tokens = itemsSampled * EST_TOKENS_PER_ITEM;\n const cost = (tokens / 1000) * EST_COST_PER_1K_TOKENS;\n return { ItemsSampled: itemsSampled, EstimatedTokens: tokens, EstimatedCost: cost };\n }\n\n // ── Template helpers ──\n\n /** Status-token-backed CSS class for a disposition pill. */\n public DispositionClass(d: Disposition): string {\n switch (d) {\n case 'auto-apply': return 'disp disp-apply';\n case 'route-to-inbox': return 'disp disp-inbox';\n case 'create-new': return 'disp disp-create';\n case 'reject': return 'disp disp-reject';\n }\n }\n\n /** Human label for a disposition pill. */\n public DispositionLabel(d: Disposition): string {\n switch (d) {\n case 'auto-apply': return 'AUTO-APPLY';\n case 'route-to-inbox': return '→ INBOX';\n case 'create-new': return this.EffectiveMode === 'free-flow' ? 'CREATE (free-flow)' : 'CREATE (auto-grow)';\n case 'reject': return 'REJECT';\n }\n }\n\n public FormatScore(score: number | null): string {\n return score == null ? '—' : score.toFixed(2);\n }\n\n public FormatTokens(tokens: number): string {\n return tokens.toLocaleString();\n }\n\n public FormatCost(cost: number): string {\n return `$${cost.toFixed(2)}`;\n }\n\n public ModeLabel(mode: DryRunConfig['mode']): string {\n switch (mode) {\n case 'constrained': return 'Constrained';\n case 'auto-grow': return 'Auto-grow';\n case 'free-flow': return 'Free-flow';\n }\n }\n}\n","<!-- ══════ DRY-RUN / DISPOSITION PREVIEW SLIDE-IN ══════ -->\n@if (Show) {\n <div class=\"at-slide-overlay\" (click)=\"close()\"></div>\n <div class=\"at-slide-panel dry-run-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-flask\"></i> Dry-run preview</h3>\n <button class=\"at-slide-close\" aria-label=\"Close dry-run preview\" (click)=\"close()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n\n <div class=\"at-slide-body\">\n <!-- Source + intent line -->\n @if (SourceCard) {\n <div class=\"dry-source-line\">\n <i [class]=\"SourceCard.Icon\"></i>\n <span class=\"dry-source-name\">{{ SourceCard.Name }}</span>\n </div>\n }\n\n <!-- \"nothing persisted\" banner -->\n <div class=\"dry-banner\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <span>\n Preview of how this source's sampled tags resolve under the current\n <b>mode &amp; thresholds</b> — <b>no LLM call, nothing persisted</b>.\n </span>\n </div>\n\n <!-- Effective config -->\n <div class=\"dry-effective\">\n <span class=\"pill purple\"><i class=\"fa-solid fa-flask\"></i> PREVIEW</span>\n <span class=\"dry-eff-item\">Mode <b>{{ ModeLabel(EffectiveMode) }}</b></span>\n <span class=\"dry-eff-item\">Match <b>{{ FormatScore(EffectiveMatchThreshold) }}</b></span>\n <span class=\"dry-eff-item\">Suggest <b>{{ FormatScore(EffectiveSuggestThreshold) }}</b></span>\n </div>\n\n @if (Loading) {\n <mj-loading text=\"Sampling existing tags…\"></mj-loading>\n } @else if (NoTagsSampled) {\n <div class=\"dry-empty\">\n <i class=\"fa-solid fa-tags\"></i>\n <p>No extracted tags found for this source yet. Run the pipeline first, then preview how its tags would be dispositioned.</p>\n </div>\n } @else {\n <!-- Estimate line (illustrative) -->\n <div class=\"dry-estimate\">\n <i class=\"fa-solid fa-calculator\"></i>\n <span>\n {{ Estimate.ItemsSampled }} sampled tag{{ Estimate.ItemsSampled === 1 ? '' : 's' }} ·\n est. {{ FormatTokens(Estimate.EstimatedTokens) }} tokens ·\n ~{{ FormatCost(Estimate.EstimatedCost) }}\n <span class=\"dry-est-note\">(rough estimate)</span>\n </span>\n </div>\n\n <!-- Summary counts -->\n <div class=\"dry-summary\">\n <span class=\"disp disp-apply\">{{ Counts.AutoApply }} auto-apply</span>\n <span class=\"disp disp-inbox\">{{ Counts.RouteToInbox }} → inbox</span>\n <span class=\"disp disp-create\">{{ Counts.CreateNew }} create</span>\n @if (Counts.Reject > 0) {\n <span class=\"disp disp-reject\">{{ Counts.Reject }} reject</span>\n }\n </div>\n\n <!-- Disposition table -->\n <table class=\"dry-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Matched</th>\n <th class=\"dry-col-score\">Score</th>\n <th>What would happen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of Rows; track $index) {\n <tr>\n <td class=\"dry-cell-tag\">{{ row.tag }}</td>\n <td class=\"dry-cell-matched\">{{ row.matchedTag ?? '—' }}</td>\n <td class=\"dry-col-score dry-mono\">{{ FormatScore(row.score) }}</td>\n <td>\n <span [class]=\"DispositionClass(row.disposition)\" [title]=\"row.reason\">\n {{ DispositionLabel(row.disposition) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <div class=\"dry-disclaimer\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n A real run also uses a semantic / embedding match tier not reproducible here,\n so borderline rows may resolve differently.\n </div>\n }\n\n <!-- Footer -->\n <div class=\"dry-footer\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"close()\">Close</button>\n </div>\n </div>\n </div>\n}\n"]}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Classify · Content Item Detail slide-in dialog.
3
+ *
4
+ * Presentational slide-in panel showing a content item's details, tags, text,
5
+ * metadata, and actions. Opened from multiple tabs, so it is rendered by the
6
+ * HOST (the data orchestrator), which builds the `ContentItemDetail` and toggles
7
+ * visibility. This component is purely presentational: data DOWN via `[Item]` /
8
+ * `[Show]`, intents UP via `(Closed)` / `(OpenRecordRequested)`.
9
+ */
10
+ import { EventEmitter } from '@angular/core';
11
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
12
+ import { ContentItemDetail } from '../shared/classify.types';
13
+ import { formatWeight, tagFontSize } from '../shared/classify.format';
14
+ import * as i0 from "@angular/core";
15
+ export declare class ClassifyItemDetailDialogComponent extends BaseAngularComponent {
16
+ /** The content item to display, built and supplied by the host orchestrator. */
17
+ Item: ContentItemDetail | null;
18
+ /** Whether the slide-in is visible. */
19
+ Show: boolean;
20
+ /** Emitted when the user dismisses the panel (overlay/close button). */
21
+ Closed: EventEmitter<void>;
22
+ /** Emitted when the user requests to open the underlying record. */
23
+ OpenRecordRequested: EventEmitter<ContentItemDetail>;
24
+ readonly FormatWeight: typeof formatWeight;
25
+ readonly TagFontSize: typeof tagFontSize;
26
+ static ɵfac: i0.ɵɵFactoryDeclaration<ClassifyItemDetailDialogComponent, never>;
27
+ static ɵcmp: i0.ɵɵComponentDeclaration<ClassifyItemDetailDialogComponent, "classify-item-detail-dialog", never, { "Item": { "alias": "Item"; "required": false; }; "Show": { "alias": "Show"; "required": false; }; }, { "Closed": "Closed"; "OpenRecordRequested": "OpenRecordRequested"; }, never, never, false, never>;
28
+ }
29
+ //# sourceMappingURL=item-detail.dialog.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-detail.dialog.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/dialogs/item-detail.dialog.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAA4B,YAAY,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;;AAEtE,qBAMa,iCAAkC,SAAQ,oBAAoB;IACvE,gFAAgF;IACvE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAC/C,uCAAuC;IAC9B,IAAI,UAAS;IAEtB,wEAAwE;IAC9D,MAAM,qBAA4B;IAC5C,oEAAoE;IAC1D,mBAAmB,kCAAyC;IAGtE,SAAgB,YAAY,sBAAgB;IAC5C,SAAgB,WAAW,qBAAe;yCAbjC,iCAAiC;2CAAjC,iCAAiC;CAc7C"}