@beastmode-develeap/beastmode 0.1.362 → 0.1.364
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 +148 -7
- 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__ = "20260605-
|
|
18
|
+
<script>window.__BUILD_STAMP__ = "20260605-023046-eb133e1";</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">
|
|
@@ -9947,6 +9947,14 @@ function SettingsPage() {
|
|
|
9947
9947
|
|
|
9948
9948
|
const [restartFields, setRestartFields] = useState(new Set());
|
|
9949
9949
|
|
|
9950
|
+
// Cost knobs (feature #888): the highest-cost in-flight item, shown next to
|
|
9951
|
+
// the per_item_usd_cap field so the operator can pick a sensible ceiling.
|
|
9952
|
+
const [costsByItems, setCostsByItems] = useState(null);
|
|
9953
|
+
// FR-2 hot-reload confirmation: the `cost` category is AUTO-reloaded by the
|
|
9954
|
+
// daemon (no restart), so after a save we surface "Reloading…" then
|
|
9955
|
+
// "Applied at HH:MM:SS" instead of a restart badge.
|
|
9956
|
+
const [costReload, setCostReload] = useState(null);
|
|
9957
|
+
|
|
9950
9958
|
useEffect(() => {
|
|
9951
9959
|
api('GET', '/api/config')
|
|
9952
9960
|
.then(setConfig)
|
|
@@ -9954,6 +9962,15 @@ function SettingsPage() {
|
|
|
9954
9962
|
.finally(() => setLoading(false));
|
|
9955
9963
|
}, []);
|
|
9956
9964
|
|
|
9965
|
+
useEffect(() => {
|
|
9966
|
+
// Not board-scoped: we want the global highest-cost item regardless of the
|
|
9967
|
+
// project filter. Swallow errors — the indicator falls back to "—".
|
|
9968
|
+
fetch('/api/costs/by-items')
|
|
9969
|
+
.then(r => r.ok ? r.json() : {})
|
|
9970
|
+
.then(data => setCostsByItems(data || {}))
|
|
9971
|
+
.catch(() => setCostsByItems({}));
|
|
9972
|
+
}, []);
|
|
9973
|
+
|
|
9957
9974
|
useEffect(() => {
|
|
9958
9975
|
api('GET', '/api/daemon/reload-categories')
|
|
9959
9976
|
.then(data => {
|
|
@@ -10007,6 +10024,15 @@ function SettingsPage() {
|
|
|
10007
10024
|
setConfig(result);
|
|
10008
10025
|
setSuccess('Configuration saved');
|
|
10009
10026
|
setTimeout(() => setSuccess(null), 3000);
|
|
10027
|
+
|
|
10028
|
+
// FR-2: the cost category hot-reloads without a restart. Show a brief
|
|
10029
|
+
// "Reloading…" then a timestamped "Applied" so the operator knows the
|
|
10030
|
+
// new ceiling is live, not pending a daemon bounce.
|
|
10031
|
+
setCostReload('reloading');
|
|
10032
|
+
setTimeout(() => {
|
|
10033
|
+
const t = new Date().toLocaleTimeString([], { hour12: false });
|
|
10034
|
+
setCostReload({ appliedAt: t });
|
|
10035
|
+
}, 700);
|
|
10010
10036
|
} catch (e) { setError(e.message); }
|
|
10011
10037
|
setSaving(false);
|
|
10012
10038
|
};
|
|
@@ -10044,6 +10070,17 @@ function SettingsPage() {
|
|
|
10044
10070
|
const cost = config.cost || {};
|
|
10045
10071
|
const humanGates = config.human_gates || {};
|
|
10046
10072
|
|
|
10073
|
+
// FR-3: highest in-flight item cost, used as a reference point next to the
|
|
10074
|
+
// per_item_usd_cap field. costsByItems is keyed by item id → { total_cost_usd }.
|
|
10075
|
+
// null = still loading; {} = loaded but no data → show "—".
|
|
10076
|
+
const highestItemCost = costsByItems
|
|
10077
|
+
? Object.values(costsByItems).reduce(
|
|
10078
|
+
(max, c) => Math.max(max, (c && c.total_cost_usd) || 0), 0)
|
|
10079
|
+
: null;
|
|
10080
|
+
const highestItemCostLabel = (highestItemCost && highestItemCost > 0)
|
|
10081
|
+
? (formatCost(highestItemCost) || '$' + highestItemCost.toFixed(2))
|
|
10082
|
+
: '—';
|
|
10083
|
+
|
|
10047
10084
|
// Build model options dynamically from whatever the config actually uses,
|
|
10048
10085
|
// plus well-known model families. No more hardcoding — when Anthropic
|
|
10049
10086
|
// releases a new model, it shows up as soon as someone sets it in config.
|
|
@@ -10232,13 +10269,40 @@ function SettingsPage() {
|
|
|
10232
10269
|
</div>
|
|
10233
10270
|
</div>
|
|
10234
10271
|
|
|
10235
|
-
<!-- Cost Section
|
|
10272
|
+
<!-- Cost Section. The "cost" category hot-reloads (ReloadCategory.AUTO),
|
|
10273
|
+
so it carries NO RestartBadge — instead saveConfig surfaces an
|
|
10274
|
+
inline "Reloading / Applied at HH:MM:SS" confirmation (FR-2). -->
|
|
10236
10275
|
<div class="settings-section">
|
|
10237
|
-
<h3 style="display:flex;align-items:center;gap:8px">
|
|
10276
|
+
<h3 style="display:flex;align-items:center;gap:8px">
|
|
10277
|
+
Cost Optimization
|
|
10278
|
+
${costReload === 'reloading'
|
|
10279
|
+
? html`<span style="font-size:12px;color:#888;font-weight:normal">⏳ Reloading…</span>`
|
|
10280
|
+
: (costReload && costReload.appliedAt)
|
|
10281
|
+
? html`<span style="font-size:12px;color:#16a34a;font-weight:normal">✅ Applied at ${costReload.appliedAt}</span>`
|
|
10282
|
+
: null}
|
|
10283
|
+
</h3>
|
|
10284
|
+
|
|
10285
|
+
<!-- Per-item USD cap (FR-3/FR-5): hard spend ceiling per item. -->
|
|
10286
|
+
<div class="setting-row">
|
|
10287
|
+
<div>
|
|
10288
|
+
<div class="setting-label">Per-Item Cost Cap (USD)</div>
|
|
10289
|
+
<div class="setting-desc">Hard ceiling on Claude cost per item in USD. Set to 0 to disable. When exceeded, the item transitions to Stuck on next dispatch.</div>
|
|
10290
|
+
<div class="setting-desc" style="margin-top:4px">Current item with highest cost: ${highestItemCostLabel}</div>
|
|
10291
|
+
</div>
|
|
10292
|
+
<div class="setting-control">
|
|
10293
|
+
<input type="number" class="form-input" min="0" max="10000" step="1" style="width:90px;text-align:center"
|
|
10294
|
+
value=${cost.per_item_usd_cap ?? 50.0}
|
|
10295
|
+
onInput=${e => {
|
|
10296
|
+
const v = parseFloat(e.target.value);
|
|
10297
|
+
updateField('cost.per_item_usd_cap', Number.isFinite(v) ? v : 50.0);
|
|
10298
|
+
}} />
|
|
10299
|
+
</div>
|
|
10300
|
+
</div>
|
|
10301
|
+
|
|
10238
10302
|
<div class="setting-row">
|
|
10239
10303
|
<div>
|
|
10240
10304
|
<div class="setting-label">Model Tiering</div>
|
|
10241
|
-
<div class="setting-desc">Use cheaper models for
|
|
10305
|
+
<div class="setting-desc">Use cheaper models for cheaper sub-tasks.</div>
|
|
10242
10306
|
</div>
|
|
10243
10307
|
<div class="setting-control">
|
|
10244
10308
|
<label class="toggle-switch">
|
|
@@ -10248,10 +10312,11 @@ function SettingsPage() {
|
|
|
10248
10312
|
</label>
|
|
10249
10313
|
</div>
|
|
10250
10314
|
</div>
|
|
10315
|
+
|
|
10251
10316
|
<div class="setting-row">
|
|
10252
10317
|
<div>
|
|
10253
10318
|
<div class="setting-label">Incremental Verification</div>
|
|
10254
|
-
<div class="setting-desc">
|
|
10319
|
+
<div class="setting-desc">Re-verify only changed scenarios between iterations.</div>
|
|
10255
10320
|
</div>
|
|
10256
10321
|
<div class="setting-control">
|
|
10257
10322
|
<label class="toggle-switch">
|
|
@@ -10261,19 +10326,95 @@ function SettingsPage() {
|
|
|
10261
10326
|
</label>
|
|
10262
10327
|
</div>
|
|
10263
10328
|
</div>
|
|
10329
|
+
|
|
10330
|
+
<div class="setting-row">
|
|
10331
|
+
<div>
|
|
10332
|
+
<div class="setting-label">Full Re-Verify Interval</div>
|
|
10333
|
+
<div class="setting-desc">Run a full re-verification every N iterations.</div>
|
|
10334
|
+
</div>
|
|
10335
|
+
<div class="setting-control">
|
|
10336
|
+
<input type="number" class="form-input" min="1" max="20" style="width:80px;text-align:center"
|
|
10337
|
+
value=${cost.full_reverify_interval ?? 3}
|
|
10338
|
+
onInput=${e => updateField('cost.full_reverify_interval', parseInt(e.target.value) || 3)} />
|
|
10339
|
+
</div>
|
|
10340
|
+
</div>
|
|
10341
|
+
|
|
10342
|
+
<!-- Build Check toggle (FR-6): disabling needs an explicit confirm so a
|
|
10343
|
+
broken build can't silently slip past verification. -->
|
|
10264
10344
|
<div class="setting-row">
|
|
10265
10345
|
<div>
|
|
10266
10346
|
<div class="setting-label">Build Check</div>
|
|
10267
|
-
<div class="setting-desc">
|
|
10347
|
+
<div class="setting-desc">Whether to run the build/compile check between iterations.</div>
|
|
10268
10348
|
</div>
|
|
10269
10349
|
<div class="setting-control">
|
|
10270
10350
|
<label class="toggle-switch">
|
|
10271
10351
|
<input type="checkbox" checked=${cost.build_check_enabled !== false}
|
|
10272
|
-
onChange=${e =>
|
|
10352
|
+
onChange=${e => {
|
|
10353
|
+
if (!e.target.checked && !window.confirm('Disable the build check? Broken builds will no longer be caught before verification.')) {
|
|
10354
|
+
return; // controlled input reverts to the prior state
|
|
10355
|
+
}
|
|
10356
|
+
updateField('cost.build_check_enabled', e.target.checked);
|
|
10357
|
+
}} />
|
|
10358
|
+
<span class="toggle-slider"></span>
|
|
10359
|
+
</label>
|
|
10360
|
+
</div>
|
|
10361
|
+
</div>
|
|
10362
|
+
|
|
10363
|
+
<div class="setting-row">
|
|
10364
|
+
<div>
|
|
10365
|
+
<div class="setting-label">Build Command</div>
|
|
10366
|
+
<div class="setting-desc">Shell command used for the incremental build check.</div>
|
|
10367
|
+
</div>
|
|
10368
|
+
<div class="setting-control">
|
|
10369
|
+
<input type="text" class="form-input" style="width:180px"
|
|
10370
|
+
placeholder="npm run build"
|
|
10371
|
+
value=${cost.build_check_command ?? 'npm run build'}
|
|
10372
|
+
onInput=${e => updateField('cost.build_check_command', e.target.value)} />
|
|
10373
|
+
</div>
|
|
10374
|
+
</div>
|
|
10375
|
+
|
|
10376
|
+
<div class="setting-row">
|
|
10377
|
+
<div>
|
|
10378
|
+
<div class="setting-label">Build Timeout (seconds)</div>
|
|
10379
|
+
<div class="setting-desc">Timeout in seconds for the build check command.</div>
|
|
10380
|
+
</div>
|
|
10381
|
+
<div class="setting-control">
|
|
10382
|
+
<input type="number" class="form-input" min="1" max="3600" style="width:90px;text-align:center"
|
|
10383
|
+
value=${cost.build_check_timeout_seconds ?? 90}
|
|
10384
|
+
onInput=${e => updateField('cost.build_check_timeout_seconds', parseInt(e.target.value) || 90)} />
|
|
10385
|
+
</div>
|
|
10386
|
+
</div>
|
|
10387
|
+
|
|
10388
|
+
<div class="setting-row">
|
|
10389
|
+
<div>
|
|
10390
|
+
<div class="setting-label">NLSpec Pre-Check</div>
|
|
10391
|
+
<div class="setting-desc">Cheap NLSpec compliance precheck before full verify.</div>
|
|
10392
|
+
</div>
|
|
10393
|
+
<div class="setting-control">
|
|
10394
|
+
<label class="toggle-switch">
|
|
10395
|
+
<input type="checkbox" checked=${cost.nlspec_precheck_enabled !== false}
|
|
10396
|
+
onChange=${e => updateField('cost.nlspec_precheck_enabled', e.target.checked)} />
|
|
10273
10397
|
<span class="toggle-slider"></span>
|
|
10274
10398
|
</label>
|
|
10275
10399
|
</div>
|
|
10276
10400
|
</div>
|
|
10401
|
+
|
|
10402
|
+
<!-- NLSpec pre-check model (FR-6): a fixed dropdown, no free text. -->
|
|
10403
|
+
<div class="setting-row">
|
|
10404
|
+
<div>
|
|
10405
|
+
<div class="setting-label">NLSpec Pre-Check Model</div>
|
|
10406
|
+
<div class="setting-desc">Model used for the NLSpec precheck.</div>
|
|
10407
|
+
</div>
|
|
10408
|
+
<div class="setting-control">
|
|
10409
|
+
<select class="form-input" style="width:220px"
|
|
10410
|
+
value=${cost.nlspec_precheck_model || 'claude-haiku-4-5-20251001'}
|
|
10411
|
+
onChange=${e => updateField('cost.nlspec_precheck_model', e.target.value)}>
|
|
10412
|
+
${[...new Set([cost.nlspec_precheck_model || 'claude-haiku-4-5-20251001', ...MODEL_OPTIONS])]
|
|
10413
|
+
.filter(Boolean)
|
|
10414
|
+
.map(m => html`<option key=${m} value=${m}>${m}</option>`)}
|
|
10415
|
+
</select>
|
|
10416
|
+
</div>
|
|
10417
|
+
</div>
|
|
10277
10418
|
</div>
|
|
10278
10419
|
|
|
10279
10420
|
<!-- Human Gates Section -->
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
eb133e19f9d3433957c65c557b350553b63d4c36
|
package/dist/web/build-stamp.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
20260605-
|
|
1
|
+
20260605-023046-eb133e1
|