donobu 5.42.0 → 5.43.1
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.
|
@@ -33,7 +33,15 @@ class DonobuGptClient extends GptClient_1.GptClient {
|
|
|
33
33
|
if (resp.status === 401) {
|
|
34
34
|
throw new GptPlatformAuthenticationFailedException_1.GptPlatformAuthenticationFailedException(this.config.type);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// 402 Payment Required = the key is valid, but the account has no
|
|
37
|
+
// wallet / no credits. The credential itself authenticated fine, so
|
|
38
|
+
// accept the config — the user just can't run flows until they top up
|
|
39
|
+
// (Studio surfaces a "0 credits remaining" nudge). Rejecting here would
|
|
40
|
+
// block the managed donobu gpt-config from ever being created.
|
|
41
|
+
if (resp.status === 402) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!resp.ok) {
|
|
37
45
|
throw new Error(`Donobu API ping failed with status ${resp.status}: ${await resp.text()}`);
|
|
38
46
|
}
|
|
39
47
|
}
|
|
@@ -33,7 +33,15 @@ class DonobuGptClient extends GptClient_1.GptClient {
|
|
|
33
33
|
if (resp.status === 401) {
|
|
34
34
|
throw new GptPlatformAuthenticationFailedException_1.GptPlatformAuthenticationFailedException(this.config.type);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// 402 Payment Required = the key is valid, but the account has no
|
|
37
|
+
// wallet / no credits. The credential itself authenticated fine, so
|
|
38
|
+
// accept the config — the user just can't run flows until they top up
|
|
39
|
+
// (Studio surfaces a "0 credits remaining" nudge). Rejecting here would
|
|
40
|
+
// block the managed donobu gpt-config from ever being created.
|
|
41
|
+
if (resp.status === 402) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!resp.ok) {
|
|
37
45
|
throw new Error(`Donobu API ping failed with status ${resp.status}: ${await resp.text()}`);
|
|
38
46
|
}
|
|
39
47
|
}
|
|
@@ -1678,7 +1678,7 @@ function renderHtml(report, triage, outputDir) {
|
|
|
1678
1678
|
? `<div class="flow-id-detail"><span class="detail-label">Flow ID</span><span class="flow-id-value">${esc(test.flowId)}<button class="copy-flow-id" data-flow-id="${esc(test.flowId)}" title="Copy flow ID"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button></span></div>`
|
|
1679
1679
|
: '';
|
|
1680
1680
|
testSectionsHtml += `
|
|
1681
|
-
<div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-tags="${esc(JSON.stringify(test.tags))}" ${hasDetails ? `data-detail="${testId}"` : ''}>
|
|
1681
|
+
<div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
|
|
1682
1682
|
<div class="test-summary">
|
|
1683
1683
|
${chevron}
|
|
1684
1684
|
<span class="status-dot" style="background:${sc.color}" title="${sc.label}"></span>
|
|
@@ -1786,6 +1786,8 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1786
1786
|
.tag-menu-item:hover{background:var(--surface)}
|
|
1787
1787
|
.tag-menu-item .tag-menu-count{color:var(--text-muted);font-size:11px;font-family:var(--mono)}
|
|
1788
1788
|
.tag-menu-empty{padding:8px 10px;font-size:12px;color:var(--text-muted);font-style:italic}
|
|
1789
|
+
.tag-menu-section{padding:8px 10px 4px;font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-dim);font-family:inherit}
|
|
1790
|
+
.tag-menu-section:not(:first-child){margin-top:4px;border-top:1px solid var(--border)}
|
|
1789
1791
|
.active-tag-filters{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
|
|
1790
1792
|
.tag-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(255,127,58,.12);border:1px solid rgba(255,127,58,.3);color:var(--accent);font-size:11px;font-family:var(--mono);padding:3px 4px 3px 8px;border-radius:4px}
|
|
1791
1793
|
.tag-chip-remove{background:transparent;border:none;color:inherit;cursor:pointer;font-size:14px;line-height:1;padding:0 4px;font-family:inherit;opacity:.7;transition:opacity .15s}
|
|
@@ -2136,7 +2138,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2136
2138
|
<div class="stat-pills">${statPillsHtml}</div>
|
|
2137
2139
|
<div class="tag-filter-controls" data-tag-filter-controls hidden>
|
|
2138
2140
|
<div class="tag-filter-trigger-wrap">
|
|
2139
|
-
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag"><span class="add-tag-plus">+</span>
|
|
2141
|
+
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag or diagnosis"><span class="add-tag-plus">+</span> Filter</button>
|
|
2140
2142
|
<div class="tag-menu" data-tag-menu hidden></div>
|
|
2141
2143
|
</div>
|
|
2142
2144
|
<div class="active-tag-filters" data-active-tag-filters></div>
|
|
@@ -2160,18 +2162,24 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2160
2162
|
|
|
2161
2163
|
<script>
|
|
2162
2164
|
(function(){
|
|
2163
|
-
// Filters compose
|
|
2164
|
-
// status
|
|
2165
|
-
//
|
|
2165
|
+
// Filters compose across three dimensions:
|
|
2166
|
+
// status — single-select; card.data-status must match (if set).
|
|
2167
|
+
// tags — multi-select AND; card must carry every active tag.
|
|
2168
|
+
// reasons — multi-select OR; card.data-reason must match any active reason
|
|
2169
|
+
// (a card has at most one diagnosis, so AND would always be 0/1).
|
|
2170
|
+
// "Clear Filters" wipes all three.
|
|
2166
2171
|
var activeStatus=null;
|
|
2167
2172
|
var activeTags=new Set();
|
|
2173
|
+
var activeReasons=new Set();
|
|
2168
2174
|
var allTags=[];
|
|
2175
|
+
var allReasons=[]; // ordered list of REASON keys present in the report
|
|
2176
|
+
var REASON_LABELS=${JSON.stringify(REASON_LABELS)};
|
|
2169
2177
|
|
|
2170
2178
|
function cardTags(card){var raw=card.getAttribute('data-tags');if(!raw)return [];try{var v=JSON.parse(raw);return Array.isArray(v)?v:[]}catch(_){return []}}
|
|
2171
2179
|
function tagCount(t){var n=0;document.querySelectorAll('.test-card').forEach(function(c){if(cardTags(c).indexOf(t)!==-1)n++});return n}
|
|
2172
2180
|
|
|
2173
2181
|
function applyFilters(){
|
|
2174
|
-
var anyActive=activeStatus!==null||activeTags.size>0;
|
|
2182
|
+
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0;
|
|
2175
2183
|
document.querySelector('.clear-filter').classList.toggle('visible',anyActive);
|
|
2176
2184
|
var visible=0;
|
|
2177
2185
|
document.querySelectorAll('.test-card').forEach(function(card){
|
|
@@ -2181,7 +2189,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2181
2189
|
var t=cardTags(card);
|
|
2182
2190
|
activeTags.forEach(function(want){if(t.indexOf(want)===-1)tagsOk=false});
|
|
2183
2191
|
}
|
|
2184
|
-
var
|
|
2192
|
+
var reasonOk=true;
|
|
2193
|
+
if(activeReasons.size>0){
|
|
2194
|
+
var r=card.getAttribute('data-reason')||'';
|
|
2195
|
+
reasonOk=activeReasons.has(r);
|
|
2196
|
+
}
|
|
2197
|
+
var hide=!(statusOk&&tagsOk&&reasonOk);
|
|
2185
2198
|
card.classList.toggle('hidden-by-filter',hide);
|
|
2186
2199
|
if(!hide)visible++;
|
|
2187
2200
|
});
|
|
@@ -2201,6 +2214,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2201
2214
|
var p=new URLSearchParams();
|
|
2202
2215
|
if(activeStatus)p.set('status',activeStatus);
|
|
2203
2216
|
activeTags.forEach(function(t){p.append('tag',t)});
|
|
2217
|
+
activeReasons.forEach(function(r){p.append('reason',r)});
|
|
2204
2218
|
var qs=p.toString();
|
|
2205
2219
|
var next=location.pathname+(qs?'?'+qs:'')+(location.hash||'');
|
|
2206
2220
|
if(next!==location.pathname+location.search+location.hash){
|
|
@@ -2214,6 +2228,15 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2214
2228
|
applyFilters();
|
|
2215
2229
|
}
|
|
2216
2230
|
|
|
2231
|
+
// Convert "#rrggbb" or "rgb(...)" into a low-alpha background for tinted
|
|
2232
|
+
// diagnosis chips. Falls back to the accent tint if parsing fails.
|
|
2233
|
+
function hexToRgba(hex,a){
|
|
2234
|
+
if(!hex||hex.charAt(0)!=='#'||(hex.length!==4&&hex.length!==7))return 'rgba(255,127,58,'+a+')';
|
|
2235
|
+
var s=hex.length===4?('#'+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3]):hex;
|
|
2236
|
+
var r=parseInt(s.slice(1,3),16),g=parseInt(s.slice(3,5),16),b=parseInt(s.slice(5,7),16);
|
|
2237
|
+
return 'rgba('+r+','+g+','+b+','+a+')';
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2217
2240
|
function renderActiveChips(){
|
|
2218
2241
|
var c=document.querySelector('[data-active-tag-filters]');
|
|
2219
2242
|
if(!c)return;
|
|
@@ -2225,28 +2248,66 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2225
2248
|
chip.appendChild(label);chip.appendChild(btn);
|
|
2226
2249
|
c.appendChild(chip);
|
|
2227
2250
|
});
|
|
2251
|
+
activeReasons.forEach(function(r){
|
|
2252
|
+
var meta=REASON_LABELS[r]||REASON_LABELS['UNKNOWN'];
|
|
2253
|
+
var chip=document.createElement('span');chip.className='tag-chip reason-chip';
|
|
2254
|
+
chip.style.background=hexToRgba(meta.color,0.14);
|
|
2255
|
+
chip.style.borderColor=hexToRgba(meta.color,0.4);
|
|
2256
|
+
chip.style.color=meta.color;
|
|
2257
|
+
var label=document.createElement('span');label.textContent=meta.label;
|
|
2258
|
+
var btn=document.createElement('button');btn.className='tag-chip-remove';btn.setAttribute('data-remove-reason',r);btn.setAttribute('title','Remove filter');btn.textContent='×';
|
|
2259
|
+
chip.appendChild(label);chip.appendChild(btn);
|
|
2260
|
+
c.appendChild(chip);
|
|
2261
|
+
});
|
|
2228
2262
|
}
|
|
2229
2263
|
function addTag(t){if(!t||activeTags.has(t))return;activeTags.add(t);renderActiveChips();applyFilters()}
|
|
2230
2264
|
function removeTag(t){if(!activeTags.delete(t))return;renderActiveChips();applyFilters()}
|
|
2265
|
+
function addReason(r){if(!r||activeReasons.has(r))return;activeReasons.add(r);renderActiveChips();applyFilters()}
|
|
2266
|
+
function removeReason(r){if(!activeReasons.delete(r))return;renderActiveChips();applyFilters()}
|
|
2267
|
+
|
|
2268
|
+
function reasonCount(r){var n=0;document.querySelectorAll('.test-card').forEach(function(c){if(c.getAttribute('data-reason')===r)n++});return n}
|
|
2231
2269
|
|
|
2232
2270
|
function openTagMenu(){
|
|
2233
2271
|
var menu=document.querySelector('[data-tag-menu]');
|
|
2234
2272
|
if(!menu)return;
|
|
2235
2273
|
var trigger=document.querySelector('[data-add-tag-filter]');
|
|
2236
2274
|
menu.innerHTML='';
|
|
2237
|
-
var
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
menu.appendChild(
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2275
|
+
var availTags=allTags.filter(function(t){return !activeTags.has(t)});
|
|
2276
|
+
var availReasons=allReasons.filter(function(r){return !activeReasons.has(r)});
|
|
2277
|
+
var added=false;
|
|
2278
|
+
if(allTags.length>0){
|
|
2279
|
+
var hT=document.createElement('div');hT.className='tag-menu-section';hT.textContent='Tags';menu.appendChild(hT);
|
|
2280
|
+
if(availTags.length===0){
|
|
2281
|
+
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent='All tags selected';menu.appendChild(emptyT);
|
|
2282
|
+
}else{
|
|
2283
|
+
availTags.forEach(function(t){
|
|
2284
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',t);
|
|
2285
|
+
var label=document.createElement('span');label.textContent=t;
|
|
2286
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=tagCount(t);
|
|
2287
|
+
item.appendChild(label);item.appendChild(count);
|
|
2288
|
+
menu.appendChild(item);
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
added=true;
|
|
2292
|
+
}
|
|
2293
|
+
if(allReasons.length>0){
|
|
2294
|
+
var hR=document.createElement('div');hR.className='tag-menu-section';hR.textContent='Diagnoses';menu.appendChild(hR);
|
|
2295
|
+
if(availReasons.length===0){
|
|
2296
|
+
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent='All diagnoses selected';menu.appendChild(emptyR);
|
|
2297
|
+
}else{
|
|
2298
|
+
availReasons.forEach(function(r){
|
|
2299
|
+
var meta=REASON_LABELS[r]||REASON_LABELS['UNKNOWN'];
|
|
2300
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',r);
|
|
2301
|
+
var label=document.createElement('span');label.textContent=meta.label;label.style.color=meta.color;
|
|
2302
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=reasonCount(r);
|
|
2303
|
+
item.appendChild(label);item.appendChild(count);
|
|
2304
|
+
menu.appendChild(item);
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
added=true;
|
|
2308
|
+
}
|
|
2309
|
+
if(!added){
|
|
2310
|
+
var empty=document.createElement('div');empty.className='tag-menu-empty';empty.textContent='No filters available';menu.appendChild(empty);
|
|
2250
2311
|
}
|
|
2251
2312
|
menu.hidden=false;
|
|
2252
2313
|
if(trigger)trigger.classList.add('active');
|
|
@@ -2261,6 +2322,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2261
2322
|
function clearAllFilters(){
|
|
2262
2323
|
activeStatus=null;
|
|
2263
2324
|
activeTags.clear();
|
|
2325
|
+
activeReasons.clear();
|
|
2264
2326
|
document.querySelectorAll('.stat-pill').forEach(function(p){p.classList.remove('active')});
|
|
2265
2327
|
renderActiveChips();
|
|
2266
2328
|
closeTagMenu();
|
|
@@ -2303,8 +2365,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2303
2365
|
if(addTagBtn){if(tagMenuOpen()){closeTagMenu()}else{openTagMenu()}return}
|
|
2304
2366
|
var tagItem=e.target.closest('[data-tag-menu-item]');
|
|
2305
2367
|
if(tagItem){addTag(tagItem.getAttribute('data-tag-menu-item'));closeTagMenu();return}
|
|
2368
|
+
var reasonItem=e.target.closest('[data-reason-menu-item]');
|
|
2369
|
+
if(reasonItem){addReason(reasonItem.getAttribute('data-reason-menu-item'));closeTagMenu();return}
|
|
2306
2370
|
var tagRemove=e.target.closest('[data-remove-tag]');
|
|
2307
2371
|
if(tagRemove){removeTag(tagRemove.getAttribute('data-remove-tag'));return}
|
|
2372
|
+
var reasonRemove=e.target.closest('[data-remove-reason]');
|
|
2373
|
+
if(reasonRemove){removeReason(reasonRemove.getAttribute('data-remove-reason'));return}
|
|
2308
2374
|
// Stat pill filter
|
|
2309
2375
|
var pill=e.target.closest('.stat-pill[data-filter]');
|
|
2310
2376
|
if(pill){toggleStatus(pill.getAttribute('data-filter'));return}
|
|
@@ -2349,23 +2415,29 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2349
2415
|
// Auto-expand failed/timedout/interrupted/healed tests
|
|
2350
2416
|
document.querySelectorAll('.test-card.failed,.test-card.timedout,.test-card.interrupted,.test-card.healed').forEach(function(r){r.classList.add('expanded')});
|
|
2351
2417
|
|
|
2352
|
-
// Collect the cumulative set of tags present across all
|
|
2353
|
-
//
|
|
2418
|
+
// Collect the cumulative set of tags + diagnosis reasons present across all
|
|
2419
|
+
// test cards. Reveal the +filter controls when at least one of either exists.
|
|
2354
2420
|
(function(){
|
|
2355
|
-
var
|
|
2421
|
+
var seenTags=Object.create(null);
|
|
2422
|
+
var seenReasons=Object.create(null);
|
|
2356
2423
|
document.querySelectorAll('.test-card').forEach(function(card){
|
|
2357
|
-
var raw=card.getAttribute('data-tags');
|
|
2358
|
-
try{var tags=JSON.parse(raw);if(Array.isArray(tags)){tags.forEach(function(t){if(typeof t==='string'&&t)
|
|
2424
|
+
var raw=card.getAttribute('data-tags');
|
|
2425
|
+
if(raw){try{var tags=JSON.parse(raw);if(Array.isArray(tags)){tags.forEach(function(t){if(typeof t==='string'&&t)seenTags[t]=true})}}catch(_){}}
|
|
2426
|
+
var r=card.getAttribute('data-reason');
|
|
2427
|
+
if(r)seenReasons[r]=true;
|
|
2359
2428
|
});
|
|
2360
|
-
allTags=Object.keys(
|
|
2429
|
+
allTags=Object.keys(seenTags).sort();
|
|
2430
|
+
// Preserve the REASON_LABELS declaration order rather than alphabetical —
|
|
2431
|
+
// they're already arranged from most-frequent/specific to UNKNOWN catch-all.
|
|
2432
|
+
allReasons=Object.keys(REASON_LABELS).filter(function(r){return seenReasons[r]});
|
|
2361
2433
|
var controls=document.querySelector('[data-tag-filter-controls]');
|
|
2362
|
-
if(controls&&allTags.length>0)controls.hidden=false;
|
|
2434
|
+
if(controls&&(allTags.length>0||allReasons.length>0))controls.hidden=false;
|
|
2363
2435
|
})();
|
|
2364
2436
|
|
|
2365
|
-
// Seed filter state from ?status=...&tag=... so shared URLs
|
|
2366
|
-
// view. Status values not in the known stat-pill set are
|
|
2367
|
-
// values not present in this report are dropped
|
|
2368
|
-
// poison the state.
|
|
2437
|
+
// Seed filter state from ?status=...&tag=...&reason=... so shared URLs
|
|
2438
|
+
// restore the view. Status values not in the known stat-pill set are
|
|
2439
|
+
// ignored; tag and reason values not present in this report are dropped
|
|
2440
|
+
// so a stale URL can't poison the state.
|
|
2369
2441
|
(function(){
|
|
2370
2442
|
var p=new URLSearchParams(location.search);
|
|
2371
2443
|
var s=p.get('status');
|
|
@@ -2377,8 +2449,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2377
2449
|
}
|
|
2378
2450
|
var tagSet={};allTags.forEach(function(t){tagSet[t]=true});
|
|
2379
2451
|
p.getAll('tag').forEach(function(t){if(tagSet[t])activeTags.add(t)});
|
|
2380
|
-
|
|
2381
|
-
|
|
2452
|
+
var reasonSet={};allReasons.forEach(function(r){reasonSet[r]=true});
|
|
2453
|
+
p.getAll('reason').forEach(function(r){if(reasonSet[r])activeReasons.add(r)});
|
|
2454
|
+
if(activeTags.size>0||activeReasons.size>0)renderActiveChips();
|
|
2455
|
+
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0)applyFilters();
|
|
2382
2456
|
})();
|
|
2383
2457
|
|
|
2384
2458
|
// Open #?testId=<id> deep links to the matching test card. Used by the
|
package/dist/reporter/render.js
CHANGED
|
@@ -1678,7 +1678,7 @@ function renderHtml(report, triage, outputDir) {
|
|
|
1678
1678
|
? `<div class="flow-id-detail"><span class="detail-label">Flow ID</span><span class="flow-id-value">${esc(test.flowId)}<button class="copy-flow-id" data-flow-id="${esc(test.flowId)}" title="Copy flow ID"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button></span></div>`
|
|
1679
1679
|
: '';
|
|
1680
1680
|
testSectionsHtml += `
|
|
1681
|
-
<div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-tags="${esc(JSON.stringify(test.tags))}" ${hasDetails ? `data-detail="${testId}"` : ''}>
|
|
1681
|
+
<div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
|
|
1682
1682
|
<div class="test-summary">
|
|
1683
1683
|
${chevron}
|
|
1684
1684
|
<span class="status-dot" style="background:${sc.color}" title="${sc.label}"></span>
|
|
@@ -1786,6 +1786,8 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1786
1786
|
.tag-menu-item:hover{background:var(--surface)}
|
|
1787
1787
|
.tag-menu-item .tag-menu-count{color:var(--text-muted);font-size:11px;font-family:var(--mono)}
|
|
1788
1788
|
.tag-menu-empty{padding:8px 10px;font-size:12px;color:var(--text-muted);font-style:italic}
|
|
1789
|
+
.tag-menu-section{padding:8px 10px 4px;font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-dim);font-family:inherit}
|
|
1790
|
+
.tag-menu-section:not(:first-child){margin-top:4px;border-top:1px solid var(--border)}
|
|
1789
1791
|
.active-tag-filters{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
|
|
1790
1792
|
.tag-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(255,127,58,.12);border:1px solid rgba(255,127,58,.3);color:var(--accent);font-size:11px;font-family:var(--mono);padding:3px 4px 3px 8px;border-radius:4px}
|
|
1791
1793
|
.tag-chip-remove{background:transparent;border:none;color:inherit;cursor:pointer;font-size:14px;line-height:1;padding:0 4px;font-family:inherit;opacity:.7;transition:opacity .15s}
|
|
@@ -2136,7 +2138,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2136
2138
|
<div class="stat-pills">${statPillsHtml}</div>
|
|
2137
2139
|
<div class="tag-filter-controls" data-tag-filter-controls hidden>
|
|
2138
2140
|
<div class="tag-filter-trigger-wrap">
|
|
2139
|
-
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag"><span class="add-tag-plus">+</span>
|
|
2141
|
+
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag or diagnosis"><span class="add-tag-plus">+</span> Filter</button>
|
|
2140
2142
|
<div class="tag-menu" data-tag-menu hidden></div>
|
|
2141
2143
|
</div>
|
|
2142
2144
|
<div class="active-tag-filters" data-active-tag-filters></div>
|
|
@@ -2160,18 +2162,24 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2160
2162
|
|
|
2161
2163
|
<script>
|
|
2162
2164
|
(function(){
|
|
2163
|
-
// Filters compose
|
|
2164
|
-
// status
|
|
2165
|
-
//
|
|
2165
|
+
// Filters compose across three dimensions:
|
|
2166
|
+
// status — single-select; card.data-status must match (if set).
|
|
2167
|
+
// tags — multi-select AND; card must carry every active tag.
|
|
2168
|
+
// reasons — multi-select OR; card.data-reason must match any active reason
|
|
2169
|
+
// (a card has at most one diagnosis, so AND would always be 0/1).
|
|
2170
|
+
// "Clear Filters" wipes all three.
|
|
2166
2171
|
var activeStatus=null;
|
|
2167
2172
|
var activeTags=new Set();
|
|
2173
|
+
var activeReasons=new Set();
|
|
2168
2174
|
var allTags=[];
|
|
2175
|
+
var allReasons=[]; // ordered list of REASON keys present in the report
|
|
2176
|
+
var REASON_LABELS=${JSON.stringify(REASON_LABELS)};
|
|
2169
2177
|
|
|
2170
2178
|
function cardTags(card){var raw=card.getAttribute('data-tags');if(!raw)return [];try{var v=JSON.parse(raw);return Array.isArray(v)?v:[]}catch(_){return []}}
|
|
2171
2179
|
function tagCount(t){var n=0;document.querySelectorAll('.test-card').forEach(function(c){if(cardTags(c).indexOf(t)!==-1)n++});return n}
|
|
2172
2180
|
|
|
2173
2181
|
function applyFilters(){
|
|
2174
|
-
var anyActive=activeStatus!==null||activeTags.size>0;
|
|
2182
|
+
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0;
|
|
2175
2183
|
document.querySelector('.clear-filter').classList.toggle('visible',anyActive);
|
|
2176
2184
|
var visible=0;
|
|
2177
2185
|
document.querySelectorAll('.test-card').forEach(function(card){
|
|
@@ -2181,7 +2189,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2181
2189
|
var t=cardTags(card);
|
|
2182
2190
|
activeTags.forEach(function(want){if(t.indexOf(want)===-1)tagsOk=false});
|
|
2183
2191
|
}
|
|
2184
|
-
var
|
|
2192
|
+
var reasonOk=true;
|
|
2193
|
+
if(activeReasons.size>0){
|
|
2194
|
+
var r=card.getAttribute('data-reason')||'';
|
|
2195
|
+
reasonOk=activeReasons.has(r);
|
|
2196
|
+
}
|
|
2197
|
+
var hide=!(statusOk&&tagsOk&&reasonOk);
|
|
2185
2198
|
card.classList.toggle('hidden-by-filter',hide);
|
|
2186
2199
|
if(!hide)visible++;
|
|
2187
2200
|
});
|
|
@@ -2201,6 +2214,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2201
2214
|
var p=new URLSearchParams();
|
|
2202
2215
|
if(activeStatus)p.set('status',activeStatus);
|
|
2203
2216
|
activeTags.forEach(function(t){p.append('tag',t)});
|
|
2217
|
+
activeReasons.forEach(function(r){p.append('reason',r)});
|
|
2204
2218
|
var qs=p.toString();
|
|
2205
2219
|
var next=location.pathname+(qs?'?'+qs:'')+(location.hash||'');
|
|
2206
2220
|
if(next!==location.pathname+location.search+location.hash){
|
|
@@ -2214,6 +2228,15 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2214
2228
|
applyFilters();
|
|
2215
2229
|
}
|
|
2216
2230
|
|
|
2231
|
+
// Convert "#rrggbb" or "rgb(...)" into a low-alpha background for tinted
|
|
2232
|
+
// diagnosis chips. Falls back to the accent tint if parsing fails.
|
|
2233
|
+
function hexToRgba(hex,a){
|
|
2234
|
+
if(!hex||hex.charAt(0)!=='#'||(hex.length!==4&&hex.length!==7))return 'rgba(255,127,58,'+a+')';
|
|
2235
|
+
var s=hex.length===4?('#'+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3]):hex;
|
|
2236
|
+
var r=parseInt(s.slice(1,3),16),g=parseInt(s.slice(3,5),16),b=parseInt(s.slice(5,7),16);
|
|
2237
|
+
return 'rgba('+r+','+g+','+b+','+a+')';
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2217
2240
|
function renderActiveChips(){
|
|
2218
2241
|
var c=document.querySelector('[data-active-tag-filters]');
|
|
2219
2242
|
if(!c)return;
|
|
@@ -2225,28 +2248,66 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2225
2248
|
chip.appendChild(label);chip.appendChild(btn);
|
|
2226
2249
|
c.appendChild(chip);
|
|
2227
2250
|
});
|
|
2251
|
+
activeReasons.forEach(function(r){
|
|
2252
|
+
var meta=REASON_LABELS[r]||REASON_LABELS['UNKNOWN'];
|
|
2253
|
+
var chip=document.createElement('span');chip.className='tag-chip reason-chip';
|
|
2254
|
+
chip.style.background=hexToRgba(meta.color,0.14);
|
|
2255
|
+
chip.style.borderColor=hexToRgba(meta.color,0.4);
|
|
2256
|
+
chip.style.color=meta.color;
|
|
2257
|
+
var label=document.createElement('span');label.textContent=meta.label;
|
|
2258
|
+
var btn=document.createElement('button');btn.className='tag-chip-remove';btn.setAttribute('data-remove-reason',r);btn.setAttribute('title','Remove filter');btn.textContent='×';
|
|
2259
|
+
chip.appendChild(label);chip.appendChild(btn);
|
|
2260
|
+
c.appendChild(chip);
|
|
2261
|
+
});
|
|
2228
2262
|
}
|
|
2229
2263
|
function addTag(t){if(!t||activeTags.has(t))return;activeTags.add(t);renderActiveChips();applyFilters()}
|
|
2230
2264
|
function removeTag(t){if(!activeTags.delete(t))return;renderActiveChips();applyFilters()}
|
|
2265
|
+
function addReason(r){if(!r||activeReasons.has(r))return;activeReasons.add(r);renderActiveChips();applyFilters()}
|
|
2266
|
+
function removeReason(r){if(!activeReasons.delete(r))return;renderActiveChips();applyFilters()}
|
|
2267
|
+
|
|
2268
|
+
function reasonCount(r){var n=0;document.querySelectorAll('.test-card').forEach(function(c){if(c.getAttribute('data-reason')===r)n++});return n}
|
|
2231
2269
|
|
|
2232
2270
|
function openTagMenu(){
|
|
2233
2271
|
var menu=document.querySelector('[data-tag-menu]');
|
|
2234
2272
|
if(!menu)return;
|
|
2235
2273
|
var trigger=document.querySelector('[data-add-tag-filter]');
|
|
2236
2274
|
menu.innerHTML='';
|
|
2237
|
-
var
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
menu.appendChild(
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2275
|
+
var availTags=allTags.filter(function(t){return !activeTags.has(t)});
|
|
2276
|
+
var availReasons=allReasons.filter(function(r){return !activeReasons.has(r)});
|
|
2277
|
+
var added=false;
|
|
2278
|
+
if(allTags.length>0){
|
|
2279
|
+
var hT=document.createElement('div');hT.className='tag-menu-section';hT.textContent='Tags';menu.appendChild(hT);
|
|
2280
|
+
if(availTags.length===0){
|
|
2281
|
+
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent='All tags selected';menu.appendChild(emptyT);
|
|
2282
|
+
}else{
|
|
2283
|
+
availTags.forEach(function(t){
|
|
2284
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',t);
|
|
2285
|
+
var label=document.createElement('span');label.textContent=t;
|
|
2286
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=tagCount(t);
|
|
2287
|
+
item.appendChild(label);item.appendChild(count);
|
|
2288
|
+
menu.appendChild(item);
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
added=true;
|
|
2292
|
+
}
|
|
2293
|
+
if(allReasons.length>0){
|
|
2294
|
+
var hR=document.createElement('div');hR.className='tag-menu-section';hR.textContent='Diagnoses';menu.appendChild(hR);
|
|
2295
|
+
if(availReasons.length===0){
|
|
2296
|
+
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent='All diagnoses selected';menu.appendChild(emptyR);
|
|
2297
|
+
}else{
|
|
2298
|
+
availReasons.forEach(function(r){
|
|
2299
|
+
var meta=REASON_LABELS[r]||REASON_LABELS['UNKNOWN'];
|
|
2300
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',r);
|
|
2301
|
+
var label=document.createElement('span');label.textContent=meta.label;label.style.color=meta.color;
|
|
2302
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=reasonCount(r);
|
|
2303
|
+
item.appendChild(label);item.appendChild(count);
|
|
2304
|
+
menu.appendChild(item);
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
added=true;
|
|
2308
|
+
}
|
|
2309
|
+
if(!added){
|
|
2310
|
+
var empty=document.createElement('div');empty.className='tag-menu-empty';empty.textContent='No filters available';menu.appendChild(empty);
|
|
2250
2311
|
}
|
|
2251
2312
|
menu.hidden=false;
|
|
2252
2313
|
if(trigger)trigger.classList.add('active');
|
|
@@ -2261,6 +2322,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2261
2322
|
function clearAllFilters(){
|
|
2262
2323
|
activeStatus=null;
|
|
2263
2324
|
activeTags.clear();
|
|
2325
|
+
activeReasons.clear();
|
|
2264
2326
|
document.querySelectorAll('.stat-pill').forEach(function(p){p.classList.remove('active')});
|
|
2265
2327
|
renderActiveChips();
|
|
2266
2328
|
closeTagMenu();
|
|
@@ -2303,8 +2365,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2303
2365
|
if(addTagBtn){if(tagMenuOpen()){closeTagMenu()}else{openTagMenu()}return}
|
|
2304
2366
|
var tagItem=e.target.closest('[data-tag-menu-item]');
|
|
2305
2367
|
if(tagItem){addTag(tagItem.getAttribute('data-tag-menu-item'));closeTagMenu();return}
|
|
2368
|
+
var reasonItem=e.target.closest('[data-reason-menu-item]');
|
|
2369
|
+
if(reasonItem){addReason(reasonItem.getAttribute('data-reason-menu-item'));closeTagMenu();return}
|
|
2306
2370
|
var tagRemove=e.target.closest('[data-remove-tag]');
|
|
2307
2371
|
if(tagRemove){removeTag(tagRemove.getAttribute('data-remove-tag'));return}
|
|
2372
|
+
var reasonRemove=e.target.closest('[data-remove-reason]');
|
|
2373
|
+
if(reasonRemove){removeReason(reasonRemove.getAttribute('data-remove-reason'));return}
|
|
2308
2374
|
// Stat pill filter
|
|
2309
2375
|
var pill=e.target.closest('.stat-pill[data-filter]');
|
|
2310
2376
|
if(pill){toggleStatus(pill.getAttribute('data-filter'));return}
|
|
@@ -2349,23 +2415,29 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2349
2415
|
// Auto-expand failed/timedout/interrupted/healed tests
|
|
2350
2416
|
document.querySelectorAll('.test-card.failed,.test-card.timedout,.test-card.interrupted,.test-card.healed').forEach(function(r){r.classList.add('expanded')});
|
|
2351
2417
|
|
|
2352
|
-
// Collect the cumulative set of tags present across all
|
|
2353
|
-
//
|
|
2418
|
+
// Collect the cumulative set of tags + diagnosis reasons present across all
|
|
2419
|
+
// test cards. Reveal the +filter controls when at least one of either exists.
|
|
2354
2420
|
(function(){
|
|
2355
|
-
var
|
|
2421
|
+
var seenTags=Object.create(null);
|
|
2422
|
+
var seenReasons=Object.create(null);
|
|
2356
2423
|
document.querySelectorAll('.test-card').forEach(function(card){
|
|
2357
|
-
var raw=card.getAttribute('data-tags');
|
|
2358
|
-
try{var tags=JSON.parse(raw);if(Array.isArray(tags)){tags.forEach(function(t){if(typeof t==='string'&&t)
|
|
2424
|
+
var raw=card.getAttribute('data-tags');
|
|
2425
|
+
if(raw){try{var tags=JSON.parse(raw);if(Array.isArray(tags)){tags.forEach(function(t){if(typeof t==='string'&&t)seenTags[t]=true})}}catch(_){}}
|
|
2426
|
+
var r=card.getAttribute('data-reason');
|
|
2427
|
+
if(r)seenReasons[r]=true;
|
|
2359
2428
|
});
|
|
2360
|
-
allTags=Object.keys(
|
|
2429
|
+
allTags=Object.keys(seenTags).sort();
|
|
2430
|
+
// Preserve the REASON_LABELS declaration order rather than alphabetical —
|
|
2431
|
+
// they're already arranged from most-frequent/specific to UNKNOWN catch-all.
|
|
2432
|
+
allReasons=Object.keys(REASON_LABELS).filter(function(r){return seenReasons[r]});
|
|
2361
2433
|
var controls=document.querySelector('[data-tag-filter-controls]');
|
|
2362
|
-
if(controls&&allTags.length>0)controls.hidden=false;
|
|
2434
|
+
if(controls&&(allTags.length>0||allReasons.length>0))controls.hidden=false;
|
|
2363
2435
|
})();
|
|
2364
2436
|
|
|
2365
|
-
// Seed filter state from ?status=...&tag=... so shared URLs
|
|
2366
|
-
// view. Status values not in the known stat-pill set are
|
|
2367
|
-
// values not present in this report are dropped
|
|
2368
|
-
// poison the state.
|
|
2437
|
+
// Seed filter state from ?status=...&tag=...&reason=... so shared URLs
|
|
2438
|
+
// restore the view. Status values not in the known stat-pill set are
|
|
2439
|
+
// ignored; tag and reason values not present in this report are dropped
|
|
2440
|
+
// so a stale URL can't poison the state.
|
|
2369
2441
|
(function(){
|
|
2370
2442
|
var p=new URLSearchParams(location.search);
|
|
2371
2443
|
var s=p.get('status');
|
|
@@ -2377,8 +2449,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2377
2449
|
}
|
|
2378
2450
|
var tagSet={};allTags.forEach(function(t){tagSet[t]=true});
|
|
2379
2451
|
p.getAll('tag').forEach(function(t){if(tagSet[t])activeTags.add(t)});
|
|
2380
|
-
|
|
2381
|
-
|
|
2452
|
+
var reasonSet={};allReasons.forEach(function(r){reasonSet[r]=true});
|
|
2453
|
+
p.getAll('reason').forEach(function(r){if(reasonSet[r])activeReasons.add(r)});
|
|
2454
|
+
if(activeTags.size>0||activeReasons.size>0)renderActiveChips();
|
|
2455
|
+
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0)applyFilters();
|
|
2382
2456
|
})();
|
|
2383
2457
|
|
|
2384
2458
|
// Open #?testId=<id> deep links to the matching test card. Used by the
|