@memberjunction/ng-dashboards 5.47.0 → 5.49.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 (67) hide show
  1. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +15 -4
  2. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  3. package/dist/DataExplorer/data-explorer-dashboard.component.js +45 -35
  4. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  5. package/dist/DataExplorer/models/explorer-state.interface.d.ts +7 -0
  6. package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
  7. package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
  8. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js +2 -2
  9. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js.map +1 -1
  10. package/dist/Lists/components/lists-browse-resource.component.d.ts +4 -0
  11. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  12. package/dist/Lists/components/lists-browse-resource.component.js +39 -30
  13. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  14. package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
  15. package/dist/Lists/components/lists-my-lists-resource.component.js +14 -12
  16. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  17. package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
  18. package/dist/Lists/components/lists-operations-resource.component.js +6 -1
  19. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  20. package/dist/Lists/services/list-set-operations.service.d.ts +11 -0
  21. package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
  22. package/dist/Lists/services/list-set-operations.service.js +56 -14
  23. package/dist/Lists/services/list-set-operations.service.js.map +1 -1
  24. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +7 -1
  25. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
  26. package/dist/PredictiveStudio/components/ps-pipelines.component.js +11 -4
  27. package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
  28. package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
  29. package/dist/Testing/components/testing-runs.component.js +35 -25
  30. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  31. package/dist/Testing/services/testing-instrumentation.service.d.ts +5 -0
  32. package/dist/Testing/services/testing-instrumentation.service.d.ts.map +1 -1
  33. package/dist/Testing/services/testing-instrumentation.service.js +8 -2
  34. package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
  35. package/dist/ThemeStudio/theme-agent-context.d.ts +64 -0
  36. package/dist/ThemeStudio/theme-agent-context.d.ts.map +1 -0
  37. package/dist/ThemeStudio/theme-agent-context.js +129 -0
  38. package/dist/ThemeStudio/theme-agent-context.js.map +1 -0
  39. package/dist/ThemeStudio/theme-manager-dashboard.component.d.ts +62 -0
  40. package/dist/ThemeStudio/theme-manager-dashboard.component.d.ts.map +1 -0
  41. package/dist/ThemeStudio/theme-manager-dashboard.component.js +464 -0
  42. package/dist/ThemeStudio/theme-manager-dashboard.component.js.map +1 -0
  43. package/dist/ThemeStudio/theme-manager-resource.component.d.ts +31 -0
  44. package/dist/ThemeStudio/theme-manager-resource.component.d.ts.map +1 -0
  45. package/dist/ThemeStudio/theme-manager-resource.component.js +97 -0
  46. package/dist/ThemeStudio/theme-manager-resource.component.js.map +1 -0
  47. package/dist/ThemeStudio/theme-studio-dashboard.component.d.ts +351 -0
  48. package/dist/ThemeStudio/theme-studio-dashboard.component.d.ts.map +1 -0
  49. package/dist/ThemeStudio/theme-studio-dashboard.component.js +2931 -0
  50. package/dist/ThemeStudio/theme-studio-dashboard.component.js.map +1 -0
  51. package/dist/ThemeStudio/theme-studio-resource.component.d.ts +28 -0
  52. package/dist/ThemeStudio/theme-studio-resource.component.d.ts.map +1 -0
  53. package/dist/ThemeStudio/theme-studio-resource.component.js +96 -0
  54. package/dist/ThemeStudio/theme-studio-resource.component.js.map +1 -0
  55. package/dist/ThemeStudio/theme-studio.constants.d.ts +79 -0
  56. package/dist/ThemeStudio/theme-studio.constants.d.ts.map +1 -0
  57. package/dist/ThemeStudio/theme-studio.constants.js +217 -0
  58. package/dist/ThemeStudio/theme-studio.constants.js.map +1 -0
  59. package/dist/core-dashboards.module.d.ts +56 -52
  60. package/dist/core-dashboards.module.d.ts.map +1 -1
  61. package/dist/core-dashboards.module.js +24 -1
  62. package/dist/core-dashboards.module.js.map +1 -1
  63. package/dist/public-api.d.ts +4 -0
  64. package/dist/public-api.d.ts.map +1 -1
  65. package/dist/public-api.js +4 -0
  66. package/dist/public-api.js.map +1 -1
  67. package/package.json +63 -60
