@beastmode-develeap/beastmode 0.1.260 → 0.1.262
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/dist/web/board.html +94 -3
- package/dist/web/build-commit.txt +1 -1
- package/dist/web/build-stamp.txt +1 -1
- package/package.json +1 -1
package/dist/web/board.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
</script>
|
|
17
17
|
<!--BOARD_DATA-->
|
|
18
|
-
<script>window.__BUILD_STAMP__ = "20260515-
|
|
18
|
+
<script>window.__BUILD_STAMP__ = "20260515-105557-41eb86a";</script>
|
|
19
19
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
20
20
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
21
21
|
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
@@ -5579,8 +5579,11 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
|
|
|
5579
5579
|
const [attachments, setAttachments] = useState([]);
|
|
5580
5580
|
const [loadingAttachments, setLoadingAttachments] = useState(true);
|
|
5581
5581
|
const [costSummary, setCostSummary] = useState(null);
|
|
5582
|
+
const [liveCost, setLiveCost] = useState(null);
|
|
5582
5583
|
const [loadingCost, setLoadingCost] = useState(true);
|
|
5583
5584
|
const [phaseData, setPhaseData] = useState([]);
|
|
5585
|
+
const TERMINAL_STATUSES = ['Done', 'Superseded', 'New', 'Drafts', 'Ready'];
|
|
5586
|
+
const isNonTerminal = item && item.status && !TERMINAL_STATUSES.includes(item.status);
|
|
5584
5587
|
const [envTimeline, setEnvTimeline] = useState(null);
|
|
5585
5588
|
const [deployModal, setDeployModal] = useState(null);
|
|
5586
5589
|
const [auditEvents, setAuditEvents] = useState([]);
|
|
@@ -5658,7 +5661,15 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
|
|
|
5658
5661
|
.then(r => r.ok ? r.json() : null)
|
|
5659
5662
|
.then(data => setCostSummary(data && data.record_count > 0 ? data : null))
|
|
5660
5663
|
.catch(() => setCostSummary(null));
|
|
5661
|
-
|
|
5664
|
+
if (isNonTerminal) {
|
|
5665
|
+
fetch('/api/items/' + item.id + '/costs/live' + boardParam)
|
|
5666
|
+
.then(r => r.ok ? r.json() : null)
|
|
5667
|
+
.then(data => setLiveCost(data && data.record_count > 0 ? data : null))
|
|
5668
|
+
.catch(() => setLiveCost(null));
|
|
5669
|
+
} else {
|
|
5670
|
+
setLiveCost(null);
|
|
5671
|
+
}
|
|
5672
|
+
}, [item && item.id, isNonTerminal]);
|
|
5662
5673
|
|
|
5663
5674
|
const refreshPhaseData = useCallback(() => {
|
|
5664
5675
|
if (!item) return;
|
|
@@ -5716,6 +5727,14 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
|
|
|
5716
5727
|
.then(data => setCostSummary(data && data.record_count > 0 ? data : null))
|
|
5717
5728
|
.catch(() => setCostSummary(null))
|
|
5718
5729
|
.finally(() => setLoadingCost(false));
|
|
5730
|
+
if (isNonTerminal) {
|
|
5731
|
+
fetch('/api/items/' + item.id + '/costs/live' + boardParam)
|
|
5732
|
+
.then(r => r.ok ? r.json() : null)
|
|
5733
|
+
.then(data => setLiveCost(data && data.record_count > 0 ? data : null))
|
|
5734
|
+
.catch(() => setLiveCost(null));
|
|
5735
|
+
} else {
|
|
5736
|
+
setLiveCost(null);
|
|
5737
|
+
}
|
|
5719
5738
|
// Also fetch the per-phase breakdown for the expandable table
|
|
5720
5739
|
fetch('/api/items/' + item.id + '/costs/by-phase' + boardParam)
|
|
5721
5740
|
.then(r => r.ok ? r.json() : [])
|
|
@@ -5902,6 +5921,11 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
|
|
|
5902
5921
|
<span style="font-family:var(--font-mono);color:var(--success);">$</span>
|
|
5903
5922
|
Cost Summary
|
|
5904
5923
|
</h4>
|
|
5924
|
+
${liveCost && html`
|
|
5925
|
+
<div class="cost-live-iter-indicator" data-testid="live-iteration-indicator" style="margin-bottom:8px;padding:6px 10px;border-radius:4px;background:rgba(245,158,11,0.1);color:#f59e0b;font-size:12px;font-weight:600;">
|
|
5926
|
+
Iteration ${liveCost.current_iteration} · ${liveCost.latest_phase || 'pending'}
|
|
5927
|
+
</div>
|
|
5928
|
+
`}
|
|
5905
5929
|
<div class="cost-totals">
|
|
5906
5930
|
<div class="cost-total-item">
|
|
5907
5931
|
<span class="cost-total-label">Total Cost</span>
|
|
@@ -5916,6 +5940,21 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
|
|
|
5916
5940
|
<span class="cost-total-value">${formatDuration(costSummary.total_duration_seconds)}</span>
|
|
5917
5941
|
</div>
|
|
5918
5942
|
</div>
|
|
5943
|
+
${liveCost && liveCost.by_iteration && liveCost.by_iteration.length > 0 && html`
|
|
5944
|
+
<div class="cost-by-iteration" data-testid="live-by-iteration" style="margin-top:10px;font-size:12px;">
|
|
5945
|
+
<div style="font-weight:600;margin-bottom:4px;color:var(--text-dim);">By Iteration</div>
|
|
5946
|
+
${liveCost.by_iteration.map((it, idx) => {
|
|
5947
|
+
const isLast = idx === liveCost.by_iteration.length - 1;
|
|
5948
|
+
const isCurrent = isNonTerminal && isLast;
|
|
5949
|
+
const phaseList = (it.phases || []).join(', ');
|
|
5950
|
+
return html`
|
|
5951
|
+
<div key=${it.iteration} data-testid=${'live-iter-' + it.iteration} style="display:flex;justify-content:space-between;padding:2px 0;">
|
|
5952
|
+
<span>Iter ${it.iteration}: ${formatCost(it.cost_usd) || '$0.00'} (${phaseList})${isCurrent ? html`<span style="color:#f59e0b;margin-left:6px;">← current</span>` : ''}</span>
|
|
5953
|
+
</div>
|
|
5954
|
+
`;
|
|
5955
|
+
})}
|
|
5956
|
+
</div>
|
|
5957
|
+
`}
|
|
5919
5958
|
${phaseData && phaseData.length > 0
|
|
5920
5959
|
? html`<${CostPhaseTable} itemId=${item.id} boardParam=${(() => { const p = localStorage.getItem('beastmode-selected-project') || ''; return (p && p !== 'all') ? '?board=' + encodeURIComponent(p) : ''; })()} />`
|
|
5921
5960
|
: (costSummary.phases && Object.keys(costSummary.phases).length > 0 && html`
|
|
@@ -10736,6 +10775,7 @@ function CostsPage({ selectedProject }) {
|
|
|
10736
10775
|
const [costsByItems, setCostsByItems] = useState({});
|
|
10737
10776
|
const [boardItems, setBoardItems] = useState([]);
|
|
10738
10777
|
const [phaseData, setPhaseData] = useState([]);
|
|
10778
|
+
const [inFlightItems, setInFlightItems] = useState([]);
|
|
10739
10779
|
const [loading, setLoading] = useState(true);
|
|
10740
10780
|
const [error, setError] = useState(null);
|
|
10741
10781
|
const [sortCol, setSortCol] = useState('cost');
|
|
@@ -10749,15 +10789,30 @@ function CostsPage({ selectedProject }) {
|
|
|
10749
10789
|
const costQs = (selectedProject && selectedProject !== 'all')
|
|
10750
10790
|
? '?board=' + encodeURIComponent(selectedProject)
|
|
10751
10791
|
: '';
|
|
10792
|
+
const inFlightQs = (selectedProject && selectedProject !== 'all')
|
|
10793
|
+
? '?board=' + encodeURIComponent(selectedProject) + '&threshold=5'
|
|
10794
|
+
: '?threshold=5';
|
|
10752
10795
|
|
|
10753
|
-
const [costsData, boardData] = await Promise.all([
|
|
10796
|
+
const [costsData, boardData, inFlightData] = await Promise.all([
|
|
10754
10797
|
api('GET', '/api/costs/by-items' + costQs),
|
|
10755
10798
|
api('GET', '/api/board/items'),
|
|
10799
|
+
api('GET', '/api/costs/in-flight' + inFlightQs).catch(() => ({})),
|
|
10756
10800
|
]);
|
|
10757
10801
|
|
|
10758
10802
|
if (cancelled) return;
|
|
10759
10803
|
setCostsByItems(costsData || {});
|
|
10760
10804
|
setBoardItems((boardData && boardData.items) || []);
|
|
10805
|
+
const inFlightArr = Object.values(inFlightData || {})
|
|
10806
|
+
.map(r => ({
|
|
10807
|
+
id: r.item_id,
|
|
10808
|
+
name: r.name || ('Item #' + r.item_id),
|
|
10809
|
+
status: r.status || '',
|
|
10810
|
+
costUsd: r.total_cost_usd || 0,
|
|
10811
|
+
iteration: r.max_iteration || 0,
|
|
10812
|
+
latestPhase: r.latest_phase || '',
|
|
10813
|
+
}))
|
|
10814
|
+
.sort((a, b) => b.costUsd - a.costUsd);
|
|
10815
|
+
setInFlightItems(inFlightArr);
|
|
10761
10816
|
|
|
10762
10817
|
const itemIds = Object.keys(costsData || {});
|
|
10763
10818
|
if (itemIds.length > 0) {
|
|
@@ -10883,6 +10938,42 @@ function CostsPage({ selectedProject }) {
|
|
|
10883
10938
|
</div>
|
|
10884
10939
|
</div>
|
|
10885
10940
|
|
|
10941
|
+
${inFlightItems.length > 0 && html`
|
|
10942
|
+
<div class="card" data-testid="currently-running-card" style="margin-bottom:24px;border-left:4px solid #f59e0b;">
|
|
10943
|
+
<div class="card-header">
|
|
10944
|
+
<h3 style="color:#f59e0b;">Currently Running</h3>
|
|
10945
|
+
<span class="badge badge-accent">${inFlightItems.length} in-flight</span>
|
|
10946
|
+
</div>
|
|
10947
|
+
<div class="costs-table-wrapper">
|
|
10948
|
+
<table class="costs-table" data-testid="currently-running-table">
|
|
10949
|
+
<thead>
|
|
10950
|
+
<tr>
|
|
10951
|
+
<th class="costs-th costs-th-id">ID</th>
|
|
10952
|
+
<th class="costs-th costs-th-name">Task</th>
|
|
10953
|
+
<th class="costs-th costs-th-status">Status</th>
|
|
10954
|
+
<th class="costs-th costs-th-cost">Cost (USD)</th>
|
|
10955
|
+
<th class="costs-th costs-th-records">Iter</th>
|
|
10956
|
+
</tr>
|
|
10957
|
+
</thead>
|
|
10958
|
+
<tbody>
|
|
10959
|
+
${inFlightItems.map(row => {
|
|
10960
|
+
const truncatedName = row.name.length > 40 ? row.name.slice(0, 40) + '…' : row.name;
|
|
10961
|
+
return html`
|
|
10962
|
+
<tr key=${row.id} class="costs-tr" data-testid=${'in-flight-row-' + row.id} onClick=${() => navigate('#/board?item=' + row.id)}>
|
|
10963
|
+
<td class="costs-td costs-td-mono">#${row.id}</td>
|
|
10964
|
+
<td class="costs-td costs-td-name" title=${row.name}>${truncatedName}</td>
|
|
10965
|
+
<td class="costs-td"><span class=${'badge ' + statusBadgeClass(row.status)}>${row.status}</span></td>
|
|
10966
|
+
<td class="costs-td costs-td-mono" data-testid=${'in-flight-cost-' + row.id}>$${row.costUsd.toFixed(2)}</td>
|
|
10967
|
+
<td class="costs-td costs-td-mono">${row.iteration}</td>
|
|
10968
|
+
</tr>
|
|
10969
|
+
`;
|
|
10970
|
+
})}
|
|
10971
|
+
</tbody>
|
|
10972
|
+
</table>
|
|
10973
|
+
</div>
|
|
10974
|
+
</div>
|
|
10975
|
+
`}
|
|
10976
|
+
|
|
10886
10977
|
<div class="card">
|
|
10887
10978
|
<div class="card-header">
|
|
10888
10979
|
<h3>Cost by Task</h3>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
41eb86adb1d258a1079cdd20df0288a10655dc77
|
package/dist/web/build-stamp.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
20260515-
|
|
1
|
+
20260515-105557-41eb86a
|