claude-code-workflow 6.3.37 → 6.3.39
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/commands/workflow/lite-execute.md +2 -0
- package/.codex/agents/action-planning-agent.md +885 -0
- package/.codex/agents/ccw-loop-b-complete.md +227 -0
- package/.codex/agents/ccw-loop-b-debug.md +172 -0
- package/.codex/agents/ccw-loop-b-develop.md +147 -0
- package/.codex/agents/ccw-loop-b-init.md +82 -0
- package/.codex/agents/ccw-loop-b-validate.md +204 -0
- package/.codex/agents/ccw-loop-executor.md +260 -0
- package/.codex/agents/cli-discuss-agent.md +391 -0
- package/.codex/agents/cli-execution-agent.md +333 -0
- package/.codex/agents/cli-explore-agent.md +186 -0
- package/.codex/agents/cli-lite-planning-agent.md +736 -0
- package/.codex/agents/cli-planning-agent.md +562 -0
- package/.codex/agents/code-developer.md +408 -0
- package/.codex/agents/conceptual-planning-agent.md +321 -0
- package/.codex/agents/context-search-agent.md +585 -0
- package/.codex/agents/debug-explore-agent.md +436 -0
- package/.codex/agents/doc-generator.md +334 -0
- package/.codex/agents/issue-plan-agent.md +417 -0
- package/.codex/agents/issue-queue-agent.md +311 -0
- package/.codex/agents/memory-bridge.md +96 -0
- package/.codex/agents/test-context-search-agent.md +402 -0
- package/.codex/agents/test-fix-agent.md +359 -0
- package/.codex/agents/ui-design-agent.md +595 -0
- package/.codex/agents/universal-executor.md +135 -0
- package/.codex/prompts/clean.md +409 -0
- package/.codex/prompts/issue-discover-by-prompt.md +364 -0
- package/.codex/prompts/issue-discover.md +261 -0
- package/.codex/prompts/issue-execute.md +10 -0
- package/.codex/prompts/issue-new.md +285 -0
- package/.codex/prompts/issue-plan.md +161 -63
- package/.codex/prompts/issue-queue.md +298 -288
- package/.codex/prompts/lite-execute.md +627 -133
- package/.codex/prompts/lite-fix.md +670 -0
- package/.codex/prompts/lite-plan-a.md +337 -0
- package/.codex/prompts/lite-plan-b.md +485 -0
- package/.codex/prompts/{lite-plan.md → lite-plan-c.md} +601 -469
- package/.codex/skills/ccw-loop/README.md +171 -0
- package/.codex/skills/ccw-loop/SKILL.md +349 -0
- package/.codex/skills/ccw-loop/phases/actions/action-complete.md +269 -0
- package/.codex/skills/ccw-loop/phases/actions/action-debug.md +286 -0
- package/.codex/skills/ccw-loop/phases/actions/action-develop.md +183 -0
- package/.codex/skills/ccw-loop/phases/actions/action-init.md +164 -0
- package/.codex/skills/ccw-loop/phases/actions/action-menu.md +205 -0
- package/.codex/skills/ccw-loop/phases/actions/action-validate.md +250 -0
- package/.codex/skills/ccw-loop/phases/orchestrator.md +416 -0
- package/.codex/skills/ccw-loop/phases/state-schema.md +388 -0
- package/.codex/skills/ccw-loop/specs/action-catalog.md +182 -0
- package/.codex/skills/ccw-loop-b/README.md +301 -0
- package/.codex/skills/ccw-loop-b/SKILL.md +322 -0
- package/.codex/skills/ccw-loop-b/phases/orchestrator.md +257 -0
- package/.codex/skills/ccw-loop-b/phases/state-schema.md +181 -0
- package/.codex/skills/ccw-loop-b/specs/action-catalog.md +383 -0
- package/.codex/skills/parallel-dev-cycle/README.md +382 -0
- package/.codex/skills/parallel-dev-cycle/SKILL.md +512 -0
- package/.codex/skills/parallel-dev-cycle/phases/agents/code-developer.md +242 -0
- package/.codex/skills/parallel-dev-cycle/phases/agents/exploration-planner.md +285 -0
- package/.codex/skills/parallel-dev-cycle/phases/agents/requirements-analyst.md +285 -0
- package/.codex/skills/parallel-dev-cycle/phases/agents/validation-archivist.md +381 -0
- package/.codex/skills/parallel-dev-cycle/phases/orchestrator.md +696 -0
- package/.codex/skills/parallel-dev-cycle/phases/state-schema.md +436 -0
- package/.codex/skills/parallel-dev-cycle/specs/communication-optimization.md +423 -0
- package/.codex/skills/parallel-dev-cycle/specs/coordination-protocol.md +391 -0
- package/.codex/skills/parallel-dev-cycle/specs/versioning-strategy.md +330 -0
- package/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +4 -0
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/commands/install.d.ts.map +1 -1
- package/ccw/dist/commands/install.js +39 -8
- package/ccw/dist/commands/install.js.map +1 -1
- package/ccw/dist/commands/issue.d.ts +3 -0
- package/ccw/dist/commands/issue.d.ts.map +1 -1
- package/ccw/dist/commands/issue.js +107 -0
- package/ccw/dist/commands/issue.js.map +1 -1
- package/ccw/dist/commands/upgrade.js +1 -1
- package/ccw/dist/commands/upgrade.js.map +1 -1
- package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
- package/ccw/dist/config/litellm-api-config-manager.js +3 -2
- package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
- package/ccw/dist/core/memory-embedder-bridge.d.ts.map +1 -1
- package/ccw/dist/core/memory-embedder-bridge.js +2 -5
- package/ccw/dist/core/memory-embedder-bridge.js.map +1 -1
- package/ccw/dist/core/routes/cli-routes.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 +7 -6
- package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -1
- package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens/semantic-handlers.js +2 -2
- package/ccw/dist/core/routes/codexlens/semantic-handlers.js.map +1 -1
- package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/graph-routes.js +17 -2
- package/ccw/dist/core/routes/graph-routes.js.map +1 -1
- package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/issue-routes.js +280 -33
- package/ccw/dist/core/routes/issue-routes.js.map +1 -1
- package/ccw/dist/core/routes/loop-v2-routes.d.ts +9 -0
- package/ccw/dist/core/routes/loop-v2-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/loop-v2-routes.js +56 -4
- package/ccw/dist/core/routes/loop-v2-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 +3 -2
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/dist/core/server.d.ts.map +1 -1
- package/ccw/dist/core/server.js +5 -3
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.js +4 -3
- package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
- package/ccw/dist/tools/cli-config-manager.d.ts +1 -0
- package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
- package/ccw/dist/tools/cli-config-manager.js +2 -1
- package/ccw/dist/tools/cli-config-manager.js.map +1 -1
- package/ccw/dist/tools/codex-lens-lsp.d.ts.map +1 -1
- package/ccw/dist/tools/codex-lens-lsp.js +2 -5
- package/ccw/dist/tools/codex-lens-lsp.js.map +1 -1
- package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
- package/ccw/dist/tools/codex-lens.js +22 -32
- package/ccw/dist/tools/codex-lens.js.map +1 -1
- package/ccw/dist/tools/litellm-client.d.ts +6 -0
- package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
- package/ccw/dist/tools/litellm-client.js +15 -2
- package/ccw/dist/tools/litellm-client.js.map +1 -1
- package/ccw/dist/tools/loop-task-manager.d.ts +13 -2
- package/ccw/dist/tools/loop-task-manager.d.ts.map +1 -1
- package/ccw/dist/tools/loop-task-manager.js.map +1 -1
- package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -1
- package/ccw/dist/tools/native-session-discovery.js +35 -7
- package/ccw/dist/tools/native-session-discovery.js.map +1 -1
- package/ccw/dist/utils/codexlens-path.d.ts +36 -0
- package/ccw/dist/utils/codexlens-path.d.ts.map +1 -0
- package/ccw/dist/utils/codexlens-path.js +56 -0
- package/ccw/dist/utils/codexlens-path.js.map +1 -0
- package/ccw/dist/utils/uv-manager.d.ts.map +1 -1
- package/ccw/dist/utils/uv-manager.js +3 -2
- package/ccw/dist/utils/uv-manager.js.map +1 -1
- package/ccw/src/cli.ts +4 -0
- package/ccw/src/commands/install.ts +51 -8
- package/ccw/src/commands/issue.ts +119 -0
- package/ccw/src/commands/upgrade.ts +1 -1
- package/ccw/src/config/litellm-api-config-manager.ts +3 -2
- package/ccw/src/core/memory-embedder-bridge.ts +2 -6
- package/ccw/src/core/routes/cli-routes.ts +1 -1
- package/ccw/src/core/routes/codexlens/config-handlers.ts +7 -6
- package/ccw/src/core/routes/codexlens/semantic-handlers.ts +2 -2
- package/ccw/src/core/routes/graph-routes.ts +18 -2
- package/ccw/src/core/routes/issue-routes.ts +308 -33
- package/ccw/src/core/routes/loop-v2-routes.ts +64 -6
- package/ccw/src/core/routes/system-routes.ts +3 -2
- package/ccw/src/core/server.ts +6 -3
- package/ccw/src/templates/dashboard-css/02-session.css +2 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +103 -1
- package/ccw/src/templates/dashboard-css/32-issue-manager.css +32 -0
- package/ccw/src/templates/dashboard-js/components/cli-history.js +48 -48
- package/ccw/src/templates/dashboard-js/components/navigation.js +6 -0
- package/ccw/src/templates/dashboard-js/components/notifications.js +6 -0
- package/ccw/src/templates/dashboard-js/components/version-check.js +38 -0
- package/ccw/src/templates/dashboard-js/i18n.js +126 -0
- package/ccw/src/templates/dashboard-js/state.js +2 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +1 -1
- package/ccw/src/templates/dashboard-js/views/issue-manager.js +183 -1
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +55 -11
- package/ccw/src/templates/dashboard-js/views/loop-monitor.js +112 -11
- package/ccw/src/templates/dashboard.html +48 -2
- package/ccw/src/tools/claude-cli-tools.ts +4 -3
- package/ccw/src/tools/cli-config-manager.ts +3 -1
- package/ccw/src/tools/codex-lens-lsp.ts +2 -5
- package/ccw/src/tools/codex-lens.ts +27 -38
- package/ccw/src/tools/litellm-client.ts +16 -2
- package/ccw/src/tools/loop-task-manager.ts +13 -2
- package/ccw/src/tools/native-session-discovery.ts +38 -7
- package/ccw/src/utils/codexlens-path.ts +60 -0
- package/ccw/src/utils/uv-manager.ts +3 -2
- package/package.json +1 -1
|
@@ -1732,12 +1732,25 @@
|
|
|
1732
1732
|
align-items: center;
|
|
1733
1733
|
justify-content: space-between;
|
|
1734
1734
|
gap: 1rem;
|
|
1735
|
-
margin-bottom: 0.75rem;
|
|
1736
1735
|
padding: 0.75rem 1rem;
|
|
1737
1736
|
background: hsl(var(--muted) / 0.2);
|
|
1738
1737
|
border-bottom: 1px solid hsl(var(--border));
|
|
1739
1738
|
}
|
|
1740
1739
|
|
|
1740
|
+
.solution-title-row {
|
|
1741
|
+
display: flex;
|
|
1742
|
+
align-items: center;
|
|
1743
|
+
gap: 0.5rem;
|
|
1744
|
+
flex: 1;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
.solution-badges {
|
|
1748
|
+
display: flex;
|
|
1749
|
+
align-items: center;
|
|
1750
|
+
gap: 0.5rem;
|
|
1751
|
+
flex-shrink: 0;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1741
1754
|
.solution-title {
|
|
1742
1755
|
font-weight: 600;
|
|
1743
1756
|
font-size: 0.95rem;
|
|
@@ -2782,6 +2795,39 @@
|
|
|
2782
2795
|
border-bottom: 1px solid hsl(var(--border));
|
|
2783
2796
|
}
|
|
2784
2797
|
|
|
2798
|
+
.solution-details {
|
|
2799
|
+
padding: 0.75rem 1rem;
|
|
2800
|
+
border-bottom: 1px solid hsl(var(--border) / 0.5);
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
.solution-details:last-child {
|
|
2804
|
+
border-bottom: none;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
.details-label {
|
|
2808
|
+
font-size: 0.8125rem;
|
|
2809
|
+
font-weight: 600;
|
|
2810
|
+
margin: 0 0 0.5rem 0;
|
|
2811
|
+
color: hsl(var(--foreground));
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
.details-list {
|
|
2815
|
+
margin: 0;
|
|
2816
|
+
padding-left: 1.25rem;
|
|
2817
|
+
list-style: disc;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
.details-list li {
|
|
2821
|
+
font-size: 0.8125rem;
|
|
2822
|
+
line-height: 1.6;
|
|
2823
|
+
color: hsl(var(--muted-foreground));
|
|
2824
|
+
margin-bottom: 0.375rem;
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
.details-list li:last-child {
|
|
2828
|
+
margin-bottom: 0;
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2785
2831
|
.solution-approach,
|
|
2786
2832
|
.solution-dependencies,
|
|
2787
2833
|
.solution-concerns {
|
|
@@ -3976,6 +4022,62 @@
|
|
|
3976
4022
|
border-top: 1px solid hsl(var(--border) / 0.5);
|
|
3977
4023
|
}
|
|
3978
4024
|
|
|
4025
|
+
/* Badge - generic badge styling */
|
|
4026
|
+
.badge {
|
|
4027
|
+
display: inline-flex;
|
|
4028
|
+
align-items: center;
|
|
4029
|
+
padding: 0.25rem 0.625rem;
|
|
4030
|
+
border-radius: 0.25rem;
|
|
4031
|
+
font-size: 0.75rem;
|
|
4032
|
+
font-weight: 500;
|
|
4033
|
+
white-space: nowrap;
|
|
4034
|
+
}
|
|
4035
|
+
|
|
4036
|
+
.badge.feasibility {
|
|
4037
|
+
background: hsl(var(--primary) / 0.1);
|
|
4038
|
+
color: hsl(var(--primary));
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4041
|
+
.badge.effort {
|
|
4042
|
+
background: hsl(var(--muted));
|
|
4043
|
+
color: hsl(var(--foreground));
|
|
4044
|
+
}
|
|
4045
|
+
|
|
4046
|
+
.badge.effort.low {
|
|
4047
|
+
background: hsl(142 70% 50% / 0.15);
|
|
4048
|
+
color: hsl(142 70% 35%);
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
.badge.effort.medium {
|
|
4052
|
+
background: hsl(30 90% 50% / 0.15);
|
|
4053
|
+
color: hsl(30 90% 40%);
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
.badge.effort.high {
|
|
4057
|
+
background: hsl(0 70% 50% / 0.15);
|
|
4058
|
+
color: hsl(0 70% 45%);
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
.badge.risk {
|
|
4062
|
+
background: hsl(var(--muted));
|
|
4063
|
+
color: hsl(var(--foreground));
|
|
4064
|
+
}
|
|
4065
|
+
|
|
4066
|
+
.badge.risk.low {
|
|
4067
|
+
background: hsl(142 70% 50% / 0.15);
|
|
4068
|
+
color: hsl(142 70% 35%);
|
|
4069
|
+
}
|
|
4070
|
+
|
|
4071
|
+
.badge.risk.medium {
|
|
4072
|
+
background: hsl(30 90% 50% / 0.15);
|
|
4073
|
+
color: hsl(30 90% 40%);
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
.badge.risk.high {
|
|
4077
|
+
background: hsl(0 70% 50% / 0.15);
|
|
4078
|
+
color: hsl(0 70% 45%);
|
|
4079
|
+
}
|
|
4080
|
+
|
|
3979
4081
|
/* Feasibility badge */
|
|
3980
4082
|
.feasibility-badge {
|
|
3981
4083
|
display: inline-flex;
|
|
@@ -1508,6 +1508,38 @@
|
|
|
1508
1508
|
transform: translateY(0);
|
|
1509
1509
|
}
|
|
1510
1510
|
|
|
1511
|
+
.issue-pull-btn {
|
|
1512
|
+
display: inline-flex;
|
|
1513
|
+
align-items: center;
|
|
1514
|
+
gap: 0.375rem;
|
|
1515
|
+
padding: 0.5rem 1rem;
|
|
1516
|
+
background: #1a1a1a;
|
|
1517
|
+
color: #ffffff;
|
|
1518
|
+
border: 1px solid #2d2d2d;
|
|
1519
|
+
border-radius: 0.375rem;
|
|
1520
|
+
font-size: 0.875rem;
|
|
1521
|
+
font-weight: 500;
|
|
1522
|
+
cursor: pointer;
|
|
1523
|
+
transition: all 0.15s ease;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
.issue-pull-btn:hover {
|
|
1527
|
+
background: #2d2d2d;
|
|
1528
|
+
border-color: #404040;
|
|
1529
|
+
transform: translateY(-1px);
|
|
1530
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
.issue-pull-btn:active {
|
|
1534
|
+
transform: translateY(0);
|
|
1535
|
+
background: #1a1a1a;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
.issue-pull-btn:disabled {
|
|
1539
|
+
opacity: 0.5;
|
|
1540
|
+
cursor: not-allowed;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1511
1543
|
/* ==========================================
|
|
1512
1544
|
ISSUE STATS
|
|
1513
1545
|
========================================== */
|
|
@@ -102,7 +102,7 @@ function renderCliHistory() {
|
|
|
102
102
|
if (cliExecutionHistory.length === 0) {
|
|
103
103
|
container.innerHTML = `
|
|
104
104
|
<div class="cli-history-header">
|
|
105
|
-
<h3><i data-lucide="history" class="w-4 h-4"></i>
|
|
105
|
+
<h3><i data-lucide="history" class="w-4 h-4"></i> ${t('cli.executionHistory')}</h3>
|
|
106
106
|
<div class="cli-history-controls">
|
|
107
107
|
${renderHistorySearch()}
|
|
108
108
|
${renderToolFilter()}
|
|
@@ -113,7 +113,7 @@ function renderCliHistory() {
|
|
|
113
113
|
</div>
|
|
114
114
|
<div class="empty-state">
|
|
115
115
|
<i data-lucide="terminal" class="w-8 h-8"></i>
|
|
116
|
-
<p
|
|
116
|
+
<p>${t('cli.noExecutions')}</p>
|
|
117
117
|
</div>
|
|
118
118
|
`;
|
|
119
119
|
|
|
@@ -124,7 +124,7 @@ function renderCliHistory() {
|
|
|
124
124
|
const historyHtml = filteredHistory.length === 0
|
|
125
125
|
? `<div class="empty-state">
|
|
126
126
|
<i data-lucide="search-x" class="w-6 h-6"></i>
|
|
127
|
-
<p
|
|
127
|
+
<p>${t('cli.noMatchingResults')}</p>
|
|
128
128
|
</div>`
|
|
129
129
|
: filteredHistory.map(exec => {
|
|
130
130
|
const statusIcon = exec.status === 'success' ? 'check-circle' :
|
|
@@ -140,7 +140,7 @@ function renderCliHistory() {
|
|
|
140
140
|
// Native session indicator
|
|
141
141
|
const hasNative = exec.hasNativeSession || exec.nativeSessionId;
|
|
142
142
|
const nativeBadge = hasNative
|
|
143
|
-
? `<span class="cli-native-badge" title="
|
|
143
|
+
? `<span class="cli-native-badge" title="${t('cli.nativeSessionBadge')}: ${exec.nativeSessionId}">
|
|
144
144
|
<i data-lucide="file-json" class="w-3 h-3"></i>
|
|
145
145
|
</span>`
|
|
146
146
|
: '';
|
|
@@ -173,14 +173,14 @@ function renderCliHistory() {
|
|
|
173
173
|
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
|
174
174
|
</button>
|
|
175
175
|
${hasNative ? `
|
|
176
|
-
<button class="btn-icon" onclick="event.stopPropagation(); showNativeSessionDetail('${exec.id}', '${sourceDirEscaped}')" title="
|
|
176
|
+
<button class="btn-icon" onclick="event.stopPropagation(); showNativeSessionDetail('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.viewNativeSession')}">
|
|
177
177
|
<i data-lucide="file-json" class="w-3.5 h-3.5"></i>
|
|
178
178
|
</button>
|
|
179
179
|
` : ''}
|
|
180
|
-
<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail('${exec.id}', '${sourceDirEscaped}')" title="
|
|
180
|
+
<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.viewDetails')}">
|
|
181
181
|
<i data-lucide="eye" class="w-3.5 h-3.5"></i>
|
|
182
182
|
</button>
|
|
183
|
-
<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution('${exec.id}', '${sourceDirEscaped}')" title="
|
|
183
|
+
<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.delete')}">
|
|
184
184
|
<i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
|
|
185
185
|
</button>
|
|
186
186
|
</div>
|
|
@@ -211,7 +211,7 @@ function renderHistorySearch() {
|
|
|
211
211
|
return `
|
|
212
212
|
<input type="text"
|
|
213
213
|
class="cli-history-search"
|
|
214
|
-
placeholder="
|
|
214
|
+
placeholder="${t('cli.searchHistory')}"
|
|
215
215
|
value="${escapeHtml(cliHistorySearch)}"
|
|
216
216
|
onkeyup="searchCliHistory(this.value)"
|
|
217
217
|
oninput="searchCliHistory(this.value)">
|
|
@@ -224,7 +224,7 @@ function renderToolFilter() {
|
|
|
224
224
|
<select class="cli-tool-filter" onchange="filterCliHistory(this.value)">
|
|
225
225
|
${tools.map(tool => `
|
|
226
226
|
<option value="${tool === 'all' ? '' : tool}" ${cliHistoryFilter === (tool === 'all' ? null : tool) ? 'selected' : ''}>
|
|
227
|
-
${tool === 'all' ? '
|
|
227
|
+
${tool === 'all' ? t('cli.allTools') : tool.charAt(0).toUpperCase() + tool.slice(1)}
|
|
228
228
|
</option>
|
|
229
229
|
`).join('')}
|
|
230
230
|
</select>
|
|
@@ -235,7 +235,7 @@ function renderToolFilter() {
|
|
|
235
235
|
async function showExecutionDetail(executionId, sourceDir) {
|
|
236
236
|
const conversation = await loadExecutionDetail(executionId, sourceDir);
|
|
237
237
|
if (!conversation) {
|
|
238
|
-
showRefreshToast('
|
|
238
|
+
showRefreshToast(t('cli.conversationNotFound'), 'error');
|
|
239
239
|
return;
|
|
240
240
|
}
|
|
241
241
|
|
|
@@ -264,7 +264,7 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
264
264
|
<div class="cli-turn-header">
|
|
265
265
|
<div class="cli-turn-marker">
|
|
266
266
|
<span class="cli-turn-number">${isFirst ? '▶' : '↳'} Turn ${turn.turn}</span>
|
|
267
|
-
${isLast ?
|
|
267
|
+
${isLast ? `<span class="cli-turn-latest-badge">${t('cli.latest')}</span>` : ''}
|
|
268
268
|
</div>
|
|
269
269
|
<div class="cli-turn-meta">
|
|
270
270
|
<span class="cli-turn-time"><i data-lucide="clock" class="w-3 h-3"></i> ${turnTime}</span>
|
|
@@ -276,12 +276,12 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
276
276
|
</div>
|
|
277
277
|
<div class="cli-turn-body">
|
|
278
278
|
<div class="cli-detail-section cli-prompt-section">
|
|
279
|
-
<h4><i data-lucide="user" class="w-3.5 h-3.5"></i>
|
|
279
|
+
<h4><i data-lucide="user" class="w-3.5 h-3.5"></i> ${t('cli.userPrompt')}</h4>
|
|
280
280
|
<pre class="cli-detail-prompt">${escapeHtml(turn.prompt)}</pre>
|
|
281
281
|
</div>
|
|
282
282
|
${turn.output.stdout ? `
|
|
283
283
|
<div class="cli-detail-section cli-output-section">
|
|
284
|
-
<h4><i data-lucide="bot" class="w-3.5 h-3.5"></i>
|
|
284
|
+
<h4><i data-lucide="bot" class="w-3.5 h-3.5"></i> ${t('cli.assistantResponse')}</h4>
|
|
285
285
|
<pre class="cli-detail-output">${escapeHtml(turn.output.stdout)}</pre>
|
|
286
286
|
</div>
|
|
287
287
|
` : ''}
|
|
@@ -340,7 +340,7 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
340
340
|
concatenatedPromptHtml = `
|
|
341
341
|
<div class="cli-concat-section" id="concatPromptSection" style="display: none;">
|
|
342
342
|
<div class="cli-detail-section">
|
|
343
|
-
<h4><i data-lucide="layers" class="w-3.5 h-3.5"></i>
|
|
343
|
+
<h4><i data-lucide="layers" class="w-3.5 h-3.5"></i> ${t('cli.concatenatedPrompt')}</h4>
|
|
344
344
|
<div class="cli-concat-format-selector">
|
|
345
345
|
<button class="btn btn-xs ${true ? 'btn-primary' : 'btn-outline'}" onclick="switchConcatFormat('plain', '${executionId}')">Plain</button>
|
|
346
346
|
<button class="btn btn-xs btn-outline" onclick="switchConcatFormat('yaml', '${executionId}')">YAML</button>
|
|
@@ -372,7 +372,7 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
372
372
|
${hasNativeSession ? `
|
|
373
373
|
<div class="cli-detail-native-action">
|
|
374
374
|
<button class="btn btn-sm btn-primary" onclick="showNativeSessionDetail('${executionId}', '${sourceDirEscaped}')">
|
|
375
|
-
<i data-lucide="eye" class="w-3.5 h-3.5"></i>
|
|
375
|
+
<i data-lucide="eye" class="w-3.5 h-3.5"></i> ${t('cli.viewFullConversation')}
|
|
376
376
|
</button>
|
|
377
377
|
</div>
|
|
378
378
|
` : ''}
|
|
@@ -380,10 +380,10 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
380
380
|
${turnCount > 1 ? `
|
|
381
381
|
<div class="cli-view-toggle">
|
|
382
382
|
<button class="btn btn-sm btn-outline active" onclick="toggleConversationView('turns')">
|
|
383
|
-
<i data-lucide="list" class="w-3.5 h-3.5"></i>
|
|
383
|
+
<i data-lucide="list" class="w-3.5 h-3.5"></i> ${t('cli.perTurnView')}
|
|
384
384
|
</button>
|
|
385
385
|
<button class="btn btn-sm btn-outline" onclick="toggleConversationView('concat')">
|
|
386
|
-
<i data-lucide="layers" class="w-3.5 h-3.5"></i>
|
|
386
|
+
<i data-lucide="layers" class="w-3.5 h-3.5"></i> ${t('cli.concatenatedView')}
|
|
387
387
|
</button>
|
|
388
388
|
</div>
|
|
389
389
|
` : ''}
|
|
@@ -393,15 +393,15 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
393
393
|
${concatenatedPromptHtml}
|
|
394
394
|
<div class="cli-detail-actions">
|
|
395
395
|
<button class="btn btn-sm btn-outline" onclick="copyConversationId('${executionId}')">
|
|
396
|
-
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
|
396
|
+
<i data-lucide="copy" class="w-3.5 h-3.5"></i> ${t('cli.copyId')}
|
|
397
397
|
</button>
|
|
398
398
|
${turnCount > 1 ? `
|
|
399
399
|
<button class="btn btn-sm btn-outline" onclick="copyConcatenatedPrompt('${executionId}')">
|
|
400
|
-
<i data-lucide="clipboard-copy" class="w-3.5 h-3.5"></i>
|
|
400
|
+
<i data-lucide="clipboard-copy" class="w-3.5 h-3.5"></i> ${t('cli.copyFullPrompt')}
|
|
401
401
|
</button>
|
|
402
402
|
` : ''}
|
|
403
403
|
<button class="btn btn-sm btn-outline btn-danger" onclick="confirmDeleteExecution('${executionId}'); closeModal();">
|
|
404
|
-
<i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
|
|
404
|
+
<i data-lucide="trash-2" class="w-3.5 h-3.5"></i> ${t('cli.delete')}
|
|
405
405
|
</button>
|
|
406
406
|
</div>
|
|
407
407
|
`;
|
|
@@ -409,7 +409,7 @@ async function showExecutionDetail(executionId, sourceDir) {
|
|
|
409
409
|
// Store conversation data for format switching
|
|
410
410
|
window._currentConversation = conversation;
|
|
411
411
|
|
|
412
|
-
showModal('
|
|
412
|
+
showModal(t('cli.conversationDetail'), modalContent);
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
// ========== Actions ==========
|
|
@@ -433,12 +433,12 @@ function searchCliHistory(query) {
|
|
|
433
433
|
async function refreshCliHistory() {
|
|
434
434
|
await loadCliHistory();
|
|
435
435
|
renderCliHistory();
|
|
436
|
-
showRefreshToast('
|
|
436
|
+
showRefreshToast(t('cli.historyRefreshed'), 'success');
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
// ========== Delete Execution ==========
|
|
440
440
|
function confirmDeleteExecution(executionId, sourceDir) {
|
|
441
|
-
if (confirm('
|
|
441
|
+
if (confirm(t('cli.confirmDelete'))) {
|
|
442
442
|
deleteExecution(executionId, sourceDir);
|
|
443
443
|
}
|
|
444
444
|
}
|
|
@@ -471,10 +471,10 @@ async function deleteExecution(executionId, sourceDir) {
|
|
|
471
471
|
} else {
|
|
472
472
|
renderCliHistory();
|
|
473
473
|
}
|
|
474
|
-
showRefreshToast('
|
|
474
|
+
showRefreshToast(t('cli.executionDeleted'), 'success');
|
|
475
475
|
} catch (err) {
|
|
476
476
|
console.error('Failed to delete execution:', err);
|
|
477
|
-
showRefreshToast('
|
|
477
|
+
showRefreshToast(t('cli.deleteFailed') + ': ' + err.message, 'error');
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
|
|
@@ -483,10 +483,10 @@ async function copyCliExecutionId(executionId) {
|
|
|
483
483
|
if (navigator.clipboard) {
|
|
484
484
|
try {
|
|
485
485
|
await navigator.clipboard.writeText(executionId);
|
|
486
|
-
showRefreshToast('
|
|
486
|
+
showRefreshToast(t('cli.idCopied') + ': ' + executionId, 'success');
|
|
487
487
|
} catch (err) {
|
|
488
488
|
console.error('Failed to copy ID:', err);
|
|
489
|
-
showRefreshToast('
|
|
489
|
+
showRefreshToast(t('cli.failedToCopy'), 'error');
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
}
|
|
@@ -494,16 +494,16 @@ async function copyCliExecutionId(executionId) {
|
|
|
494
494
|
async function copyExecutionPrompt(executionId) {
|
|
495
495
|
const detail = await loadExecutionDetail(executionId);
|
|
496
496
|
if (!detail) {
|
|
497
|
-
showRefreshToast('
|
|
497
|
+
showRefreshToast(t('cli.executionNotFound'), 'error');
|
|
498
498
|
return;
|
|
499
499
|
}
|
|
500
500
|
|
|
501
501
|
if (navigator.clipboard) {
|
|
502
502
|
try {
|
|
503
503
|
await navigator.clipboard.writeText(detail.prompt);
|
|
504
|
-
showRefreshToast('
|
|
504
|
+
showRefreshToast(t('cli.promptCopied'), 'success');
|
|
505
505
|
} catch (err) {
|
|
506
|
-
showRefreshToast('
|
|
506
|
+
showRefreshToast(t('cli.failedToCopy'), 'error');
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
}
|
|
@@ -512,7 +512,7 @@ async function copyConversationId(conversationId) {
|
|
|
512
512
|
if (navigator.clipboard) {
|
|
513
513
|
try {
|
|
514
514
|
await navigator.clipboard.writeText(conversationId);
|
|
515
|
-
showRefreshToast('
|
|
515
|
+
showRefreshToast(t('cli.idCopied'), 'success');
|
|
516
516
|
} catch (err) {
|
|
517
517
|
showRefreshToast('Failed to copy', 'error');
|
|
518
518
|
}
|
|
@@ -667,7 +667,7 @@ function switchConcatFormat(format, executionId) {
|
|
|
667
667
|
async function copyConcatenatedPrompt(executionId) {
|
|
668
668
|
var conversation = window._currentConversation;
|
|
669
669
|
if (!conversation) {
|
|
670
|
-
showRefreshToast('
|
|
670
|
+
showRefreshToast(t('cli.conversationNotFound'), 'error');
|
|
671
671
|
return;
|
|
672
672
|
}
|
|
673
673
|
|
|
@@ -675,7 +675,7 @@ async function copyConcatenatedPrompt(executionId) {
|
|
|
675
675
|
if (navigator.clipboard) {
|
|
676
676
|
try {
|
|
677
677
|
await navigator.clipboard.writeText(prompt);
|
|
678
|
-
showRefreshToast('
|
|
678
|
+
showRefreshToast(t('cli.fullPromptCopied'), 'success');
|
|
679
679
|
} catch (err) {
|
|
680
680
|
showRefreshToast('Failed to copy', 'error');
|
|
681
681
|
}
|
|
@@ -692,7 +692,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
692
692
|
const nativeSession = await loadNativeSessionContent(executionId, sourceDir);
|
|
693
693
|
|
|
694
694
|
if (!nativeSession) {
|
|
695
|
-
showRefreshToast('
|
|
695
|
+
showRefreshToast(t('cli.nativeSessionNotFound'), 'error');
|
|
696
696
|
return;
|
|
697
697
|
}
|
|
698
698
|
|
|
@@ -718,7 +718,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
718
718
|
<details class="turn-thinking-details">
|
|
719
719
|
<summary class="turn-thinking-summary">
|
|
720
720
|
<i data-lucide="brain" class="w-3 h-3"></i>
|
|
721
|
-
💭
|
|
721
|
+
💭 ${t('cli.thinkingProcess')} (${turn.thoughts.length} ${t('cli.thoughts')})
|
|
722
722
|
</summary>
|
|
723
723
|
<div class="turn-thinking-content">
|
|
724
724
|
<ul class="native-thoughts-list">
|
|
@@ -734,7 +734,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
734
734
|
? `<div class="native-tools-section">
|
|
735
735
|
<div class="turn-tool-calls-header">
|
|
736
736
|
<i data-lucide="wrench" class="w-3 h-3"></i>
|
|
737
|
-
<strong
|
|
737
|
+
<strong>${t('cli.toolCalls')} (${turn.toolCalls.length})</strong>
|
|
738
738
|
</div>
|
|
739
739
|
<div class="native-tools-list">
|
|
740
740
|
${turn.toolCalls.map((tc, tcIdx) => `
|
|
@@ -768,11 +768,11 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
768
768
|
<div class="native-turn-header">
|
|
769
769
|
<span class="native-turn-role">
|
|
770
770
|
<i data-lucide="${roleIcon}" class="w-3.5 h-3.5"></i>
|
|
771
|
-
${turn.role === 'user' ? '
|
|
771
|
+
${turn.role === 'user' ? t('cli.user') : t('cli.assistant')}
|
|
772
772
|
</span>
|
|
773
773
|
<span class="native-turn-number">Turn ${turn.turnNumber}</span>
|
|
774
774
|
${tokenInfo}
|
|
775
|
-
${isLast ?
|
|
775
|
+
${isLast ? `<span class="native-turn-latest">${t('cli.latest')}</span>` : ''}
|
|
776
776
|
</div>
|
|
777
777
|
<div class="native-turn-content">
|
|
778
778
|
<pre>${escapeHtml(turn.content)}</pre>
|
|
@@ -788,7 +788,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
788
788
|
const totalTokensHtml = nativeSession.totalTokens
|
|
789
789
|
? `<div class="native-tokens-summary">
|
|
790
790
|
<i data-lucide="bar-chart-3" class="w-4 h-4"></i>
|
|
791
|
-
<strong
|
|
791
|
+
<strong>${t('cli.totalTokens')}:</strong>
|
|
792
792
|
${nativeSession.totalTokens.total || 0}
|
|
793
793
|
(Input: ${nativeSession.totalTokens.input || 0},
|
|
794
794
|
Output: ${nativeSession.totalTokens.output || 0}
|
|
@@ -816,13 +816,13 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
816
816
|
</div>
|
|
817
817
|
<div class="native-session-actions">
|
|
818
818
|
<button class="btn btn-sm btn-outline" onclick="copyNativeSessionId('${nativeSession.sessionId}')">
|
|
819
|
-
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
|
819
|
+
<i data-lucide="copy" class="w-3.5 h-3.5"></i> ${t('cli.copySessionId')}
|
|
820
820
|
</button>
|
|
821
821
|
<button class="btn btn-sm btn-outline" onclick="copyNativeSessionPath('${executionId}')">
|
|
822
|
-
<i data-lucide="file" class="w-3.5 h-3.5"></i>
|
|
822
|
+
<i data-lucide="file" class="w-3.5 h-3.5"></i> ${t('cli.copyFilePath')}
|
|
823
823
|
</button>
|
|
824
824
|
<button class="btn btn-sm btn-outline" onclick="exportNativeSession('${executionId}')">
|
|
825
|
-
<i data-lucide="download" class="w-3.5 h-3.5"></i>
|
|
825
|
+
<i data-lucide="download" class="w-3.5 h-3.5"></i> ${t('cli.exportJson')}
|
|
826
826
|
</button>
|
|
827
827
|
</div>
|
|
828
828
|
</div>
|
|
@@ -831,7 +831,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
|
|
|
831
831
|
// Store for export
|
|
832
832
|
window._currentNativeSession = nativeSession;
|
|
833
833
|
|
|
834
|
-
showModal('
|
|
834
|
+
showModal(t('cli.nativeSessionDetail'), modalContent, { size: 'lg' });
|
|
835
835
|
}
|
|
836
836
|
|
|
837
837
|
/**
|
|
@@ -841,7 +841,7 @@ async function copyNativeSessionId(sessionId) {
|
|
|
841
841
|
if (navigator.clipboard) {
|
|
842
842
|
try {
|
|
843
843
|
await navigator.clipboard.writeText(sessionId);
|
|
844
|
-
showRefreshToast('
|
|
844
|
+
showRefreshToast(t('cli.sessionIdCopied'), 'success');
|
|
845
845
|
} catch (err) {
|
|
846
846
|
showRefreshToast('Failed to copy', 'error');
|
|
847
847
|
}
|
|
@@ -858,13 +858,13 @@ async function copyNativeSessionPath(executionId) {
|
|
|
858
858
|
if (navigator.clipboard) {
|
|
859
859
|
try {
|
|
860
860
|
await navigator.clipboard.writeText(exec.nativeSessionPath);
|
|
861
|
-
showRefreshToast('
|
|
861
|
+
showRefreshToast(t('cli.filePathCopied'), 'success');
|
|
862
862
|
} catch (err) {
|
|
863
863
|
showRefreshToast('Failed to copy', 'error');
|
|
864
864
|
}
|
|
865
865
|
}
|
|
866
866
|
} else {
|
|
867
|
-
showRefreshToast('
|
|
867
|
+
showRefreshToast(t('cli.pathNotAvailable'), 'error');
|
|
868
868
|
}
|
|
869
869
|
}
|
|
870
870
|
|
|
@@ -874,7 +874,7 @@ async function copyNativeSessionPath(executionId) {
|
|
|
874
874
|
function exportNativeSession(executionId) {
|
|
875
875
|
const session = window._currentNativeSession;
|
|
876
876
|
if (!session) {
|
|
877
|
-
showRefreshToast('
|
|
877
|
+
showRefreshToast(t('cli.noSessionData'), 'error');
|
|
878
878
|
return;
|
|
879
879
|
}
|
|
880
880
|
|
|
@@ -887,7 +887,7 @@ function exportNativeSession(executionId) {
|
|
|
887
887
|
a.click();
|
|
888
888
|
document.body.removeChild(a);
|
|
889
889
|
URL.revokeObjectURL(url);
|
|
890
|
-
showRefreshToast('
|
|
890
|
+
showRefreshToast(t('cli.sessionExported'), 'success');
|
|
891
891
|
}
|
|
892
892
|
|
|
893
893
|
// ========== Helpers ==========
|
|
@@ -303,6 +303,12 @@ async function refreshWorkspace() {
|
|
|
303
303
|
liteTaskDataStore[sessionKey] = s;
|
|
304
304
|
});
|
|
305
305
|
|
|
306
|
+
// Populate multiCliPlan sessions
|
|
307
|
+
(data.liteTasks?.multiCliPlan || []).forEach(s => {
|
|
308
|
+
const sessionKey = `multi-cli-${s.id}`.replace(/[^a-zA-Z0-9-]/g, '-');
|
|
309
|
+
liteTaskDataStore[sessionKey] = s;
|
|
310
|
+
});
|
|
311
|
+
|
|
306
312
|
// Update global data
|
|
307
313
|
window.workflowData = data;
|
|
308
314
|
|
|
@@ -827,6 +827,12 @@ async function refreshWorkspaceData(newData) {
|
|
|
827
827
|
liteTaskDataStore[key] = s;
|
|
828
828
|
});
|
|
829
829
|
|
|
830
|
+
// Populate multiCliPlan sessions
|
|
831
|
+
(newData.liteTasks?.multiCliPlan || []).forEach(s => {
|
|
832
|
+
const key = `multi-cli-${s.id}`.replace(/[^a-zA-Z0-9-]/g, '-');
|
|
833
|
+
liteTaskDataStore[key] = s;
|
|
834
|
+
});
|
|
835
|
+
|
|
830
836
|
// Update UI silently
|
|
831
837
|
updateStats();
|
|
832
838
|
updateBadges();
|
|
@@ -60,6 +60,9 @@ async function checkForUpdatesNow() {
|
|
|
60
60
|
btn.disabled = true;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// Show checking state on badge
|
|
64
|
+
updateVersionBadge('checking');
|
|
65
|
+
|
|
63
66
|
// Show checking notification
|
|
64
67
|
console.log('[Version Check] Starting update check...');
|
|
65
68
|
if (typeof addGlobalNotification === 'function') {
|
|
@@ -83,6 +86,9 @@ async function checkForUpdatesNow() {
|
|
|
83
86
|
versionCheckData = data;
|
|
84
87
|
console.log('[Version Check] Result:', data);
|
|
85
88
|
|
|
89
|
+
// Update badge based on result
|
|
90
|
+
updateVersionBadge(data.hasUpdate ? 'has-update' : 'none');
|
|
91
|
+
|
|
86
92
|
if (data.hasUpdate) {
|
|
87
93
|
// New version available
|
|
88
94
|
console.log('[Version Check] Update available:', data.latestVersion);
|
|
@@ -109,6 +115,8 @@ async function checkForUpdatesNow() {
|
|
|
109
115
|
}
|
|
110
116
|
} catch (err) {
|
|
111
117
|
console.error('[Version Check] Error:', err);
|
|
118
|
+
// Clear badge on error
|
|
119
|
+
updateVersionBadge('none');
|
|
112
120
|
if (typeof addGlobalNotification === 'function') {
|
|
113
121
|
addGlobalNotification(
|
|
114
122
|
'error',
|
|
@@ -154,6 +162,9 @@ async function checkForUpdates() {
|
|
|
154
162
|
|
|
155
163
|
versionCheckData = await res.json();
|
|
156
164
|
|
|
165
|
+
// Update badge
|
|
166
|
+
updateVersionBadge(versionCheckData.hasUpdate ? 'has-update' : 'none');
|
|
167
|
+
|
|
157
168
|
if (versionCheckData.hasUpdate && !versionBannerDismissed) {
|
|
158
169
|
showUpdateBanner(versionCheckData);
|
|
159
170
|
addGlobalNotification(
|
|
@@ -299,3 +310,30 @@ function getVersionInfo() {
|
|
|
299
310
|
function isAutoUpdateEnabled() {
|
|
300
311
|
return autoUpdateEnabled;
|
|
301
312
|
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Update version badge state
|
|
316
|
+
* @param {string} state - 'checking', 'has-update', 'none'
|
|
317
|
+
*/
|
|
318
|
+
function updateVersionBadge(state) {
|
|
319
|
+
const badge = document.getElementById('versionBadge');
|
|
320
|
+
if (!badge) return;
|
|
321
|
+
|
|
322
|
+
// Remove all state classes
|
|
323
|
+
badge.classList.remove('has-update', 'checking');
|
|
324
|
+
badge.textContent = '';
|
|
325
|
+
|
|
326
|
+
switch (state) {
|
|
327
|
+
case 'checking':
|
|
328
|
+
badge.classList.add('checking');
|
|
329
|
+
break;
|
|
330
|
+
case 'has-update':
|
|
331
|
+
badge.classList.add('has-update');
|
|
332
|
+
badge.textContent = '!';
|
|
333
|
+
break;
|
|
334
|
+
case 'none':
|
|
335
|
+
default:
|
|
336
|
+
// Hide badge
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
}
|