@beastmode-develeap/beastmode 0.1.263 → 0.1.264

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.
@@ -15,7 +15,7 @@
15
15
  }
16
16
  </script>
17
17
  <!--BOARD_DATA-->
18
- <script>window.__BUILD_STAMP__ = "20260515-111550-43871cf";</script>
18
+ <script>window.__BUILD_STAMP__ = "20260515-112233-b18940e";</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">
@@ -3957,7 +3957,7 @@ fetch('/api/pipeline-config')
3957
3957
  // ================================================================
3958
3958
  // CDN Imports
3959
3959
  // ================================================================
3960
- import { h, render } from 'https://unpkg.com/preact@10.25.4/dist/preact.module.js';
3960
+ import { h, render, Fragment } from 'https://unpkg.com/preact@10.25.4/dist/preact.module.js';
3961
3961
  import { useState, useEffect, useCallback, useRef, useMemo } from 'https://unpkg.com/preact@10.25.4/hooks/dist/hooks.module.js';
3962
3962
  import htm from 'https://unpkg.com/htm@3.1.1/dist/htm.module.js';
3963
3963
 
@@ -10776,6 +10776,8 @@ function CostsPage({ selectedProject }) {
10776
10776
  const [boardItems, setBoardItems] = useState([]);
10777
10777
  const [phaseData, setPhaseData] = useState([]);
10778
10778
  const [inFlightItems, setInFlightItems] = useState([]);
10779
+ const [byIterationMap, setByIterationMap] = useState({});
10780
+ const [expandedRows, setExpandedRows] = useState({});
10779
10781
  const [loading, setLoading] = useState(true);
10780
10782
  const [error, setError] = useState(null);
10781
10783
  const [sortCol, setSortCol] = useState('cost');
@@ -10817,6 +10819,7 @@ function CostsPage({ selectedProject }) {
10817
10819
  const itemIds = Object.keys(costsData || {});
10818
10820
  if (itemIds.length > 0) {
10819
10821
  const phaseMap = {};
10822
+ const iterMap = {};
10820
10823
  const summaryResults = await Promise.allSettled(
10821
10824
  itemIds.map(id => {
10822
10825
  const qs = (selectedProject && selectedProject !== 'all')
@@ -10825,17 +10828,26 @@ function CostsPage({ selectedProject }) {
10825
10828
  return api('GET', '/api/items/' + id + '/costs/summary' + qs);
10826
10829
  })
10827
10830
  );
10828
- summaryResults.forEach(result => {
10829
- if (result.status === 'fulfilled' && result.value && result.value.phases) {
10830
- for (const [phaseName, phaseInfo] of Object.entries(result.value.phases)) {
10831
- phaseMap[phaseName] = (phaseMap[phaseName] || 0) + (phaseInfo.cost_usd || 0);
10831
+ summaryResults.forEach((result, idx) => {
10832
+ if (result.status === 'fulfilled' && result.value) {
10833
+ const itemId = itemIds[idx];
10834
+ if (result.value.phases) {
10835
+ for (const [phaseName, phaseInfo] of Object.entries(result.value.phases)) {
10836
+ phaseMap[phaseName] = (phaseMap[phaseName] || 0) + (phaseInfo.cost_usd || 0);
10837
+ }
10838
+ }
10839
+ if (Array.isArray(result.value.by_iteration)) {
10840
+ iterMap[itemId] = result.value.by_iteration;
10832
10841
  }
10833
10842
  }
10834
10843
  });
10835
10844
  const sorted = Object.entries(phaseMap)
10836
10845
  .map(([phase, cost]) => ({ phase, cost }))
10837
10846
  .sort((a, b) => b.cost - a.cost);
10838
- if (!cancelled) setPhaseData(sorted);
10847
+ if (!cancelled) {
10848
+ setPhaseData(sorted);
10849
+ setByIterationMap(iterMap);
10850
+ }
10839
10851
  }
10840
10852
  } catch (e) {
10841
10853
  if (!cancelled) setError(e.message || 'Failed to load cost data');
@@ -10878,6 +10890,7 @@ function CostsPage({ selectedProject }) {
10878
10890
  totalTokens: (costs.total_input_tokens || 0) + (costs.total_output_tokens || 0),
10879
10891
  costUsd: costs.total_cost_usd || 0,
10880
10892
  records: costs.record_count || 0,
10893
+ byIteration: byIterationMap[itemId] || [],
10881
10894
  };
10882
10895
  });
10883
10896
 
@@ -10992,16 +11005,38 @@ function CostsPage({ selectedProject }) {
10992
11005
  </tr>
10993
11006
  </thead>
10994
11007
  <tbody>
10995
- ${sortedRows.map(row => html`
10996
- <tr key=${row.id} class="costs-tr" onClick=${() => navigate('#/board?item=' + row.id)}>
10997
- <td class="costs-td costs-td-mono">#${row.id}</td>
10998
- <td class="costs-td costs-td-name" title=${row.name}>${row.name}</td>
10999
- <td class="costs-td"><span class=${'badge ' + statusBadgeClass(row.status)}>${row.status}</span></td>
11000
- <td class="costs-td costs-td-mono">${formatTokens(row.totalTokens)}</td>
11001
- <td class="costs-td costs-td-mono">$${row.costUsd.toFixed(2)}</td>
11002
- <td class="costs-td costs-td-mono">${row.records}</td>
11003
- </tr>
11004
- `)}
11008
+ ${sortedRows.map(row => {
11009
+ const hasMultiIter = row.byIteration && row.byIteration.length > 1;
11010
+ const isExpanded = !!expandedRows[row.id];
11011
+ const toggle = (e) => {
11012
+ e.stopPropagation();
11013
+ setExpandedRows(prev => ({ ...prev, [row.id]: !prev[row.id] }));
11014
+ };
11015
+ return html`
11016
+ <${Fragment} key=${row.id}>
11017
+ <tr class="costs-tr" onClick=${() => navigate('#/board?item=' + row.id)}>
11018
+ <td class="costs-td costs-td-mono">
11019
+ ${hasMultiIter ? html`<span class="costs-expand-toggle" onClick=${toggle} style="cursor:pointer;display:inline-block;width:14px;">${isExpanded ? '▼' : '▶'}</span> ` : ''}#${row.id}
11020
+ </td>
11021
+ <td class="costs-td costs-td-name" title=${row.name}>${row.name}</td>
11022
+ <td class="costs-td"><span class=${'badge ' + statusBadgeClass(row.status)}>${row.status}</span></td>
11023
+ <td class="costs-td costs-td-mono">${formatTokens(row.totalTokens)}</td>
11024
+ <td class="costs-td costs-td-mono">$${row.costUsd.toFixed(2)}</td>
11025
+ <td class="costs-td costs-td-mono">${row.records}</td>
11026
+ </tr>
11027
+ ${hasMultiIter && isExpanded ? row.byIteration.map(it => html`
11028
+ <tr key=${'iter-' + row.id + '-' + it.iteration} class="costs-tr costs-iter-row" style="background:rgba(0,0,0,0.02);">
11029
+ <td class="costs-td costs-td-mono" style="padding-left:32px;">Iter ${it.iteration}</td>
11030
+ <td class="costs-td costs-td-name" style="opacity:0.7;">↳ iteration ${it.iteration}</td>
11031
+ <td class="costs-td"></td>
11032
+ <td class="costs-td costs-td-mono">${formatTokens((it.input_tokens || 0) + (it.output_tokens || 0))}</td>
11033
+ <td class="costs-td costs-td-mono">${it.cost_usd != null ? '$' + it.cost_usd.toFixed(2) : '—'}</td>
11034
+ <td class="costs-td costs-td-mono">${it.record_count || 0}</td>
11035
+ </tr>
11036
+ `) : ''}
11037
+ </${Fragment}>
11038
+ `;
11039
+ })}
11005
11040
  </tbody>
11006
11041
  </table>
11007
11042
  </div>
@@ -1 +1 @@
1
- 43871cf4eea7789ef20aeed2f50e97a7b722d510
1
+ b18940e14eaa9237e2ee985b0e2a369348447fe0
@@ -1 +1 @@
1
- 20260515-111550-43871cf
1
+ 20260515-112233-b18940e
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.263",
3
+ "version": "0.1.264",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {