viberadar 0.3.200 → 0.3.202
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/server/index.d.ts.map +1 -1
- package/dist/server/index.js +51 -1
- package/dist/server/index.js.map +1 -1
- package/dist/ui/dashboard.html +61 -31
- package/package.json +2 -2
package/dist/ui/dashboard.html
CHANGED
|
@@ -2697,20 +2697,33 @@ function updateAgentRightsInfo() {
|
|
|
2697
2697
|
const el = document.getElementById('headerAgentRights');
|
|
2698
2698
|
if (!el || !D) return;
|
|
2699
2699
|
const runtime = D.agentRuntime || {};
|
|
2700
|
-
const sandbox = runtime.codexSandboxMode || 'read-only';
|
|
2701
|
-
const approval = runtime.approvalPolicy || 'never';
|
|
2702
|
-
|
|
2703
|
-
if (D.agent === 'codex') {
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2700
|
+
const sandbox = runtime.codexSandboxMode || 'read-only';
|
|
2701
|
+
const approval = runtime.approvalPolicy || 'never';
|
|
2702
|
+
|
|
2703
|
+
if (D.agent === 'codex') {
|
|
2704
|
+
const cached = window._codexAccount;
|
|
2705
|
+
const account = cached ? ` · ${cached}` : '';
|
|
2706
|
+
el.textContent = `🔐 Codex${account}: ${sandbox}, approval: ${approval}`;
|
|
2707
|
+
el.title = cached
|
|
2708
|
+
? `Codex аккаунт: ${cached}. Права: ${sandbox}, approval: ${approval}`
|
|
2709
|
+
: 'Загружаю аккаунт Codex…';
|
|
2710
|
+
if (!cached) {
|
|
2711
|
+
fetch('/api/agent-whoami?agent=codex').then(r => r.json()).then(d => {
|
|
2712
|
+
window._codexAccount = d.email || d.name || d.accountId || d.raw || 'неизвестно';
|
|
2713
|
+
updateAgentRightsInfo();
|
|
2714
|
+
}).catch(() => {
|
|
2715
|
+
window._codexAccount = 'неизвестно';
|
|
2716
|
+
updateAgentRightsInfo();
|
|
2717
|
+
});
|
|
2718
|
+
}
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2708
2721
|
if (D.agent === 'claude') {
|
|
2709
2722
|
const cached = window._claudeAccount;
|
|
2710
2723
|
el.textContent = cached ? `🔐 ${cached}` : '🔐 Claude';
|
|
2711
2724
|
el.title = cached ? `Claude аккаунт: ${cached}` : 'Загружаю аккаунт…';
|
|
2712
2725
|
if (!cached) {
|
|
2713
|
-
fetch('/api/agent-whoami').then(r => r.json()).then(d => {
|
|
2726
|
+
fetch('/api/agent-whoami?agent=claude').then(r => r.json()).then(d => {
|
|
2714
2727
|
window._claudeAccount = d.email || d.raw?.split('\n')[0] || 'неизвестно';
|
|
2715
2728
|
updateAgentRightsInfo();
|
|
2716
2729
|
}).catch(() => {});
|
|
@@ -4694,9 +4707,10 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4694
4707
|
}).join('') || '<div class="obs-sub">Шумных паттернов не обнаружено</div>';
|
|
4695
4708
|
|
|
4696
4709
|
// ── Missing critical logs (V2: grouped by risk tier with failure points) ──
|
|
4697
|
-
const v2Data = missingV2.filter(m => m.failurePoints.length > 0);
|
|
4698
|
-
window.__obsMissingV2 = v2Data;
|
|
4699
|
-
|
|
4710
|
+
const v2Data = missingV2.filter(m => m.failurePoints.length > 0);
|
|
4711
|
+
window.__obsMissingV2 = v2Data;
|
|
4712
|
+
window.__obsMissingGroupMeta = {};
|
|
4713
|
+
const fpTypeLabels = {
|
|
4700
4714
|
'empty-catch':'пустой catch','catch-no-log':'catch без лога','promise-catch-no-log':'.catch без лога',
|
|
4701
4715
|
'http-no-error-handling':'HTTP без обработки','db-no-error-handling':'DB без обработки',
|
|
4702
4716
|
'throw-no-log':'throw без лога','error-check-no-log':'if(err) без лога',
|
|
@@ -4706,11 +4720,19 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4706
4720
|
const tierLabels = { critical:'Критичные', important:'Важные', normal:'Обычные' };
|
|
4707
4721
|
const tiers = ['critical','important','normal'];
|
|
4708
4722
|
const tierSections = tiers.map(tier => {
|
|
4709
|
-
const items = v2Data.filter(m => m.riskTier === tier);
|
|
4710
|
-
if (!items.length) return '';
|
|
4711
|
-
const groupId = 'missing-' + tier;
|
|
4712
|
-
const
|
|
4713
|
-
|
|
4723
|
+
const items = v2Data.filter(m => m.riskTier === tier);
|
|
4724
|
+
if (!items.length) return '';
|
|
4725
|
+
const groupId = 'missing-' + tier;
|
|
4726
|
+
const groupIndices = items
|
|
4727
|
+
.map(m => (o.missingCriticalLogsV2 || []).indexOf(m))
|
|
4728
|
+
.filter(idx => idx >= 0);
|
|
4729
|
+
window.__obsMissingGroupMeta[groupId] = {
|
|
4730
|
+
missingLogIndices: groupIndices,
|
|
4731
|
+
recommendationType: 'add event',
|
|
4732
|
+
};
|
|
4733
|
+
const expandBtn = hasAgent ? `<button class="obs-expand-btn" onclick="event.stopPropagation();toggleObsDetail('${groupId}')">▼</button>` : '';
|
|
4734
|
+
const copyGroupBtn = `<button class="obs-copy-btn" title="Скопировать prompt для всей группы" onclick="event.stopPropagation();obsCopyPrompt('obs-fix-selected',window.__obsMissingGroupMeta['${groupId}'])">📋 Промпт</button>`;
|
|
4735
|
+
const totalFPs = items.reduce((s,m) => s + m.failurePoints.length, 0);
|
|
4714
4736
|
const detailItems = items.map(m => {
|
|
4715
4737
|
const globalIdx = (o.missingCriticalLogsV2 || []).indexOf(m); // index in full unfiltered array — must match server's missingCriticalLogsV2
|
|
4716
4738
|
const fpCount = m.failurePoints.length;
|
|
@@ -4740,10 +4762,11 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4740
4762
|
const _blTier = _bl?.tiers?.[tier];
|
|
4741
4763
|
return `<div class="obs-tier-group">
|
|
4742
4764
|
<div class="obs-tier-group-header">
|
|
4743
|
-
<span class="obs-tier-badge obs-tier-${tier}">${tierLabels[tier]}</span>
|
|
4744
|
-
<span>${items.length}${_d(items.length, _blTier?.modules)} модулей, ${totalFPs}${_d(totalFPs, _blTier?.fps)} точек отказа</span>
|
|
4745
|
-
${
|
|
4746
|
-
|
|
4765
|
+
<span class="obs-tier-badge obs-tier-${tier}">${tierLabels[tier]}</span>
|
|
4766
|
+
<span>${items.length}${_d(items.length, _blTier?.modules)} модулей, ${totalFPs}${_d(totalFPs, _blTier?.fps)} точек отказа</span>
|
|
4767
|
+
${copyGroupBtn}
|
|
4768
|
+
${expandBtn}
|
|
4769
|
+
</div>
|
|
4747
4770
|
${detail}
|
|
4748
4771
|
</div>`;
|
|
4749
4772
|
}).join('');
|
|
@@ -4752,12 +4775,18 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4752
4775
|
missingSection = '<div class="obs-sub" style="color:var(--green)">Критичные сценарии покрыты</div>';
|
|
4753
4776
|
}
|
|
4754
4777
|
|
|
4755
|
-
const fieldGaps = fieldGapsData;
|
|
4756
|
-
|
|
4757
|
-
const
|
|
4758
|
-
|
|
4759
|
-
const
|
|
4760
|
-
const
|
|
4778
|
+
const fieldGaps = fieldGapsData;
|
|
4779
|
+
window.__obsFieldGroupMeta = {};
|
|
4780
|
+
const fieldGapEntries = Object.entries(fieldGaps).filter(([,v]) => v > 0).sort((a,b) => b[1] - a[1]);
|
|
4781
|
+
const fieldGapRows = fieldGapEntries.map(([name, count]) => {
|
|
4782
|
+
const groupId = 'field-' + name.replace(/[^a-z0-9]/gi, '_');
|
|
4783
|
+
const affectedItems = catalog.filter(c => (c.missingFields||[]).includes(name));
|
|
4784
|
+
window.__obsFieldGroupMeta[groupId] = {
|
|
4785
|
+
fieldName: name,
|
|
4786
|
+
catalogPaths: affectedItems.map(c => c.modulePath),
|
|
4787
|
+
};
|
|
4788
|
+
const expandBtn = hasAgent ? `<button class="obs-expand-btn" onclick="event.stopPropagation();toggleObsDetail('${groupId}')">▼</button>` : '';
|
|
4789
|
+
const copyFieldBtn = `<button class="obs-copy-btn" title="Скопировать prompt для всех модулей с этим полем" onclick="event.stopPropagation();obsCopyPrompt('obs-fix-selected',window.__obsFieldGroupMeta['${groupId}'])">📋 Промпт</button>`;
|
|
4761
4790
|
const detailItems = affectedItems.map(ci => {
|
|
4762
4791
|
const catIdx = catalog.indexOf(ci);
|
|
4763
4792
|
const otherMissing = (ci.missingFields||[]).filter(f => f !== name);
|
|
@@ -4776,10 +4805,11 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4776
4805
|
</div>` : '';
|
|
4777
4806
|
return `<div>
|
|
4778
4807
|
<div class="obs-list-item">
|
|
4779
|
-
<span><code>${escapeHtml(name)}</code></span>
|
|
4780
|
-
<strong style="color:${count > 20 ? 'var(--red)' : count > 5 ? 'var(--yellow)' : 'var(--muted)'}">${count} пропусков в ${affectedItems.length} модул${affectedItems.length === 1 ? 'е' : affectedItems.length < 5 ? 'ях' : 'ях'}</strong>
|
|
4781
|
-
${
|
|
4782
|
-
|
|
4808
|
+
<span><code>${escapeHtml(name)}</code></span>
|
|
4809
|
+
<strong style="color:${count > 20 ? 'var(--red)' : count > 5 ? 'var(--yellow)' : 'var(--muted)'}">${count} пропусков в ${affectedItems.length} модул${affectedItems.length === 1 ? 'е' : affectedItems.length < 5 ? 'ях' : 'ях'}</strong>
|
|
4810
|
+
${copyFieldBtn}
|
|
4811
|
+
${expandBtn}
|
|
4812
|
+
</div>
|
|
4783
4813
|
${detail}
|
|
4784
4814
|
</div>`;
|
|
4785
4815
|
}).join('') || '<div class="obs-sub" style="color:var(--green)">Все обязательные поля на месте</div>';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "viberadar",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.202",
|
|
4
4
|
"description": "Live module map with test coverage for vibecoding projects",
|
|
5
5
|
"main": "./dist/cli.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"viberadar": "
|
|
7
|
+
"viberadar": "viberadar.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc && node scripts/bundle-ui.js",
|