feat: structured artifact rendering, UX improvements

- Render structured artifacts from agent results with type-aware
  formatting: code blocks with syntax highlighting and copy button,
  terminal-style command output, search result cards, and text findings
- Make FinalResult panel collapsible (default collapsed) with scrollable
  content (max-h-96) to prevent dominating the chat view
- Add clickable URL detection in summaries and artifact content
- Fix code block contrast for both light and dark mode
- Animate progress bar with pulse ring on active step and gradient
  shimmer on connecting lines
- Fix tab-switching bug: use module-level orchestrationStore singleton
  so orchestration state survives route navigation
- Remove sample/demo data seeding and clean up persisted localStorage
  entries from previous sample sessions
- Remove showSampleBadge prop from PageHeader
- Regenerate proto types for new Artifact message and ArtifactType enum
- Update README project structure (remove deleted data/ directory)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shahondin1624
2026-03-12 23:13:33 +01:00
parent cfd338028a
commit 2c6c961e08
17 changed files with 456 additions and 346 deletions

View File

@@ -6,7 +6,7 @@ import { OrchestrationState } from '$lib/proto/llm_multiverse/v1/orchestrator_pb
import { sessionStore } from '$lib/stores/sessions.svelte';
import { memoryStore } from '$lib/stores/memory.svelte';
import { auditStore } from '$lib/stores/audit.svelte';
import { toastStore } from '$lib/stores/toast.svelte';
import { logger } from '$lib/utils/logger';
export function createOrchestration() {
let isStreaming = $state(false);
@@ -57,6 +57,10 @@ export function createOrchestration() {
if (response.state !== lastAuditState) {
const stateLabel = OrchestrationState[response.state] ?? String(response.state);
logger.debug('useOrchestration', `State: ${stateLabel}`, {
sessionId,
state: response.state
});
auditStore.addEvent(sessionId, {
eventType: 'state_change',
details: response.message || `State changed to ${stateLabel}`,
@@ -88,21 +92,27 @@ export function createOrchestration() {
};
}
} catch (err) {
const friendlyMsg =
err instanceof OrchestratorError
? friendlyMessage(err.code)
: 'An unexpected error occurred';
error = friendlyMsg;
const isOrcErr = err instanceof OrchestratorError;
const code = isOrcErr ? err.code : 'unknown';
const details = isOrcErr ? err.details : undefined;
const friendlyMsg = isOrcErr
? friendlyMessage(err.code)
: 'An unexpected error occurred';
const displayMsg =
code && code !== 'unknown'
? `${friendlyMsg} (${code})`
: friendlyMsg;
error = displayMsg;
lastFailedContent = content;
toastStore.addToast({ message: friendlyMsg, type: 'error' });
logger.error('useOrchestration', 'Request failed', { code, details });
auditStore.addEvent(sessionId, {
eventType: 'error',
details: friendlyMsg
details: `${friendlyMsg} | code=${code}${details ? ` | details=${details}` : ''}`
});
const idx = messages.length - 1;
messages[idx] = {
...messages[idx],
content: `\u26A0 ${friendlyMsg}`
content: `\u26A0 ${displayMsg}`
};
} finally {
isStreaming = false;
@@ -149,3 +159,9 @@ export function createOrchestration() {
reset
};
}
/**
* Module-level singleton so orchestration state survives tab/route changes.
* The chat page uses this instead of calling createOrchestration() per mount.
*/
export const orchestrationStore = createOrchestration();