@@ -1 +1 @@
1
- {"version":3,"file":"testing-instrumentation.service.js","sourceRoot":"","sources":["../../../src/Testing/services/testing-instrumentation.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { Observable, BehaviorSubject, from, combineLatest } from 'rxjs';\nimport { map, switchMap, shareReplay, tap } from 'rxjs/operators';\nimport { RunView, Metadata, IMetadataProvider } from '@memberjunction/core';\nimport { MJTestRunFeedbackEntity } from '@memberjunction/core-entities';\nimport { TestEngineBase } from '@memberjunction/testing-engine-base';\n\nexport interface TestingDashboardKPIs {\n totalTestsActive: number;\n passRateThisMonth: number;\n totalCostThisMonth: number;\n averageDuration: number;\n testsPendingReview: number;\n totalTestRuns: number;\n failedTests: number;\n skippedTests: number;\n passRateTrend: number; // Percentage change from previous period\n}\n\nexport interface TestRunSummary {\n id: string;\n testId: string;\n testName: string;\n suiteName: string;\n testType: string;\n status: 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running' | 'Timeout';\n score: number; // 0-1.0000\n duration: number; // milliseconds\n cost: number; // USD\n runDateTime: Date;\n targetType: string;\n targetLogID: string;\n}\n\nexport interface SuiteHierarchyNode {\n id: string;\n name: string;\n parentID: string | null;\n level: number;\n children: SuiteHierarchyNode[];\n testCount: number;\n passRate: number;\n totalCost: number;\n averageScore: number;\n expanded?: boolean;\n}\n\nexport interface VersionMetrics {\n version: string; // GitCommit + AgentVersion combination\n gitCommit: string;\n agentVersion: string;\n runDate: Date;\n totalTests: number;\n passRate: number;\n averageScore: number;\n totalCost: number;\n averageDuration: number;\n newFailures: number;\n newPasses: number;\n}\n\nexport interface TestTrendData {\n timestamp: Date;\n totalRuns: number;\n passed: number;\n failed: number;\n skipped: number;\n errors: number;\n averageScore: number;\n totalCost: number;\n averageDuration: number;\n}\n\nexport interface FeedbackPending {\n testRunID: string;\n testName: string;\n automatedScore: number;\n automatedStatus: string;\n runDateTime: Date;\n reason: 'no-feedback' | 'high-score-failed' | 'low-score-passed';\n}\n\nexport interface TestAnalytics {\n topFailingTests: Array<{ testName: string; failureCount: number; failureRate: number }>;\n mostExpensiveTests: Array<{ testName: string; totalCost: number; avgCost: number }>;\n slowestTests: Array<{ testName: string; avgDuration: number; maxDuration: number }>;\n costByType: Array<{ testType: string; totalCost: number; testCount: number }>;\n costBySuite: Array<{ suiteName: string; totalCost: number; testCount: number }>;\n passingRateByType: Array<{ testType: string; passRate: number; totalTests: number }>;\n}\n\nexport interface FeedbackStats {\n totalFeedback: number;\n reviewedCount: number;\n avgRating: number;\n agreementRate: number;\n disagreementRate: number;\n accuracyRate: number;\n}\n\n/**\n * Extended test run summary with human feedback data included\n */\nexport interface TestRunWithFeedbackSummary extends TestRunSummary {\n // Human feedback\n humanRating: number | null;\n humanIsCorrect: boolean | null;\n humanComments: string | null;\n hasHumanFeedback: boolean;\n feedbackId: string | null;\n // Checks (from automated evaluation)\n passedChecks: number | null;\n failedChecks: number | null;\n totalChecks: number | null;\n}\n\n/**\n * Aggregated evaluation metrics\n */\nexport interface EvaluationSummaryMetrics {\n totalRuns: number;\n // Execution\n execCompletedCount: number;\n execErrorCount: number;\n execSuccessRate: number;\n // Human\n humanReviewedCount: number;\n humanPendingCount: number;\n humanAvgRating: number;\n humanCorrectRate: number;\n // Auto\n autoEvaluatedCount: number;\n autoAvgScore: number;\n autoPassRate: number;\n // Agreement\n agreementRate: number;\n}\n\n// Simple result types for optimized queries (only fields needed for display)\ninterface TestRunSimple {\n ID: string;\n TestID: string;\n Test: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: Date;\n CompletedAt: Date | null;\n TargetType: string;\n TargetLogID: string;\n}\n\ninterface TestSuiteRunSimple {\n ID: string;\n TestSuiteID: string;\n TotalTests: number;\n PassedTests: number;\n TotalCostUSD: number;\n StartedAt: Date;\n GitCommit: string;\n AgentVersion: string;\n}\n\ninterface TestRunFeedbackSimple {\n ID: string;\n TestRunID: string;\n Rating: number;\n IsCorrect: boolean;\n Comments: string;\n CreatedAt: Date;\n}\n\n/**\n * A filter intent published by the AI agent (via the Testing dashboard's client\n * tools) for the Runs surface to apply. Both fields are optional — only the\n * provided ones are applied. This decouples the agent-actionable Runs filters\n * from any specific component instance: the agent sets an intent on this shared\n * root service, and the (possibly not-yet-mounted) Runs component consumes it.\n */\nexport interface RunsFilterIntent {\n status?: 'all' | 'running' | 'passed' | 'failed' | 'error';\n searchText?: string;\n}\n\n/**\n * A run-selection intent published by the AI agent (via the Testing dashboard's\n * `SelectTestRun` client tool) for the Runs surface to act on. The Runs component\n * owns the actual `SelectedRun` UI state (per the data-down/events-up Angular\n * convention), so the agent publishes the target run ID here and the (possibly\n * not-yet-mounted) Runs component consumes it when it mounts / when it changes.\n *\n * `open` distinguishes \"open the detail panel for this run\" (select) from\n * \"open the run's record in the entity workspace\" — both are read-only,\n * navigational affordances (no test execution side effects).\n */\nexport interface RunSelectionIntent {\n /** Target test-run ID to select (and optionally open). */\n runId: string;\n /** When true, also open the run's record in the entity workspace. */\n open?: boolean;\n /** Monotonic nonce so re-selecting the SAME run id still replays the intent. */\n nonce: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class TestingInstrumentationService {\n private readonly _dateRange$ = new BehaviorSubject<{ start: Date; end: Date }>({\n start: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // Last 30 days\n end: new Date()\n });\n\n /**\n * Agent-driven filter intents for the Runs surface. Published by the Testing\n * dashboard's client tools; consumed by the Runs component. Starts as null\n * (no pending intent).\n */\n private readonly _runsFilterIntent$ = new BehaviorSubject<RunsFilterIntent | null>(null);\n\n /** Observable of agent-driven Runs filter intents. */\n readonly runsFilterIntent$ = this._runsFilterIntent$.asObservable();\n\n /** Publish an agent-driven filter intent for the Runs surface to apply. */\n setRunsFilterIntent(intent: RunsFilterIntent): void {\n this._runsFilterIntent$.next(intent);\n }\n\n /**\n * Agent-driven run-SELECTION intents for the Runs surface. Published by the\n * Testing dashboard's `SelectTestRun` / open-run client tools; consumed by the\n * Runs component (which owns the actual {@link TestRunWithFeedbackSummary}\n * `SelectedRun` UI state). Starts as null (no pending intent). A monotonic\n * nonce on each intent lets the Runs component replay the SAME run id again\n * (re-select / re-open) even though the BehaviorSubject would otherwise\n * de-duplicate identical references.\n */\n private readonly _runSelectionIntent$ = new BehaviorSubject<RunSelectionIntent | null>(null);\n\n /** Observable of agent-driven run-selection intents. */\n readonly runSelectionIntent$ = this._runSelectionIntent$.asObservable();\n\n /** Monotonic source for {@link RunSelectionIntent.nonce}. */\n private _runSelectionNonce = 0;\n\n /**\n * Publish an agent-driven run-selection intent for the Runs surface to act on.\n * Assigns the next monotonic nonce so re-selecting the same run id still\n * replays. Returns the published intent (with its assigned nonce).\n */\n setRunSelectionIntent(runId: string, open: boolean = false): RunSelectionIntent {\n const intent: RunSelectionIntent = { runId, open, nonce: ++this._runSelectionNonce };\n this._runSelectionIntent$.next(intent);\n return intent;\n }\n\n private readonly _suiteFilter$ = new BehaviorSubject<string | null>(null);\n private readonly _testTypeFilter$ = new BehaviorSubject<string | null>(null);\n private readonly _refreshTrigger$ = new BehaviorSubject<number>(0);\n private readonly _isLoading$ = new BehaviorSubject<boolean>(false);\n private _provider: IMetadataProvider | null = null;\n\n /** Set the metadata provider this service should use. Components should call this after injection. */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n private get metadata(): IMetadataProvider {\n return this.Provider;\n }\n\n // Expose observables\n readonly isLoading$ = this._isLoading$.asObservable();\n readonly dateRange$ = this._dateRange$.asObservable();\n\n constructor() {}\n\n // Main data streams\n readonly kpis$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadKPIs())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly testRuns$ = combineLatest([\n this._refreshTrigger$,\n this._dateRange$,\n this._suiteFilter$,\n this._testTypeFilter$\n ]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTestRuns())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly suiteHierarchy$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadSuiteHierarchy())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly trends$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTrends())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly analytics$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadAnalytics())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly pendingFeedback$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadPendingFeedback())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly feedbackStats$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadFeedbackStats())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n /**\n * Test runs with feedback data joined - for evaluation display\n */\n readonly testRunsWithFeedback$ = combineLatest([\n this._refreshTrigger$,\n this._dateRange$,\n this._suiteFilter$,\n this._testTypeFilter$\n ]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTestRunsWithFeedback())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n /**\n * Aggregated evaluation metrics from test runs with feedback\n */\n readonly evaluationMetrics$ = this.testRunsWithFeedback$.pipe(\n map(runs => this.calculateEvaluationMetrics(runs)),\n shareReplay(1)\n );\n\n private checkLoadingComplete(): void {\n setTimeout(() => {\n this._isLoading$.next(false);\n }, 100);\n }\n\n setDateRange(start: Date, end: Date): void {\n this._dateRange$.next({ start, end });\n }\n\n /**\n * Set the active date range from a named time range. Centralizes the\n * range-to-dates computation so both the Runs surface UI and the agent's\n * `FilterTestsByTimeRange` tool resolve identical windows.\n */\n setDateRangeByName(range: 'today' | 'week' | 'month' | '90days'): void {\n const now = new Date();\n let start: Date;\n switch (range) {\n case 'today':\n start = new Date(now);\n start.setHours(0, 0, 0, 0);\n break;\n case 'week':\n start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n break;\n case '90days':\n start = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);\n break;\n case 'month':\n default:\n start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n }\n this.setDateRange(start, now);\n }\n\n setSuiteFilter(suiteId: string | null): void {\n this._suiteFilter$.next(suiteId);\n }\n\n setTestTypeFilter(typeId: string | null): void {\n this._testTypeFilter$.next(typeId);\n }\n\n refresh(): void {\n this._refreshTrigger$.next(this._refreshTrigger$.value + 1);\n }\n\n private async loadKPIs(): Promise<TestingDashboardKPIs> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get Tests from TestEngineBase cache instead of querying DB\n const engine = TestEngineBase.Instance;\n const activeTests = engine.Tests.filter(t => t.Status === 'Active');\n\n // Only load runs via RunView (not cached in engine) - use simple result type with only needed fields\n const [testRunsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = testRunsResult.Results as TestRunSimple[];\n\n // Calculate KPIs\n const totalTestsActive = activeTests.length;\n const totalTestRuns = testRuns.length;\n\n const passedRuns = testRuns.filter(r => r.Status === 'Passed');\n const failedRuns = testRuns.filter(r => r.Status === 'Failed');\n const skippedRuns = testRuns.filter(r => r.Status === 'Skipped');\n\n const passRateThisMonth = totalTestRuns > 0 ? (passedRuns.length / totalTestRuns) * 100 : 0;\n\n const totalCostThisMonth = testRuns.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n\n const completedRuns = testRuns.filter(r => r.CompletedAt != null && r.StartedAt != null);\n const averageDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return sum + (endTime - startTime);\n }, 0) / completedRuns.length\n : 0;\n\n // Count tests pending review (no feedback)\n const testRunIDs = testRuns.map(r => r.ID);\n const testsPendingReview = await this.countTestsPendingReview(testRunIDs);\n\n // Calculate trend (compare to previous period)\n const periodDuration = end.getTime() - start.getTime();\n const previousStart = new Date(start.getTime() - periodDuration);\n const previousEnd = new Date(start.getTime());\n\n const previousRunsResult = await rv.RunView<TestRunSimple>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${previousStart.toISOString()}' AND StartedAt < '${previousEnd.toISOString()}'`,\n Fields: ['ID', 'Status'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const previousRuns = previousRunsResult.Results || [];\n const previousPassRate = previousRuns.length > 0\n ? (previousRuns.filter(r => r.Status === 'Passed').length / previousRuns.length) * 100\n : 0;\n\n const passRateTrend = previousPassRate > 0 ? passRateThisMonth - previousPassRate : 0;\n\n return {\n totalTestsActive,\n passRateThisMonth,\n totalCostThisMonth,\n averageDuration,\n testsPendingReview,\n totalTestRuns,\n failedTests: failedRuns.length,\n skippedTests: skippedRuns.length,\n passRateTrend\n };\n }\n\n private async countTestsPendingReview(testRunIDs: string[]): Promise<number> {\n if (testRunIDs.length === 0) return 0;\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const idList = testRunIDs.join(\"','\");\n\n const feedbackResult = await rv.RunView<{TestRunID: string}>({\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `TestRunID IN ('${idList}')`,\n Fields: ['TestRunID'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const feedbackTestRunIDs = new Set((feedbackResult.Results || []).map(f => f.TestRunID));\n\n return testRunIDs.filter(id => !feedbackTestRunIDs.has(id)).length;\n }\n\n private async loadTestRuns(): Promise<TestRunSummary[]> {\n const { start, end } = this._dateRange$.value;\n const suiteFilter = this._suiteFilter$.value;\n const typeFilter = this._testTypeFilter$.value;\n\n let filter = `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`;\n\n if (suiteFilter) {\n // Need to join through TestSuiteTest\n filter += ` AND TestID IN (SELECT TestID FROM [__mj].[vwTestSuiteTests] WHERE TestSuiteID = '${suiteFilter}')`;\n }\n\n if (typeFilter) {\n filter += ` AND TestID IN (SELECT ID FROM [__mj].[vwTests] WHERE TypeID = '${typeFilter}')`;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<TestRunSimple>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 1000,\n Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = result.Results || [];\n\n return testRuns.map(run => {\n const startedAt = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n const completedAt = run.CompletedAt\n ? (run.CompletedAt instanceof Date ? run.CompletedAt : new Date(run.CompletedAt))\n : null;\n\n return {\n id: run.ID,\n testId: run.TestID || '',\n testName: run.Test || 'Unknown Test',\n suiteName: '', // Will be populated from join\n testType: run.Test || 'Unknown',\n status: run.Status as 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running',\n score: run.Score || 0,\n duration: completedAt && startedAt\n ? completedAt.getTime() - startedAt.getTime()\n : (startedAt ? Date.now() - startedAt.getTime() : 0),\n cost: run.CostUSD || 0,\n runDateTime: startedAt,\n targetType: run.TargetType || '',\n targetLogID: run.TargetLogID || ''\n };\n });\n }\n\n private async loadSuiteHierarchy(): Promise<SuiteHierarchyNode[]> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get Test Suites from TestEngineBase cache instead of querying DB\n const engine = TestEngineBase.Instance;\n const suites = engine.TestSuites.filter(s => s.Status === 'Active');\n\n // Only load test runs via RunView (not cached in engine) - use simple result type\n const testRunsResult = await rv.RunView<{ID: string; TestID: string; Status: string; Score: number; CostUSD: number}>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'TestID', 'Status', 'Score', 'CostUSD'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = testRunsResult.Results || [];\n\n // Build hierarchy\n const nodes: SuiteHierarchyNode[] = suites.map(suite => ({\n id: suite.ID,\n name: suite.Name,\n parentID: suite.ParentID || null,\n level: 0,\n children: [],\n testCount: 0,\n passRate: 0,\n totalCost: 0,\n averageScore: 0,\n expanded: false\n }));\n\n // Calculate metrics for each suite (simplified - would need TestSuiteTest join for accuracy)\n type SimpleTestRun = {ID: string; TestID: string; Status: string; Score: number; CostUSD: number};\n const suiteTestRuns = new Map<string, SimpleTestRun[]>();\n\n testRuns.forEach(run => {\n // This is simplified - would need to query TestSuiteTest to get actual suite membership\n const suiteID = run.TestID; // Placeholder\n if (!suiteTestRuns.has(suiteID)) {\n suiteTestRuns.set(suiteID, []);\n }\n suiteTestRuns.get(suiteID)!.push(run);\n });\n\n nodes.forEach(node => {\n const runs = suiteTestRuns.get(node.id) || [];\n node.testCount = runs.length;\n node.passRate = runs.length > 0\n ? (runs.filter(r => r.Status === 'Passed').length / runs.length) * 100\n : 0;\n node.totalCost = runs.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n node.averageScore = runs.length > 0\n ? runs.reduce((sum, r) => sum + (r.Score || 0), 0) / runs.length\n : 0;\n });\n\n // Build tree structure\n const rootNodes: SuiteHierarchyNode[] = [];\n const nodeMap = new Map<string, SuiteHierarchyNode>();\n\n nodes.forEach(node => nodeMap.set(node.id, node));\n\n nodes.forEach(node => {\n if (node.parentID) {\n const parent = nodeMap.get(node.parentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n });\n\n return rootNodes;\n }\n\n private async loadTrends(): Promise<TestTrendData[]> {\n const { start, end } = this._dateRange$.value;\n\n // Create time buckets\n const buckets = this.createTimeBuckets(start, end);\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load all test runs for the period - use simple result type with only needed fields\n type TrendRun = {Status: string; Score: number; CostUSD: number; StartedAt: string | Date; CompletedAt: string | Date | null};\n const result = await rv.RunView<TrendRun>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n OrderBy: 'StartedAt',\n Fields: ['Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const allRuns = result.Results || [];\n\n // Aggregate into buckets\n const trends: TestTrendData[] = buckets.map(bucketStart => {\n const bucketEnd = new Date(bucketStart.getTime() + this.getBucketSize(start, end));\n\n const bucketRuns = allRuns.filter(r => {\n if (!r.StartedAt) return false;\n const runTime = r.StartedAt instanceof Date ? r.StartedAt : new Date(r.StartedAt);\n return runTime >= bucketStart && runTime < bucketEnd;\n });\n\n const passed = bucketRuns.filter(r => r.Status === 'Passed').length;\n const failed = bucketRuns.filter(r => r.Status === 'Failed').length;\n const skipped = bucketRuns.filter(r => r.Status === 'Skipped').length;\n const errors = bucketRuns.filter(r => r.Status === 'Error').length;\n\n const averageScore = bucketRuns.length > 0\n ? bucketRuns.reduce((sum, r) => sum + (r.Score || 0), 0) / bucketRuns.length\n : 0;\n\n const totalCost = bucketRuns.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n\n const completedRuns = bucketRuns.filter(r => r.CompletedAt != null && r.StartedAt != null);\n const averageDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return sum + (endTime - startTime);\n }, 0) / completedRuns.length\n : 0;\n\n return {\n timestamp: bucketStart,\n totalRuns: bucketRuns.length,\n passed,\n failed,\n skipped,\n errors,\n averageScore,\n totalCost,\n averageDuration\n };\n });\n\n return trends;\n }\n\n private async loadAnalytics(): Promise<TestAnalytics> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result type with only needed fields\n type AnalyticsRun = {Test: string; Status: string; Score: number; CostUSD: number; StartedAt: string | Date; CompletedAt: string | Date | null};\n const result = await rv.RunView<AnalyticsRun>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = result.Results || [];\n\n // Group by test name\n const testMetrics = new Map<string, { runs: AnalyticsRun[], failures: number }>();\n\n testRuns.forEach(run => {\n const testName = run.Test || 'Unknown';\n if (!testMetrics.has(testName)) {\n testMetrics.set(testName, { runs: [], failures: 0 });\n }\n const metrics = testMetrics.get(testName)!;\n metrics.runs.push(run);\n if (run.Status === 'Failed' || run.Status === 'Error') {\n metrics.failures++;\n }\n });\n\n // Top failing tests\n const topFailingTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => ({\n testName,\n failureCount: metrics.failures,\n failureRate: metrics.runs.length > 0 ? (metrics.failures / metrics.runs.length) * 100 : 0\n }))\n .sort((a, b) => b.failureCount - a.failureCount)\n .slice(0, 10);\n\n // Most expensive tests\n const mostExpensiveTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => {\n const totalCost = metrics.runs.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n const avgCost = metrics.runs.length > 0 ? totalCost / metrics.runs.length : 0;\n return { testName, totalCost, avgCost };\n })\n .sort((a, b) => b.totalCost - a.totalCost)\n .slice(0, 10);\n\n // Slowest tests\n const slowestTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => {\n const durations = metrics.runs\n .filter(r => r.CompletedAt != null && r.StartedAt != null)\n .map(r => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return endTime - startTime;\n });\n\n const avgDuration = durations.length > 0\n ? durations.reduce((sum, d) => sum + d, 0) / durations.length\n : 0;\n const maxDuration = durations.length > 0 ? Math.max(...durations) : 0;\n\n return { testName, avgDuration, maxDuration };\n })\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, 10);\n\n // Cost by type (simplified - would need actual type data)\n const typeMetrics = new Map<string, { cost: number, count: number }>();\n testRuns.forEach(run => {\n const type = run.Test || 'Unknown';\n if (!typeMetrics.has(type)) {\n typeMetrics.set(type, { cost: 0, count: 0 });\n }\n const metrics = typeMetrics.get(type)!;\n metrics.cost += run.CostUSD || 0;\n metrics.count++;\n });\n\n const costByType = Array.from(typeMetrics.entries())\n .map(([testType, metrics]) => ({\n testType,\n totalCost: metrics.cost,\n testCount: metrics.count\n }))\n .sort((a, b) => b.totalCost - a.totalCost);\n\n // Passing rate by type\n const typePassingMetrics = new Map<string, { total: number, passed: number }>();\n testRuns.forEach(run => {\n const type = run.Test || 'Unknown';\n if (!typePassingMetrics.has(type)) {\n typePassingMetrics.set(type, { total: 0, passed: 0 });\n }\n const metrics = typePassingMetrics.get(type)!;\n metrics.total++;\n if (run.Status === 'Passed') {\n metrics.passed++;\n }\n });\n\n const passingRateByType = Array.from(typePassingMetrics.entries())\n .map(([testType, metrics]) => ({\n testType,\n passRate: metrics.total > 0 ? (metrics.passed / metrics.total) * 100 : 0,\n totalTests: metrics.total\n }))\n .sort((a, b) => a.passRate - b.passRate);\n\n return {\n topFailingTests,\n mostExpensiveTests,\n slowestTests,\n costByType,\n costBySuite: [], // Would need suite data\n passingRateByType\n };\n }\n\n private async loadPendingFeedback(): Promise<FeedbackPending[]> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result types with only needed fields\n type FeedbackTestRun = {ID: string; Test: string; Score: number; Status: string; StartedAt: string | Date};\n type FeedbackItem = {TestRunID: string};\n\n const [testRunsResult, feedbackResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'Test', 'Score', 'Status', 'StartedAt'],\n ResultType: 'simple',\n CacheLocal: true\n },\n {\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}'`,\n Fields: ['TestRunID'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = testRunsResult.Results as FeedbackTestRun[];\n const feedbacks = feedbackResult.Results as FeedbackItem[];\n\n const feedbackTestRunIDs = new Set(feedbacks.map(f => f.TestRunID));\n\n const pending: FeedbackPending[] = [];\n\n testRuns.forEach(run => {\n const hasFeedback = feedbackTestRunIDs.has(run.ID);\n const runDateTime = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n\n if (!hasFeedback) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score || 0,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'no-feedback'\n });\n } else {\n // Check for discrepancies\n if (run.Status === 'Failed' && run.Score != null && run.Score >= 0.8) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'high-score-failed'\n });\n } else if (run.Status === 'Passed' && run.Score != null && run.Score < 0.5) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'low-score-passed'\n });\n }\n }\n });\n\n return pending.sort((a, b) => b.runDateTime.getTime() - a.runDateTime.getTime());\n }\n\n private async loadFeedbackStats(): Promise<FeedbackStats> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load all feedback for the period - use simple result type with only needed fields\n type FeedbackStatItem = {Rating: number; IsCorrect: boolean};\n const feedbackResult = await rv.RunView<FeedbackStatItem>({\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}' AND CreatedAt <= '${end.toISOString()}'`,\n Fields: ['Rating', 'IsCorrect'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const feedbacks = feedbackResult.Results || [];\n const totalFeedback = feedbacks.length;\n\n if (totalFeedback === 0) {\n return {\n totalFeedback: 0,\n reviewedCount: 0,\n avgRating: 0,\n agreementRate: 0,\n disagreementRate: 0,\n accuracyRate: 0\n };\n }\n\n // Calculate average rating\n const avgRating = feedbacks.reduce((sum, f) => sum + (f.Rating || 0), 0) / totalFeedback;\n\n // Calculate agreement/disagreement rates based on IsCorrect field\n const correctCount = feedbacks.filter(f => f.IsCorrect === true).length;\n const incorrectCount = feedbacks.filter(f => f.IsCorrect === false).length;\n\n const agreementRate = (correctCount / totalFeedback) * 100;\n const disagreementRate = (incorrectCount / totalFeedback) * 100;\n\n // Accuracy rate is the same as agreement rate (% of times human agreed with automated result)\n const accuracyRate = agreementRate;\n\n return {\n totalFeedback,\n reviewedCount: totalFeedback, // All feedbacks in this query are reviewed\n avgRating,\n agreementRate,\n disagreementRate,\n accuracyRate\n };\n }\n\n async submitFeedback(testRunID: string, rating: number, isCorrect: boolean, comments: string): Promise<boolean> {\n try {\n const feedback = await this.metadata.GetEntityObject<MJTestRunFeedbackEntity>('MJ: Test Run Feedbacks');\n feedback.TestRunID = testRunID;\n feedback.Rating = rating;\n feedback.IsCorrect = isCorrect;\n feedback.Comments = comments;\n\n const result = await feedback.Save();\n if (result) {\n this.refresh(); // Refresh data after submission\n return true;\n }\n return false;\n } catch (error) {\n console.error('Error submitting feedback:', error);\n return false;\n }\n }\n\n async getVersionMetrics(): Promise<VersionMetrics[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result type with only needed fields\n type VersionRun = {TotalTests: number; PassedTests: number; TotalCostUSD: number; StartedAt: string | Date; GitCommit: string; AgentVersion: string};\n const result = await rv.RunView<VersionRun>({\n EntityName: 'MJ: Test Suite Runs',\n ExtraFilter: '',\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n Fields: ['TotalTests', 'PassedTests', 'TotalCostUSD', 'StartedAt', 'GitCommit', 'AgentVersion'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const suiteRuns = result.Results || [];\n\n // Group by version combination\n const versionMap = new Map<string, VersionRun[]>();\n\n suiteRuns.forEach(run => {\n const key = `${run.GitCommit || 'unknown'}_${run.AgentVersion || 'unknown'}`;\n if (!versionMap.has(key)) {\n versionMap.set(key, []);\n }\n versionMap.get(key)!.push(run);\n });\n\n const metrics: VersionMetrics[] = Array.from(versionMap.entries()).map(([key, runs]) => {\n const [gitCommit, agentVersion] = key.split('_');\n const latest = runs[0];\n\n const totalTests = runs.reduce((sum, r) => sum + (r.TotalTests || 0), 0);\n const totalPassed = runs.reduce((sum, r) => sum + (r.PassedTests || 0), 0);\n const totalCost = runs.reduce((sum, r) => sum + (r.TotalCostUSD || 0), 0);\n\n const runDate = latest.StartedAt instanceof Date ? latest.StartedAt : new Date(latest.StartedAt);\n\n return {\n version: `${gitCommit.substring(0, 7)} / ${agentVersion}`,\n gitCommit,\n agentVersion,\n runDate,\n totalTests,\n passRate: totalTests > 0 ? (totalPassed / totalTests) * 100 : 0,\n averageScore: 0, // Would need to calculate from test runs\n totalCost,\n averageDuration: 0, // Would need to calculate from test runs\n newFailures: 0, // Would need comparison\n newPasses: 0 // Would need comparison\n };\n });\n\n return metrics.sort((a, b) => b.runDate.getTime() - a.runDate.getTime());\n }\n\n private createTimeBuckets(start: Date, end: Date): Date[] {\n const buckets: Date[] = [];\n const bucketSize = this.getBucketSize(start, end);\n const current = new Date(start);\n\n while (current < end) {\n buckets.push(new Date(current));\n current.setTime(current.getTime() + bucketSize);\n }\n\n return buckets;\n }\n\n private getBucketSize(start: Date, end: Date): number {\n const duration = end.getTime() - start.getTime();\n const days = duration / (1000 * 60 * 60 * 24);\n\n if (days <= 1) {\n return 60 * 60 * 1000; // 1 hour\n } else if (days <= 7) {\n return 4 * 60 * 60 * 1000; // 4 hours\n } else if (days <= 30) {\n return 24 * 60 * 60 * 1000; // 1 day\n } else {\n return 7 * 24 * 60 * 60 * 1000; // 1 week\n }\n }\n\n /**\n * Load test runs with feedback data joined for evaluation display\n */\n private async loadTestRunsWithFeedback(): Promise<TestRunWithFeedbackSummary[]> {\n const { start, end } = this._dateRange$.value;\n const suiteFilter = this._suiteFilter$.value;\n const typeFilter = this._testTypeFilter$.value;\n\n let filter = `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`;\n\n if (suiteFilter) {\n filter += ` AND TestID IN (SELECT TestID FROM [__mj].[vwTestSuiteTests] WHERE TestSuiteID = '${suiteFilter}')`;\n }\n\n if (typeFilter) {\n filter += ` AND TestID IN (SELECT ID FROM [__mj].[vwTests] WHERE TypeID = '${typeFilter}')`;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load test runs with additional fields for evaluation\n type MJTestRunExtended = {\n ID: string;\n TestID: string;\n Test: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: Date;\n CompletedAt: Date | null;\n TargetType: string;\n TargetLogID: string;\n PassedChecks: number | null;\n FailedChecks: number | null;\n TotalChecks: number | null;\n };\n\n const [testRunsResult, feedbackResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 1000,\n Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID', 'PassedChecks', 'FailedChecks', 'TotalChecks'],\n ResultType: 'simple',\n CacheLocal: true\n },\n {\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}'`,\n Fields: ['ID', 'TestRunID', 'Rating', 'IsCorrect', 'Comments'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = (testRunsResult.Results || []) as MJTestRunExtended[];\n const feedbacks = (feedbackResult.Results || []) as TestRunFeedbackSimple[];\n\n // Create feedback lookup map\n const feedbackMap = new Map<string, TestRunFeedbackSimple>();\n feedbacks.forEach(f => {\n feedbackMap.set(f.TestRunID, f);\n });\n\n // Map test runs with feedback\n return testRuns.map(run => {\n const startedAt = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n const completedAt = run.CompletedAt\n ? (run.CompletedAt instanceof Date ? run.CompletedAt : new Date(run.CompletedAt))\n : null;\n\n const feedback = feedbackMap.get(run.ID);\n\n return {\n id: run.ID,\n testId: run.TestID || '',\n testName: run.Test || 'Unknown Test',\n suiteName: '',\n testType: run.Test || 'Unknown',\n status: run.Status as 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running' | 'Timeout',\n score: run.Score || 0,\n duration: completedAt && startedAt\n ? completedAt.getTime() - startedAt.getTime()\n : (startedAt ? Date.now() - startedAt.getTime() : 0),\n cost: run.CostUSD || 0,\n runDateTime: startedAt,\n targetType: run.TargetType || '',\n targetLogID: run.TargetLogID || '',\n // Checks\n passedChecks: run.PassedChecks,\n failedChecks: run.FailedChecks,\n totalChecks: run.TotalChecks,\n // Human feedback\n humanRating: feedback?.Rating ?? null,\n humanIsCorrect: feedback?.IsCorrect ?? null,\n humanComments: feedback?.Comments ?? null,\n hasHumanFeedback: !!feedback,\n feedbackId: feedback?.ID ?? null\n };\n });\n }\n\n /**\n * Calculate aggregated evaluation metrics from test runs with feedback\n */\n private calculateEvaluationMetrics(runs: TestRunWithFeedbackSummary[]): EvaluationSummaryMetrics {\n const totalRuns = runs.length;\n\n if (totalRuns === 0) {\n return {\n totalRuns: 0,\n execCompletedCount: 0,\n execErrorCount: 0,\n execSuccessRate: 0,\n humanReviewedCount: 0,\n humanPendingCount: 0,\n humanAvgRating: 0,\n humanCorrectRate: 0,\n autoEvaluatedCount: 0,\n autoAvgScore: 0,\n autoPassRate: 0,\n agreementRate: 0\n };\n }\n\n // Execution metrics\n const execCompleted = runs.filter(r =>\n r.status === 'Passed' || r.status === 'Failed'\n );\n const execErrors = runs.filter(r =>\n r.status === 'Error' || r.status === 'Timeout'\n );\n const execSuccessRate = totalRuns > 0 ? (execCompleted.length / totalRuns) * 100 : 0;\n\n // Human feedback metrics\n const reviewed = runs.filter(r => r.hasHumanFeedback);\n const pending = runs.filter(r => !r.hasHumanFeedback);\n const withRating = reviewed.filter(r => r.humanRating != null);\n const humanAvgRating = withRating.length > 0\n ? withRating.reduce((sum, r) => sum + (r.humanRating || 0), 0) / withRating.length\n : 0;\n const correct = reviewed.filter(r => r.humanIsCorrect === true);\n const humanCorrectRate = reviewed.length > 0 ? (correct.length / reviewed.length) * 100 : 0;\n\n // Auto score metrics\n const evaluated = runs.filter(r => r.score > 0);\n const autoAvgScore = evaluated.length > 0\n ? evaluated.reduce((sum, r) => sum + r.score, 0) / evaluated.length\n : 0;\n const autoPass = evaluated.filter(r => r.score >= 0.8);\n const autoPassRate = evaluated.length > 0 ? (autoPass.length / evaluated.length) * 100 : 0;\n\n // Agreement metrics\n const bothEvaluated = runs.filter(r =>\n r.hasHumanFeedback && r.score > 0 && r.humanIsCorrect != null\n );\n let agreementCount = 0;\n\n bothEvaluated.forEach(r => {\n const autoConsideredPass = r.score >= 0.5;\n const humanConsideredPass = r.humanIsCorrect === true;\n\n if (autoConsideredPass === humanConsideredPass) {\n agreementCount++;\n }\n });\n\n const agreementRate = bothEvaluated.length > 0\n ? (agreementCount / bothEvaluated.length) * 100\n : 0;\n\n return {\n totalRuns,\n execCompletedCount: execCompleted.length,\n execErrorCount: execErrors.length,\n execSuccessRate,\n humanReviewedCount: reviewed.length,\n humanPendingCount: pending.length,\n humanAvgRating,\n humanCorrectRate,\n autoEvaluatedCount: evaluated.length,\n autoAvgScore,\n autoPassRate,\n agreementRate\n };\n }\n}\n"]}
1
+ {"version":3,"file":"testing-instrumentation.service.js","sourceRoot":"","sources":["../../../src/Testing/services/testing-instrumentation.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { Observable, BehaviorSubject, from, combineLatest } from 'rxjs';\nimport { map, switchMap, shareReplay, tap } from 'rxjs/operators';\nimport { RunView, Metadata, IMetadataProvider } from '@memberjunction/core';\nimport { MJTestRunFeedbackEntity } from '@memberjunction/core-entities';\nimport { TestEngineBase } from '@memberjunction/testing-engine-base';\n\nexport interface TestingDashboardKPIs {\n totalTestsActive: number;\n passRateThisMonth: number;\n totalCostThisMonth: number;\n averageDuration: number;\n testsPendingReview: number;\n totalTestRuns: number;\n failedTests: number;\n skippedTests: number;\n passRateTrend: number; // Percentage change from previous period\n}\n\nexport interface TestRunSummary {\n id: string;\n testId: string;\n testName: string;\n suiteName: string;\n testType: string;\n status: 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running' | 'Timeout';\n score: number; // 0-1.0000\n duration: number; // milliseconds\n cost: number; // USD\n runDateTime: Date;\n targetType: string;\n targetLogID: string;\n // Execution context (machine / CI / run-by) — present for runs persisted with this metadata.\n machineName?: string | null;\n machineID?: string | null;\n runByUserName?: string | null;\n runByUserEmail?: string | null;\n runContextDetails?: string | null;\n}\n\nexport interface SuiteHierarchyNode {\n id: string;\n name: string;\n parentID: string | null;\n level: number;\n children: SuiteHierarchyNode[];\n testCount: number;\n passRate: number;\n totalCost: number;\n averageScore: number;\n expanded?: boolean;\n}\n\nexport interface VersionMetrics {\n version: string; // GitCommit + AgentVersion combination\n gitCommit: string;\n agentVersion: string;\n runDate: Date;\n totalTests: number;\n passRate: number;\n averageScore: number;\n totalCost: number;\n averageDuration: number;\n newFailures: number;\n newPasses: number;\n}\n\nexport interface TestTrendData {\n timestamp: Date;\n totalRuns: number;\n passed: number;\n failed: number;\n skipped: number;\n errors: number;\n averageScore: number;\n totalCost: number;\n averageDuration: number;\n}\n\nexport interface FeedbackPending {\n testRunID: string;\n testName: string;\n automatedScore: number;\n automatedStatus: string;\n runDateTime: Date;\n reason: 'no-feedback' | 'high-score-failed' | 'low-score-passed';\n}\n\nexport interface TestAnalytics {\n topFailingTests: Array<{ testName: string; failureCount: number; failureRate: number }>;\n mostExpensiveTests: Array<{ testName: string; totalCost: number; avgCost: number }>;\n slowestTests: Array<{ testName: string; avgDuration: number; maxDuration: number }>;\n costByType: Array<{ testType: string; totalCost: number; testCount: number }>;\n costBySuite: Array<{ suiteName: string; totalCost: number; testCount: number }>;\n passingRateByType: Array<{ testType: string; passRate: number; totalTests: number }>;\n}\n\nexport interface FeedbackStats {\n totalFeedback: number;\n reviewedCount: number;\n avgRating: number;\n agreementRate: number;\n disagreementRate: number;\n accuracyRate: number;\n}\n\n/**\n * Extended test run summary with human feedback data included\n */\nexport interface TestRunWithFeedbackSummary extends TestRunSummary {\n // Human feedback\n humanRating: number | null;\n humanIsCorrect: boolean | null;\n humanComments: string | null;\n hasHumanFeedback: boolean;\n feedbackId: string | null;\n // Checks (from automated evaluation)\n passedChecks: number | null;\n failedChecks: number | null;\n totalChecks: number | null;\n}\n\n/**\n * Aggregated evaluation metrics\n */\nexport interface EvaluationSummaryMetrics {\n totalRuns: number;\n // Execution\n execCompletedCount: number;\n execErrorCount: number;\n execSuccessRate: number;\n // Human\n humanReviewedCount: number;\n humanPendingCount: number;\n humanAvgRating: number;\n humanCorrectRate: number;\n // Auto\n autoEvaluatedCount: number;\n autoAvgScore: number;\n autoPassRate: number;\n // Agreement\n agreementRate: number;\n}\n\n// Simple result types for optimized queries (only fields needed for display)\ninterface TestRunSimple {\n ID: string;\n TestID: string;\n Test: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: Date;\n CompletedAt: Date | null;\n TargetType: string;\n TargetLogID: string;\n}\n\ninterface TestSuiteRunSimple {\n ID: string;\n TestSuiteID: string;\n TotalTests: number;\n PassedTests: number;\n TotalCostUSD: number;\n StartedAt: Date;\n GitCommit: string;\n AgentVersion: string;\n}\n\ninterface TestRunFeedbackSimple {\n ID: string;\n TestRunID: string;\n Rating: number;\n IsCorrect: boolean;\n Comments: string;\n CreatedAt: Date;\n}\n\n/**\n * A filter intent published by the AI agent (via the Testing dashboard's client\n * tools) for the Runs surface to apply. Both fields are optional — only the\n * provided ones are applied. This decouples the agent-actionable Runs filters\n * from any specific component instance: the agent sets an intent on this shared\n * root service, and the (possibly not-yet-mounted) Runs component consumes it.\n */\nexport interface RunsFilterIntent {\n status?: 'all' | 'running' | 'passed' | 'failed' | 'error';\n searchText?: string;\n}\n\n/**\n * A run-selection intent published by the AI agent (via the Testing dashboard's\n * `SelectTestRun` client tool) for the Runs surface to act on. The Runs component\n * owns the actual `SelectedRun` UI state (per the data-down/events-up Angular\n * convention), so the agent publishes the target run ID here and the (possibly\n * not-yet-mounted) Runs component consumes it when it mounts / when it changes.\n *\n * `open` distinguishes \"open the detail panel for this run\" (select) from\n * \"open the run's record in the entity workspace\" — both are read-only,\n * navigational affordances (no test execution side effects).\n */\nexport interface RunSelectionIntent {\n /** Target test-run ID to select (and optionally open). */\n runId: string;\n /** When true, also open the run's record in the entity workspace. */\n open?: boolean;\n /** Monotonic nonce so re-selecting the SAME run id still replays the intent. */\n nonce: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class TestingInstrumentationService {\n private readonly _dateRange$ = new BehaviorSubject<{ start: Date; end: Date }>({\n start: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // Last 30 days\n end: new Date()\n });\n\n /**\n * Agent-driven filter intents for the Runs surface. Published by the Testing\n * dashboard's client tools; consumed by the Runs component. Starts as null\n * (no pending intent).\n */\n private readonly _runsFilterIntent$ = new BehaviorSubject<RunsFilterIntent | null>(null);\n\n /** Observable of agent-driven Runs filter intents. */\n readonly runsFilterIntent$ = this._runsFilterIntent$.asObservable();\n\n /** Publish an agent-driven filter intent for the Runs surface to apply. */\n setRunsFilterIntent(intent: RunsFilterIntent): void {\n this._runsFilterIntent$.next(intent);\n }\n\n /**\n * Agent-driven run-SELECTION intents for the Runs surface. Published by the\n * Testing dashboard's `SelectTestRun` / open-run client tools; consumed by the\n * Runs component (which owns the actual {@link TestRunWithFeedbackSummary}\n * `SelectedRun` UI state). Starts as null (no pending intent). A monotonic\n * nonce on each intent lets the Runs component replay the SAME run id again\n * (re-select / re-open) even though the BehaviorSubject would otherwise\n * de-duplicate identical references.\n */\n private readonly _runSelectionIntent$ = new BehaviorSubject<RunSelectionIntent | null>(null);\n\n /** Observable of agent-driven run-selection intents. */\n readonly runSelectionIntent$ = this._runSelectionIntent$.asObservable();\n\n /** Monotonic source for {@link RunSelectionIntent.nonce}. */\n private _runSelectionNonce = 0;\n\n /**\n * Publish an agent-driven run-selection intent for the Runs surface to act on.\n * Assigns the next monotonic nonce so re-selecting the same run id still\n * replays. Returns the published intent (with its assigned nonce).\n */\n setRunSelectionIntent(runId: string, open: boolean = false): RunSelectionIntent {\n const intent: RunSelectionIntent = { runId, open, nonce: ++this._runSelectionNonce };\n this._runSelectionIntent$.next(intent);\n return intent;\n }\n\n private readonly _suiteFilter$ = new BehaviorSubject<string | null>(null);\n private readonly _testTypeFilter$ = new BehaviorSubject<string | null>(null);\n private readonly _refreshTrigger$ = new BehaviorSubject<number>(0);\n private readonly _isLoading$ = new BehaviorSubject<boolean>(false);\n private _provider: IMetadataProvider | null = null;\n\n /** Set the metadata provider this service should use. Components should call this after injection. */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n private get metadata(): IMetadataProvider {\n return this.Provider;\n }\n\n // Expose observables\n readonly isLoading$ = this._isLoading$.asObservable();\n readonly dateRange$ = this._dateRange$.asObservable();\n\n constructor() {}\n\n // Main data streams\n readonly kpis$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadKPIs())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly testRuns$ = combineLatest([\n this._refreshTrigger$,\n this._dateRange$,\n this._suiteFilter$,\n this._testTypeFilter$\n ]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTestRuns())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly suiteHierarchy$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadSuiteHierarchy())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly trends$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTrends())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly analytics$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadAnalytics())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly pendingFeedback$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadPendingFeedback())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n readonly feedbackStats$ = combineLatest([this._refreshTrigger$, this._dateRange$]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadFeedbackStats())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n /**\n * Test runs with feedback data joined - for evaluation display\n */\n readonly testRunsWithFeedback$ = combineLatest([\n this._refreshTrigger$,\n this._dateRange$,\n this._suiteFilter$,\n this._testTypeFilter$\n ]).pipe(\n tap(() => this._isLoading$.next(true)),\n switchMap(() => from(this.loadTestRunsWithFeedback())),\n tap(() => this.checkLoadingComplete()),\n shareReplay(1)\n );\n\n /**\n * Aggregated evaluation metrics from test runs with feedback\n */\n readonly evaluationMetrics$ = this.testRunsWithFeedback$.pipe(\n map(runs => this.calculateEvaluationMetrics(runs)),\n shareReplay(1)\n );\n\n private checkLoadingComplete(): void {\n setTimeout(() => {\n this._isLoading$.next(false);\n }, 100);\n }\n\n setDateRange(start: Date, end: Date): void {\n this._dateRange$.next({ start, end });\n }\n\n /**\n * Set the active date range from a named time range. Centralizes the\n * range-to-dates computation so both the Runs surface UI and the agent's\n * `FilterTestsByTimeRange` tool resolve identical windows.\n */\n setDateRangeByName(range: 'today' | 'week' | 'month' | '90days'): void {\n const now = new Date();\n let start: Date;\n switch (range) {\n case 'today':\n start = new Date(now);\n start.setHours(0, 0, 0, 0);\n break;\n case 'week':\n start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n break;\n case '90days':\n start = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);\n break;\n case 'month':\n default:\n start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n }\n this.setDateRange(start, now);\n }\n\n setSuiteFilter(suiteId: string | null): void {\n this._suiteFilter$.next(suiteId);\n }\n\n setTestTypeFilter(typeId: string | null): void {\n this._testTypeFilter$.next(typeId);\n }\n\n refresh(): void {\n this._refreshTrigger$.next(this._refreshTrigger$.value + 1);\n }\n\n private async loadKPIs(): Promise<TestingDashboardKPIs> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get Tests from TestEngineBase cache instead of querying DB\n const engine = TestEngineBase.Instance;\n const activeTests = engine.Tests.filter(t => t.Status === 'Active');\n\n // Only load runs via RunView (not cached in engine) - use simple result type with only needed fields\n const [testRunsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = testRunsResult.Results as TestRunSimple[];\n\n // Calculate KPIs\n const totalTestsActive = activeTests.length;\n const totalTestRuns = testRuns.length;\n\n const passedRuns = testRuns.filter(r => r.Status === 'Passed');\n const failedRuns = testRuns.filter(r => r.Status === 'Failed');\n const skippedRuns = testRuns.filter(r => r.Status === 'Skipped');\n\n const passRateThisMonth = totalTestRuns > 0 ? (passedRuns.length / totalTestRuns) * 100 : 0;\n\n const totalCostThisMonth = testRuns.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n\n const completedRuns = testRuns.filter(r => r.CompletedAt != null && r.StartedAt != null);\n const averageDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return sum + (endTime - startTime);\n }, 0) / completedRuns.length\n : 0;\n\n // Count tests pending review (no feedback)\n const testRunIDs = testRuns.map(r => r.ID);\n const testsPendingReview = await this.countTestsPendingReview(testRunIDs);\n\n // Calculate trend (compare to previous period)\n const periodDuration = end.getTime() - start.getTime();\n const previousStart = new Date(start.getTime() - periodDuration);\n const previousEnd = new Date(start.getTime());\n\n const previousRunsResult = await rv.RunView<TestRunSimple>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${previousStart.toISOString()}' AND StartedAt < '${previousEnd.toISOString()}'`,\n Fields: ['ID', 'Status'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const previousRuns = previousRunsResult.Results || [];\n const previousPassRate = previousRuns.length > 0\n ? (previousRuns.filter(r => r.Status === 'Passed').length / previousRuns.length) * 100\n : 0;\n\n const passRateTrend = previousPassRate > 0 ? passRateThisMonth - previousPassRate : 0;\n\n return {\n totalTestsActive,\n passRateThisMonth,\n totalCostThisMonth,\n averageDuration,\n testsPendingReview,\n totalTestRuns,\n failedTests: failedRuns.length,\n skippedTests: skippedRuns.length,\n passRateTrend\n };\n }\n\n private async countTestsPendingReview(testRunIDs: string[]): Promise<number> {\n if (testRunIDs.length === 0) return 0;\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const idList = testRunIDs.join(\"','\");\n\n const feedbackResult = await rv.RunView<{TestRunID: string}>({\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `TestRunID IN ('${idList}')`,\n Fields: ['TestRunID'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const feedbackTestRunIDs = new Set((feedbackResult.Results || []).map(f => f.TestRunID));\n\n return testRunIDs.filter(id => !feedbackTestRunIDs.has(id)).length;\n }\n\n private async loadTestRuns(): Promise<TestRunSummary[]> {\n const { start, end } = this._dateRange$.value;\n const suiteFilter = this._suiteFilter$.value;\n const typeFilter = this._testTypeFilter$.value;\n\n let filter = `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`;\n\n if (suiteFilter) {\n // Need to join through TestSuiteTest\n filter += ` AND TestID IN (SELECT TestID FROM [__mj].[vwTestSuiteTests] WHERE TestSuiteID = '${suiteFilter}')`;\n }\n\n if (typeFilter) {\n filter += ` AND TestID IN (SELECT ID FROM [__mj].[vwTests] WHERE TypeID = '${typeFilter}')`;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<TestRunSimple>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 1000,\n Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = result.Results || [];\n\n return testRuns.map(run => {\n const startedAt = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n const completedAt = run.CompletedAt\n ? (run.CompletedAt instanceof Date ? run.CompletedAt : new Date(run.CompletedAt))\n : null;\n\n return {\n id: run.ID,\n testId: run.TestID || '',\n testName: run.Test || 'Unknown Test',\n suiteName: '', // Will be populated from join\n testType: run.Test || 'Unknown',\n status: run.Status as 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running',\n score: run.Score || 0,\n duration: completedAt && startedAt\n ? completedAt.getTime() - startedAt.getTime()\n : (startedAt ? Date.now() - startedAt.getTime() : 0),\n cost: run.CostUSD || 0,\n runDateTime: startedAt,\n targetType: run.TargetType || '',\n targetLogID: run.TargetLogID || ''\n };\n });\n }\n\n private async loadSuiteHierarchy(): Promise<SuiteHierarchyNode[]> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get Test Suites from TestEngineBase cache instead of querying DB\n const engine = TestEngineBase.Instance;\n const suites = engine.TestSuites.filter(s => s.Status === 'Active');\n\n // Only load test runs via RunView (not cached in engine) - use simple result type\n const testRunsResult = await rv.RunView<{ID: string; TestID: string; Status: string; Score: number; CostUSD: number}>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'TestID', 'Status', 'Score', 'CostUSD'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = testRunsResult.Results || [];\n\n // Build hierarchy\n const nodes: SuiteHierarchyNode[] = suites.map(suite => ({\n id: suite.ID,\n name: suite.Name,\n parentID: suite.ParentID || null,\n level: 0,\n children: [],\n testCount: 0,\n passRate: 0,\n totalCost: 0,\n averageScore: 0,\n expanded: false\n }));\n\n // Calculate metrics for each suite (simplified - would need TestSuiteTest join for accuracy)\n type SimpleTestRun = {ID: string; TestID: string; Status: string; Score: number; CostUSD: number};\n const suiteTestRuns = new Map<string, SimpleTestRun[]>();\n\n testRuns.forEach(run => {\n // This is simplified - would need to query TestSuiteTest to get actual suite membership\n const suiteID = run.TestID; // Placeholder\n if (!suiteTestRuns.has(suiteID)) {\n suiteTestRuns.set(suiteID, []);\n }\n suiteTestRuns.get(suiteID)!.push(run);\n });\n\n nodes.forEach(node => {\n const runs = suiteTestRuns.get(node.id) || [];\n node.testCount = runs.length;\n node.passRate = runs.length > 0\n ? (runs.filter(r => r.Status === 'Passed').length / runs.length) * 100\n : 0;\n node.totalCost = runs.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n node.averageScore = runs.length > 0\n ? runs.reduce((sum, r) => sum + (r.Score || 0), 0) / runs.length\n : 0;\n });\n\n // Build tree structure\n const rootNodes: SuiteHierarchyNode[] = [];\n const nodeMap = new Map<string, SuiteHierarchyNode>();\n\n nodes.forEach(node => nodeMap.set(node.id, node));\n\n nodes.forEach(node => {\n if (node.parentID) {\n const parent = nodeMap.get(node.parentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n });\n\n return rootNodes;\n }\n\n private async loadTrends(): Promise<TestTrendData[]> {\n const { start, end } = this._dateRange$.value;\n\n // Create time buckets\n const buckets = this.createTimeBuckets(start, end);\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load all test runs for the period - use simple result type with only needed fields\n type TrendRun = {Status: string; Score: number; CostUSD: number; StartedAt: string | Date; CompletedAt: string | Date | null};\n const result = await rv.RunView<TrendRun>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n OrderBy: 'StartedAt',\n Fields: ['Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const allRuns = result.Results || [];\n\n // Aggregate into buckets\n const trends: TestTrendData[] = buckets.map(bucketStart => {\n const bucketEnd = new Date(bucketStart.getTime() + this.getBucketSize(start, end));\n\n const bucketRuns = allRuns.filter(r => {\n if (!r.StartedAt) return false;\n const runTime = r.StartedAt instanceof Date ? r.StartedAt : new Date(r.StartedAt);\n return runTime >= bucketStart && runTime < bucketEnd;\n });\n\n const passed = bucketRuns.filter(r => r.Status === 'Passed').length;\n const failed = bucketRuns.filter(r => r.Status === 'Failed').length;\n const skipped = bucketRuns.filter(r => r.Status === 'Skipped').length;\n const errors = bucketRuns.filter(r => r.Status === 'Error').length;\n\n const averageScore = bucketRuns.length > 0\n ? bucketRuns.reduce((sum, r) => sum + (r.Score || 0), 0) / bucketRuns.length\n : 0;\n\n const totalCost = bucketRuns.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n\n const completedRuns = bucketRuns.filter(r => r.CompletedAt != null && r.StartedAt != null);\n const averageDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return sum + (endTime - startTime);\n }, 0) / completedRuns.length\n : 0;\n\n return {\n timestamp: bucketStart,\n totalRuns: bucketRuns.length,\n passed,\n failed,\n skipped,\n errors,\n averageScore,\n totalCost,\n averageDuration\n };\n });\n\n return trends;\n }\n\n private async loadAnalytics(): Promise<TestAnalytics> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result type with only needed fields\n type AnalyticsRun = {Test: string; Status: string; Score: number; CostUSD: number; StartedAt: string | Date; CompletedAt: string | Date | null};\n const result = await rv.RunView<AnalyticsRun>({\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const testRuns = result.Results || [];\n\n // Group by test name\n const testMetrics = new Map<string, { runs: AnalyticsRun[], failures: number }>();\n\n testRuns.forEach(run => {\n const testName = run.Test || 'Unknown';\n if (!testMetrics.has(testName)) {\n testMetrics.set(testName, { runs: [], failures: 0 });\n }\n const metrics = testMetrics.get(testName)!;\n metrics.runs.push(run);\n if (run.Status === 'Failed' || run.Status === 'Error') {\n metrics.failures++;\n }\n });\n\n // Top failing tests\n const topFailingTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => ({\n testName,\n failureCount: metrics.failures,\n failureRate: metrics.runs.length > 0 ? (metrics.failures / metrics.runs.length) * 100 : 0\n }))\n .sort((a, b) => b.failureCount - a.failureCount)\n .slice(0, 10);\n\n // Most expensive tests\n const mostExpensiveTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => {\n const totalCost = metrics.runs.reduce((sum, r) => sum + (r.CostUSD || 0), 0);\n const avgCost = metrics.runs.length > 0 ? totalCost / metrics.runs.length : 0;\n return { testName, totalCost, avgCost };\n })\n .sort((a, b) => b.totalCost - a.totalCost)\n .slice(0, 10);\n\n // Slowest tests\n const slowestTests = Array.from(testMetrics.entries())\n .map(([testName, metrics]) => {\n const durations = metrics.runs\n .filter(r => r.CompletedAt != null && r.StartedAt != null)\n .map(r => {\n const startTime = r.StartedAt instanceof Date ? r.StartedAt.getTime() : new Date(r.StartedAt).getTime();\n const endTime = r.CompletedAt instanceof Date ? r.CompletedAt.getTime() : new Date(r.CompletedAt!).getTime();\n return endTime - startTime;\n });\n\n const avgDuration = durations.length > 0\n ? durations.reduce((sum, d) => sum + d, 0) / durations.length\n : 0;\n const maxDuration = durations.length > 0 ? Math.max(...durations) : 0;\n\n return { testName, avgDuration, maxDuration };\n })\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, 10);\n\n // Cost by type (simplified - would need actual type data)\n const typeMetrics = new Map<string, { cost: number, count: number }>();\n testRuns.forEach(run => {\n const type = run.Test || 'Unknown';\n if (!typeMetrics.has(type)) {\n typeMetrics.set(type, { cost: 0, count: 0 });\n }\n const metrics = typeMetrics.get(type)!;\n metrics.cost += run.CostUSD || 0;\n metrics.count++;\n });\n\n const costByType = Array.from(typeMetrics.entries())\n .map(([testType, metrics]) => ({\n testType,\n totalCost: metrics.cost,\n testCount: metrics.count\n }))\n .sort((a, b) => b.totalCost - a.totalCost);\n\n // Passing rate by type\n const typePassingMetrics = new Map<string, { total: number, passed: number }>();\n testRuns.forEach(run => {\n const type = run.Test || 'Unknown';\n if (!typePassingMetrics.has(type)) {\n typePassingMetrics.set(type, { total: 0, passed: 0 });\n }\n const metrics = typePassingMetrics.get(type)!;\n metrics.total++;\n if (run.Status === 'Passed') {\n metrics.passed++;\n }\n });\n\n const passingRateByType = Array.from(typePassingMetrics.entries())\n .map(([testType, metrics]) => ({\n testType,\n passRate: metrics.total > 0 ? (metrics.passed / metrics.total) * 100 : 0,\n totalTests: metrics.total\n }))\n .sort((a, b) => a.passRate - b.passRate);\n\n return {\n topFailingTests,\n mostExpensiveTests,\n slowestTests,\n costByType,\n costBySuite: [], // Would need suite data\n passingRateByType\n };\n }\n\n private async loadPendingFeedback(): Promise<FeedbackPending[]> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result types with only needed fields\n type FeedbackTestRun = {ID: string; Test: string; Score: number; Status: string; StartedAt: string | Date};\n type FeedbackItem = {TestRunID: string};\n\n const [testRunsResult, feedbackResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,\n Fields: ['ID', 'Test', 'Score', 'Status', 'StartedAt'],\n ResultType: 'simple',\n CacheLocal: true\n },\n {\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}'`,\n Fields: ['TestRunID'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = testRunsResult.Results as FeedbackTestRun[];\n const feedbacks = feedbackResult.Results as FeedbackItem[];\n\n const feedbackTestRunIDs = new Set(feedbacks.map(f => f.TestRunID));\n\n const pending: FeedbackPending[] = [];\n\n testRuns.forEach(run => {\n const hasFeedback = feedbackTestRunIDs.has(run.ID);\n const runDateTime = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n\n if (!hasFeedback) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score || 0,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'no-feedback'\n });\n } else {\n // Check for discrepancies\n if (run.Status === 'Failed' && run.Score != null && run.Score >= 0.8) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'high-score-failed'\n });\n } else if (run.Status === 'Passed' && run.Score != null && run.Score < 0.5) {\n pending.push({\n testRunID: run.ID,\n testName: run.Test || 'Unknown',\n automatedScore: run.Score,\n automatedStatus: run.Status,\n runDateTime,\n reason: 'low-score-passed'\n });\n }\n }\n });\n\n return pending.sort((a, b) => b.runDateTime.getTime() - a.runDateTime.getTime());\n }\n\n private async loadFeedbackStats(): Promise<FeedbackStats> {\n const { start, end } = this._dateRange$.value;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load all feedback for the period - use simple result type with only needed fields\n type FeedbackStatItem = {Rating: number; IsCorrect: boolean};\n const feedbackResult = await rv.RunView<FeedbackStatItem>({\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}' AND CreatedAt <= '${end.toISOString()}'`,\n Fields: ['Rating', 'IsCorrect'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const feedbacks = feedbackResult.Results || [];\n const totalFeedback = feedbacks.length;\n\n if (totalFeedback === 0) {\n return {\n totalFeedback: 0,\n reviewedCount: 0,\n avgRating: 0,\n agreementRate: 0,\n disagreementRate: 0,\n accuracyRate: 0\n };\n }\n\n // Calculate average rating\n const avgRating = feedbacks.reduce((sum, f) => sum + (f.Rating || 0), 0) / totalFeedback;\n\n // Calculate agreement/disagreement rates based on IsCorrect field\n const correctCount = feedbacks.filter(f => f.IsCorrect === true).length;\n const incorrectCount = feedbacks.filter(f => f.IsCorrect === false).length;\n\n const agreementRate = (correctCount / totalFeedback) * 100;\n const disagreementRate = (incorrectCount / totalFeedback) * 100;\n\n // Accuracy rate is the same as agreement rate (% of times human agreed with automated result)\n const accuracyRate = agreementRate;\n\n return {\n totalFeedback,\n reviewedCount: totalFeedback, // All feedbacks in this query are reviewed\n avgRating,\n agreementRate,\n disagreementRate,\n accuracyRate\n };\n }\n\n async submitFeedback(testRunID: string, rating: number, isCorrect: boolean, comments: string): Promise<boolean> {\n try {\n const feedback = await this.metadata.GetEntityObject<MJTestRunFeedbackEntity>('MJ: Test Run Feedbacks');\n feedback.TestRunID = testRunID;\n feedback.Rating = rating;\n feedback.IsCorrect = isCorrect;\n feedback.Comments = comments;\n\n const result = await feedback.Save();\n if (result) {\n this.refresh(); // Refresh data after submission\n return true;\n }\n return false;\n } catch (error) {\n console.error('Error submitting feedback:', error);\n return false;\n }\n }\n\n async getVersionMetrics(): Promise<VersionMetrics[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Use simple result type with only needed fields\n type VersionRun = {TotalTests: number; PassedTests: number; TotalCostUSD: number; StartedAt: string | Date; GitCommit: string; AgentVersion: string};\n const result = await rv.RunView<VersionRun>({\n EntityName: 'MJ: Test Suite Runs',\n ExtraFilter: '',\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n Fields: ['TotalTests', 'PassedTests', 'TotalCostUSD', 'StartedAt', 'GitCommit', 'AgentVersion'],\n ResultType: 'simple',\n CacheLocal: true\n });\n\n const suiteRuns = result.Results || [];\n\n // Group by version combination\n const versionMap = new Map<string, VersionRun[]>();\n\n suiteRuns.forEach(run => {\n const key = `${run.GitCommit || 'unknown'}_${run.AgentVersion || 'unknown'}`;\n if (!versionMap.has(key)) {\n versionMap.set(key, []);\n }\n versionMap.get(key)!.push(run);\n });\n\n const metrics: VersionMetrics[] = Array.from(versionMap.entries()).map(([key, runs]) => {\n const [gitCommit, agentVersion] = key.split('_');\n const latest = runs[0];\n\n const totalTests = runs.reduce((sum, r) => sum + (r.TotalTests || 0), 0);\n const totalPassed = runs.reduce((sum, r) => sum + (r.PassedTests || 0), 0);\n const totalCost = runs.reduce((sum, r) => sum + (r.TotalCostUSD || 0), 0);\n\n const runDate = latest.StartedAt instanceof Date ? latest.StartedAt : new Date(latest.StartedAt);\n\n return {\n version: `${gitCommit.substring(0, 7)} / ${agentVersion}`,\n gitCommit,\n agentVersion,\n runDate,\n totalTests,\n passRate: totalTests > 0 ? (totalPassed / totalTests) * 100 : 0,\n averageScore: 0, // Would need to calculate from test runs\n totalCost,\n averageDuration: 0, // Would need to calculate from test runs\n newFailures: 0, // Would need comparison\n newPasses: 0 // Would need comparison\n };\n });\n\n return metrics.sort((a, b) => b.runDate.getTime() - a.runDate.getTime());\n }\n\n private createTimeBuckets(start: Date, end: Date): Date[] {\n const buckets: Date[] = [];\n const bucketSize = this.getBucketSize(start, end);\n const current = new Date(start);\n\n while (current < end) {\n buckets.push(new Date(current));\n current.setTime(current.getTime() + bucketSize);\n }\n\n return buckets;\n }\n\n private getBucketSize(start: Date, end: Date): number {\n const duration = end.getTime() - start.getTime();\n const days = duration / (1000 * 60 * 60 * 24);\n\n if (days <= 1) {\n return 60 * 60 * 1000; // 1 hour\n } else if (days <= 7) {\n return 4 * 60 * 60 * 1000; // 4 hours\n } else if (days <= 30) {\n return 24 * 60 * 60 * 1000; // 1 day\n } else {\n return 7 * 24 * 60 * 60 * 1000; // 1 week\n }\n }\n\n /**\n * Load test runs with feedback data joined for evaluation display\n */\n private async loadTestRunsWithFeedback(): Promise<TestRunWithFeedbackSummary[]> {\n const { start, end } = this._dateRange$.value;\n const suiteFilter = this._suiteFilter$.value;\n const typeFilter = this._testTypeFilter$.value;\n\n let filter = `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`;\n\n if (suiteFilter) {\n filter += ` AND TestID IN (SELECT TestID FROM [__mj].[vwTestSuiteTests] WHERE TestSuiteID = '${suiteFilter}')`;\n }\n\n if (typeFilter) {\n filter += ` AND TestID IN (SELECT ID FROM [__mj].[vwTests] WHERE TypeID = '${typeFilter}')`;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load test runs with additional fields for evaluation\n type MJTestRunExtended = {\n ID: string;\n TestID: string;\n Test: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: Date;\n CompletedAt: Date | null;\n TargetType: string;\n TargetLogID: string;\n PassedChecks: number | null;\n FailedChecks: number | null;\n TotalChecks: number | null;\n MachineName: string | null;\n MachineID: string | null;\n RunByUserName: string | null;\n RunByUserEmail: string | null;\n RunContextDetails: string | null;\n };\n\n const [testRunsResult, feedbackResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Test Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 1000,\n Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID', 'PassedChecks', 'FailedChecks', 'TotalChecks', 'MachineName', 'MachineID', 'RunByUserName', 'RunByUserEmail', 'RunContextDetails'],\n ResultType: 'simple',\n CacheLocal: true\n },\n {\n EntityName: 'MJ: Test Run Feedbacks',\n ExtraFilter: `CreatedAt >= '${start.toISOString()}'`,\n Fields: ['ID', 'TestRunID', 'Rating', 'IsCorrect', 'Comments'],\n ResultType: 'simple',\n CacheLocal: true\n }\n ]);\n\n const testRuns = (testRunsResult.Results || []) as MJTestRunExtended[];\n const feedbacks = (feedbackResult.Results || []) as TestRunFeedbackSimple[];\n\n // Create feedback lookup map\n const feedbackMap = new Map<string, TestRunFeedbackSimple>();\n feedbacks.forEach(f => {\n feedbackMap.set(f.TestRunID, f);\n });\n\n // Map test runs with feedback\n return testRuns.map(run => {\n const startedAt = run.StartedAt instanceof Date ? run.StartedAt : new Date(run.StartedAt);\n const completedAt = run.CompletedAt\n ? (run.CompletedAt instanceof Date ? run.CompletedAt : new Date(run.CompletedAt))\n : null;\n\n const feedback = feedbackMap.get(run.ID);\n\n return {\n id: run.ID,\n testId: run.TestID || '',\n testName: run.Test || 'Unknown Test',\n suiteName: '',\n testType: run.Test || 'Unknown',\n status: run.Status as 'Passed' | 'Failed' | 'Skipped' | 'Error' | 'Running' | 'Timeout',\n score: run.Score || 0,\n duration: completedAt && startedAt\n ? completedAt.getTime() - startedAt.getTime()\n : (startedAt ? Date.now() - startedAt.getTime() : 0),\n cost: run.CostUSD || 0,\n runDateTime: startedAt,\n targetType: run.TargetType || '',\n targetLogID: run.TargetLogID || '',\n // Checks\n passedChecks: run.PassedChecks,\n failedChecks: run.FailedChecks,\n totalChecks: run.TotalChecks,\n // Human feedback\n humanRating: feedback?.Rating ?? null,\n humanIsCorrect: feedback?.IsCorrect ?? null,\n humanComments: feedback?.Comments ?? null,\n hasHumanFeedback: !!feedback,\n feedbackId: feedback?.ID ?? null,\n // Execution context\n machineName: run.MachineName,\n machineID: run.MachineID,\n runByUserName: run.RunByUserName,\n runByUserEmail: run.RunByUserEmail,\n runContextDetails: run.RunContextDetails\n };\n });\n }\n\n /**\n * Calculate aggregated evaluation metrics from test runs with feedback\n */\n private calculateEvaluationMetrics(runs: TestRunWithFeedbackSummary[]): EvaluationSummaryMetrics {\n const totalRuns = runs.length;\n\n if (totalRuns === 0) {\n return {\n totalRuns: 0,\n execCompletedCount: 0,\n execErrorCount: 0,\n execSuccessRate: 0,\n humanReviewedCount: 0,\n humanPendingCount: 0,\n humanAvgRating: 0,\n humanCorrectRate: 0,\n autoEvaluatedCount: 0,\n autoAvgScore: 0,\n autoPassRate: 0,\n agreementRate: 0\n };\n }\n\n // Execution metrics\n const execCompleted = runs.filter(r =>\n r.status === 'Passed' || r.status === 'Failed'\n );\n const execErrors = runs.filter(r =>\n r.status === 'Error' || r.status === 'Timeout'\n );\n const execSuccessRate = totalRuns > 0 ? (execCompleted.length / totalRuns) * 100 : 0;\n\n // Human feedback metrics\n const reviewed = runs.filter(r => r.hasHumanFeedback);\n const pending = runs.filter(r => !r.hasHumanFeedback);\n const withRating = reviewed.filter(r => r.humanRating != null);\n const humanAvgRating = withRating.length > 0\n ? withRating.reduce((sum, r) => sum + (r.humanRating || 0), 0) / withRating.length\n : 0;\n const correct = reviewed.filter(r => r.humanIsCorrect === true);\n const humanCorrectRate = reviewed.length > 0 ? (correct.length / reviewed.length) * 100 : 0;\n\n // Auto score metrics\n const evaluated = runs.filter(r => r.score > 0);\n const autoAvgScore = evaluated.length > 0\n ? evaluated.reduce((sum, r) => sum + r.score, 0) / evaluated.length\n : 0;\n const autoPass = evaluated.filter(r => r.score >= 0.8);\n const autoPassRate = evaluated.length > 0 ? (autoPass.length / evaluated.length) * 100 : 0;\n\n // Agreement metrics\n const bothEvaluated = runs.filter(r =>\n r.hasHumanFeedback && r.score > 0 && r.humanIsCorrect != null\n );\n let agreementCount = 0;\n\n bothEvaluated.forEach(r => {\n const autoConsideredPass = r.score >= 0.5;\n const humanConsideredPass = r.humanIsCorrect === true;\n\n if (autoConsideredPass === humanConsideredPass) {\n agreementCount++;\n }\n });\n\n const agreementRate = bothEvaluated.length > 0\n ? (agreementCount / bothEvaluated.length) * 100\n : 0;\n\n return {\n totalRuns,\n execCompletedCount: execCompleted.length,\n execErrorCount: execErrors.length,\n execSuccessRate,\n humanReviewedCount: reviewed.length,\n humanPendingCount: pending.length,\n humanAvgRating,\n humanCorrectRate,\n autoEvaluatedCount: evaluated.length,\n autoAvgScore,\n autoPassRate,\n agreementRate\n };\n }\n}\n"]}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Pure, unit-testable helpers for the Theme Studio + Theme Manager agent context
3
+ * and tools (context builders + tolerant id→name→contains resolver).
4
+ *
5
+ * 🚨 SAFETY BOUNDARY 🚨
6
+ * The theming surfaces expose ONLY read / navigate / preview-state / user-scoped
7
+ * tools to the agent: list + select themes, apply presets and seed edits to the
8
+ * IN-MEMORY editor draft (nothing persists until the user saves), flip preview
9
+ * mode/surface, apply a theme to the CURRENT USER's workspace, and star/unstar
10
+ * (both per-user preferences). DELIBERATELY NOT exposed (org-wide or destructive
11
+ * writes stay human-driven in the UI): SAVE a theme, RENAME, SET ORG DEFAULT,
12
+ * DUPLICATE (creates records), and DELETE. Context exposes only theme display
13
+ * names, statuses, seed values, and contrast pass/fail summaries — never the
14
+ * Overrides / CustomCSS bodies.
15
+ */
16
+ import type { ContrastReport, ThemeSeeds } from '@memberjunction/theme-engine';
17
+ /** Cap applied to every published name list. */
18
+ export declare const THEME_NAME_LIST_CAP = 25;
19
+ /** Minimal theme shape the pure helpers operate on. */
20
+ export interface ThemeSummaryRow {
21
+ ID: string;
22
+ Name: string;
23
+ Status: string;
24
+ IsDefault: boolean;
25
+ BuiltIn: boolean;
26
+ }
27
+ /** State snapshot the Theme Manager passes to its context builder. */
28
+ export interface ThemeManagerAgentState {
29
+ Themes: ThemeSummaryRow[];
30
+ AppliedThemeID: string | null;
31
+ StarredThemeIDs: string[];
32
+ }
33
+ /** State snapshot the Theme Studio passes to its context builder. */
34
+ export interface ThemeStudioAgentState {
35
+ Themes: ThemeSummaryRow[];
36
+ CurrentThemeID: string | null;
37
+ CurrentThemeName: string;
38
+ IsBuiltInSelected: boolean;
39
+ PreviewMode: 'light' | 'dark';
40
+ PreviewSurface: string;
41
+ EditorPanelOpen: boolean;
42
+ Seeds: ThemeSeeds;
43
+ /** Advanced-layer shape only — never the bodies. */
44
+ OverrideTokenCount: number;
45
+ HasCustomCss: boolean;
46
+ Contrast: ContrastReport;
47
+ }
48
+ /** Bounded, secret-free context published by the Theme Manager via SetAgentContext. */
49
+ export declare function buildThemeManagerAgentContext(state: ThemeManagerAgentState): Record<string, unknown>;
50
+ /** Bounded, secret-free context published by the Theme Studio via SetAgentContext. */
51
+ export declare function buildThemeStudioAgentContext(state: ThemeStudioAgentState): Record<string, unknown>;
52
+ /**
53
+ * Tolerant theme resolver: exact ID (case-insensitive GUID) → exact name →
54
+ * partial name contains (all case-insensitive). Returns a structured failure
55
+ * listing available names (bounded) on a miss.
56
+ */
57
+ export declare function resolveThemeByIDOrName(themes: ThemeSummaryRow[], rawRef: unknown): {
58
+ ok: true;
59
+ value: ThemeSummaryRow;
60
+ } | {
61
+ ok: false;
62
+ error: string;
63
+ };
64
+ //# sourceMappingURL=theme-agent-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-agent-context.d.ts","sourceRoot":"","sources":["../../src/ThemeStudio/theme-agent-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/E,gDAAgD;AAChD,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,oDAAoD;IACpD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,cAAc,CAAC;CAC5B;AAYD,uFAAuF;AACvF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmBpG;AAED,sFAAsF;AACtF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmClG;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,OAAO,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA2BrE"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Pure, unit-testable helpers for the Theme Studio + Theme Manager agent context
3
+ * and tools (context builders + tolerant id→name→contains resolver).
4
+ *
5
+ * 🚨 SAFETY BOUNDARY 🚨
6
+ * The theming surfaces expose ONLY read / navigate / preview-state / user-scoped
7
+ * tools to the agent: list + select themes, apply presets and seed edits to the
8
+ * IN-MEMORY editor draft (nothing persists until the user saves), flip preview
9
+ * mode/surface, apply a theme to the CURRENT USER's workspace, and star/unstar
10
+ * (both per-user preferences). DELIBERATELY NOT exposed (org-wide or destructive
11
+ * writes stay human-driven in the UI): SAVE a theme, RENAME, SET ORG DEFAULT,
12
+ * DUPLICATE (creates records), and DELETE. Context exposes only theme display
13
+ * names, statuses, seed values, and contrast pass/fail summaries — never the
14
+ * Overrides / CustomCSS bodies.
15
+ */
16
+ import { UUIDsEqual } from '@memberjunction/global';
17
+ /** Cap applied to every published name list. */
18
+ export const THEME_NAME_LIST_CAP = 25;
19
+ /** Bound a name list to the cap, reporting truncation via the returned tuple. */
20
+ function boundNames(names) {
21
+ const filtered = names.filter((n) => !!n);
22
+ return {
23
+ names: filtered.slice(0, THEME_NAME_LIST_CAP),
24
+ truncated: filtered.length > THEME_NAME_LIST_CAP,
25
+ total: filtered.length,
26
+ };
27
+ }
28
+ /** Bounded, secret-free context published by the Theme Manager via SetAgentContext. */
29
+ export function buildThemeManagerAgentContext(state) {
30
+ const applied = state.AppliedThemeID
31
+ ? state.Themes.find((t) => UUIDsEqual(t.ID, state.AppliedThemeID)) ?? null
32
+ : null;
33
+ const bounded = boundNames(state.Themes.map((t) => t.Name));
34
+ const context = {
35
+ TotalThemeCount: state.Themes.length,
36
+ ActiveThemeCount: state.Themes.filter((t) => t.Status === 'Active').length,
37
+ DefaultThemeName: state.Themes.find((t) => t.IsDefault)?.Name ?? null,
38
+ AppliedThemeID: state.AppliedThemeID,
39
+ AppliedThemeName: applied?.Name ?? null,
40
+ StarredThemeCount: state.StarredThemeIDs.length,
41
+ VisibleThemeNames: bounded.names,
42
+ };
43
+ if (bounded.truncated) {
44
+ context['VisibleThemeNamesTruncated'] = true;
45
+ context['VisibleThemeNamesTotal'] = bounded.total;
46
+ }
47
+ return context;
48
+ }
49
+ /** Bounded, secret-free context published by the Theme Studio via SetAgentContext. */
50
+ export function buildThemeStudioAgentContext(state) {
51
+ const bounded = boundNames(state.Themes.map((t) => t.Name));
52
+ const failingPairs = (checks) => checks.filter((c) => !c.passes).map((c) => c.name).slice(0, THEME_NAME_LIST_CAP);
53
+ const context = {
54
+ CurrentThemeID: state.CurrentThemeID,
55
+ CurrentThemeName: state.CurrentThemeName,
56
+ IsUnsavedDraft: state.CurrentThemeID === null,
57
+ IsBuiltInReadOnly: state.IsBuiltInSelected,
58
+ PreviewMode: state.PreviewMode,
59
+ PreviewSurface: state.PreviewSurface,
60
+ EditorPanelOpen: state.EditorPanelOpen,
61
+ Seeds: {
62
+ Primary: state.Seeds.primary,
63
+ Accent: state.Seeds.accent ?? null,
64
+ Tertiary: state.Seeds.tertiary ?? null,
65
+ NeutralChroma: state.Seeds.neutralChroma ?? null,
66
+ Vibrancy: state.Seeds.vibrancy ?? null,
67
+ Radius: state.Seeds.radius ?? null,
68
+ Depth: state.Seeds.depth ?? null,
69
+ FontFamily: state.Seeds.fontFamily ?? null,
70
+ },
71
+ VizPaletteOverridden: !!state.Seeds.vizPalette && state.Seeds.vizPalette.length > 0,
72
+ OverrideTokenCount: state.OverrideTokenCount,
73
+ HasCustomCss: state.HasCustomCss,
74
+ ContrastPasses: state.Contrast.passes,
75
+ ContrastFailingLight: failingPairs(state.Contrast.light),
76
+ ContrastFailingDark: failingPairs(state.Contrast.dark),
77
+ AvailableThemeNames: bounded.names,
78
+ };
79
+ if (bounded.truncated) {
80
+ context['AvailableThemeNamesTruncated'] = true;
81
+ context['AvailableThemeNamesTotal'] = bounded.total;
82
+ }
83
+ return context;
84
+ }
85
+ /**
86
+ * Tolerant theme resolver: exact ID (case-insensitive GUID) → exact name →
87
+ * partial name contains (all case-insensitive). Returns a structured failure
88
+ * listing available names (bounded) on a miss.
89
+ */
90
+ export function resolveThemeByIDOrName(themes, rawRef) {
91
+ if (typeof rawRef !== 'string' || rawRef.trim().length === 0) {
92
+ return { ok: false, error: `Provide the theme's ID or name. ${availableNames(themes)}` };
93
+ }
94
+ const ref = rawRef.trim();
95
+ const byId = themes.find((t) => UUIDsEqual(t.ID, ref));
96
+ if (byId) {
97
+ return { ok: true, value: byId };
98
+ }
99
+ const byName = themes.find((t) => equalsIgnoreCase(t.Name, ref));
100
+ if (byName) {
101
+ return { ok: true, value: byName };
102
+ }
103
+ const contains = themes.filter((t) => t.Name.toLowerCase().includes(ref.toLowerCase()));
104
+ if (contains.length === 1) {
105
+ return { ok: true, value: contains[0] };
106
+ }
107
+ if (contains.length > 1) {
108
+ return {
109
+ ok: false,
110
+ error: `'${ref}' matches multiple themes: ${contains
111
+ .slice(0, THEME_NAME_LIST_CAP)
112
+ .map((t) => t.Name)
113
+ .join(', ')}. Be more specific.`,
114
+ };
115
+ }
116
+ return { ok: false, error: `No theme matches '${ref}'. ${availableNames(themes)}` };
117
+ }
118
+ function availableNames(themes) {
119
+ if (themes.length === 0) {
120
+ return 'There are no saved themes yet.';
121
+ }
122
+ const names = themes.slice(0, THEME_NAME_LIST_CAP).map((t) => t.Name);
123
+ const suffix = themes.length > THEME_NAME_LIST_CAP ? ', …' : '';
124
+ return `Available themes: ${names.join(', ')}${suffix}`;
125
+ }
126
+ function equalsIgnoreCase(a, b) {
127
+ return a.trim().toLowerCase() === b.trim().toLowerCase();
128
+ }
129
+ //# sourceMappingURL=theme-agent-context.js.map