RayMelius Claude Opus 4.6 commited on
Commit
0c73e6f
·
1 Parent(s): 48ee346

LLM popup: show live usage stats as probability slider moves

Browse files

Slider now shows real-time estimates that update on drag:
- "X% of decisions via LLM" (how many agent actions use LLM vs routine)
- "~Y calls/hour" (accounting for RPM cap, budget per tick, agent count)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. web/index.html +31 -5
web/index.html CHANGED
@@ -3469,21 +3469,42 @@ document.getElementById('llm-model').addEventListener('click', async (e) => {
3469
  }
3470
 
3471
  const runtime = estimateRuntime(pqForCalc);
 
3472
  // Default probability for rate-limited providers (not inherited from NN's 100%)
3473
  const defaultProb = 10;
3474
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3475
  panel.innerHTML =
3476
  `<div style="color:#4ecca3;font-weight:600;margin-bottom:4px">${p.icon} ${p.label}</div>` +
3477
- `<div style="margin-bottom:4px">Daily limit: <b>${lim}</b> requests</div>` +
3478
- `<div style="margin-bottom:6px;font-size:10px;color:#8899aa">` +
3479
- `${rpm} req/min · Max runtime: <b style="color:#4ecca3">${runtime}</b></div>` +
3480
  `<div style="display:flex;align-items:center;gap:8px;margin-top:6px">` +
3481
  `<label style="font-size:11px;color:#8899aa">Probability:</label>` +
3482
  `<input type="range" min="1" max="100" value="${defaultProb}" style="flex:1;accent-color:#4ecca3" class="popup-prob-slider">` +
3483
  `<span class="popup-prob-val" style="font-size:12px;color:#4ecca3;min-width:32px">${defaultProb}%</span>` +
3484
  `</div>` +
3485
- `<div style="font-size:10px;color:#8899aa;margin:2px 0 8px 0">` +
3486
- `Higher = more LLM decisions, lower = more routine behavior</div>` +
 
 
3487
  `<button class="popup-switch-btn" style="width:100%;padding:6px;border:none;border-radius:4px;` +
3488
  `background:#4ecca3;color:#0a0a23;font-weight:600;cursor:pointer;font-size:12px">` +
3489
  `Switch to ${p.label} at ${defaultProb}%</button>`;
@@ -3493,12 +3514,17 @@ document.getElementById('llm-model').addEventListener('click', async (e) => {
3493
  // Wire up slider
3494
  const slider = panel.querySelector('.popup-prob-slider');
3495
  const valLabel = panel.querySelector('.popup-prob-val');
 
3496
  const btn = panel.querySelector('.popup-switch-btn');
3497
 
3498
  slider.addEventListener('input', (e) => {
3499
  e.stopPropagation();
3500
  const pv = parseInt(slider.value);
3501
  valLabel.textContent = pv + '%';
 
 
 
 
3502
  btn.textContent = `Switch to ${p.label} at ${pv}%`;
3503
  });
3504
 
 
3469
  }
3470
 
3471
  const runtime = estimateRuntime(pqForCalc);
3472
+ const numAgents = quota.num_agents || 50;
3473
  // Default probability for rate-limited providers (not inherited from NN's 100%)
3474
  const defaultProb = 10;
3475
 
3476
+ // Calculate usage stats for a given probability
3477
+ function usageStats(probPct) {
3478
+ const prob = probPct / 100;
3479
+ // ~40% of agents are idle (not busy/sleeping) and eligible for LLM each tick
3480
+ const idleFraction = 0.4;
3481
+ const eligibleAgents = Math.round(numAgents * idleFraction);
3482
+ // Expected LLM attempts per tick: eligible agents × prob (action) + prob (social)
3483
+ const attemptsPerTick = eligibleAgents * prob + prob;
3484
+ // Budget caps at 2 calls/tick for rate-limited providers
3485
+ const callsPerTick = Math.min(attemptsPerTick, 2);
3486
+ // Ticks per hour (4s tick delay at 1x speed)
3487
+ const ticksH = 900;
3488
+ const callsPerHour = Math.min(callsPerTick * ticksH, rpm * 60);
3489
+ // What % of agent decisions go through LLM vs routine
3490
+ const llmPct = Math.min(prob * 100, 100);
3491
+ return { callsPerHour: Math.round(callsPerHour), llmPct: Math.round(llmPct) };
3492
+ }
3493
+
3494
+ const initStats = usageStats(defaultProb);
3495
+
3496
  panel.innerHTML =
3497
  `<div style="color:#4ecca3;font-weight:600;margin-bottom:4px">${p.icon} ${p.label}</div>` +
3498
+ `<div style="margin-bottom:4px">Daily limit: <b>${lim}</b> requests · ${rpm} req/min</div>` +
 
 
3499
  `<div style="display:flex;align-items:center;gap:8px;margin-top:6px">` +
3500
  `<label style="font-size:11px;color:#8899aa">Probability:</label>` +
3501
  `<input type="range" min="1" max="100" value="${defaultProb}" style="flex:1;accent-color:#4ecca3" class="popup-prob-slider">` +
3502
  `<span class="popup-prob-val" style="font-size:12px;color:#4ecca3;min-width:32px">${defaultProb}%</span>` +
3503
  `</div>` +
3504
+ `<div class="popup-usage-info" style="font-size:10px;color:#8899aa;margin:4px 0 8px 0;line-height:1.5">` +
3505
+ `<span style="color:#c8c8d8">${initStats.llmPct}%</span> of decisions via LLM · ` +
3506
+ `<span style="color:#c8c8d8">~${initStats.callsPerHour}</span> calls/hour` +
3507
+ `</div>` +
3508
  `<button class="popup-switch-btn" style="width:100%;padding:6px;border:none;border-radius:4px;` +
3509
  `background:#4ecca3;color:#0a0a23;font-weight:600;cursor:pointer;font-size:12px">` +
3510
  `Switch to ${p.label} at ${defaultProb}%</button>`;
 
3514
  // Wire up slider
3515
  const slider = panel.querySelector('.popup-prob-slider');
3516
  const valLabel = panel.querySelector('.popup-prob-val');
3517
+ const usageInfo = panel.querySelector('.popup-usage-info');
3518
  const btn = panel.querySelector('.popup-switch-btn');
3519
 
3520
  slider.addEventListener('input', (e) => {
3521
  e.stopPropagation();
3522
  const pv = parseInt(slider.value);
3523
  valLabel.textContent = pv + '%';
3524
+ const stats = usageStats(pv);
3525
+ usageInfo.innerHTML =
3526
+ `<span style="color:#c8c8d8">${stats.llmPct}%</span> of decisions via LLM · ` +
3527
+ `<span style="color:#c8c8d8">~${stats.callsPerHour}</span> calls/hour`;
3528
  btn.textContent = `Switch to ${p.label} at ${pv}%`;
3529
  });
3530