@memberjunction/ng-ai-test-harness 2.111.0 → 2.112.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.
- package/dist/lib/ai-test-harness-dialog.component.d.ts.map +1 -1
- package/dist/lib/ai-test-harness-dialog.component.js +16 -12
- package/dist/lib/ai-test-harness-dialog.component.js.map +1 -1
- package/dist/lib/ai-test-harness-window.component.d.ts.map +1 -1
- package/dist/lib/ai-test-harness-window.component.js +2 -2
- package/dist/lib/ai-test-harness-window.component.js.map +1 -1
- package/dist/lib/ai-test-harness.component.d.ts.map +1 -1
- package/dist/lib/ai-test-harness.component.js +126 -135
- package/dist/lib/ai-test-harness.component.js.map +1 -1
- package/dist/lib/test-harness-custom-window.component.d.ts.map +1 -1
- package/dist/lib/test-harness-custom-window.component.js +4 -5
- package/dist/lib/test-harness-custom-window.component.js.map +1 -1
- package/package.json +8 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, ViewChild, SecurityContext } from '@angular/core';
|
|
2
|
-
import { Metadata, RunView, CompositeKey } from '@memberjunction/
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ViewChild, SecurityContext, } from '@angular/core';
|
|
2
|
+
import { Metadata, RunView, CompositeKey } from '@memberjunction/global';
|
|
3
3
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
4
4
|
import { SharedService } from '@memberjunction/ng-shared';
|
|
5
5
|
import { Subject } from 'rxjs';
|
|
@@ -1277,7 +1277,7 @@ export class AITestHarnessComponent {
|
|
|
1277
1277
|
seed: null,
|
|
1278
1278
|
stopSequences: [],
|
|
1279
1279
|
includeLogProbs: false,
|
|
1280
|
-
topLogProbs: 2
|
|
1280
|
+
topLogProbs: 2,
|
|
1281
1281
|
};
|
|
1282
1282
|
/** Raw stop sequences input for textarea */
|
|
1283
1283
|
this.stopSequencesText = '';
|
|
@@ -1291,7 +1291,7 @@ export class AITestHarnessComponent {
|
|
|
1291
1291
|
{ text: 'Text', value: 'Text' },
|
|
1292
1292
|
{ text: 'Markdown', value: 'Markdown' },
|
|
1293
1293
|
{ text: 'JSON', value: 'JSON' },
|
|
1294
|
-
{ text: 'Model Specific', value: 'ModelSpecific' }
|
|
1294
|
+
{ text: 'Model Specific', value: 'ModelSpecific' },
|
|
1295
1295
|
];
|
|
1296
1296
|
/** Selected response format for prompt execution */
|
|
1297
1297
|
this.selectedResponseFormat = this.responseFormatOptions[0];
|
|
@@ -1477,7 +1477,7 @@ export class AITestHarnessComponent {
|
|
|
1477
1477
|
const serializedAgentRun = message.data.agentRun;
|
|
1478
1478
|
// Update streaming message content if available
|
|
1479
1479
|
if (message.data.progress?.message) {
|
|
1480
|
-
const streamingMessage = this.conversationMessages.find(m => m.isStreaming);
|
|
1480
|
+
const streamingMessage = this.conversationMessages.find((m) => m.isStreaming);
|
|
1481
1481
|
if (streamingMessage) {
|
|
1482
1482
|
// Clear any typing animation interval
|
|
1483
1483
|
const typingInterval = streamingMessage._typingInterval;
|
|
@@ -1499,7 +1499,7 @@ export class AITestHarnessComponent {
|
|
|
1499
1499
|
// Load the serialized data into our entity
|
|
1500
1500
|
await this.currentAgentRun.LoadFromData(serializedAgentRun);
|
|
1501
1501
|
// Update assistant message with agent run ID if available
|
|
1502
|
-
const streamingMessage = this.conversationMessages.find(m => m.isStreaming);
|
|
1502
|
+
const streamingMessage = this.conversationMessages.find((m) => m.isStreaming);
|
|
1503
1503
|
if (streamingMessage && this.currentAgentRun.ID) {
|
|
1504
1504
|
streamingMessage.agentRunId = this.currentAgentRun.ID;
|
|
1505
1505
|
}
|
|
@@ -1512,19 +1512,19 @@ export class AITestHarnessComponent {
|
|
|
1512
1512
|
status: this.currentAgentRun.Status,
|
|
1513
1513
|
stepCount: this.currentAgentRun.Steps?.length || 0,
|
|
1514
1514
|
executionMonitorMode: this.executionMonitorMode,
|
|
1515
|
-
steps: this.currentAgentRun.Steps?.map(s => ({
|
|
1515
|
+
steps: this.currentAgentRun.Steps?.map((s) => ({
|
|
1516
1516
|
id: s.ID,
|
|
1517
1517
|
type: s.StepType,
|
|
1518
1518
|
status: s.Status,
|
|
1519
1519
|
hasSubAgentRun: !!s.SubAgentRun,
|
|
1520
|
-
subStepCount: s.SubAgentRun?.Steps?.length || 0
|
|
1521
|
-
}))
|
|
1520
|
+
subStepCount: s.SubAgentRun?.Steps?.length || 0,
|
|
1521
|
+
})),
|
|
1522
1522
|
});
|
|
1523
1523
|
// Force change detection
|
|
1524
1524
|
this.cdr.detectChanges();
|
|
1525
1525
|
}
|
|
1526
1526
|
else if (message?.type === 'StreamingContent' && message.data?.streaming) {
|
|
1527
|
-
const streamingMessage = this.conversationMessages.find(m => m.isStreaming);
|
|
1527
|
+
const streamingMessage = this.conversationMessages.find((m) => m.isStreaming);
|
|
1528
1528
|
if (streamingMessage) {
|
|
1529
1529
|
// Append streaming content
|
|
1530
1530
|
if (!streamingMessage.streamingContent) {
|
|
@@ -1555,15 +1555,15 @@ export class AITestHarnessComponent {
|
|
|
1555
1555
|
if (this.entity && 'AIModelTypeID' in this.entity) {
|
|
1556
1556
|
const prompt = this.entity;
|
|
1557
1557
|
if (prompt.AIModelTypeID) {
|
|
1558
|
-
filteredModels = AIEngineBase.Instance.Models.filter(model => model.AIModelTypeID === prompt.AIModelTypeID && model.IsActive);
|
|
1558
|
+
filteredModels = AIEngineBase.Instance.Models.filter((model) => model.AIModelTypeID === prompt.AIModelTypeID && model.IsActive);
|
|
1559
1559
|
}
|
|
1560
1560
|
else {
|
|
1561
1561
|
// No model type restriction, show all active models
|
|
1562
|
-
filteredModels = AIEngineBase.Instance.Models.filter(model => model.IsActive);
|
|
1562
|
+
filteredModels = AIEngineBase.Instance.Models.filter((model) => model.IsActive);
|
|
1563
1563
|
}
|
|
1564
1564
|
// Set default response format from prompt with slight delay for Kendo dropdown
|
|
1565
1565
|
setTimeout(() => {
|
|
1566
|
-
const format = this.responseFormatOptions.find(f => f.value.trim().toLowerCase() === prompt.ResponseFormat.trim().toLowerCase());
|
|
1566
|
+
const format = this.responseFormatOptions.find((f) => f.value.trim().toLowerCase() === prompt.ResponseFormat.trim().toLowerCase());
|
|
1567
1567
|
if (format) {
|
|
1568
1568
|
this.selectedResponseFormat = format;
|
|
1569
1569
|
}
|
|
@@ -1574,7 +1574,7 @@ export class AITestHarnessComponent {
|
|
|
1574
1574
|
}
|
|
1575
1575
|
else {
|
|
1576
1576
|
// Not a prompt entity, show all active models
|
|
1577
|
-
filteredModels = AIEngineBase.Instance.Models.filter(model => model.IsActive);
|
|
1577
|
+
filteredModels = AIEngineBase.Instance.Models.filter((model) => model.IsActive);
|
|
1578
1578
|
}
|
|
1579
1579
|
// Sort models by name
|
|
1580
1580
|
filteredModels.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
@@ -1586,7 +1586,7 @@ export class AITestHarnessComponent {
|
|
|
1586
1586
|
// Add a blank option at the beginning with the default model name
|
|
1587
1587
|
this.availableModels = [
|
|
1588
1588
|
{ ID: '', Name: this.defaultModelName ? `-- Default: ${this.defaultModelName} --` : '-- Use Default Model --' },
|
|
1589
|
-
...filteredModels
|
|
1589
|
+
...filteredModels,
|
|
1590
1590
|
];
|
|
1591
1591
|
// Don't auto-select a model - let the dropdown show the blank option
|
|
1592
1592
|
this.selectedModelId = '';
|
|
@@ -1605,15 +1605,14 @@ export class AITestHarnessComponent {
|
|
|
1605
1605
|
async getDefaultModelName(prompt) {
|
|
1606
1606
|
try {
|
|
1607
1607
|
// Get prompt-specific model associations
|
|
1608
|
-
const promptModels = AIEngineBase.Instance.PromptModels.filter(pm => pm.PromptID === prompt.ID &&
|
|
1609
|
-
(pm.Status === 'Active' || pm.Status === 'Preview'));
|
|
1608
|
+
const promptModels = AIEngineBase.Instance.PromptModels.filter((pm) => pm.PromptID === prompt.ID && (pm.Status === 'Active' || pm.Status === 'Preview'));
|
|
1610
1609
|
let defaultModel = null;
|
|
1611
1610
|
if (promptModels.length > 0) {
|
|
1612
1611
|
// Sort by priority (higher priority first)
|
|
1613
1612
|
promptModels.sort((a, b) => (b.Priority || 0) - (a.Priority || 0));
|
|
1614
1613
|
// Find the first active model
|
|
1615
1614
|
for (const pm of promptModels) {
|
|
1616
|
-
const model = AIEngineBase.Instance.Models.find(m => m.ID === pm.ModelID && m.IsActive);
|
|
1615
|
+
const model = AIEngineBase.Instance.Models.find((m) => m.ID === pm.ModelID && m.IsActive);
|
|
1617
1616
|
if (model) {
|
|
1618
1617
|
defaultModel = model;
|
|
1619
1618
|
break;
|
|
@@ -1622,8 +1621,7 @@ export class AITestHarnessComponent {
|
|
|
1622
1621
|
}
|
|
1623
1622
|
// If no prompt-specific model, use selection strategy
|
|
1624
1623
|
if (!defaultModel) {
|
|
1625
|
-
const candidates = AIEngineBase.Instance.Models.filter(m => m.IsActive &&
|
|
1626
|
-
(!prompt.AIModelTypeID || m.AIModelTypeID === prompt.AIModelTypeID));
|
|
1624
|
+
const candidates = AIEngineBase.Instance.Models.filter((m) => m.IsActive && (!prompt.AIModelTypeID || m.AIModelTypeID === prompt.AIModelTypeID));
|
|
1627
1625
|
if (candidates.length > 0) {
|
|
1628
1626
|
// Apply selection strategy
|
|
1629
1627
|
if (prompt.SelectionStrategy === 'ByPower') {
|
|
@@ -1660,18 +1658,16 @@ export class AITestHarnessComponent {
|
|
|
1660
1658
|
return;
|
|
1661
1659
|
}
|
|
1662
1660
|
// Get vendors that offer this model - same logic as loadVendorsForModel
|
|
1663
|
-
const modelVendors = AIEngineBase.Instance.ModelVendors.filter(mv => mv.ModelID === this.defaultModel.ID &&
|
|
1664
|
-
mv.Status === 'Active' &&
|
|
1665
|
-
mv.Type?.trim().toLowerCase() === 'inference provider');
|
|
1661
|
+
const modelVendors = AIEngineBase.Instance.ModelVendors.filter((mv) => mv.ModelID === this.defaultModel.ID && mv.Status === 'Active' && mv.Type?.trim().toLowerCase() === 'inference provider');
|
|
1666
1662
|
// Map to vendor objects with priority from ModelVendor
|
|
1667
1663
|
const vendorObjects = [];
|
|
1668
1664
|
for (const mv of modelVendors) {
|
|
1669
|
-
const vendor = AIEngineBase.Instance.Vendors.find(v => v.ID === mv.VendorID);
|
|
1665
|
+
const vendor = AIEngineBase.Instance.Vendors.find((v) => v.ID === mv.VendorID);
|
|
1670
1666
|
if (vendor) {
|
|
1671
1667
|
vendorObjects.push({
|
|
1672
1668
|
ID: vendor.ID,
|
|
1673
1669
|
Name: vendor.Name,
|
|
1674
|
-
Priority: mv.Priority || 999 // Use ModelVendor priority
|
|
1670
|
+
Priority: mv.Priority || 999, // Use ModelVendor priority
|
|
1675
1671
|
});
|
|
1676
1672
|
}
|
|
1677
1673
|
}
|
|
@@ -1699,12 +1695,12 @@ export class AITestHarnessComponent {
|
|
|
1699
1695
|
EntityName: 'MJ: AI Configurations',
|
|
1700
1696
|
ExtraFilter: `Status IN ('Active', 'Preview')`,
|
|
1701
1697
|
OrderBy: 'IsDefault DESC, Name',
|
|
1702
|
-
ResultType: 'entity_object'
|
|
1698
|
+
ResultType: 'entity_object',
|
|
1703
1699
|
});
|
|
1704
1700
|
if (result.Success && result.Results) {
|
|
1705
1701
|
this.availableConfigurations = result.Results;
|
|
1706
1702
|
// Auto-select the default configuration if one exists
|
|
1707
|
-
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1703
|
+
const defaultConfig = this.availableConfigurations.find((c) => c.IsDefault);
|
|
1708
1704
|
if (defaultConfig) {
|
|
1709
1705
|
this.selectedConfigurationId = defaultConfig.ID;
|
|
1710
1706
|
}
|
|
@@ -1750,19 +1746,17 @@ export class AITestHarnessComponent {
|
|
|
1750
1746
|
return;
|
|
1751
1747
|
}
|
|
1752
1748
|
// Get model-specific vendors
|
|
1753
|
-
const modelVendors = AIEngineBase.Instance.ModelVendors.filter(mv => mv.ModelID === this.selectedModelId &&
|
|
1754
|
-
mv.Status === 'Active' &&
|
|
1755
|
-
mv.Type?.trim().toLowerCase() === 'inference provider');
|
|
1749
|
+
const modelVendors = AIEngineBase.Instance.ModelVendors.filter((mv) => mv.ModelID === this.selectedModelId && mv.Status === 'Active' && mv.Type?.trim().toLowerCase() === 'inference provider');
|
|
1756
1750
|
// Map to vendor objects with priority from ModelVendor
|
|
1757
1751
|
const vendorObjects = [];
|
|
1758
1752
|
for (const mv of modelVendors) {
|
|
1759
|
-
const vendor = AIEngineBase.Instance.Vendors.find(v => v.ID === mv.VendorID);
|
|
1753
|
+
const vendor = AIEngineBase.Instance.Vendors.find((v) => v.ID === mv.VendorID);
|
|
1760
1754
|
if (vendor) {
|
|
1761
1755
|
// For now, include all vendors. TODO: Filter by vendor type when available
|
|
1762
1756
|
vendorObjects.push({
|
|
1763
1757
|
ID: vendor.ID,
|
|
1764
1758
|
Name: vendor.Name,
|
|
1765
|
-
Priority: mv.Priority || 999 // Use ModelVendor priority
|
|
1759
|
+
Priority: mv.Priority || 999, // Use ModelVendor priority
|
|
1766
1760
|
});
|
|
1767
1761
|
}
|
|
1768
1762
|
}
|
|
@@ -1801,7 +1795,9 @@ export class AITestHarnessComponent {
|
|
|
1801
1795
|
this.advancedParams.seed = prompt.Seed;
|
|
1802
1796
|
if (prompt.StopSequences) {
|
|
1803
1797
|
this.stopSequencesText = prompt.StopSequences;
|
|
1804
|
-
this.advancedParams.stopSequences = prompt.StopSequences.split(',')
|
|
1798
|
+
this.advancedParams.stopSequences = prompt.StopSequences.split(',')
|
|
1799
|
+
.map((s) => s.trim())
|
|
1800
|
+
.filter((s) => s.length > 0);
|
|
1805
1801
|
}
|
|
1806
1802
|
if (prompt.IncludeLogProbs != null)
|
|
1807
1803
|
this.advancedParams.includeLogProbs = prompt.IncludeLogProbs;
|
|
@@ -1825,7 +1821,7 @@ export class AITestHarnessComponent {
|
|
|
1825
1821
|
EntityName: 'Template Params',
|
|
1826
1822
|
ExtraFilter: `TemplateID='${prompt.TemplateID}'`,
|
|
1827
1823
|
OrderBy: 'Name ASC',
|
|
1828
|
-
ResultType: 'entity_object'
|
|
1824
|
+
ResultType: 'entity_object',
|
|
1829
1825
|
});
|
|
1830
1826
|
if (result.Success && result.Results && result.Results.length > 0) {
|
|
1831
1827
|
// Clear existing template variables
|
|
@@ -1835,7 +1831,7 @@ export class AITestHarnessComponent {
|
|
|
1835
1831
|
this.templateVariables.push({
|
|
1836
1832
|
name: param.Name,
|
|
1837
1833
|
value: param.DefaultValue || '',
|
|
1838
|
-
type: this.getVariableTypeFromParamType(param.Type)
|
|
1834
|
+
type: this.getVariableTypeFromParamType(param.Type),
|
|
1839
1835
|
});
|
|
1840
1836
|
}
|
|
1841
1837
|
// If no parameters found, add one empty variable to start
|
|
@@ -1883,14 +1879,14 @@ export class AITestHarnessComponent {
|
|
|
1883
1879
|
// Reset vendor - will be loaded by loadDefaultVendor
|
|
1884
1880
|
this.selectedVendorId = '';
|
|
1885
1881
|
// Reset response format to prompt's setting
|
|
1886
|
-
const format = this.responseFormatOptions.find(f => f.value.trim().toLowerCase() === prompt.ResponseFormat.trim().toLowerCase());
|
|
1882
|
+
const format = this.responseFormatOptions.find((f) => f.value.trim().toLowerCase() === prompt.ResponseFormat.trim().toLowerCase());
|
|
1887
1883
|
this.selectedResponseFormat = format || this.responseFormatOptions[0];
|
|
1888
1884
|
// Reset max tokens
|
|
1889
1885
|
this.maxTokens = null;
|
|
1890
1886
|
// Reset skip validation
|
|
1891
1887
|
this.skipValidation = false;
|
|
1892
1888
|
// Reset configuration to default
|
|
1893
|
-
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1889
|
+
const defaultConfig = this.availableConfigurations.find((c) => c.IsDefault);
|
|
1894
1890
|
if (defaultConfig) {
|
|
1895
1891
|
this.selectedConfigurationId = defaultConfig.ID;
|
|
1896
1892
|
}
|
|
@@ -1908,7 +1904,7 @@ export class AITestHarnessComponent {
|
|
|
1908
1904
|
seed: null,
|
|
1909
1905
|
stopSequences: [],
|
|
1910
1906
|
includeLogProbs: false,
|
|
1911
|
-
topLogProbs: 2
|
|
1907
|
+
topLogProbs: 2,
|
|
1912
1908
|
};
|
|
1913
1909
|
this.stopSequencesText = '';
|
|
1914
1910
|
// Reload prompt defaults for advanced params
|
|
@@ -1953,14 +1949,14 @@ export class AITestHarnessComponent {
|
|
|
1953
1949
|
seed: null,
|
|
1954
1950
|
stopSequences: [],
|
|
1955
1951
|
includeLogProbs: false,
|
|
1956
|
-
topLogProbs: 2
|
|
1952
|
+
topLogProbs: 2,
|
|
1957
1953
|
};
|
|
1958
1954
|
this.stopSequencesText = '';
|
|
1959
1955
|
this.advancedParamsExpanded = false;
|
|
1960
1956
|
this.skipValidation = false;
|
|
1961
1957
|
// Reset agent configuration to default
|
|
1962
1958
|
if (this.mode === 'agent') {
|
|
1963
|
-
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1959
|
+
const defaultConfig = this.availableConfigurations.find((c) => c.IsDefault);
|
|
1964
1960
|
this.agentConfigurationId = defaultConfig?.ID || '';
|
|
1965
1961
|
}
|
|
1966
1962
|
}
|
|
@@ -2006,7 +2002,7 @@ export class AITestHarnessComponent {
|
|
|
2006
2002
|
currentAgentRun: !!this.currentAgentRun,
|
|
2007
2003
|
agentRunStatus: this.currentAgentRun?.Status || 'none',
|
|
2008
2004
|
conversationMessages: this.conversationMessages.length,
|
|
2009
|
-
executionMonitorMode: this.executionMonitorMode
|
|
2005
|
+
executionMonitorMode: this.executionMonitorMode,
|
|
2010
2006
|
});
|
|
2011
2007
|
this.activeTab = tab;
|
|
2012
2008
|
// If switching to execution monitor tab, ensure it has the latest data
|
|
@@ -2014,13 +2010,11 @@ export class AITestHarnessComponent {
|
|
|
2014
2010
|
console.log('📊 Switching to execution monitor tab');
|
|
2015
2011
|
// Always ensure we have the latest execution data when switching to monitor
|
|
2016
2012
|
if (this.conversationMessages.length > 0) {
|
|
2017
|
-
const lastAssistantMessage = this.conversationMessages
|
|
2018
|
-
.filter(m => m.role === 'assistant' && m.agentRunId)
|
|
2019
|
-
.pop();
|
|
2013
|
+
const lastAssistantMessage = this.conversationMessages.filter((m) => m.role === 'assistant' && m.agentRunId).pop();
|
|
2020
2014
|
console.log('🔍 Last assistant message with agent run:', {
|
|
2021
2015
|
found: !!lastAssistantMessage,
|
|
2022
2016
|
hasAgentRunId: !!lastAssistantMessage?.agentRunId,
|
|
2023
|
-
agentRunId: lastAssistantMessage?.agentRunId
|
|
2017
|
+
agentRunId: lastAssistantMessage?.agentRunId,
|
|
2024
2018
|
});
|
|
2025
2019
|
if (lastAssistantMessage && lastAssistantMessage.agentRunId) {
|
|
2026
2020
|
// Always update agent run to ensure it's fresh
|
|
@@ -2031,7 +2025,7 @@ export class AITestHarnessComponent {
|
|
|
2031
2025
|
this.lastProcessedRunId = messageRunId;
|
|
2032
2026
|
console.log('✅ Loading agent run:', {
|
|
2033
2027
|
mode: this.executionMonitorMode,
|
|
2034
|
-
runId: this.lastProcessedRunId
|
|
2028
|
+
runId: this.lastProcessedRunId,
|
|
2035
2029
|
});
|
|
2036
2030
|
// Trigger change detection to ensure the execution monitor updates
|
|
2037
2031
|
setTimeout(() => {
|
|
@@ -2048,7 +2042,7 @@ export class AITestHarnessComponent {
|
|
|
2048
2042
|
}
|
|
2049
2043
|
else {
|
|
2050
2044
|
console.log('📄 Switching away from execution monitor, preserving data:', {
|
|
2051
|
-
currentAgentRunExists: !!this.currentAgentRun
|
|
2045
|
+
currentAgentRunExists: !!this.currentAgentRun,
|
|
2052
2046
|
});
|
|
2053
2047
|
// Don't clear currentAgentRun when switching away from execution monitor
|
|
2054
2048
|
// This preserves the state for when the user switches back
|
|
@@ -2094,7 +2088,7 @@ export class AITestHarnessComponent {
|
|
|
2094
2088
|
this.executionMonitorMode = 'historical';
|
|
2095
2089
|
console.log('✅ Loaded agent run:', {
|
|
2096
2090
|
id: agentRunEntity.ID,
|
|
2097
|
-
stepCount: this.currentAgentRun.Steps?.length || 0
|
|
2091
|
+
stepCount: this.currentAgentRun.Steps?.length || 0,
|
|
2098
2092
|
});
|
|
2099
2093
|
// Force change detection to update the execution monitor
|
|
2100
2094
|
this.cdr.detectChanges();
|
|
@@ -2151,7 +2145,7 @@ export class AITestHarnessComponent {
|
|
|
2151
2145
|
id: this.generateMessageId(),
|
|
2152
2146
|
role: 'user',
|
|
2153
2147
|
content: this.currentUserMessage.trim(),
|
|
2154
|
-
timestamp: new Date()
|
|
2148
|
+
timestamp: new Date(),
|
|
2155
2149
|
};
|
|
2156
2150
|
this.conversationMessages.push(userMessage);
|
|
2157
2151
|
// Clear input and update change detection
|
|
@@ -2203,7 +2197,7 @@ export class AITestHarnessComponent {
|
|
|
2203
2197
|
streamingContent: this.mode === 'agent' ? 'Running agent...' : 'Running prompt...',
|
|
2204
2198
|
agentRunId: '',
|
|
2205
2199
|
streamingStartTime: Date.now(),
|
|
2206
|
-
elapsedTime: 0
|
|
2200
|
+
elapsedTime: 0,
|
|
2207
2201
|
};
|
|
2208
2202
|
this.conversationMessages.push(assistantMessage);
|
|
2209
2203
|
this.scrollNeeded = true;
|
|
@@ -2235,7 +2229,7 @@ export class AITestHarnessComponent {
|
|
|
2235
2229
|
data: Object.keys(dataContext).length > 0 ? dataContext : undefined,
|
|
2236
2230
|
lastRunId: this.lastAgentRunId || undefined,
|
|
2237
2231
|
autoPopulateLastRunPayload: this.lastAgentRunId ? true : false,
|
|
2238
|
-
configurationId: this.agentConfigurationId || undefined
|
|
2232
|
+
configurationId: this.agentConfigurationId || undefined,
|
|
2239
2233
|
});
|
|
2240
2234
|
// Stop elapsed time counter
|
|
2241
2235
|
if (this.elapsedTimeInterval) {
|
|
@@ -2250,7 +2244,7 @@ export class AITestHarnessComponent {
|
|
|
2250
2244
|
const parseOptions = {
|
|
2251
2245
|
extractInlineJson: true,
|
|
2252
2246
|
maxDepth: 100,
|
|
2253
|
-
debug: false
|
|
2247
|
+
debug: false,
|
|
2254
2248
|
};
|
|
2255
2249
|
// Apply recursive JSON parsing to extract any nested JSON strings
|
|
2256
2250
|
const fullResult = ParseJSONRecursive(executionResult, parseOptions);
|
|
@@ -2292,7 +2286,7 @@ export class AITestHarnessComponent {
|
|
|
2292
2286
|
assistantMessage.payload = payloadData; // Store the payload if present
|
|
2293
2287
|
const startedAt = executionResult.agentRun?.StartedAt ? new Date(executionResult.agentRun.StartedAt).getTime() : 0;
|
|
2294
2288
|
const completedAt = executionResult.agentRun?.CompletedAt ? new Date(executionResult.agentRun.CompletedAt).getTime() : 0;
|
|
2295
|
-
const executionTime =
|
|
2289
|
+
const executionTime = startedAt && completedAt ? completedAt - startedAt : 0;
|
|
2296
2290
|
assistantMessage.executionTime = executionTime;
|
|
2297
2291
|
assistantMessage.agentRunId = fullResult.agentRun?.ID || assistantMessage.agentRunId;
|
|
2298
2292
|
// Update the tracking ID when we set new execution data
|
|
@@ -2310,7 +2304,7 @@ export class AITestHarnessComponent {
|
|
|
2310
2304
|
console.error('❌ AI Test Harness: Execution failed', {
|
|
2311
2305
|
success: executionResult?.success,
|
|
2312
2306
|
errorMessage: executionResult?.agentRun?.ErrorMessage,
|
|
2313
|
-
hasPayload: !!executionResult?.payload
|
|
2307
|
+
hasPayload: !!executionResult?.payload,
|
|
2314
2308
|
});
|
|
2315
2309
|
assistantMessage.content = 'I encountered an error processing your request.';
|
|
2316
2310
|
assistantMessage.error = executionResult?.agentRun?.ErrorMessage || 'Unknown error occurred';
|
|
@@ -2340,7 +2334,7 @@ export class AITestHarnessComponent {
|
|
|
2340
2334
|
error: error,
|
|
2341
2335
|
message: error?.message,
|
|
2342
2336
|
stack: error?.stack,
|
|
2343
|
-
type: error?.constructor?.name
|
|
2337
|
+
type: error?.constructor?.name,
|
|
2344
2338
|
});
|
|
2345
2339
|
// Update assistant message with error
|
|
2346
2340
|
const lastMessage = this.conversationMessages[this.conversationMessages.length - 1];
|
|
@@ -2381,7 +2375,7 @@ export class AITestHarnessComponent {
|
|
|
2381
2375
|
streamingContent: this.mode === 'agent' ? 'Running agent...' : 'Running prompt...',
|
|
2382
2376
|
agentRunId: '',
|
|
2383
2377
|
streamingStartTime: Date.now(),
|
|
2384
|
-
elapsedTime: 0
|
|
2378
|
+
elapsedTime: 0,
|
|
2385
2379
|
};
|
|
2386
2380
|
this.conversationMessages.push(assistantMessage);
|
|
2387
2381
|
this.scrollNeeded = true;
|
|
@@ -2395,14 +2389,14 @@ export class AITestHarnessComponent {
|
|
|
2395
2389
|
// Prepare data context (template variables + user message)
|
|
2396
2390
|
const dataContext = {
|
|
2397
2391
|
...templateVariables,
|
|
2398
|
-
userMessage: userMessage
|
|
2392
|
+
userMessage: userMessage,
|
|
2399
2393
|
};
|
|
2400
2394
|
// Build conversation messages
|
|
2401
2395
|
const messages = this.conversationMessages
|
|
2402
|
-
.filter(m => !m.isStreaming && m.content) // Only include non-streaming messages with content
|
|
2403
|
-
.map(m => ({
|
|
2396
|
+
.filter((m) => !m.isStreaming && m.content) // Only include non-streaming messages with content
|
|
2397
|
+
.map((m) => ({
|
|
2404
2398
|
role: m.role,
|
|
2405
|
-
content: m.content
|
|
2399
|
+
content: m.content,
|
|
2406
2400
|
}));
|
|
2407
2401
|
// Execute the prompt using the new AI client
|
|
2408
2402
|
const executionResult = await dataProvider.AI.RunAIPrompt({
|
|
@@ -2426,7 +2420,7 @@ export class AITestHarnessComponent {
|
|
|
2426
2420
|
topLogProbs: this.advancedParams.includeLogProbs ? this.advancedParams.topLogProbs : undefined,
|
|
2427
2421
|
messages: messages.length > 0 ? messages : undefined,
|
|
2428
2422
|
rerunFromPromptRunID: this.originalPromptRunId || undefined,
|
|
2429
|
-
systemPromptOverride: this.systemPromptOverride || undefined
|
|
2423
|
+
systemPromptOverride: this.systemPromptOverride || undefined,
|
|
2430
2424
|
});
|
|
2431
2425
|
// Stop elapsed time counter
|
|
2432
2426
|
if (this.elapsedTimeInterval) {
|
|
@@ -2439,16 +2433,16 @@ export class AITestHarnessComponent {
|
|
|
2439
2433
|
const parseOptions = {
|
|
2440
2434
|
extractInlineJson: true,
|
|
2441
2435
|
maxDepth: 100,
|
|
2442
|
-
debug: false
|
|
2436
|
+
debug: false,
|
|
2443
2437
|
};
|
|
2444
2438
|
if (executionResult?.success) {
|
|
2445
2439
|
// Use parsedResult if available, otherwise fall back to output
|
|
2446
2440
|
// Handle case where parsedResult is already an object (from GraphQL client)
|
|
2447
2441
|
const contentToDisplay = executionResult.parsedResult
|
|
2448
|
-
?
|
|
2442
|
+
? typeof executionResult.parsedResult === 'object'
|
|
2449
2443
|
? JSON.stringify(executionResult.parsedResult, null, 2)
|
|
2450
|
-
: executionResult.parsedResult
|
|
2451
|
-
:
|
|
2444
|
+
: executionResult.parsedResult
|
|
2445
|
+
: executionResult.output || 'No response generated';
|
|
2452
2446
|
assistantMessage.content = contentToDisplay;
|
|
2453
2447
|
assistantMessage.executionTime = executionResult.executionTimeMs;
|
|
2454
2448
|
// Store the complete execution result for JSON display
|
|
@@ -2522,10 +2516,10 @@ export class AITestHarnessComponent {
|
|
|
2522
2516
|
startTypingAnimation(message) {
|
|
2523
2517
|
const initialMessages = [
|
|
2524
2518
|
"I'm processing your request...",
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2519
|
+
'Let me think about that...',
|
|
2520
|
+
'Working on your request...',
|
|
2521
|
+
'Analyzing your question...',
|
|
2522
|
+
'Processing...',
|
|
2529
2523
|
];
|
|
2530
2524
|
const selectedMessage = initialMessages[Math.floor(Math.random() * initialMessages.length)];
|
|
2531
2525
|
let index = 0;
|
|
@@ -2592,7 +2586,7 @@ export class AITestHarnessComponent {
|
|
|
2592
2586
|
this.agentVariables.push({
|
|
2593
2587
|
name: '',
|
|
2594
2588
|
value: '',
|
|
2595
|
-
type: 'string'
|
|
2589
|
+
type: 'string',
|
|
2596
2590
|
});
|
|
2597
2591
|
}
|
|
2598
2592
|
/**
|
|
@@ -2610,7 +2604,7 @@ export class AITestHarnessComponent {
|
|
|
2610
2604
|
this.templateVariables.push({
|
|
2611
2605
|
name: '',
|
|
2612
2606
|
value: '',
|
|
2613
|
-
type: 'string'
|
|
2607
|
+
type: 'string',
|
|
2614
2608
|
});
|
|
2615
2609
|
}
|
|
2616
2610
|
/**
|
|
@@ -2654,10 +2648,10 @@ export class AITestHarnessComponent {
|
|
|
2654
2648
|
const parsedData = JSON.parse(saved);
|
|
2655
2649
|
this.savedConversations = parsedData || [];
|
|
2656
2650
|
// Convert date strings back to Date objects
|
|
2657
|
-
this.savedConversations.forEach(conv => {
|
|
2651
|
+
this.savedConversations.forEach((conv) => {
|
|
2658
2652
|
conv.createdAt = new Date(conv.createdAt);
|
|
2659
2653
|
conv.updatedAt = new Date(conv.updatedAt);
|
|
2660
|
-
conv.messages.forEach(msg => {
|
|
2654
|
+
conv.messages.forEach((msg) => {
|
|
2661
2655
|
msg.timestamp = new Date(msg.timestamp);
|
|
2662
2656
|
});
|
|
2663
2657
|
});
|
|
@@ -2700,7 +2694,7 @@ export class AITestHarnessComponent {
|
|
|
2700
2694
|
}
|
|
2701
2695
|
// If updating existing conversation, pre-fill the name
|
|
2702
2696
|
if (this.currentConversationId) {
|
|
2703
|
-
const currentConv = this.savedConversations.find(c => c.id === this.currentConversationId);
|
|
2697
|
+
const currentConv = this.savedConversations.find((c) => c.id === this.currentConversationId);
|
|
2704
2698
|
this.tempConversationName = currentConv ? currentConv.name : '';
|
|
2705
2699
|
}
|
|
2706
2700
|
else {
|
|
@@ -2746,11 +2740,11 @@ export class AITestHarnessComponent {
|
|
|
2746
2740
|
skipValidation: this.mode === 'prompt' ? this.skipValidation : undefined,
|
|
2747
2741
|
agentConfigurationId: this.mode === 'agent' ? this.agentConfigurationId : undefined,
|
|
2748
2742
|
createdAt: new Date(),
|
|
2749
|
-
updatedAt: new Date()
|
|
2743
|
+
updatedAt: new Date(),
|
|
2750
2744
|
};
|
|
2751
2745
|
if (this.currentConversationId) {
|
|
2752
2746
|
// Update existing conversation
|
|
2753
|
-
const index = this.savedConversations.findIndex(c => c.id === this.currentConversationId);
|
|
2747
|
+
const index = this.savedConversations.findIndex((c) => c.id === this.currentConversationId);
|
|
2754
2748
|
if (index >= 0) {
|
|
2755
2749
|
conversation.id = this.currentConversationId;
|
|
2756
2750
|
conversation.createdAt = this.savedConversations[index].createdAt;
|
|
@@ -2803,7 +2797,7 @@ export class AITestHarnessComponent {
|
|
|
2803
2797
|
}
|
|
2804
2798
|
autoSaveConversation() {
|
|
2805
2799
|
if (this.currentConversationId && this.conversationMessages.length > 0) {
|
|
2806
|
-
const index = this.savedConversations.findIndex(c => c.id === this.currentConversationId);
|
|
2800
|
+
const index = this.savedConversations.findIndex((c) => c.id === this.currentConversationId);
|
|
2807
2801
|
if (index >= 0) {
|
|
2808
2802
|
this.savedConversations[index].messages = [...this.conversationMessages];
|
|
2809
2803
|
this.savedConversations[index].dataContext = this.buildDataContext();
|
|
@@ -2868,9 +2862,7 @@ export class AITestHarnessComponent {
|
|
|
2868
2862
|
this.agentVariables.push({
|
|
2869
2863
|
name: key,
|
|
2870
2864
|
value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
2871
|
-
type: typeof value === 'boolean' ? 'boolean' :
|
|
2872
|
-
typeof value === 'number' ? 'number' :
|
|
2873
|
-
typeof value === 'object' ? 'object' : 'string'
|
|
2865
|
+
type: typeof value === 'boolean' ? 'boolean' : typeof value === 'number' ? 'number' : typeof value === 'object' ? 'object' : 'string',
|
|
2874
2866
|
});
|
|
2875
2867
|
}
|
|
2876
2868
|
// Restore configuration for agent mode
|
|
@@ -2886,9 +2878,7 @@ export class AITestHarnessComponent {
|
|
|
2886
2878
|
this.templateVariables.push({
|
|
2887
2879
|
name: key,
|
|
2888
2880
|
value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
2889
|
-
type: typeof value === 'boolean' ? 'boolean' :
|
|
2890
|
-
typeof value === 'number' ? 'number' :
|
|
2891
|
-
typeof value === 'object' ? 'object' : 'string'
|
|
2881
|
+
type: typeof value === 'boolean' ? 'boolean' : typeof value === 'number' ? 'number' : typeof value === 'object' ? 'object' : 'string',
|
|
2892
2882
|
});
|
|
2893
2883
|
}
|
|
2894
2884
|
// Restore advanced parameters
|
|
@@ -2924,9 +2914,7 @@ export class AITestHarnessComponent {
|
|
|
2924
2914
|
}
|
|
2925
2915
|
}
|
|
2926
2916
|
// Load agent run from the last assistant message if available
|
|
2927
|
-
const lastAssistantMessage = this.conversationMessages
|
|
2928
|
-
.filter(m => m.role === 'assistant' && m.agentRunId)
|
|
2929
|
-
.pop();
|
|
2917
|
+
const lastAssistantMessage = this.conversationMessages.filter((m) => m.role === 'assistant' && m.agentRunId).pop();
|
|
2930
2918
|
if (lastAssistantMessage && lastAssistantMessage.agentRunId) {
|
|
2931
2919
|
this.loadAgentRun(lastAssistantMessage.agentRunId);
|
|
2932
2920
|
this.executionMonitorMode = 'historical';
|
|
@@ -2944,7 +2932,7 @@ export class AITestHarnessComponent {
|
|
|
2944
2932
|
async deleteConversation(conversation, event) {
|
|
2945
2933
|
event.stopPropagation();
|
|
2946
2934
|
if (confirm(`Delete conversation "${conversation.name}"?`)) {
|
|
2947
|
-
const index = this.savedConversations.findIndex(c => c.id === conversation.id);
|
|
2935
|
+
const index = this.savedConversations.findIndex((c) => c.id === conversation.id);
|
|
2948
2936
|
if (index >= 0) {
|
|
2949
2937
|
this.savedConversations.splice(index, 1);
|
|
2950
2938
|
// Save to localStorage
|
|
@@ -2965,17 +2953,17 @@ export class AITestHarnessComponent {
|
|
|
2965
2953
|
entity: {
|
|
2966
2954
|
id: this.entity?.ID,
|
|
2967
2955
|
name: this.getEntityName(),
|
|
2968
|
-
type: this.mode
|
|
2956
|
+
type: this.mode,
|
|
2969
2957
|
},
|
|
2970
2958
|
messages: this.conversationMessages,
|
|
2971
2959
|
dataContext: this.buildDataContext(),
|
|
2972
|
-
exportedAt: new Date().toISOString()
|
|
2960
|
+
exportedAt: new Date().toISOString(),
|
|
2973
2961
|
};
|
|
2974
2962
|
// Add mode-specific data
|
|
2975
2963
|
if (this.mode === 'agent') {
|
|
2976
2964
|
exportData.templateData = this.buildTemplateData();
|
|
2977
2965
|
exportData.agentSettings = {
|
|
2978
|
-
configurationId: this.agentConfigurationId
|
|
2966
|
+
configurationId: this.agentConfigurationId,
|
|
2979
2967
|
};
|
|
2980
2968
|
}
|
|
2981
2969
|
else {
|
|
@@ -2985,7 +2973,7 @@ export class AITestHarnessComponent {
|
|
|
2985
2973
|
vendorId: this.selectedVendorId,
|
|
2986
2974
|
configurationId: this.selectedConfigurationId,
|
|
2987
2975
|
maxTokens: this.maxTokens,
|
|
2988
|
-
skipValidation: this.skipValidation
|
|
2976
|
+
skipValidation: this.skipValidation,
|
|
2989
2977
|
};
|
|
2990
2978
|
exportData.advancedParams = this.advancedParams;
|
|
2991
2979
|
}
|
|
@@ -3018,7 +3006,7 @@ export class AITestHarnessComponent {
|
|
|
3018
3006
|
}
|
|
3019
3007
|
this.conversationMessages = data.messages.map((msg) => ({
|
|
3020
3008
|
...msg,
|
|
3021
|
-
timestamp: new Date(msg.timestamp)
|
|
3009
|
+
timestamp: new Date(msg.timestamp),
|
|
3022
3010
|
}));
|
|
3023
3011
|
// Import agent variables (unified from dataContext and templateData)
|
|
3024
3012
|
this.agentVariables = [];
|
|
@@ -3027,9 +3015,13 @@ export class AITestHarnessComponent {
|
|
|
3027
3015
|
this.agentVariables.push({
|
|
3028
3016
|
name: key,
|
|
3029
3017
|
value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
3030
|
-
type: typeof value === 'boolean'
|
|
3031
|
-
|
|
3032
|
-
|
|
3018
|
+
type: typeof value === 'boolean'
|
|
3019
|
+
? 'boolean'
|
|
3020
|
+
: typeof value === 'number'
|
|
3021
|
+
? 'number'
|
|
3022
|
+
: typeof value === 'object'
|
|
3023
|
+
? 'object'
|
|
3024
|
+
: 'string',
|
|
3033
3025
|
});
|
|
3034
3026
|
}
|
|
3035
3027
|
// Template data is already imported into agentVariables above
|
|
@@ -3116,7 +3108,7 @@ export class AITestHarnessComponent {
|
|
|
3116
3108
|
formatTimestamp(date) {
|
|
3117
3109
|
return date.toLocaleTimeString('en-US', {
|
|
3118
3110
|
hour: '2-digit',
|
|
3119
|
-
minute: '2-digit'
|
|
3111
|
+
minute: '2-digit',
|
|
3120
3112
|
});
|
|
3121
3113
|
}
|
|
3122
3114
|
/**
|
|
@@ -3180,7 +3172,7 @@ export class AITestHarnessComponent {
|
|
|
3180
3172
|
// Add agent run ID for reference
|
|
3181
3173
|
const enhancedParsed = {
|
|
3182
3174
|
...parsed,
|
|
3183
|
-
_agentRunID: parsed.agentRunID
|
|
3175
|
+
_agentRunID: parsed.agentRunID,
|
|
3184
3176
|
};
|
|
3185
3177
|
this.currentJsonContent = this.formatJson(enhancedParsed);
|
|
3186
3178
|
}
|
|
@@ -3211,7 +3203,7 @@ export class AITestHarnessComponent {
|
|
|
3211
3203
|
resizable: true,
|
|
3212
3204
|
draggable: true,
|
|
3213
3205
|
top: centerTop,
|
|
3214
|
-
left: centerLeft
|
|
3206
|
+
left: centerLeft,
|
|
3215
3207
|
});
|
|
3216
3208
|
// Pass the JSON content to the component
|
|
3217
3209
|
const windowContent = this.jsonWindowRef.content.instance;
|
|
@@ -3228,9 +3220,7 @@ export class AITestHarnessComponent {
|
|
|
3228
3220
|
* Get the last run ID from conversation messages
|
|
3229
3221
|
*/
|
|
3230
3222
|
getLastRunId() {
|
|
3231
|
-
const lastAssistantMessage = this.conversationMessages
|
|
3232
|
-
.filter(m => m.role === 'assistant' && m.agentRunId)
|
|
3233
|
-
.pop();
|
|
3223
|
+
const lastAssistantMessage = this.conversationMessages.filter((m) => m.role === 'assistant' && m.agentRunId).pop();
|
|
3234
3224
|
return lastAssistantMessage?.agentRunId || null;
|
|
3235
3225
|
}
|
|
3236
3226
|
/**
|
|
@@ -3264,9 +3254,7 @@ export class AITestHarnessComponent {
|
|
|
3264
3254
|
async copyMessage(message) {
|
|
3265
3255
|
try {
|
|
3266
3256
|
// Convert content to string if needed
|
|
3267
|
-
const content = typeof message.content === 'string'
|
|
3268
|
-
? message.content
|
|
3269
|
-
: JSON.stringify(message.content);
|
|
3257
|
+
const content = typeof message.content === 'string' ? message.content : JSON.stringify(message.content);
|
|
3270
3258
|
await navigator.clipboard.writeText(content);
|
|
3271
3259
|
MJNotificationService.Instance.CreateSimpleNotification('Message copied to clipboard', 'success', 2000);
|
|
3272
3260
|
}
|
|
@@ -3310,7 +3298,7 @@ export class AITestHarnessComponent {
|
|
|
3310
3298
|
const parseOptions = {
|
|
3311
3299
|
extractInlineJson: true,
|
|
3312
3300
|
maxDepth: 100,
|
|
3313
|
-
debug: false
|
|
3301
|
+
debug: false,
|
|
3314
3302
|
};
|
|
3315
3303
|
try {
|
|
3316
3304
|
let parsed;
|
|
@@ -3392,9 +3380,9 @@ export class AITestHarnessComponent {
|
|
|
3392
3380
|
/```[\s\S]*?```/, // Code blocks
|
|
3393
3381
|
/`[^`]+`/, // Inline code
|
|
3394
3382
|
/^[-*+]\s/m, // Lists
|
|
3395
|
-
/^\d+\.\s/m // Numbered lists
|
|
3383
|
+
/^\d+\.\s/m, // Numbered lists
|
|
3396
3384
|
];
|
|
3397
|
-
if (markdownPatterns.some(pattern => pattern.test(content))) {
|
|
3385
|
+
if (markdownPatterns.some((pattern) => pattern.test(content))) {
|
|
3398
3386
|
return 'markdown';
|
|
3399
3387
|
}
|
|
3400
3388
|
return 'text';
|
|
@@ -3403,9 +3391,7 @@ export class AITestHarnessComponent {
|
|
|
3403
3391
|
// Basic markdown to HTML conversion with improved formatting
|
|
3404
3392
|
let html = content;
|
|
3405
3393
|
// Escape HTML first
|
|
3406
|
-
html = html.replace(/&/g, '&')
|
|
3407
|
-
.replace(/</g, '<')
|
|
3408
|
-
.replace(/>/g, '>');
|
|
3394
|
+
html = html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
3409
3395
|
// Code blocks with language support
|
|
3410
3396
|
html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
|
|
3411
3397
|
const language = lang || '';
|
|
@@ -3495,12 +3481,7 @@ export class AITestHarnessComponent {
|
|
|
3495
3481
|
* Escapes HTML content for use in attributes
|
|
3496
3482
|
*/
|
|
3497
3483
|
escapeHtmlAttribute(text) {
|
|
3498
|
-
return text
|
|
3499
|
-
.replace(/&/g, '&')
|
|
3500
|
-
.replace(/"/g, '"')
|
|
3501
|
-
.replace(/'/g, ''')
|
|
3502
|
-
.replace(/</g, '<')
|
|
3503
|
-
.replace(/>/g, '>');
|
|
3484
|
+
return text.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
3504
3485
|
}
|
|
3505
3486
|
/**
|
|
3506
3487
|
* Renders JSON content with human-readable content prominently displayed
|
|
@@ -3541,9 +3522,12 @@ export class AITestHarnessComponent {
|
|
|
3541
3522
|
*/
|
|
3542
3523
|
copyJsonContent() {
|
|
3543
3524
|
if (this.currentJsonContent) {
|
|
3544
|
-
navigator.clipboard
|
|
3525
|
+
navigator.clipboard
|
|
3526
|
+
.writeText(this.currentJsonContent)
|
|
3527
|
+
.then(() => {
|
|
3545
3528
|
// Success - JSON copied
|
|
3546
|
-
})
|
|
3529
|
+
})
|
|
3530
|
+
.catch((err) => {
|
|
3547
3531
|
// Error copying
|
|
3548
3532
|
});
|
|
3549
3533
|
}
|
|
@@ -3562,15 +3546,14 @@ export class AITestHarnessComponent {
|
|
|
3562
3546
|
return parsed.userMessage;
|
|
3563
3547
|
}
|
|
3564
3548
|
// Priority 2: Check for nested userMessage in nextStep or other objects
|
|
3565
|
-
if (parsed.nextStep &&
|
|
3566
|
-
|
|
3549
|
+
if (parsed.nextStep &&
|
|
3550
|
+
parsed.nextStep.userMessage &&
|
|
3551
|
+
typeof parsed.nextStep.userMessage === 'string' &&
|
|
3552
|
+
parsed.nextStep.userMessage.trim()) {
|
|
3567
3553
|
return parsed.nextStep.userMessage;
|
|
3568
3554
|
}
|
|
3569
3555
|
// Priority 3: Other common human-readable fields
|
|
3570
|
-
const contentFields = [
|
|
3571
|
-
'message', 'content', 'response', 'text', 'output',
|
|
3572
|
-
'result', 'answer', 'reply', 'description', 'summary'
|
|
3573
|
-
];
|
|
3556
|
+
const contentFields = ['message', 'content', 'response', 'text', 'output', 'result', 'answer', 'reply', 'description', 'summary'];
|
|
3574
3557
|
for (const field of contentFields) {
|
|
3575
3558
|
if (parsed[field] && typeof parsed[field] === 'string' && parsed[field].trim()) {
|
|
3576
3559
|
return parsed[field];
|
|
@@ -3665,18 +3648,22 @@ export class AITestHarnessComponent {
|
|
|
3665
3648
|
if (Array.isArray(obj)) {
|
|
3666
3649
|
if (obj.length === 0)
|
|
3667
3650
|
return '<span class="json-bracket">[]</span>';
|
|
3668
|
-
const items = obj
|
|
3651
|
+
const items = obj
|
|
3652
|
+
.map((item) => `<div class="json-array-item">${nextIndent}${this.createJsonDisplayHtml(item, depth + 1)}</div>`)
|
|
3653
|
+
.join(',\n');
|
|
3669
3654
|
return `<span class="json-bracket">[</span>\n${items}\n<div class="json-indent">${indent}</div><span class="json-bracket">]</span>`;
|
|
3670
3655
|
}
|
|
3671
3656
|
if (typeof obj === 'object') {
|
|
3672
3657
|
const keys = Object.keys(obj);
|
|
3673
3658
|
if (keys.length === 0)
|
|
3674
3659
|
return '<span class="json-bracket">{}</span>';
|
|
3675
|
-
const properties = keys
|
|
3660
|
+
const properties = keys
|
|
3661
|
+
.map((key) => {
|
|
3676
3662
|
const escapedKey = this.escapeHtml(key);
|
|
3677
3663
|
const value = this.createJsonDisplayHtml(obj[key], depth + 1);
|
|
3678
3664
|
return `<div class="json-property">${nextIndent}<span class="json-key">"${escapedKey}"</span><span class="json-colon">:</span> ${value}</div>`;
|
|
3679
|
-
})
|
|
3665
|
+
})
|
|
3666
|
+
.join(',\n');
|
|
3680
3667
|
return `<span class="json-bracket">{</span>\n${properties}\n<div class="json-indent">${indent}</div><span class="json-bracket">}</span>`;
|
|
3681
3668
|
}
|
|
3682
3669
|
return String(obj);
|
|
@@ -3747,8 +3734,8 @@ export class AITestHarnessComponent {
|
|
|
3747
3734
|
// Split by comma and trim each sequence
|
|
3748
3735
|
this.advancedParams.stopSequences = this.stopSequencesText
|
|
3749
3736
|
.split(',')
|
|
3750
|
-
.map(s => s.trim())
|
|
3751
|
-
.filter(s => s.length > 0);
|
|
3737
|
+
.map((s) => s.trim())
|
|
3738
|
+
.filter((s) => s.length > 0);
|
|
3752
3739
|
}
|
|
3753
3740
|
}
|
|
3754
3741
|
/**
|
|
@@ -3821,12 +3808,16 @@ export class AITestHarnessComponent {
|
|
|
3821
3808
|
const convertedMessages = chatMessages.map((msg, index) => ({
|
|
3822
3809
|
id: `msg-${Date.now()}-${index}`,
|
|
3823
3810
|
role: msg.role,
|
|
3824
|
-
content: typeof msg.content === 'string'
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3811
|
+
content: typeof msg.content === 'string'
|
|
3812
|
+
? msg.content
|
|
3813
|
+
: Array.isArray(msg.content)
|
|
3814
|
+
? msg.content
|
|
3815
|
+
.filter((block) => block.type === 'text')
|
|
3816
|
+
.map((block) => block.content)
|
|
3817
|
+
.join('\n')
|
|
3818
|
+
: '',
|
|
3828
3819
|
timestamp: new Date(),
|
|
3829
|
-
isStreaming: false
|
|
3820
|
+
isStreaming: false,
|
|
3830
3821
|
}));
|
|
3831
3822
|
console.log('🎯 Converted messages for test harness:', convertedMessages);
|
|
3832
3823
|
this.conversationMessages = convertedMessages;
|
|
@@ -3912,5 +3903,5 @@ export class AITestHarnessComponent {
|
|
|
3912
3903
|
type: ViewChild,
|
|
3913
3904
|
args: ['saveDialogInput']
|
|
3914
3905
|
}] }); })();
|
|
3915
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber:
|
|
3906
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber: 178 }); })();
|
|
3916
3907
|
//# sourceMappingURL=ai-test-harness.component.js.map
|