farming-code 2.2.18 → 2.2.20
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/backend/agent-manager.js +145 -42
- package/backend/bundle-update-helper.js +109 -0
- package/backend/config-manager.js +110 -4
- package/backend/farming-session-store.js +62 -2
- package/backend/server.js +369 -59
- package/backend/terminal-screen-worker-pool.js +15 -6
- package/backend/update-service.js +46 -23
- package/backend/usage-monitor.js +11 -0
- package/dist/assets/App-BupehIbc.js +210 -0
- package/dist/assets/{FileEditorPane-DNy3LAqS.js → FileEditorPane-CJs6kfZO.js} +1 -1
- package/dist/assets/{IconGlyphs-BsUfqpKN.js → IconGlyphs-CZzDr5o2.js} +1 -1
- package/dist/assets/{ProjectFilesSection-BhDEUVHA.js → ProjectFilesSection-DWCV07lA.js} +1 -1
- package/dist/assets/{ReviewPage-ChtByBe3.js → ReviewPage-DBKNOWsJ.js} +1 -1
- package/dist/assets/code-dark-BAt0Q_Op.css +1 -0
- package/dist/assets/{index-fp8VhOes.js → index-DuMjesL2.js} +2 -2
- package/dist/assets/main-y2aK_56c.css +1 -0
- package/dist/index.html +1 -1
- package/frontend/skins/crt/app.js +257 -35
- package/frontend/skins/crt/index.html +21 -38
- package/frontend/skins/crt/styles/billing.css +6 -1
- package/package.json +1 -1
- package/dist/assets/App-DTAQilnX.js +0 -210
- package/dist/assets/code-dark-5esj0bRu.css +0 -1
- package/dist/assets/main-DSO3i_Gs.css +0 -1
package/dist/index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<link rel="apple-touch-icon" sizes="180x180" href="/farming/farming-2/app-icon-v2-180.png" />
|
|
16
16
|
<link rel="manifest" href="/farming/farming-2/site.webmanifest" />
|
|
17
17
|
<title>Farming 2</title>
|
|
18
|
-
<script type="module" crossorigin src="/farming/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/farming/assets/index-DuMjesL2.js"></script>
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/farming/assets/chunk-DECur_0Z.js">
|
|
20
20
|
<link rel="modulepreload" crossorigin href="/farming/assets/preload-helper-mJowh_hw.js">
|
|
21
21
|
<link rel="modulepreload" crossorigin href="/farming/assets/jsx-runtime-BthL93pI.js">
|
|
@@ -55,6 +55,9 @@ let billingRequestSequence = 0;
|
|
|
55
55
|
let billingAbortController = null;
|
|
56
56
|
let billingRefreshTimer = null;
|
|
57
57
|
let billingLiveDayRefreshTimer = null;
|
|
58
|
+
let crtTokenRateRefreshTimer = null;
|
|
59
|
+
let crtTokenRateFirstLoadTimer = null;
|
|
60
|
+
let crtTokenRateAbortController = null;
|
|
58
61
|
let billingCanvasFrame = null;
|
|
59
62
|
let billingMode = 'days';
|
|
60
63
|
let billingSelectedDate = '';
|
|
@@ -116,8 +119,10 @@ const CRT_AGENT_GRID_GAP = 15;
|
|
|
116
119
|
const CRT_AGENT_GRID_PADDING = 20;
|
|
117
120
|
const CRT_SEARCH_DEBOUNCE_MS = 180;
|
|
118
121
|
const CRT_SEARCH_RESULT_LIMIT = 100;
|
|
119
|
-
const CRT_BILLING_REFRESH_MS =
|
|
122
|
+
const CRT_BILLING_REFRESH_MS = 15_000;
|
|
120
123
|
const CRT_BILLING_LIVE_DAY_REFRESH_MS = 5_000;
|
|
124
|
+
const CRT_TOKEN_RATE_REFRESH_MS = 60_000;
|
|
125
|
+
const CRT_TOKEN_RATE_FIRST_LOAD_MS = 1_500;
|
|
121
126
|
const CRT_BILLING_DAY_DETAIL_CACHE_MS = 30_000;
|
|
122
127
|
const CRT_BILLING_TOTAL_ANIMATION_MS = 900;
|
|
123
128
|
const CRT_BILLING_DAY_DETAIL_RETRY_MS = 750;
|
|
@@ -3159,6 +3164,7 @@ function setCrtMainView(view) {
|
|
|
3159
3164
|
if (historySidebarItem) historySidebarItem.classList.toggle('active', crtMainView === 'history');
|
|
3160
3165
|
if (searchSidebarItem) searchSidebarItem.classList.toggle('active', crtMainView === 'search');
|
|
3161
3166
|
if (billingSidebarItem) billingSidebarItem.classList.toggle('active', crtMainView === 'billing');
|
|
3167
|
+
if (previousView !== 'agents' && crtMainView === 'agents') checkMainAgentStatus();
|
|
3162
3168
|
}
|
|
3163
3169
|
|
|
3164
3170
|
function getCrtSearchResults() {
|
|
@@ -3409,6 +3415,7 @@ function setupCrtSearchControls() {
|
|
|
3409
3415
|
}
|
|
3410
3416
|
|
|
3411
3417
|
function formatCrtUsageValue(value) {
|
|
3418
|
+
if (value === null || value === undefined || value === '') return '--';
|
|
3412
3419
|
const numberValue = Number(value);
|
|
3413
3420
|
if (!Number.isFinite(numberValue) || numberValue < 0) return '--';
|
|
3414
3421
|
if (numberValue >= 1_000_000_000) {
|
|
@@ -4005,6 +4012,30 @@ function scrollCrtBillingSelectedDayIntoView() {
|
|
|
4005
4012
|
else if (right > scroll.scrollLeft + scroll.clientWidth) scroll.scrollLeft = right - scroll.clientWidth;
|
|
4006
4013
|
}
|
|
4007
4014
|
|
|
4015
|
+
function crtBillingDayArrowTargetIndex(points, index, key) {
|
|
4016
|
+
if (!Array.isArray(points) || index < 0 || index >= points.length) return -1;
|
|
4017
|
+
const firstDate = parseCrtBillingDate(points[0] && points[0].date);
|
|
4018
|
+
const leadingDays = firstDate ? (firstDate.getDay() + 6) % 7 : 0;
|
|
4019
|
+
const position = leadingDays + index;
|
|
4020
|
+
const weekdayRow = position % 7;
|
|
4021
|
+
let targetPosition = position;
|
|
4022
|
+
if (key === 'ArrowUp') {
|
|
4023
|
+
if (weekdayRow === 0) return -1;
|
|
4024
|
+
targetPosition -= 1;
|
|
4025
|
+
} else if (key === 'ArrowDown') {
|
|
4026
|
+
if (weekdayRow === 6) return -1;
|
|
4027
|
+
targetPosition += 1;
|
|
4028
|
+
} else if (key === 'ArrowLeft') {
|
|
4029
|
+
targetPosition -= 7;
|
|
4030
|
+
} else if (key === 'ArrowRight') {
|
|
4031
|
+
targetPosition += 7;
|
|
4032
|
+
} else {
|
|
4033
|
+
return -1;
|
|
4034
|
+
}
|
|
4035
|
+
const targetIndex = targetPosition - leadingDays;
|
|
4036
|
+
return targetIndex >= 0 && targetIndex < points.length ? targetIndex : -1;
|
|
4037
|
+
}
|
|
4038
|
+
|
|
4008
4039
|
function selectCrtBillingDayByArrow(key) {
|
|
4009
4040
|
if (crtMainView !== 'billing' || billingMode !== 'days') return false;
|
|
4010
4041
|
const points = billingSummary && billingSummary.daily && Array.isArray(billingSummary.daily.points)
|
|
@@ -4013,8 +4044,8 @@ function selectCrtBillingDayByArrow(key) {
|
|
|
4013
4044
|
if (points.length === 0) return false;
|
|
4014
4045
|
let index = points.findIndex(point => point.date === billingSelectedDate);
|
|
4015
4046
|
if (index < 0) index = points.length - 1;
|
|
4016
|
-
const
|
|
4017
|
-
|
|
4047
|
+
const nextIndex = crtBillingDayArrowTargetIndex(points, index, key);
|
|
4048
|
+
if (nextIndex < 0) return false;
|
|
4018
4049
|
return selectCrtBillingDay(points[nextIndex].date, { focus: true });
|
|
4019
4050
|
}
|
|
4020
4051
|
|
|
@@ -4155,11 +4186,35 @@ function setCrtBillingMode(mode) {
|
|
|
4155
4186
|
}
|
|
4156
4187
|
const status = document.getElementById('billing-status');
|
|
4157
4188
|
if (status && billingSummary && !billingLoading && !billingError) {
|
|
4158
|
-
status.textContent =
|
|
4189
|
+
status.textContent = crtBillingStatusText();
|
|
4159
4190
|
}
|
|
4160
4191
|
if (billingMode === 'live') window.requestAnimationFrame(() => drawCrtBillingScope());
|
|
4161
4192
|
}
|
|
4162
4193
|
|
|
4194
|
+
function selectCrtBillingMode(mode) {
|
|
4195
|
+
setCrtBillingMode(mode);
|
|
4196
|
+
const selectedTab = document.getElementById(
|
|
4197
|
+
billingMode === 'live' ? 'billing-live-tab' : 'billing-days-tab',
|
|
4198
|
+
);
|
|
4199
|
+
if (selectedTab) setCrtNavigationSelection(selectedTab);
|
|
4200
|
+
if (billingMode === 'live' && !billingLoading) void loadCrtBilling();
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
function crtBillingTimeline(summary = billingSummary) {
|
|
4204
|
+
return summary && summary.liveTimeline || summary && summary.timeline || null;
|
|
4205
|
+
}
|
|
4206
|
+
|
|
4207
|
+
function crtBillingStatusText(summary = billingSummary) {
|
|
4208
|
+
if (billingMode === 'days') return 'HISTORY READY';
|
|
4209
|
+
const sampledAt = Number(summary && summary.sampledAt);
|
|
4210
|
+
if (!Number.isFinite(sampledAt) || sampledAt <= 0) return 'LIVE';
|
|
4211
|
+
const sampled = new Date(sampledAt);
|
|
4212
|
+
const time = [sampled.getHours(), sampled.getMinutes(), sampled.getSeconds()]
|
|
4213
|
+
.map(value => String(value).padStart(2, '0'))
|
|
4214
|
+
.join(':');
|
|
4215
|
+
return `LIVE ${time}`;
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4163
4218
|
function formatCrtBillingWindow(windowMinutes) {
|
|
4164
4219
|
const minutes = Number(windowMinutes);
|
|
4165
4220
|
if (!Number.isFinite(minutes) || minutes <= 0) return 'WINDOW';
|
|
@@ -4169,6 +4224,20 @@ function formatCrtBillingWindow(windowMinutes) {
|
|
|
4169
4224
|
return `${Math.round(minutes)}M`;
|
|
4170
4225
|
}
|
|
4171
4226
|
|
|
4227
|
+
function crtBillingTimelineLabels(timeline) {
|
|
4228
|
+
const windowMinutes = Number(timeline && timeline.windowMs) / 60_000;
|
|
4229
|
+
const windowLabel = formatCrtBillingWindow(windowMinutes);
|
|
4230
|
+
const midpointLabel = formatCrtBillingWindow(windowMinutes / 2);
|
|
4231
|
+
return {
|
|
4232
|
+
integral: `TOKENS · ${windowLabel}`,
|
|
4233
|
+
peak: `TOK/MIN · ${windowLabel}`,
|
|
4234
|
+
title: `TOKEN BURN // ${windowLabel}`,
|
|
4235
|
+
ariaLabel: `Token burn rate over the last ${windowLabel}`,
|
|
4236
|
+
start: `-${windowLabel}`,
|
|
4237
|
+
midpoint: `-${midpointLabel}`,
|
|
4238
|
+
};
|
|
4239
|
+
}
|
|
4240
|
+
|
|
4172
4241
|
function formatCrtBillingReset(resetsAt, now = Date.now()) {
|
|
4173
4242
|
const timestamp = Number(resetsAt);
|
|
4174
4243
|
if (!Number.isFinite(timestamp) || timestamp <= 0) return 'RESET --';
|
|
@@ -4180,10 +4249,30 @@ function formatCrtBillingReset(resetsAt, now = Date.now()) {
|
|
|
4180
4249
|
|
|
4181
4250
|
function crtBillingCurrentRate(summary = billingSummary) {
|
|
4182
4251
|
const providers = summary && Array.isArray(summary.providers) ? summary.providers : [];
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4252
|
+
let total = 0;
|
|
4253
|
+
let hasRate = false;
|
|
4254
|
+
providers.forEach((provider) => {
|
|
4255
|
+
const tokenUsage = provider && provider.tokenUsage;
|
|
4256
|
+
const rate = tokenUsage && tokenUsage.tokensPerMinute;
|
|
4257
|
+
if (
|
|
4258
|
+
tokenUsage
|
|
4259
|
+
&& tokenUsage.available !== false
|
|
4260
|
+
&& typeof rate === 'number'
|
|
4261
|
+
&& Number.isFinite(rate)
|
|
4262
|
+
&& rate >= 0
|
|
4263
|
+
) {
|
|
4264
|
+
total += rate;
|
|
4265
|
+
hasRate = true;
|
|
4266
|
+
}
|
|
4267
|
+
});
|
|
4268
|
+
return hasRate ? total : null;
|
|
4269
|
+
}
|
|
4270
|
+
|
|
4271
|
+
function renderCrtTopBarTokenRate(summary = billingSummary) {
|
|
4272
|
+
const tokensPerMinute = document.getElementById('tokens-per-minute');
|
|
4273
|
+
if (tokensPerMinute) {
|
|
4274
|
+
tokensPerMinute.textContent = formatCrtTokenRate(crtBillingCurrentRate(summary));
|
|
4275
|
+
}
|
|
4187
4276
|
}
|
|
4188
4277
|
|
|
4189
4278
|
function appendCrtBillingMessage(container, text, isError = false) {
|
|
@@ -4286,7 +4375,7 @@ function drawCrtBillingScope(summary = billingSummary) {
|
|
|
4286
4375
|
context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
4287
4376
|
context.clearRect(0, 0, rect.width, rect.height);
|
|
4288
4377
|
|
|
4289
|
-
const timeline = summary
|
|
4378
|
+
const timeline = crtBillingTimeline(summary);
|
|
4290
4379
|
const points = timeline && Array.isArray(timeline.points) ? timeline.points : [];
|
|
4291
4380
|
const values = points.map(point => Math.max(0, Number(point.tokensPerMinute) || 0));
|
|
4292
4381
|
const providerNames = points.length > 0 ? Object.keys(points[0].providers || {}) : [];
|
|
@@ -4364,7 +4453,7 @@ function renderCrtBilling() {
|
|
|
4364
4453
|
const status = document.getElementById('billing-status');
|
|
4365
4454
|
const refresh = document.getElementById('billing-refresh');
|
|
4366
4455
|
const empty = document.getElementById('billing-scope-empty');
|
|
4367
|
-
const timeline =
|
|
4456
|
+
const timeline = crtBillingTimeline();
|
|
4368
4457
|
const hasSignal = Boolean(timeline && Number(timeline.totalTokens) > 0);
|
|
4369
4458
|
if (status) {
|
|
4370
4459
|
status.classList.toggle('is-busy', billingLoading);
|
|
@@ -4374,7 +4463,7 @@ function renderCrtBilling() {
|
|
|
4374
4463
|
: billingLoading
|
|
4375
4464
|
? (billingSummary ? 'REFRESHING' : 'SCANNING LOGS')
|
|
4376
4465
|
: billingSummary
|
|
4377
|
-
? (
|
|
4466
|
+
? crtBillingStatusText()
|
|
4378
4467
|
: 'STANDBY';
|
|
4379
4468
|
}
|
|
4380
4469
|
if (refresh) refresh.disabled = billingLoading;
|
|
@@ -4384,11 +4473,24 @@ function renderCrtBilling() {
|
|
|
4384
4473
|
const peakRate = document.getElementById('billing-peak-rate');
|
|
4385
4474
|
const dutyCycle = document.getElementById('billing-duty-cycle');
|
|
4386
4475
|
const scopeScale = document.getElementById('billing-scope-scale');
|
|
4476
|
+
const windowLabel = document.getElementById('billing-window-label');
|
|
4477
|
+
const peakLabel = document.getElementById('billing-peak-label');
|
|
4478
|
+
const scopeTitle = document.getElementById('billing-scope-title');
|
|
4479
|
+
const scope = document.getElementById('billing-scope');
|
|
4480
|
+
const scopeStart = document.getElementById('billing-scope-start');
|
|
4481
|
+
const scopeMidpoint = document.getElementById('billing-scope-midpoint');
|
|
4482
|
+
const timelineLabels = crtBillingTimelineLabels(timeline);
|
|
4387
4483
|
if (currentRate) currentRate.textContent = formatCrtUsageValue(crtBillingCurrentRate());
|
|
4388
4484
|
if (windowTotal) windowTotal.textContent = formatCrtUsageValue(timeline && timeline.totalTokens);
|
|
4389
4485
|
if (peakRate) peakRate.textContent = formatCrtUsageValue(timeline && timeline.peakTokensPerMinute);
|
|
4390
4486
|
if (dutyCycle) dutyCycle.textContent = timeline ? `${timeline.activeBucketCount}/${timeline.bucketCount}` : '--';
|
|
4391
4487
|
if (scopeScale) scopeScale.textContent = `${formatCrtUsageValue(timeline && timeline.peakTokensPerMinute)} TOK/MIN PEAK`;
|
|
4488
|
+
if (windowLabel) windowLabel.textContent = timelineLabels.integral;
|
|
4489
|
+
if (peakLabel) peakLabel.textContent = timelineLabels.peak;
|
|
4490
|
+
if (scopeTitle) scopeTitle.textContent = timelineLabels.title;
|
|
4491
|
+
if (scope) scope.setAttribute('aria-label', timelineLabels.ariaLabel);
|
|
4492
|
+
if (scopeStart) scopeStart.textContent = timelineLabels.start;
|
|
4493
|
+
if (scopeMidpoint) scopeMidpoint.textContent = timelineLabels.midpoint;
|
|
4392
4494
|
if (empty) {
|
|
4393
4495
|
empty.classList.toggle('hidden', hasSignal);
|
|
4394
4496
|
empty.textContent = billingError ? 'SIGNAL LOST' : billingLoading ? 'ACQUIRING SIGNAL' : 'NO TOKEN SIGNAL';
|
|
@@ -4408,13 +4510,18 @@ async function loadCrtBilling({ fresh = false } = {}) {
|
|
|
4408
4510
|
billingRequestSequence += 1;
|
|
4409
4511
|
const requestSequence = billingRequestSequence;
|
|
4410
4512
|
if (billingAbortController) billingAbortController.abort();
|
|
4513
|
+
if (crtTokenRateAbortController) {
|
|
4514
|
+
crtTokenRateAbortController.abort();
|
|
4515
|
+
crtTokenRateAbortController = null;
|
|
4516
|
+
}
|
|
4411
4517
|
const controller = new window.AbortController();
|
|
4412
4518
|
billingAbortController = controller;
|
|
4413
4519
|
billingLoading = true;
|
|
4414
4520
|
billingError = '';
|
|
4415
4521
|
renderCrtBilling();
|
|
4416
4522
|
try {
|
|
4417
|
-
const
|
|
4523
|
+
const query = fresh ? '?fresh=1' : billingMode === 'live' ? '?live=1' : '';
|
|
4524
|
+
const response = await fetch(farmingApiPath(`/usage${query}`), {
|
|
4418
4525
|
signal: controller.signal,
|
|
4419
4526
|
cache: 'no-store',
|
|
4420
4527
|
});
|
|
@@ -4422,6 +4529,7 @@ async function loadCrtBilling({ fresh = false } = {}) {
|
|
|
4422
4529
|
if (!response.ok || !data || !data.usage) throw new Error(data && data.error ? data.error : `Usage request failed (${response.status})`);
|
|
4423
4530
|
if (requestSequence !== billingRequestSequence) return;
|
|
4424
4531
|
billingSummary = data.usage;
|
|
4532
|
+
renderCrtTopBarTokenRate();
|
|
4425
4533
|
} catch (error) {
|
|
4426
4534
|
if (controller.signal.aborted || requestSequence !== billingRequestSequence) return;
|
|
4427
4535
|
billingError = error instanceof Error ? error.message : 'Failed to load token telemetry';
|
|
@@ -4440,6 +4548,58 @@ async function loadCrtBilling({ fresh = false } = {}) {
|
|
|
4440
4548
|
}
|
|
4441
4549
|
}
|
|
4442
4550
|
|
|
4551
|
+
async function loadCrtTopBarTokenRate() {
|
|
4552
|
+
if (billingLoading || crtTokenRateAbortController) return;
|
|
4553
|
+
const controller = new window.AbortController();
|
|
4554
|
+
crtTokenRateAbortController = controller;
|
|
4555
|
+
try {
|
|
4556
|
+
const response = await fetch(farmingApiPath('/usage'), {
|
|
4557
|
+
signal: controller.signal,
|
|
4558
|
+
cache: 'no-store',
|
|
4559
|
+
});
|
|
4560
|
+
const data = await response.json().catch(() => null);
|
|
4561
|
+
if (controller.signal.aborted) return;
|
|
4562
|
+
if (!response.ok || !data || !data.usage) {
|
|
4563
|
+
throw new Error(data && data.error ? data.error : `Usage request failed (${response.status})`);
|
|
4564
|
+
}
|
|
4565
|
+
renderCrtTopBarTokenRate(data.usage);
|
|
4566
|
+
} catch {
|
|
4567
|
+
if (!controller.signal.aborted) renderCrtTopBarTokenRate(null);
|
|
4568
|
+
} finally {
|
|
4569
|
+
if (crtTokenRateAbortController === controller) crtTokenRateAbortController = null;
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4573
|
+
function stopCrtTopBarTokenRateRefresh({ abort = false } = {}) {
|
|
4574
|
+
if (crtTokenRateFirstLoadTimer !== null) {
|
|
4575
|
+
clearTimeout(crtTokenRateFirstLoadTimer);
|
|
4576
|
+
crtTokenRateFirstLoadTimer = null;
|
|
4577
|
+
}
|
|
4578
|
+
if (crtTokenRateRefreshTimer !== null) {
|
|
4579
|
+
clearInterval(crtTokenRateRefreshTimer);
|
|
4580
|
+
crtTokenRateRefreshTimer = null;
|
|
4581
|
+
}
|
|
4582
|
+
if (abort && crtTokenRateAbortController) {
|
|
4583
|
+
crtTokenRateAbortController.abort();
|
|
4584
|
+
crtTokenRateAbortController = null;
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
|
|
4588
|
+
function startCrtTopBarTokenRateRefresh({ immediate = false } = {}) {
|
|
4589
|
+
stopCrtTopBarTokenRateRefresh();
|
|
4590
|
+
if (immediate) {
|
|
4591
|
+
void loadCrtTopBarTokenRate();
|
|
4592
|
+
} else {
|
|
4593
|
+
crtTokenRateFirstLoadTimer = setTimeout(() => {
|
|
4594
|
+
crtTokenRateFirstLoadTimer = null;
|
|
4595
|
+
if (document.visibilityState !== 'hidden') void loadCrtTopBarTokenRate();
|
|
4596
|
+
}, CRT_TOKEN_RATE_FIRST_LOAD_MS);
|
|
4597
|
+
}
|
|
4598
|
+
crtTokenRateRefreshTimer = setInterval(() => {
|
|
4599
|
+
if (document.visibilityState !== 'hidden') void loadCrtTopBarTokenRate();
|
|
4600
|
+
}, CRT_TOKEN_RATE_REFRESH_MS);
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4443
4603
|
function stopCrtBillingRefresh({ abort = false } = {}) {
|
|
4444
4604
|
if (billingRefreshTimer !== null) {
|
|
4445
4605
|
clearInterval(billingRefreshTimer);
|
|
@@ -5444,7 +5604,7 @@ function connect() {
|
|
|
5444
5604
|
else scheduleCrtPreviewCardRender(agent);
|
|
5445
5605
|
}
|
|
5446
5606
|
} else if (data.type === 'system-stats') {
|
|
5447
|
-
updateSystemStats(data.stats, data.uptime
|
|
5607
|
+
updateSystemStats(data.stats, data.uptime);
|
|
5448
5608
|
} else if (data.type === 'error') {
|
|
5449
5609
|
waitingForAgent = false;
|
|
5450
5610
|
if (workspaceDirectoryPrompt?.kind === 'creating') {
|
|
@@ -5491,6 +5651,7 @@ function connect() {
|
|
|
5491
5651
|
function suspendCrtPageConnection() {
|
|
5492
5652
|
document.body.classList.add('page-hidden');
|
|
5493
5653
|
stopCrtBillingRefresh({ abort: true });
|
|
5654
|
+
stopCrtTopBarTokenRateRefresh({ abort: true });
|
|
5494
5655
|
if (wsReconnectTimer) {
|
|
5495
5656
|
clearTimeout(wsReconnectTimer);
|
|
5496
5657
|
wsReconnectTimer = null;
|
|
@@ -5504,6 +5665,7 @@ function resumeCrtPageConnection() {
|
|
|
5504
5665
|
if (document.visibilityState === 'hidden') return;
|
|
5505
5666
|
document.body.classList.remove('page-hidden');
|
|
5506
5667
|
connect();
|
|
5668
|
+
startCrtTopBarTokenRateRefresh({ immediate: true });
|
|
5507
5669
|
if (crtMainView === 'billing') {
|
|
5508
5670
|
startCrtBillingRefresh();
|
|
5509
5671
|
void loadCrtBilling();
|
|
@@ -5513,15 +5675,33 @@ function resumeCrtPageConnection() {
|
|
|
5513
5675
|
function checkMainAgentStatus() {
|
|
5514
5676
|
if (!state) return;
|
|
5515
5677
|
|
|
5516
|
-
const
|
|
5517
|
-
|
|
5518
|
-
:
|
|
5519
|
-
|
|
5520
|
-
|
|
5678
|
+
const inputDialog = document.getElementById('input-dialog');
|
|
5679
|
+
const action = getCrtMainAgentDialogAction({
|
|
5680
|
+
currentState: state,
|
|
5681
|
+
mainView: crtMainView,
|
|
5682
|
+
dialogActive: Boolean(inputDialog && inputDialog.classList.contains('active')),
|
|
5683
|
+
pendingMainAgent: pendingMainAgentLaunch,
|
|
5684
|
+
});
|
|
5685
|
+
if (action === 'hide') {
|
|
5686
|
+
hideInputDialog();
|
|
5687
|
+
} else if (action === 'show') {
|
|
5521
5688
|
showInputDialog();
|
|
5522
5689
|
}
|
|
5523
5690
|
}
|
|
5524
5691
|
|
|
5692
|
+
function getCrtMainAgentDialogAction({
|
|
5693
|
+
currentState,
|
|
5694
|
+
mainView = 'agents',
|
|
5695
|
+
dialogActive = false,
|
|
5696
|
+
pendingMainAgent = false,
|
|
5697
|
+
} = {}) {
|
|
5698
|
+
if (!needsMainAgent(currentState)) {
|
|
5699
|
+
return dialogActive && pendingMainAgent ? 'hide' : 'none';
|
|
5700
|
+
}
|
|
5701
|
+
if (mainView !== 'agents' || dialogActive) return 'none';
|
|
5702
|
+
return 'show';
|
|
5703
|
+
}
|
|
5704
|
+
|
|
5525
5705
|
function formatSystemClock(timestamp, timeZone) {
|
|
5526
5706
|
if (!Number.isFinite(timestamp)) return '--';
|
|
5527
5707
|
try {
|
|
@@ -5541,21 +5721,22 @@ function formatSystemClock(timestamp, timeZone) {
|
|
|
5541
5721
|
}
|
|
5542
5722
|
|
|
5543
5723
|
function formatCrtTokenRate(value) {
|
|
5724
|
+
if (value === null || value === undefined || value === '') return '--';
|
|
5544
5725
|
const rate = Number(value);
|
|
5545
5726
|
if (!Number.isFinite(rate) || rate < 0) return '--';
|
|
5546
5727
|
const rounded = rate < 10 ? Math.round(rate * 10) / 10 : Math.round(rate);
|
|
5547
5728
|
if (rounded >= 1_000_000) {
|
|
5548
5729
|
const compact = rounded / 1_000_000;
|
|
5549
|
-
return
|
|
5730
|
+
return `${compact >= 10 ? Math.round(compact) : Math.round(compact * 10) / 10}M`;
|
|
5550
5731
|
}
|
|
5551
5732
|
if (rounded >= 1_000) {
|
|
5552
5733
|
const compact = rounded / 1_000;
|
|
5553
|
-
return
|
|
5734
|
+
return `${compact >= 10 ? Math.round(compact) : Math.round(compact * 10) / 10}K`;
|
|
5554
5735
|
}
|
|
5555
|
-
return
|
|
5736
|
+
return String(rounded);
|
|
5556
5737
|
}
|
|
5557
5738
|
|
|
5558
|
-
function updateSystemStats(stats, uptime
|
|
5739
|
+
function updateSystemStats(stats, uptime) {
|
|
5559
5740
|
if (stats.cpu !== undefined) {
|
|
5560
5741
|
document.getElementById('cpu-usage').textContent = stats.cpu;
|
|
5561
5742
|
}
|
|
@@ -5572,11 +5753,6 @@ function updateSystemStats(stats, uptime, usageRate) {
|
|
|
5572
5753
|
document.getElementById('system-time').textContent = formatSystemClock(stats.timestamp, stats.timeZone);
|
|
5573
5754
|
}
|
|
5574
5755
|
|
|
5575
|
-
const tokensPerMinute = document.getElementById('tokens-per-minute');
|
|
5576
|
-
if (tokensPerMinute) {
|
|
5577
|
-
tokensPerMinute.textContent = formatCrtTokenRate(usageRate && usageRate.estimatedTokensPerMinute);
|
|
5578
|
-
}
|
|
5579
|
-
|
|
5580
5756
|
if (uptime !== undefined) {
|
|
5581
5757
|
const hours = Math.floor(uptime / 3600);
|
|
5582
5758
|
const minutes = Math.floor((uptime % 3600) / 60);
|
|
@@ -6130,10 +6306,45 @@ function flushStructuredComposerFollowUp(agent) {
|
|
|
6130
6306
|
setTimeout(() => void refreshStructuredSession(agent.id, true), 160);
|
|
6131
6307
|
}
|
|
6132
6308
|
|
|
6309
|
+
function structuredContextUsage(session) {
|
|
6310
|
+
const usage = session && session.usage;
|
|
6311
|
+
const usedTokens = usage && usage.used;
|
|
6312
|
+
const limitTokens = usage && usage.size;
|
|
6313
|
+
if (
|
|
6314
|
+
typeof usedTokens !== 'number'
|
|
6315
|
+
|| !Number.isFinite(usedTokens)
|
|
6316
|
+
|| usedTokens < 0
|
|
6317
|
+
|| typeof limitTokens !== 'number'
|
|
6318
|
+
|| !Number.isFinite(limitTokens)
|
|
6319
|
+
|| limitTokens <= 0
|
|
6320
|
+
) return null;
|
|
6321
|
+
const percentUsed = Math.max(0, Math.min(100, Math.round(usedTokens / limitTokens * 100)));
|
|
6322
|
+
return {
|
|
6323
|
+
usedTokens,
|
|
6324
|
+
limitTokens,
|
|
6325
|
+
percentUsed,
|
|
6326
|
+
percentLeft: 100 - percentUsed,
|
|
6327
|
+
};
|
|
6328
|
+
}
|
|
6329
|
+
|
|
6133
6330
|
function formatStructuredUsage(session) {
|
|
6134
|
-
const
|
|
6135
|
-
if (!
|
|
6136
|
-
return `${
|
|
6331
|
+
const contextUsage = structuredContextUsage(session);
|
|
6332
|
+
if (!contextUsage) return '';
|
|
6333
|
+
return `${formatCrtUsageValue(contextUsage.usedTokens)} / ${formatCrtUsageValue(contextUsage.limitTokens)} TOK`;
|
|
6334
|
+
}
|
|
6335
|
+
|
|
6336
|
+
function updateStructuredUsageDisplay(element, session) {
|
|
6337
|
+
if (!element) return;
|
|
6338
|
+
const contextUsage = structuredContextUsage(session);
|
|
6339
|
+
element.textContent = formatStructuredUsage(session);
|
|
6340
|
+
if (!contextUsage) {
|
|
6341
|
+
element.removeAttribute('title');
|
|
6342
|
+
element.removeAttribute('aria-label');
|
|
6343
|
+
return;
|
|
6344
|
+
}
|
|
6345
|
+
const label = `Context window: ${contextUsage.percentUsed}% used (${contextUsage.percentLeft}% left)`;
|
|
6346
|
+
element.title = label;
|
|
6347
|
+
element.setAttribute('aria-label', label);
|
|
6137
6348
|
}
|
|
6138
6349
|
|
|
6139
6350
|
function structuredSelectOptions(option) {
|
|
@@ -6187,7 +6398,7 @@ function resetStructuredSessionControls() {
|
|
|
6187
6398
|
if (commandButton) commandButton.hidden = true;
|
|
6188
6399
|
if (modeButton) modeButton.hidden = true;
|
|
6189
6400
|
if (configButton) configButton.hidden = true;
|
|
6190
|
-
|
|
6401
|
+
updateStructuredUsageDisplay(usage, null);
|
|
6191
6402
|
}
|
|
6192
6403
|
|
|
6193
6404
|
function setStructuredComposerMenu(menu, { focusFirst = false, opener = null } = {}) {
|
|
@@ -6429,7 +6640,7 @@ function renderStructuredSessionControls() {
|
|
|
6429
6640
|
const currentMode = modes.find((mode) => mode.id === (session && (session.currentModeId || (session.modes && session.modes.currentModeId))));
|
|
6430
6641
|
modeButton.textContent = `[MODE ${currentMode ? currentMode.name : ''}]`;
|
|
6431
6642
|
configButton.textContent = `[${currentStructuredConfigLabel(session)}]`;
|
|
6432
|
-
usage
|
|
6643
|
+
updateStructuredUsageDisplay(usage, session);
|
|
6433
6644
|
renderStructuredComposerMenu();
|
|
6434
6645
|
}
|
|
6435
6646
|
|
|
@@ -7876,13 +8087,14 @@ if (typeof document !== 'undefined') {
|
|
|
7876
8087
|
|
|
7877
8088
|
if (
|
|
7878
8089
|
crtMainView === 'billing'
|
|
8090
|
+
&& billingMode === 'days'
|
|
7879
8091
|
&& !sessionActive
|
|
7880
8092
|
&& !e.ctrlKey
|
|
7881
8093
|
&& !e.metaKey
|
|
7882
8094
|
&& !e.altKey
|
|
7883
8095
|
&& navigationArrow
|
|
7884
|
-
&& selectCrtBillingDayByArrow(e.key)
|
|
7885
8096
|
) {
|
|
8097
|
+
selectCrtBillingDayByArrow(e.key);
|
|
7886
8098
|
e.preventDefault();
|
|
7887
8099
|
return;
|
|
7888
8100
|
}
|
|
@@ -8076,13 +8288,13 @@ if (typeof document !== 'undefined') {
|
|
|
8076
8288
|
}
|
|
8077
8289
|
|
|
8078
8290
|
if ((e.key === 'd' || e.key === 'D') && crtMainView === 'billing') {
|
|
8079
|
-
|
|
8291
|
+
selectCrtBillingMode('days');
|
|
8080
8292
|
e.preventDefault();
|
|
8081
8293
|
return;
|
|
8082
8294
|
}
|
|
8083
8295
|
|
|
8084
8296
|
if ((e.key === 'l' || e.key === 'L') && crtMainView === 'billing') {
|
|
8085
|
-
|
|
8297
|
+
selectCrtBillingMode('live');
|
|
8086
8298
|
e.preventDefault();
|
|
8087
8299
|
return;
|
|
8088
8300
|
}
|
|
@@ -8253,6 +8465,10 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
8253
8465
|
crtAgentSessionKey,
|
|
8254
8466
|
crtResumedSessionFromSource,
|
|
8255
8467
|
crtDashboardStateSignature,
|
|
8468
|
+
crtBillingDayArrowTargetIndex,
|
|
8469
|
+
crtBillingTimelineLabels,
|
|
8470
|
+
crtBillingTimeline,
|
|
8471
|
+
crtBillingCurrentRate,
|
|
8256
8472
|
findDefaultNewAgentIndex,
|
|
8257
8473
|
findDirectionalNavigationIndex,
|
|
8258
8474
|
isBrowserShortcut,
|
|
@@ -8269,11 +8485,14 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
8269
8485
|
formatCrtTokenRate,
|
|
8270
8486
|
formatCrtHistoryAge,
|
|
8271
8487
|
formatCrtCompactTotalValue,
|
|
8488
|
+
formatCrtUsageValue,
|
|
8489
|
+
formatStructuredUsage,
|
|
8272
8490
|
getCrtHistoryPage,
|
|
8273
8491
|
getCrtAgentPage,
|
|
8274
8492
|
getCrtAgentVerticalPageTarget,
|
|
8275
8493
|
getCrtLiveAgents,
|
|
8276
8494
|
getCrtRegularAgents,
|
|
8495
|
+
getCrtMainAgentDialogAction,
|
|
8277
8496
|
getCrtAgentRemovalFallback,
|
|
8278
8497
|
getAgentDisplayText,
|
|
8279
8498
|
getCrtPreviewCellStyle,
|
|
@@ -8290,6 +8509,8 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
8290
8509
|
hasCrtStructuredLocalEscapeAction,
|
|
8291
8510
|
resolveCrtSessionKeyboardCommand,
|
|
8292
8511
|
structuredComposerAction,
|
|
8512
|
+
structuredContextUsage,
|
|
8513
|
+
updateStructuredUsageDisplay,
|
|
8293
8514
|
structuredTranscriptTurns,
|
|
8294
8515
|
crtStructuredPreviewMessageLines,
|
|
8295
8516
|
getCrtBrandPaneKey,
|
|
@@ -8316,5 +8537,6 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
8316
8537
|
});
|
|
8317
8538
|
window.addEventListener('pagehide', suspendCrtPageConnection);
|
|
8318
8539
|
window.addEventListener('pageshow', resumeCrtPageConnection);
|
|
8540
|
+
startCrtTopBarTokenRateRefresh();
|
|
8319
8541
|
connect();
|
|
8320
8542
|
}
|