claude-code-workflow 6.3.26 → 6.3.28
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/.claude/CLAUDE.md +7 -1
- package/.claude/agents/action-planning-agent.md +1 -0
- package/.claude/agents/cli-discuss-agent.md +391 -0
- package/.claude/agents/cli-execution-agent.md +2 -0
- package/.claude/agents/cli-explore-agent.md +2 -1
- package/.claude/agents/cli-lite-planning-agent.md +1 -0
- package/.claude/agents/cli-planning-agent.md +1 -0
- package/.claude/agents/code-developer.md +1 -0
- package/.claude/agents/conceptual-planning-agent.md +2 -0
- package/.claude/agents/context-search-agent.md +1 -0
- package/.claude/agents/debug-explore-agent.md +2 -0
- package/.claude/agents/doc-generator.md +1 -0
- package/.claude/agents/issue-plan-agent.md +2 -1
- package/.claude/agents/issue-queue-agent.md +2 -1
- package/.claude/agents/memory-bridge.md +2 -0
- package/.claude/agents/test-context-search-agent.md +2 -0
- package/.claude/agents/test-fix-agent.md +1 -0
- package/.claude/agents/ui-design-agent.md +2 -0
- package/.claude/agents/universal-executor.md +1 -0
- package/.claude/commands/issue/execute.md +141 -163
- package/.claude/commands/workflow/lite-lite-lite.md +798 -0
- package/.claude/commands/workflow/multi-cli-plan.md +510 -0
- package/.claude/skills/ccw/SKILL.md +262 -372
- package/.claude/skills/ccw/command.json +547 -0
- package/.claude/skills/ccw-help/SKILL.md +46 -107
- package/.claude/skills/ccw-help/command.json +511 -0
- package/.claude/skills/skill-tuning/SKILL.md +303 -0
- package/.claude/skills/skill-tuning/phases/actions/action-abort.md +164 -0
- package/.claude/skills/skill-tuning/phases/actions/action-analyze-requirements.md +406 -0
- package/.claude/skills/skill-tuning/phases/actions/action-apply-fix.md +206 -0
- package/.claude/skills/skill-tuning/phases/actions/action-complete.md +195 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-agent.md +317 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-context.md +243 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-dataflow.md +318 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-docs.md +299 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-memory.md +269 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-token-consumption.md +200 -0
- package/.claude/skills/skill-tuning/phases/actions/action-gemini-analysis.md +322 -0
- package/.claude/skills/skill-tuning/phases/actions/action-generate-report.md +228 -0
- package/.claude/skills/skill-tuning/phases/actions/action-init.md +149 -0
- package/.claude/skills/skill-tuning/phases/actions/action-propose-fixes.md +317 -0
- package/.claude/skills/skill-tuning/phases/actions/action-verify.md +222 -0
- package/.claude/skills/skill-tuning/phases/orchestrator.md +377 -0
- package/.claude/skills/skill-tuning/phases/state-schema.md +378 -0
- package/.claude/skills/skill-tuning/specs/category-mappings.json +284 -0
- package/.claude/skills/skill-tuning/specs/dimension-mapping.md +212 -0
- package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +318 -0
- package/.claude/skills/skill-tuning/specs/quality-gates.md +263 -0
- package/.claude/skills/skill-tuning/specs/skill-authoring-principles.md +189 -0
- package/.claude/skills/skill-tuning/specs/tuning-strategies.md +1537 -0
- package/.claude/skills/skill-tuning/templates/diagnosis-report.md +153 -0
- package/.claude/skills/skill-tuning/templates/fix-proposal.md +204 -0
- package/.claude/workflows/cli-templates/schemas/multi-cli-discussion-schema.json +421 -0
- package/.claude/workflows/cli-tools-usage.md +0 -41
- package/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -1
- package/ccw/dist/core/auth/csrf-middleware.js +3 -1
- package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
- package/ccw/dist/core/data-aggregator.d.ts +2 -0
- package/ccw/dist/core/data-aggregator.d.ts.map +1 -1
- package/ccw/dist/core/data-aggregator.js +5 -2
- package/ccw/dist/core/data-aggregator.js.map +1 -1
- package/ccw/dist/core/lite-scanner.d.ts +2 -1
- package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
- package/ccw/dist/core/lite-scanner.js +295 -6
- package/ccw/dist/core/lite-scanner.js.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.js +5 -5
- package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -1
- package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/session-routes.js +166 -48
- package/ccw/dist/core/routes/session-routes.js.map +1 -1
- package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/system-routes.js +87 -0
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/dist/core/server.js +2 -2
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/scripts/IMPLEMENTATION-SUMMARY.md +226 -0
- package/ccw/scripts/QUICK-REFERENCE.md +135 -0
- package/ccw/scripts/README-memory-embedder.md +157 -0
- package/ccw/scripts/__pycache__/memory_embedder.cpython-313.pyc +0 -0
- package/ccw/scripts/__pycache__/test_memory_embedder.cpython-313-pytest-8.4.2.pyc +0 -0
- package/ccw/scripts/memory-embedder-example.ts +184 -0
- package/ccw/scripts/memory_embedder.py +428 -0
- package/ccw/scripts/test_memory_embedder.py +245 -0
- package/ccw/src/core/auth/csrf-middleware.ts +3 -1
- package/ccw/src/core/data-aggregator.ts +7 -2
- package/ccw/src/core/lite-scanner.ts +440 -6
- package/ccw/src/core/routes/codexlens/config-handlers.ts +12 -9
- package/ccw/src/core/routes/session-routes.ts +201 -48
- package/ccw/src/core/routes/system-routes.ts +102 -0
- package/ccw/src/core/server.ts +2 -2
- package/ccw/src/templates/dashboard-css/01-base.css +8 -0
- package/ccw/src/templates/dashboard-css/02-session.css +81 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +2442 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +157 -0
- package/ccw/src/templates/dashboard-css/32-issue-manager.css +23 -0
- package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +38 -4
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +38 -13
- package/ccw/src/templates/dashboard-js/components/navigation.js +24 -4
- package/ccw/src/templates/dashboard-js/i18n.js +194 -6
- package/ccw/src/templates/dashboard-js/views/api-settings.js +32 -0
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +44 -3
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +303 -31
- package/ccw/src/templates/dashboard-js/views/history.js +44 -6
- package/ccw/src/templates/dashboard-js/views/home.js +1 -0
- package/ccw/src/templates/dashboard-js/views/issue-manager.js +54 -7
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +1817 -4
- package/ccw/src/templates/dashboard.html +5 -0
- package/package.json +2 -1
- package/.claude/skills/ccw/index/command-capabilities.json +0 -127
- package/.claude/skills/ccw/index/intent-rules.json +0 -136
- package/.claude/skills/ccw/index/workflow-chains.json +0 -451
- package/.claude/skills/ccw/phases/actions/bugfix.md +0 -218
- package/.claude/skills/ccw/phases/actions/coupled.md +0 -194
- package/.claude/skills/ccw/phases/actions/docs.md +0 -93
- package/.claude/skills/ccw/phases/actions/full.md +0 -154
- package/.claude/skills/ccw/phases/actions/issue.md +0 -201
- package/.claude/skills/ccw/phases/actions/rapid.md +0 -104
- package/.claude/skills/ccw/phases/actions/review-fix.md +0 -84
- package/.claude/skills/ccw/phases/actions/tdd.md +0 -66
- package/.claude/skills/ccw/phases/actions/ui.md +0 -79
- package/.claude/skills/ccw/phases/orchestrator.md +0 -435
- package/.claude/skills/ccw/specs/intent-classification.md +0 -336
- package/.claude/skills/ccw-help/index/all-agents.json +0 -82
- package/.claude/skills/ccw-help/index/all-commands.json +0 -882
- package/.claude/skills/ccw-help/index/by-category.json +0 -914
- package/.claude/skills/ccw-help/index/by-use-case.json +0 -896
- package/.claude/skills/ccw-help/index/command-relationships.json +0 -160
- package/.claude/skills/ccw-help/index/essential-commands.json +0 -112
|
@@ -395,6 +395,10 @@ async function updateCliToolConfig(tool, updates) {
|
|
|
395
395
|
}
|
|
396
396
|
if (data.success && cliToolConfig && cliToolConfig.tools) {
|
|
397
397
|
cliToolConfig.tools[tool] = data.config;
|
|
398
|
+
// Invalidate cache to ensure fresh data on page refresh
|
|
399
|
+
if (window.cacheManager) {
|
|
400
|
+
window.cacheManager.invalidate('cli-config');
|
|
401
|
+
}
|
|
398
402
|
}
|
|
399
403
|
return data;
|
|
400
404
|
} catch (err) {
|
|
@@ -554,6 +558,298 @@ function buildToolConfigModalContent(tool, config, models, status) {
|
|
|
554
558
|
'</div>';
|
|
555
559
|
}
|
|
556
560
|
|
|
561
|
+
// ========== File Browser Modal ==========
|
|
562
|
+
|
|
563
|
+
var fileBrowserState = {
|
|
564
|
+
currentPath: '',
|
|
565
|
+
showHidden: false,
|
|
566
|
+
onSelect: null
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
function showFileBrowserModal(onSelect) {
|
|
570
|
+
fileBrowserState.onSelect = onSelect;
|
|
571
|
+
fileBrowserState.showHidden = false;
|
|
572
|
+
|
|
573
|
+
// Create modal overlay
|
|
574
|
+
var overlay = document.createElement('div');
|
|
575
|
+
overlay.id = 'fileBrowserOverlay';
|
|
576
|
+
overlay.className = 'modal-overlay';
|
|
577
|
+
overlay.innerHTML = buildFileBrowserModalContent();
|
|
578
|
+
document.body.appendChild(overlay);
|
|
579
|
+
|
|
580
|
+
// Load initial directory (home)
|
|
581
|
+
loadFileBrowserDirectory('');
|
|
582
|
+
|
|
583
|
+
// Initialize events
|
|
584
|
+
initFileBrowserEvents();
|
|
585
|
+
|
|
586
|
+
// Initialize icons
|
|
587
|
+
if (window.lucide) lucide.createIcons();
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function buildFileBrowserModalContent() {
|
|
591
|
+
// Detect if Windows
|
|
592
|
+
var isWindows = navigator.platform.indexOf('Win') > -1;
|
|
593
|
+
var driveButtons = '';
|
|
594
|
+
if (isWindows) {
|
|
595
|
+
driveButtons = '<div class="file-browser-drives">' +
|
|
596
|
+
'<button class="btn-xs btn-outline drive-btn" data-drive="C:/">C:</button>' +
|
|
597
|
+
'<button class="btn-xs btn-outline drive-btn" data-drive="D:/">D:</button>' +
|
|
598
|
+
'<button class="btn-xs btn-outline drive-btn" data-drive="E:/">E:</button>' +
|
|
599
|
+
'</div>';
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return '<div class="modal-content file-browser-modal">' +
|
|
603
|
+
'<div class="modal-header">' +
|
|
604
|
+
'<h3><i data-lucide="folder-open" class="w-4 h-4"></i> ' + t('cli.fileBrowser') + '</h3>' +
|
|
605
|
+
'<button class="modal-close" id="fileBrowserCloseBtn">×</button>' +
|
|
606
|
+
'</div>' +
|
|
607
|
+
'<div class="modal-body">' +
|
|
608
|
+
'<div class="file-browser-toolbar">' +
|
|
609
|
+
'<button class="btn-sm btn-outline" id="fileBrowserUpBtn" title="' + t('cli.fileBrowserUp') + '">' +
|
|
610
|
+
'<i data-lucide="arrow-up" class="w-3.5 h-3.5"></i>' +
|
|
611
|
+
'</button>' +
|
|
612
|
+
'<button class="btn-sm btn-outline" id="fileBrowserHomeBtn" title="' + t('cli.fileBrowserHome') + '">' +
|
|
613
|
+
'<i data-lucide="home" class="w-3.5 h-3.5"></i>' +
|
|
614
|
+
'</button>' +
|
|
615
|
+
driveButtons +
|
|
616
|
+
'<input type="text" id="fileBrowserPathInput" class="file-browser-path" placeholder="Enter path and press Enter" />' +
|
|
617
|
+
'<label class="file-browser-hidden-toggle">' +
|
|
618
|
+
'<input type="checkbox" id="fileBrowserShowHidden" checked />' +
|
|
619
|
+
'<span>' + t('cli.fileBrowserShowHidden') + '</span>' +
|
|
620
|
+
'</label>' +
|
|
621
|
+
'</div>' +
|
|
622
|
+
'<div class="file-browser-list" id="fileBrowserList">' +
|
|
623
|
+
'<div class="file-browser-loading"><i data-lucide="loader-2" class="w-5 h-5 animate-spin"></i></div>' +
|
|
624
|
+
'</div>' +
|
|
625
|
+
'</div>' +
|
|
626
|
+
'<div class="modal-footer">' +
|
|
627
|
+
'<button class="btn btn-outline" id="fileBrowserCancelBtn">' + t('cli.fileBrowserCancel') + '</button>' +
|
|
628
|
+
'<button class="btn btn-primary" id="fileBrowserSelectBtn" disabled>' +
|
|
629
|
+
'<i data-lucide="check" class="w-3.5 h-3.5"></i> ' + t('cli.fileBrowserSelect') +
|
|
630
|
+
'</button>' +
|
|
631
|
+
'</div>' +
|
|
632
|
+
'</div>';
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
async function loadFileBrowserDirectory(path) {
|
|
636
|
+
var listContainer = document.getElementById('fileBrowserList');
|
|
637
|
+
var pathInput = document.getElementById('fileBrowserPathInput');
|
|
638
|
+
|
|
639
|
+
if (listContainer) {
|
|
640
|
+
listContainer.innerHTML = '<div class="file-browser-loading"><i data-lucide="loader-2" class="w-5 h-5 animate-spin"></i></div>';
|
|
641
|
+
if (window.lucide) lucide.createIcons();
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
try {
|
|
645
|
+
var response = await fetch('/api/dialog/browse', {
|
|
646
|
+
method: 'POST',
|
|
647
|
+
headers: { 'Content-Type': 'application/json' },
|
|
648
|
+
body: JSON.stringify({ path: path, showHidden: fileBrowserState.showHidden })
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
if (!response.ok) {
|
|
652
|
+
throw new Error('Failed to load directory');
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
var data = await response.json();
|
|
656
|
+
fileBrowserState.currentPath = data.currentPath;
|
|
657
|
+
|
|
658
|
+
if (pathInput) {
|
|
659
|
+
pathInput.value = data.currentPath;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
renderFileBrowserItems(data.items);
|
|
663
|
+
} catch (err) {
|
|
664
|
+
console.error('Failed to load directory:', err);
|
|
665
|
+
if (listContainer) {
|
|
666
|
+
listContainer.innerHTML = '<div class="file-browser-error">' +
|
|
667
|
+
'<p>' + t('cli.fileBrowserApiError') + '</p>' +
|
|
668
|
+
'<p class="file-browser-hint">' + t('cli.fileBrowserManualHint') + '</p>' +
|
|
669
|
+
'</div>';
|
|
670
|
+
}
|
|
671
|
+
// Enable manual path entry mode - enable select button when path is typed
|
|
672
|
+
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
|
673
|
+
var pathInput = document.getElementById('fileBrowserPathInput');
|
|
674
|
+
if (selectBtn && pathInput) {
|
|
675
|
+
selectBtn.disabled = false;
|
|
676
|
+
pathInput.focus();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function renderFileBrowserItems(items) {
|
|
682
|
+
var listContainer = document.getElementById('fileBrowserList');
|
|
683
|
+
if (!listContainer) return;
|
|
684
|
+
|
|
685
|
+
if (!items || items.length === 0) {
|
|
686
|
+
listContainer.innerHTML = '<div class="file-browser-empty">Empty directory</div>';
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
var html = items.map(function(item) {
|
|
691
|
+
var icon = item.isDirectory ? 'folder' : 'file';
|
|
692
|
+
var itemClass = 'file-browser-item' + (item.isDirectory ? ' is-directory' : ' is-file');
|
|
693
|
+
return '<div class="' + itemClass + '" data-path="' + escapeHtml(item.path) + '" data-is-dir="' + item.isDirectory + '">' +
|
|
694
|
+
'<i data-lucide="' + icon + '" class="w-4 h-4"></i>' +
|
|
695
|
+
'<span class="file-browser-item-name">' + escapeHtml(item.name) + '</span>' +
|
|
696
|
+
'</div>';
|
|
697
|
+
}).join('');
|
|
698
|
+
|
|
699
|
+
listContainer.innerHTML = html;
|
|
700
|
+
|
|
701
|
+
// Initialize icons
|
|
702
|
+
if (window.lucide) lucide.createIcons();
|
|
703
|
+
|
|
704
|
+
// Add click handlers
|
|
705
|
+
listContainer.querySelectorAll('.file-browser-item').forEach(function(el) {
|
|
706
|
+
el.onclick = function() {
|
|
707
|
+
var isDir = el.getAttribute('data-is-dir') === 'true';
|
|
708
|
+
var path = el.getAttribute('data-path');
|
|
709
|
+
|
|
710
|
+
if (isDir) {
|
|
711
|
+
// Navigate into directory
|
|
712
|
+
loadFileBrowserDirectory(path);
|
|
713
|
+
} else {
|
|
714
|
+
// Select file
|
|
715
|
+
listContainer.querySelectorAll('.file-browser-item').forEach(function(item) {
|
|
716
|
+
item.classList.remove('selected');
|
|
717
|
+
});
|
|
718
|
+
el.classList.add('selected');
|
|
719
|
+
|
|
720
|
+
// Enable select button
|
|
721
|
+
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
|
722
|
+
if (selectBtn) {
|
|
723
|
+
selectBtn.disabled = false;
|
|
724
|
+
selectBtn.setAttribute('data-selected-path', path);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
// Double-click to select file or enter directory
|
|
730
|
+
el.ondblclick = function() {
|
|
731
|
+
var isDir = el.getAttribute('data-is-dir') === 'true';
|
|
732
|
+
var path = el.getAttribute('data-path');
|
|
733
|
+
|
|
734
|
+
if (isDir) {
|
|
735
|
+
loadFileBrowserDirectory(path);
|
|
736
|
+
} else {
|
|
737
|
+
// Select and close
|
|
738
|
+
closeFileBrowserModal(path);
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function initFileBrowserEvents() {
|
|
745
|
+
// Close button
|
|
746
|
+
var closeBtn = document.getElementById('fileBrowserCloseBtn');
|
|
747
|
+
if (closeBtn) {
|
|
748
|
+
closeBtn.onclick = function() { closeFileBrowserModal(null); };
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Cancel button
|
|
752
|
+
var cancelBtn = document.getElementById('fileBrowserCancelBtn');
|
|
753
|
+
if (cancelBtn) {
|
|
754
|
+
cancelBtn.onclick = function() { closeFileBrowserModal(null); };
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Select button
|
|
758
|
+
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
|
759
|
+
if (selectBtn) {
|
|
760
|
+
selectBtn.onclick = function() {
|
|
761
|
+
// First try selected path from list, then fall back to path input
|
|
762
|
+
var path = selectBtn.getAttribute('data-selected-path');
|
|
763
|
+
if (!path) {
|
|
764
|
+
var pathInput = document.getElementById('fileBrowserPathInput');
|
|
765
|
+
if (pathInput && pathInput.value.trim()) {
|
|
766
|
+
path = pathInput.value.trim();
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (path) {
|
|
770
|
+
closeFileBrowserModal(path);
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Up button
|
|
776
|
+
var upBtn = document.getElementById('fileBrowserUpBtn');
|
|
777
|
+
if (upBtn) {
|
|
778
|
+
upBtn.onclick = function() {
|
|
779
|
+
// Get parent path
|
|
780
|
+
var currentPath = fileBrowserState.currentPath;
|
|
781
|
+
var parentPath = currentPath.replace(/[/\\][^/\\]+$/, '') || '/';
|
|
782
|
+
loadFileBrowserDirectory(parentPath);
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Home button
|
|
787
|
+
var homeBtn = document.getElementById('fileBrowserHomeBtn');
|
|
788
|
+
if (homeBtn) {
|
|
789
|
+
homeBtn.onclick = function() {
|
|
790
|
+
loadFileBrowserDirectory('');
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Drive buttons (Windows)
|
|
795
|
+
document.querySelectorAll('.drive-btn').forEach(function(btn) {
|
|
796
|
+
btn.onclick = function() {
|
|
797
|
+
var drive = btn.getAttribute('data-drive');
|
|
798
|
+
if (drive) {
|
|
799
|
+
loadFileBrowserDirectory(drive);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
// Path input - allow manual entry
|
|
805
|
+
var pathInput = document.getElementById('fileBrowserPathInput');
|
|
806
|
+
if (pathInput) {
|
|
807
|
+
pathInput.onkeydown = function(e) {
|
|
808
|
+
if (e.key === 'Enter') {
|
|
809
|
+
e.preventDefault();
|
|
810
|
+
var path = pathInput.value.trim();
|
|
811
|
+
if (path) {
|
|
812
|
+
loadFileBrowserDirectory(path);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// Show hidden checkbox
|
|
819
|
+
var showHiddenCheckbox = document.getElementById('fileBrowserShowHidden');
|
|
820
|
+
if (showHiddenCheckbox) {
|
|
821
|
+
showHiddenCheckbox.checked = true; // Default to show hidden
|
|
822
|
+
fileBrowserState.showHidden = true;
|
|
823
|
+
showHiddenCheckbox.onchange = function() {
|
|
824
|
+
fileBrowserState.showHidden = showHiddenCheckbox.checked;
|
|
825
|
+
loadFileBrowserDirectory(fileBrowserState.currentPath);
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Click outside to close
|
|
830
|
+
var overlay = document.getElementById('fileBrowserOverlay');
|
|
831
|
+
if (overlay) {
|
|
832
|
+
overlay.onclick = function(e) {
|
|
833
|
+
if (e.target === overlay) {
|
|
834
|
+
closeFileBrowserModal(null);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function closeFileBrowserModal(selectedPath) {
|
|
841
|
+
var overlay = document.getElementById('fileBrowserOverlay');
|
|
842
|
+
if (overlay) {
|
|
843
|
+
overlay.remove();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (fileBrowserState.onSelect && selectedPath) {
|
|
847
|
+
fileBrowserState.onSelect(selectedPath);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
fileBrowserState.onSelect = null;
|
|
851
|
+
}
|
|
852
|
+
|
|
557
853
|
function initToolConfigModalEvents(tool, currentConfig, models) {
|
|
558
854
|
// Local tags state (copy from config)
|
|
559
855
|
var currentTags = (currentConfig.tags || []).slice();
|
|
@@ -754,38 +1050,14 @@ function initToolConfigModalEvents(tool, currentConfig, models) {
|
|
|
754
1050
|
// Environment file browse button (only for gemini/qwen)
|
|
755
1051
|
var envFileBrowseBtn = document.getElementById('envFileBrowseBtn');
|
|
756
1052
|
if (envFileBrowseBtn) {
|
|
757
|
-
envFileBrowseBtn.onclick =
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
body: JSON.stringify({
|
|
764
|
-
title: t('cli.envFile'),
|
|
765
|
-
filters: [
|
|
766
|
-
{ name: 'Environment Files', extensions: ['env'] },
|
|
767
|
-
{ name: 'All Files', extensions: ['*'] }
|
|
768
|
-
],
|
|
769
|
-
defaultPath: ''
|
|
770
|
-
})
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
if (response.ok) {
|
|
774
|
-
var data = await response.json();
|
|
775
|
-
if (data.filePath) {
|
|
776
|
-
var envFileInput = document.getElementById('envFileInput');
|
|
777
|
-
if (envFileInput) {
|
|
778
|
-
envFileInput.value = data.filePath;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
} else {
|
|
782
|
-
// Fallback: prompt user to enter path manually
|
|
783
|
-
showRefreshToast('File dialog not available. Please enter path manually.', 'info');
|
|
1053
|
+
envFileBrowseBtn.onclick = function() {
|
|
1054
|
+
showFileBrowserModal(function(selectedPath) {
|
|
1055
|
+
var envFileInput = document.getElementById('envFileInput');
|
|
1056
|
+
if (envFileInput && selectedPath) {
|
|
1057
|
+
envFileInput.value = selectedPath;
|
|
1058
|
+
envFileInput.focus();
|
|
784
1059
|
}
|
|
785
|
-
}
|
|
786
|
-
console.error('Failed to open file dialog:', err);
|
|
787
|
-
showRefreshToast('File dialog not available. Please enter path manually.', 'info');
|
|
788
|
-
}
|
|
1060
|
+
});
|
|
789
1061
|
};
|
|
790
1062
|
}
|
|
791
1063
|
|
|
@@ -7,6 +7,9 @@ var isMultiSelectMode = false;
|
|
|
7
7
|
|
|
8
8
|
// ========== Rendering ==========
|
|
9
9
|
async function renderCliHistoryView() {
|
|
10
|
+
// Reset view state to prevent stale data persistence
|
|
11
|
+
resetHistoryViewState();
|
|
12
|
+
|
|
10
13
|
var container = document.getElementById('mainContent');
|
|
11
14
|
if (!container) return;
|
|
12
15
|
|
|
@@ -183,6 +186,9 @@ async function renderCliHistoryView() {
|
|
|
183
186
|
if (window.lucide) lucide.createIcons();
|
|
184
187
|
}
|
|
185
188
|
|
|
189
|
+
// Export destroy function for lifecycle management
|
|
190
|
+
window.destroyCliHistoryView = destroyCliHistoryView;
|
|
191
|
+
|
|
186
192
|
// ========== Actions ==========
|
|
187
193
|
async function copyExecutionId(executionId) {
|
|
188
194
|
try {
|
|
@@ -218,16 +224,28 @@ async function refreshCliHistoryView() {
|
|
|
218
224
|
}
|
|
219
225
|
|
|
220
226
|
// ========== Multi-Select Functions ==========
|
|
227
|
+
var deleteDropdownListenerActive = false;
|
|
228
|
+
|
|
221
229
|
function toggleDeleteDropdown(event) {
|
|
222
230
|
event.stopPropagation();
|
|
223
231
|
var menu = document.getElementById('deleteDropdownMenu');
|
|
224
232
|
if (menu) {
|
|
225
|
-
menu.classList.toggle('show');
|
|
226
|
-
// Close on outside click
|
|
227
233
|
if (menu.classList.contains('show')) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
// Closing: remove listener if active
|
|
235
|
+
menu.classList.remove('show');
|
|
236
|
+
if (deleteDropdownListenerActive) {
|
|
237
|
+
document.removeEventListener('click', closeDeleteDropdown);
|
|
238
|
+
deleteDropdownListenerActive = false;
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
// Opening: add listener if not already active
|
|
242
|
+
menu.classList.add('show');
|
|
243
|
+
if (!deleteDropdownListenerActive) {
|
|
244
|
+
setTimeout(function() {
|
|
245
|
+
document.addEventListener('click', closeDeleteDropdown);
|
|
246
|
+
deleteDropdownListenerActive = true;
|
|
247
|
+
}, 0);
|
|
248
|
+
}
|
|
231
249
|
}
|
|
232
250
|
}
|
|
233
251
|
}
|
|
@@ -235,7 +253,10 @@ function toggleDeleteDropdown(event) {
|
|
|
235
253
|
function closeDeleteDropdown() {
|
|
236
254
|
var menu = document.getElementById('deleteDropdownMenu');
|
|
237
255
|
if (menu) menu.classList.remove('show');
|
|
238
|
-
|
|
256
|
+
if (deleteDropdownListenerActive) {
|
|
257
|
+
document.removeEventListener('click', closeDeleteDropdown);
|
|
258
|
+
deleteDropdownListenerActive = false;
|
|
259
|
+
}
|
|
239
260
|
}
|
|
240
261
|
|
|
241
262
|
function enterMultiSelectMode() {
|
|
@@ -279,6 +300,23 @@ function clearExecutionSelection() {
|
|
|
279
300
|
renderCliHistoryView();
|
|
280
301
|
}
|
|
281
302
|
|
|
303
|
+
function resetHistoryViewState() {
|
|
304
|
+
selectedExecutions.clear();
|
|
305
|
+
isMultiSelectMode = false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ========== View Lifecycle ==========
|
|
309
|
+
function destroyCliHistoryView() {
|
|
310
|
+
// Clean up dropdown listener if active
|
|
311
|
+
if (deleteDropdownListenerActive) {
|
|
312
|
+
document.removeEventListener('click', closeDeleteDropdown);
|
|
313
|
+
deleteDropdownListenerActive = false;
|
|
314
|
+
}
|
|
315
|
+
// Ensure dropdown menu is closed
|
|
316
|
+
var menu = document.getElementById('deleteDropdownMenu');
|
|
317
|
+
if (menu) menu.classList.remove('show');
|
|
318
|
+
}
|
|
319
|
+
|
|
282
320
|
// ========== Batch Delete Functions ==========
|
|
283
321
|
function confirmBatchDelete() {
|
|
284
322
|
var count = selectedExecutions.size;
|
|
@@ -51,6 +51,7 @@ function updateBadges() {
|
|
|
51
51
|
const liteTasks = workflowData.liteTasks || {};
|
|
52
52
|
document.getElementById('badgeLitePlan').textContent = liteTasks.litePlan?.length || 0;
|
|
53
53
|
document.getElementById('badgeLiteFix').textContent = liteTasks.liteFix?.length || 0;
|
|
54
|
+
document.getElementById('badgeMultiCliPlan').textContent = liteTasks.multiCliPlan?.length || 0;
|
|
54
55
|
|
|
55
56
|
// MCP badge - load async if needed
|
|
56
57
|
if (typeof loadMcpConfig === 'function') {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// ========== Issue State ==========
|
|
7
7
|
var issueData = {
|
|
8
8
|
issues: [],
|
|
9
|
+
historyIssues: [], // Archived/completed issues from history
|
|
9
10
|
queue: { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} },
|
|
10
11
|
selectedIssue: null,
|
|
11
12
|
selectedSolution: null,
|
|
@@ -58,6 +59,18 @@ async function loadIssueData() {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
async function loadIssueHistory() {
|
|
63
|
+
try {
|
|
64
|
+
const response = await fetch('/api/issues/history?path=' + encodeURIComponent(projectPath));
|
|
65
|
+
if (!response.ok) throw new Error('Failed to load issue history');
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
issueData.historyIssues = data.issues || [];
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error('Failed to load issue history:', err);
|
|
70
|
+
issueData.historyIssues = [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
async function loadQueueData() {
|
|
62
75
|
try {
|
|
63
76
|
const response = await fetch('/api/queue?path=' + encodeURIComponent(projectPath));
|
|
@@ -93,10 +106,21 @@ function renderIssueView() {
|
|
|
93
106
|
if (!container) return;
|
|
94
107
|
|
|
95
108
|
const issues = issueData.issues || [];
|
|
109
|
+
const historyIssues = issueData.historyIssues || [];
|
|
110
|
+
|
|
96
111
|
// Apply both status and search filters
|
|
97
|
-
let filteredIssues
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
let filteredIssues;
|
|
113
|
+
if (issueData.statusFilter === 'all') {
|
|
114
|
+
filteredIssues = issues;
|
|
115
|
+
} else if (issueData.statusFilter === 'completed') {
|
|
116
|
+
// For 'completed' filter, include both current completed issues and archived history issues
|
|
117
|
+
const currentCompleted = issues.filter(i => i.status === 'completed');
|
|
118
|
+
// Mark history issues as archived for visual distinction
|
|
119
|
+
const archivedIssues = historyIssues.map(i => ({ ...i, _isArchived: true }));
|
|
120
|
+
filteredIssues = [...currentCompleted, ...archivedIssues];
|
|
121
|
+
} else {
|
|
122
|
+
filteredIssues = issues.filter(i => i.status === issueData.statusFilter);
|
|
123
|
+
}
|
|
100
124
|
|
|
101
125
|
if (issueData.searchQuery) {
|
|
102
126
|
const query = issueData.searchQuery.toLowerCase();
|
|
@@ -309,12 +333,15 @@ function renderIssueCard(issue) {
|
|
|
309
333
|
failed: 'failed'
|
|
310
334
|
};
|
|
311
335
|
|
|
336
|
+
const isArchived = issue._isArchived;
|
|
337
|
+
|
|
312
338
|
return `
|
|
313
|
-
<div class="issue-card" onclick="openIssueDetail('${issue.id}')">
|
|
339
|
+
<div class="issue-card ${isArchived ? 'archived' : ''}" onclick="openIssueDetail('${issue.id}'${isArchived ? ', true' : ''})">
|
|
314
340
|
<div class="flex items-start justify-between mb-3">
|
|
315
341
|
<div class="flex items-center gap-2">
|
|
316
342
|
<span class="issue-id font-mono text-sm">${issue.id}</span>
|
|
317
343
|
<span class="issue-status ${statusColors[issue.status] || ''}">${issue.status || 'unknown'}</span>
|
|
344
|
+
${isArchived ? '<span class="issue-archived-badge">' + (t('issues.archived') || 'Archived') + '</span>' : ''}
|
|
318
345
|
</div>
|
|
319
346
|
<span class="issue-priority" title="${t('issues.priority') || 'Priority'}: ${issue.priority || 3}">
|
|
320
347
|
${renderPriorityStars(issue.priority || 3)}
|
|
@@ -360,8 +387,12 @@ function renderPriorityStars(priority) {
|
|
|
360
387
|
return stars;
|
|
361
388
|
}
|
|
362
389
|
|
|
363
|
-
function filterIssuesByStatus(status) {
|
|
390
|
+
async function filterIssuesByStatus(status) {
|
|
364
391
|
issueData.statusFilter = status;
|
|
392
|
+
// Load history data when filtering by 'completed' status
|
|
393
|
+
if (status === 'completed' && issueData.historyIssues.length === 0) {
|
|
394
|
+
await loadIssueHistory();
|
|
395
|
+
}
|
|
365
396
|
renderIssueView();
|
|
366
397
|
}
|
|
367
398
|
|
|
@@ -725,7 +756,7 @@ async function saveQueueOrder(groupId, newOrder) {
|
|
|
725
756
|
}
|
|
726
757
|
|
|
727
758
|
// ========== Detail Panel ==========
|
|
728
|
-
async function openIssueDetail(issueId) {
|
|
759
|
+
async function openIssueDetail(issueId, isArchived = false) {
|
|
729
760
|
const panel = document.getElementById('issueDetailPanel');
|
|
730
761
|
if (!panel) return;
|
|
731
762
|
|
|
@@ -733,7 +764,23 @@ async function openIssueDetail(issueId) {
|
|
|
733
764
|
panel.classList.remove('hidden');
|
|
734
765
|
lucide.createIcons();
|
|
735
766
|
|
|
736
|
-
|
|
767
|
+
let detail;
|
|
768
|
+
if (isArchived) {
|
|
769
|
+
// For archived issues, get detail from historyIssues (already loaded)
|
|
770
|
+
const historyIssue = issueData.historyIssues.find(i => i.id === issueId);
|
|
771
|
+
if (historyIssue) {
|
|
772
|
+
// Mark as archived and provide minimal detail structure
|
|
773
|
+
detail = {
|
|
774
|
+
...historyIssue,
|
|
775
|
+
_isArchived: true,
|
|
776
|
+
solutions: historyIssue.solutions || [],
|
|
777
|
+
tasks: historyIssue.tasks || []
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
detail = await loadIssueDetail(issueId);
|
|
782
|
+
}
|
|
783
|
+
|
|
737
784
|
if (!detail) {
|
|
738
785
|
panel.innerHTML = '<div class="p-8 text-center text-destructive">Failed to load issue</div>';
|
|
739
786
|
return;
|