Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ui/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ export function setupRoutes(app, isAuthenticated, dependencies) {
// API endpoint to get configuration (including default docker image)
app.get('/api/config', isAuthenticated, (req, res) => {
return res.json({
dockerImage: process.env.DOCKER_IMAGE || 'ghcr.io/manticoresoftware/manticoresearch:test-kit-latest'
dockerImage: process.env.DOCKER_IMAGE || 'ghcr.io/manticoresoftware/manticoresearch:test-kit-latest',
askAiEnabled: !!process.env.ASK_AI_COMMAND
});
});

Expand Down
33 changes: 19 additions & 14 deletions ui/src/components/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
}
}

// Fetch default docker image from backend config
async function loadDefaultImage() {
let askAiEnabled = false;

// Fetch config from backend (default docker image, feature flags)
async function loadConfig() {
try {
const response = await fetch(`${API_URL}/api/config`, {
credentials: 'include'
Expand All @@ -37,9 +39,10 @@
if (config.dockerImage) {
defaultImage = config.dockerImage;
}
askAiEnabled = !!config.askAiEnabled;
}
} catch (error) {
console.error('Failed to load default docker image:', error);
console.error('Failed to load config:', error);
}
}

Expand Down Expand Up @@ -73,7 +76,7 @@
// Fetch auth state when component mounts and initialize git status
onMount(() => {
fetchAuthState();
loadDefaultImage(); // Load default docker image from backend
loadConfig();

// Initialize git status polling with immediate fetch
gitStatusStore.fetchGitStatus().then(() => {
Expand Down Expand Up @@ -159,16 +162,18 @@

<div class="user-profile">
{#if $authStore.isAuthenticated && !$authStore.isLoading}
<button
class="interactive-button"
on:click={openInteractiveSession}
title="Ask AI"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
Ask AI
</button>
{#if askAiEnabled}
<button
class="interactive-button"
on:click={openInteractiveSession}
title="Ask AI"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
Ask AI
</button>
{/if}

<!-- Create PR Link - only show when no existing PR and has changes -->
{#if showCreatePrLink}
Expand Down
3 changes: 2 additions & 1 deletion ui/src/stores/filesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ function createFilesStore() {
// Process final results using same logic as original implementation
if (status.testStructure) {
console.log('🔍 Processing final enriched testStructure with actual outputs');
const testFailed = !status.success || status.exitCode !== 0;

update(state => {
if (!state.currentFile?.testStructure) return state;
Expand All @@ -712,7 +713,7 @@ function createFilesStore() {
const processedStep = {
...step,
actualOutput: step.actualOutput || '',
status: step.status || 'success',
status: step.status || (testFailed ? 'failed' : 'success'),
error: step.error || false
};

Expand Down
16 changes: 16 additions & 0 deletions ui/testRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,22 @@ export function setupTestRoutes(app, isAuthenticated, dependencies) {
const hasProcessError = testInfo.exitCode !== 0;
const overallStatus = hasValidationErrors || hasProcessError ? 'failed' : 'completed';

// Mark unresolved steps as failed when the process itself errored (e.g. command not found, exit 127)
if (hasProcessError && testStructure?.steps) {
function markUnresolvedStepsFailed(steps) {
steps.forEach(step => {
if (!step.status) {
step.status = 'failed';
step.error = true;
}
if (step.steps?.length > 0) {
markUnresolvedStepsFailed(step.steps);
}
});
}
markUnresolvedStepsFailed(testStructure.steps);
}

// Return final results
return res.json({
running: false,
Expand Down