' +
apiEndpointsHtml;
if (window.lucide) lucide.createIcons();
}
// ========== CCW Section (Right Column) ==========
function renderCcwSection() {
var container = document.getElementById('ccw-section');
if (!container) return;
var installationsHtml = '';
if (ccwInstallations.length === 0) {
installationsHtml = '
' +
'' +
'
' + t('ccw.noInstallations') + '
' +
'' +
'
';
} else {
installationsHtml = '
';
for (var i = 0; i < ccwInstallations.length; i++) {
var inst = ccwInstallations[i];
var isGlobal = inst.installation_mode === 'Global';
var modeIcon = isGlobal ? 'home' : 'folder';
var version = inst.application_version || 'unknown';
var installDate = new Date(inst.installation_date).toLocaleDateString();
installationsHtml += '
';
}
// Usage example
var usageExample = 'ccw tool exec ' + name;
if (propKeys.length > 0) {
var exampleParams = {};
for (var j = 0; j < Math.min(propKeys.length, 2); j++) {
var k = propKeys[j];
var p = properties[k];
if (p.type === 'string') exampleParams[k] = '';
else if (p.type === 'boolean') exampleParams[k] = true;
else if (p.type === 'number') exampleParams[k] = 0;
else exampleParams[k] = '';
}
usageExample += " '" + JSON.stringify(exampleParams) + "'";
}
var modalContent = '
' +
'
' +
'
' +
'
' +
'
' + escapeHtml(name) + '
' +
'endpoint tool' +
'
' +
'
' +
'
' + escapeHtml(desc) + '
' +
paramsHtml +
'
' +
'
Usage Example
' +
'
' +
'' + escapeHtml(usageExample) + '' +
'' +
'
' +
'
' +
'
';
showModal(name, modalContent, { size: 'lg' });
}
function copyToolUsage(btn, text) {
navigator.clipboard.writeText(text).then(function() {
var icon = btn.querySelector('i');
if (icon) {
icon.setAttribute('data-lucide', 'check');
if (window.lucide) lucide.createIcons();
setTimeout(function() {
icon.setAttribute('data-lucide', 'copy');
if (window.lucide) lucide.createIcons();
}, 2000);
}
});
}
// CCW Install Carousel State
var ccwCarouselIndex = 0;
function renderCcwInstallPanel() {
var container = document.getElementById('ccw-install-panel');
if (!container) return;
var html = '
CCW Installations
' +
'
' +
'' +
'' +
'
' +
'
';
if (ccwInstallations.length === 0) {
html += '
' +
'' +
'
No installations found
' +
'
';
} else {
// Carousel container
html += '
';
// Left arrow (show only if more than 1 installation)
if (ccwInstallations.length > 1) {
html += '';
}
html += '
';
for (var i = 0; i < ccwInstallations.length; i++) {
var inst = ccwInstallations[i];
var isGlobal = inst.installation_mode === 'Global';
var modeIcon = isGlobal ? 'home' : 'folder';
var version = inst.application_version || 'unknown';
var installDate = new Date(inst.installation_date).toLocaleDateString();
var activeClass = i === ccwCarouselIndex ? 'active' : '';
html += '
';
// Right arrow (show only if more than 1 installation)
if (ccwInstallations.length > 1) {
html += '';
}
html += '
';
// Dots indicator (show only if more than 1 installation)
if (ccwInstallations.length > 1) {
html += '
';
for (var j = 0; j < ccwInstallations.length; j++) {
var dotActive = j === ccwCarouselIndex ? 'active' : '';
html += '';
}
html += '
';
}
}
html += '
';
container.innerHTML = html;
if (window.lucide) lucide.createIcons();
// Update carousel position
updateCcwCarouselPosition();
}
function ccwCarouselPrev() {
if (ccwCarouselIndex > 0) {
ccwCarouselIndex--;
updateCcwCarouselPosition();
updateCcwCarouselDots();
}
}
function ccwCarouselNext() {
if (ccwCarouselIndex < ccwInstallations.length - 1) {
ccwCarouselIndex++;
updateCcwCarouselPosition();
updateCcwCarouselDots();
}
}
function ccwCarouselGoTo(index) {
ccwCarouselIndex = index;
updateCcwCarouselPosition();
updateCcwCarouselDots();
}
function updateCcwCarouselPosition() {
var track = document.getElementById('ccwCarouselTrack');
if (track) {
track.style.transform = 'translateX(-' + (ccwCarouselIndex * 100) + '%)';
}
// Update card active states
var cards = document.querySelectorAll('.ccw-carousel-card');
cards.forEach(function(card, idx) {
card.classList.toggle('active', idx === ccwCarouselIndex);
});
}
function updateCcwCarouselDots() {
var dots = document.querySelectorAll('.ccw-carousel-dot');
dots.forEach(function(dot, idx) {
dot.classList.toggle('active', idx === ccwCarouselIndex);
});
}
// CCW Install Modal
function showCcwInstallModal() {
var modalContent = '
' +
'
' +
'
' +
'
' +
'
' +
'
Global Installation
' +
'
Install to user home directory (~/.claude)
' +
'
' +
'' +
'
' +
'
' +
'
' +
'
' +
'
Path Installation
' +
'
Install to a specific project folder
' +
'
' +
'' +
'
' +
'
' +
'
' +
'
' +
'' +
'' +
'
' +
'
' +
'' +
'
' +
'
' +
'
';
showModal('Install CCW', modalContent);
}
function selectCcwInstallMode(mode) {
if (mode === 'Global') {
closeModal();
runCcwInstall('Global');
}
}
function toggleCcwPathInput() {
var section = document.getElementById('ccwPathInputSection');
if (section) {
section.classList.toggle('hidden');
if (!section.classList.contains('hidden')) {
var input = document.getElementById('ccwInstallPath');
if (input) input.focus();
}
}
}
function executeCcwInstall() {
var input = document.getElementById('ccwInstallPath');
var path = input ? input.value.trim() : '';
if (!path) {
showRefreshToast('Please enter a path', 'error');
return;
}
closeModal();
runCcwInstall('Path', path);
}
function truncatePath(path) {
if (!path) return '';
var maxLen = 35;
if (path.length <= maxLen) return path;
return '...' + path.slice(-maxLen + 3);
}
function renderCliExecutePanel() {
var container = document.getElementById('cli-execute-panel');
if (!container) return;
var tools = ['gemini', 'qwen', 'codex'];
var modes = ['analysis', 'write', 'auto'];
var html = '
Quick Execute
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
';
container.innerHTML = html;
if (window.lucide) lucide.createIcons();
}
// ========== CCW Actions ==========
function runCcwInstall(mode, customPath) {
var command;
if (mode === 'Global') {
command = 'ccw install --mode Global';
} else {
var installPath = customPath || projectPath;
command = 'ccw install --mode Path --path "' + installPath + '"';
}
// Copy command to clipboard
if (navigator.clipboard) {
navigator.clipboard.writeText(command).then(function() {
showRefreshToast('Command copied: ' + command, 'success');
}).catch(function() {
showRefreshToast('Run: ' + command, 'info');
});
} else {
showRefreshToast('Run: ' + command, 'info');
}
}
async function runCcwUpgrade() {
showRefreshToast(t('ccw.upgradeStarting'), 'info');
try {
var response = await fetch('/api/ccw/upgrade', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
});
var result = await response.json();
if (result.success) {
showRefreshToast(t('ccw.upgradeCompleted'), 'success');
// Reload installations after upgrade
setTimeout(function() {
loadCcwInstallations().then(function() {
renderCcwInstallPanel();
});
}, 1000);
} else {
showRefreshToast(t('ccw.upgradeFailed', { error: result.error || 'Unknown error' }), 'error');
}
} catch (err) {
showRefreshToast(t('ccw.upgradeFailed', { error: err.message }), 'error');
}
}
function confirmCcwUninstall(installPath) {
if (confirm(t('ccw.uninstallConfirm') + '\n' + (installPath || 'Current installation'))) {
var command = installPath
? 'ccw uninstall --path "' + installPath + '"'
: 'ccw uninstall';
if (navigator.clipboard) {
navigator.clipboard.writeText(command).then(function() {
showRefreshToast('Command copied: ' + command, 'success');
}).catch(function() {
showRefreshToast('Run: ' + command, 'info');
});
} else {
showRefreshToast('Run: ' + command, 'info');
}
}
}
// ========== Execution ==========
async function executeCliFromDashboard() {
var toolEl = document.getElementById('cli-exec-tool');
var modeEl = document.getElementById('cli-exec-mode');
var promptEl = document.getElementById('cli-exec-prompt');
var tool = toolEl ? toolEl.value : 'gemini';
var mode = modeEl ? modeEl.value : 'analysis';
var prompt = promptEl ? promptEl.value.trim() : '';
if (!prompt) {
showRefreshToast(t('toast.enterPrompt'), 'error');
return;
}
currentCliExecution = { tool: tool, mode: mode, prompt: prompt, startTime: Date.now() };
cliExecutionOutput = '';
var outputPanel = document.getElementById('cli-output-panel');
var outputContent = document.getElementById('cli-output-content');
var statusIndicator = document.getElementById('cli-output-status-indicator');
var statusText = document.getElementById('cli-output-status-text');
if (outputPanel) outputPanel.classList.remove('hidden');
if (outputContent) outputContent.textContent = '';
if (statusIndicator) statusIndicator.className = 'status-indicator running';
if (statusText) statusText.textContent = 'Running...';
var execBtn = document.querySelector('.cli-execute-actions .btn-primary');
if (execBtn) execBtn.disabled = true;
try {
var response = await fetch('/api/cli/execute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tool: tool,
mode: mode,
prompt: prompt,
dir: projectPath,
format: promptConcatFormat,
smartContext: {
enabled: smartContextEnabled,
maxFiles: smartContextMaxFiles
}
})
});
var result = await response.json();
if (statusIndicator) statusIndicator.className = 'status-indicator ' + (result.success ? 'success' : 'error');
if (statusText) {
var duration = formatDuration(result.execution ? result.execution.duration_ms : (Date.now() - currentCliExecution.startTime));
statusText.textContent = result.success ? 'Completed in ' + duration : 'Failed: ' + (result.error || 'Unknown');
}
await loadCliHistory();
renderCliHistory();
showRefreshToast(result.success ? t('toast.completed') : (result.error || t('toast.failed')), result.success ? 'success' : 'error');
} catch (error) {
if (statusIndicator) statusIndicator.className = 'status-indicator error';
if (statusText) statusText.textContent = 'Error: ' + error.message;
showRefreshToast(t('toast.error', { error: error.message }), 'error');
}
currentCliExecution = null;
if (execBtn) execBtn.disabled = false;
}
// ========== WebSocket Event Handlers ==========
function handleCliExecutionStarted(payload) {
currentCliExecution = {
executionId: payload.executionId,
tool: payload.tool,
mode: payload.mode,
startTime: new Date(payload.timestamp).getTime()
};
cliExecutionOutput = '';
// Show toast notification
if (typeof addGlobalNotification === 'function') {
addGlobalNotification('info', 'CLI ' + payload.tool + ' started', payload.mode + ' mode', 'CLI');
}
if (currentView === 'cli-manager') {
var outputPanel = document.getElementById('cli-output-panel');
var outputContent = document.getElementById('cli-output-content');
var statusIndicator = document.getElementById('cli-output-status-indicator');
var statusText = document.getElementById('cli-output-status-text');
if (outputPanel) outputPanel.classList.remove('hidden');
if (outputContent) outputContent.textContent = '';
if (statusIndicator) statusIndicator.className = 'status-indicator running';
if (statusText) statusText.textContent = 'Running ' + payload.tool + ' (' + payload.mode + ')...';
}
}
function handleCliOutput(payload) {
cliExecutionOutput += payload.data;
var outputContent = document.getElementById('cli-output-content');
if (outputContent) {
outputContent.textContent = cliExecutionOutput;
outputContent.scrollTop = outputContent.scrollHeight;
}
}
function handleCliExecutionCompleted(payload) {
var statusIndicator = document.getElementById('cli-output-status-indicator');
var statusText = document.getElementById('cli-output-status-text');
if (statusIndicator) statusIndicator.className = 'status-indicator ' + (payload.success ? 'success' : 'error');
if (statusText) statusText.textContent = payload.success ? 'Completed in ' + formatDuration(payload.duration_ms) : 'Failed: ' + payload.status;
// Show toast notification
if (typeof addGlobalNotification === 'function') {
if (payload.success) {
addGlobalNotification('success', 'CLI execution completed', formatDuration(payload.duration_ms), 'CLI');
} else {
addGlobalNotification('error', 'CLI execution failed', payload.status, 'CLI');
}
}
currentCliExecution = null;
if (currentView === 'cli-manager') {
loadCliHistory().then(function() { renderCliHistory(); });
}
}
function handleCliExecutionError(payload) {
var statusIndicator = document.getElementById('cli-output-status-indicator');
var statusText = document.getElementById('cli-output-status-text');
if (statusIndicator) statusIndicator.className = 'status-indicator error';
if (statusText) statusText.textContent = 'Error: ' + payload.error;
// Show toast notification
if (typeof addGlobalNotification === 'function') {
addGlobalNotification('error', 'CLI execution error', payload.error, 'CLI');
}
currentCliExecution = null;
}
// ========== CLI Tool Install/Uninstall Wizards ==========
function openCliInstallWizard(toolName) {
var toolDescriptions = {
gemini: 'Google AI for code analysis and generation',
qwen: 'Alibaba AI assistant for coding',
codex: 'OpenAI code generation and understanding',
claude: 'Anthropic AI assistant'
};
var toolPackages = {
gemini: '@google/gemini-cli',
qwen: '@qwen-code/qwen-code',
codex: '@openai/codex',
claude: '@anthropic-ai/claude-code'
};
var modal = document.createElement('div');
modal.id = 'cliInstallModal';
modal.className = 'fixed inset-0 bg-black/50 flex items-center justify-center z-50';
modal.innerHTML =
'