File size: 6,121 Bytes
a8df6b3
 
 
 
 
9f54287
 
 
 
 
 
a8df6b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9f54287
 
 
 
 
 
 
a8df6b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2254920
a8df6b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2254920
a8df6b3
2254920
 
a8df6b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

// ============================================================================
// AGENT TRAJECTORY - Chat Interface
// ============================================================================

const SCENARIO_DESCRIPTIONS = {
    'mimic': 'Exploring clinical patterns and patient outcomes in a large-scale electronic health record (EHR) database.',
    '10k': 'Extracting deep insights from SEC 10-K annual reports for longitudinal financial performance analysis.',
    'globem': 'Analyzing multi-modal longitudinal behavioral and sensor data for detecting mental health trends.'
};

let currentTrajScenario = 'mimic';

function initTrajectory() {
    if (typeof TRAJECTORY_DATA === 'undefined') {
        setTimeout(initTrajectory, 500); // Wait for data load
        return;
    }

    // Configure marked with highlight.js
    if (typeof marked !== 'undefined') {
        marked.setOptions({
            highlight: function (code, lang) {
                // Auto Format SQL
                if (lang === 'sql' && typeof sqlFormatter !== 'undefined') {
                    try {
                        code = sqlFormatter.format(code, { language: 'sql', indent: '  ' });
                    } catch (e) {
                        console.warn('SQL Formatting failed:', e);
                    }
                }

                // Highlight
                if (lang && hljs.getLanguage(lang)) {
                    return hljs.highlight(code, { language: lang }).value;
                }
                return hljs.highlightAuto(code).value;
            },
            breaks: true,
            langPrefix: 'hljs language-' // Ensure .hljs class is added for themes
        });
    }

    // Setup toggle buttons
    document.querySelectorAll('[data-traj-scenario]').forEach(btn => {
        btn.addEventListener('click', () => {
            document.querySelectorAll('[data-traj-scenario]').forEach(b => b.classList.remove('active'));
            btn.classList.add('active');
            currentTrajScenario = btn.dataset.trajScenario;

            // Update description
            const descEl = document.getElementById('trajectory-scenario-description');
            if (descEl && SCENARIO_DESCRIPTIONS[currentTrajScenario]) {
                descEl.textContent = SCENARIO_DESCRIPTIONS[currentTrajScenario];
            }

            renderTrajectory(currentTrajScenario);
        });
    });

    // Initial Render
    renderTrajectory('mimic');
}

function renderTrajectory(scenario) {
    const container = document.getElementById('chat-window');
    const messages = TRAJECTORY_DATA[scenario];

    if (!container || !messages) return;

    container.innerHTML = '';

    messages.forEach((msg, index) => {
        const msgDiv = document.createElement('div');
        msgDiv.className = `chat-message role-${msg.role}`;

        // Role Label
        const roleLabel = document.createElement('div');
        roleLabel.className = 'message-role-label';
        // Capitalize 
        roleLabel.textContent = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);
        if (msg.role === 'user') roleLabel.textContent = 'User Prompt';
        msgDiv.appendChild(roleLabel);

        // Bubble
        const bubble = document.createElement('div');
        bubble.className = 'message-bubble';

        // Parse Markdown
        let htmlContent = '';
        if (typeof marked !== 'undefined') {
            htmlContent = marked.parse(msg.content);
        } else {
            // Fallback
            htmlContent = escapeHtml(msg.content).replace(/\n/g, '<br>');
        }

        const contentDiv = document.createElement('div');
        contentDiv.innerHTML = htmlContent;
        bubble.appendChild(contentDiv);
        msgDiv.appendChild(bubble);
        container.appendChild(msgDiv); // Append to DOM to calculate height

        // Height Check (Post-render)
        // 3 lines is approx 80-100px.
        const COLLAPSE_HEIGHT = 200;
        const isLastMessage = (index === messages.length - 1);

        // Only apply collapse logic if NOT the last message
        if (!isLastMessage && contentDiv.scrollHeight > COLLAPSE_HEIGHT + 20) {
            contentDiv.style.cssText = `max-height: ${COLLAPSE_HEIGHT}px; overflow: hidden; position: relative; mask-image: linear-gradient(to bottom, black 60%, transparent 100%); -webkit-mask-image: linear-gradient(to bottom, black 60%, transparent 100%);`;

            const btn = document.createElement('button');
            btn.textContent = 'Show More';
            btn.style.cssText = 'display:block; margin: 8px auto 0; border:none; background: rgba(0,0,0,0.05); color: #0071e3; border-radius: 12px; padding: 4px 12px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s;';

            if (msg.role === 'agent') {
                btn.style.background = 'rgba(255,255,255,0.2)';
                btn.style.color = 'white';
            }

            btn.onclick = () => {
                if (contentDiv.style.maxHeight !== 'none') {
                    // Expand
                    contentDiv.style.maxHeight = 'none';
                    contentDiv.style.maskImage = 'none';
                    contentDiv.style.webkitMaskImage = 'none';
                    btn.textContent = 'Show Less';
                } else {
                    // Collapse
                    contentDiv.style.maxHeight = `${COLLAPSE_HEIGHT}px`;
                    contentDiv.style.maskImage = 'linear-gradient(to bottom, black 60%, transparent 100%)';
                    contentDiv.style.webkitMaskImage = 'linear-gradient(to bottom, black 60%, transparent 100%)';
                    btn.textContent = 'Show More';
                }
            };

            bubble.appendChild(btn);
        }
    });

    container.scrollTop = 0;
}

function escapeHtml(text) {
    if (!text) return '';
    return text
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

document.addEventListener('DOMContentLoaded', () => {
    initTrajectory();
});