agents-relay 2.0.3 → 2.0.4
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/dashboard-html.js +29 -12
- package/dist/github-runtime-usage.js +7 -4
- package/package.json +1 -1
package/dist/dashboard-html.js
CHANGED
|
@@ -397,36 +397,53 @@ function githubBucket(label,bucket){const row=element('div','usage-row');const h
|
|
|
397
397
|
function githubCounterLine(label,values){const entries=Object.entries(values||{}).sort((a,b)=>Number(b[1])-Number(a[1])).slice(0,8);return entries.length?element('div','subtle',text(label+' · '+entries.map(([key,count])=>key+' '+count).join(' · '))):null;}
|
|
398
398
|
function githubObserved(label,observed){
|
|
399
399
|
if(!observed)return null;
|
|
400
|
+
if(Number.isFinite(observed.limit)&&Number.isFinite(observed.remaining)){const row=githubBucket(label,observed);if(observed.reason)row.title=observed.reason;return row;}
|
|
400
401
|
const state=observed.throttled?'Throttled':observed.available===true?'Available':observed.available===false?'Unavailable':'Unknown';
|
|
401
402
|
const parts=[label+' observed',state];
|
|
402
403
|
if(observed.status!==null)parts.push('status '+observed.status);
|
|
403
|
-
if(observed.remaining!==null)parts.push('remaining '+observed.remaining);
|
|
404
|
-
if(observed.headersCaptured&&observed.reset!==null)parts.push(shortReset(observed.reset));
|
|
405
404
|
if(observed.retryAfterSeconds!==null)parts.push('retry '+observed.retryAfterSeconds+'s');
|
|
406
405
|
const row=element('div',observed.throttled?'usage-row error-state':'usage-row subtle');
|
|
407
406
|
row.textContent=parts.filter(Boolean).join(' · ');
|
|
408
407
|
if(observed.reason)row.title=observed.reason;
|
|
409
408
|
return row;
|
|
410
409
|
}
|
|
410
|
+
function githubSecondary(status){
|
|
411
|
+
const rejection=status?.runtimeRateUsage?.rejection;
|
|
412
|
+
const row=element('div','usage-row');
|
|
413
|
+
const heading=element('div','usage-label');
|
|
414
|
+
if(rejection?.kind!=='secondary'){heading.append(element('span','',text('Secondary protection')),element('span','',text('No active cooldown')));row.append(heading);return row;}
|
|
415
|
+
const start=Date.parse(rejection.observedAt);
|
|
416
|
+
const until=Date.parse(rejection.cooldownUntil||status?.cooldownUntil||'');
|
|
417
|
+
if(!Number.isFinite(start)||!Number.isFinite(until)||until<=start){heading.append(element('span','',text('Secondary protection')),element('span','',text('Throttled')));row.classList.add('error-state');row.append(heading);return row;}
|
|
418
|
+
const total=until-start;
|
|
419
|
+
const remaining=Math.max(0,until-Date.now());
|
|
420
|
+
const percent=Math.max(0,Math.min(100,100*remaining/total));
|
|
421
|
+
heading.append(element('span','',text('Secondary cooldown')),element('span','',text(Math.ceil(remaining/1000)+'s')));
|
|
422
|
+
const track=element('div','usage-track');track.setAttribute('role','progressbar');track.setAttribute('aria-label','Secondary cooldown remaining');track.setAttribute('aria-valuemin','0');track.setAttribute('aria-valuemax','100');track.setAttribute('aria-valuenow',String(Math.round(percent)));const fill=element('div','usage-fill');fill.style.width=percent+'%';track.append(fill);
|
|
423
|
+
const hint=element('div','subtle',text('Retry '+new Date(until).toLocaleString()));hint.title=new Date(until).toLocaleString();
|
|
424
|
+
row.append(heading,track,hint);
|
|
425
|
+
return row;
|
|
426
|
+
}
|
|
411
427
|
function githubDiagnostics(status){const body=element('div','usage-details-body');if(status?.calls)body.append(element('div','subtle',text('Calls · GraphQL '+(status.calls.graphql||0)+' · REST '+(status.calls.rest||0)+' · quota '+(status.calls.rateLimit||0))));const operations=githubCounterLine('GraphQL operations',status?.graphql?.operations);if(operations)body.append(operations);const contexts=githubCounterLine('GraphQL contexts',status?.graphql?.contexts);if(contexts)body.append(contexts);if(status?.readPaths){body.append(element('div','subtle',text('Reads · scans '+(status.readPaths.workspaceScans||0)+' · PR '+(status.readPaths.prRefreshes||0)+' · coalesced '+(status.readPaths.prRefreshCoalesced||0))));const triggers=githubCounterLine('Refresh triggers',status.readPaths.prRefreshesByTrigger);if(triggers)body.append(triggers);const coalesced=githubCounterLine('Coalesced',status.readPaths.prRefreshCoalescedByTrigger);if(coalesced)body.append(coalesced);}if(!body.children.length)return null;const details=element('details','usage-details');details.append(element('summary','',text('Diagnostics')),body);return details;}
|
|
412
428
|
function githubUsageCard(snapshot,status){
|
|
413
429
|
const card=element('section','usage-provider');
|
|
414
430
|
card.append(element('h3','',text('GitHub API')));
|
|
415
431
|
const resources=snapshot?.resources||{};
|
|
432
|
+
const observed=status?.runtimeRateUsage?.resources||{};
|
|
416
433
|
const bars=element('div','usage-bars');
|
|
434
|
+
bars.append(githubSecondary(status),element('div','usage-label',text('Request-time X-RateLimit headers')));
|
|
435
|
+
let observedCount=0;
|
|
436
|
+
for(const row of [githubObserved('REST',observed.core),githubObserved('GraphQL',observed.graphql),githubObserved('Search',observed.search)])if(row){bars.append(row);observedCount++;}
|
|
437
|
+
if(!observedCount)bars.append(element('p','empty',text('No request-time headers observed')));
|
|
417
438
|
bars.append(element('div','usage-label',text('Primary quota (/rate_limit)')));
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if(
|
|
421
|
-
if(
|
|
422
|
-
const observed=status?.runtimeRateUsage?.resources||{};
|
|
423
|
-
for(const row of [githubObserved('REST',observed.core),githubObserved('GraphQL',observed.graphql),githubObserved('Search',observed.search)])if(row)bars.append(row);
|
|
424
|
-
if(status?.runtimeRateUsage?.rejection){
|
|
439
|
+
let quotaCount=0;
|
|
440
|
+
for(const pair of [['REST',resources.core],['GraphQL',resources.graphql],['Search',resources.search]])if(pair[1]){bars.append(githubBucket(pair[0],pair[1]));quotaCount++;}
|
|
441
|
+
if(!quotaCount)bars.append(element('p','empty',text('Quota unavailable')));
|
|
442
|
+
if(status?.runtimeRateUsage?.rejection&&status.runtimeRateUsage.rejection.kind!=='secondary'){
|
|
425
443
|
const rejection=status.runtimeRateUsage.rejection;
|
|
426
|
-
|
|
427
|
-
bars.append(element('div','error-state',text('Throttled · '+(rejection.kind==='unknown'?'rate limit':rejection.kind)+' limit'+cooldown)));
|
|
444
|
+
bars.append(element('div','error-state',text('Throttled · '+(rejection.kind==='unknown'?'rate limit':rejection.kind)+' limit')));
|
|
428
445
|
}
|
|
429
|
-
if(status?.limited){
|
|
446
|
+
if(status?.limited&&status?.runtimeRateUsage?.rejection?.kind!=='secondary'){
|
|
430
447
|
const until=status.cooldownUntil?' until '+new Date(status.cooldownUntil).toLocaleTimeString():'';
|
|
431
448
|
bars.append(element('div','error-state',text('Cooldown active'+until)));
|
|
432
449
|
}
|
|
@@ -14,12 +14,13 @@ function transportResource(requestChannel, headers) {
|
|
|
14
14
|
return requestChannel === 'graphql' ? 'graphql' : 'core';
|
|
15
15
|
}
|
|
16
16
|
function rejectionKind(headers, reason) {
|
|
17
|
-
|
|
17
|
+
const remaining = headerNumber(headers['x-ratelimit-remaining']);
|
|
18
|
+
if (remaining === 0)
|
|
19
|
+
return 'primary';
|
|
20
|
+
if (/secondary rate/i.test(reason) || headerNumber(headers['retry-after']) !== null)
|
|
18
21
|
return 'secondary';
|
|
19
|
-
if (/rate limit/i.test(reason) &&
|
|
22
|
+
if (/rate limit/i.test(reason) && remaining !== null && remaining > 0)
|
|
20
23
|
return 'secondary';
|
|
21
|
-
if (/rate limit/i.test(reason))
|
|
22
|
-
return 'primary';
|
|
23
24
|
return 'unknown';
|
|
24
25
|
}
|
|
25
26
|
function isThrottled(status, reason) {
|
|
@@ -51,6 +52,8 @@ export function runtimeRejection(observation) {
|
|
|
51
52
|
const headers = {};
|
|
52
53
|
if (observation.remaining !== null)
|
|
53
54
|
headers['x-ratelimit-remaining'] = String(observation.remaining);
|
|
55
|
+
if (observation.retryAfterSeconds !== null)
|
|
56
|
+
headers['retry-after'] = String(observation.retryAfterSeconds);
|
|
54
57
|
const retryAfterSeconds = observation.retryAfterSeconds;
|
|
55
58
|
return {
|
|
56
59
|
resource: observation.resource,
|