viberadar 0.3.199 → 0.3.201
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/scanner/index.d.ts +4 -0
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +48 -6
- package/dist/scanner/index.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +136 -5
- package/dist/server/index.js.map +1 -1
- package/dist/ui/dashboard.html +67 -46
- package/package.json +2 -2
package/dist/server/index.js
CHANGED
|
@@ -1104,26 +1104,108 @@ function buildObsSuppressPatternPrompt(pattern, recommendation, catalog) {
|
|
|
1104
1104
|
})
|
|
1105
1105
|
.slice(0, 15);
|
|
1106
1106
|
return [
|
|
1107
|
-
|
|
1107
|
+
`Проведи ревизию шумных лог-вызовов уровня INFO/DEBUG/TRACE. Не применяй рекомендации VibeRadar автоматически.`,
|
|
1108
1108
|
``,
|
|
1109
1109
|
SUPPRESS_GUARD,
|
|
1110
1110
|
``,
|
|
1111
1111
|
`Конкретный паттерн для поиска: "${pattern}"`,
|
|
1112
|
+
recommendation ? `Рекомендация радара: ${recommendation}. Считай её гипотезой, а не командой.` : '',
|
|
1112
1113
|
``,
|
|
1113
1114
|
relatedModules.length > 0
|
|
1114
1115
|
? `Модули где встречается шум (с примерами сообщений):\n${relatedModules.join('\n')}`
|
|
1115
1116
|
: '',
|
|
1116
1117
|
``,
|
|
1117
|
-
|
|
1118
|
-
`-
|
|
1119
|
-
`-
|
|
1118
|
+
`Сначала классифицируй каждый найденный logger.info/debug/trace:`,
|
|
1119
|
+
`- safe_to_remove — lifecycle-мусор без бизнес-смысла: "started", "done", "ok", "loaded", "ready", "ping"`,
|
|
1120
|
+
`- safe_to_downgrade — полезно только для локальной диагностики, можно перевести в debug`,
|
|
1121
|
+
`- keep — audit/security/payment/auth/business-event, reconciliation, user action или важный lifecycle flow`,
|
|
1122
|
+
`- needs_human_review — контекст спорный или уверенность ниже высокой`,
|
|
1123
|
+
``,
|
|
1124
|
+
`Меняй код только для safe_to_remove/safe_to_downgrade:`,
|
|
1125
|
+
`- УДАЛИ полностью только очевидный lifecycle-мусор без диагностической ценности`,
|
|
1126
|
+
`- СТРУКТУРИРУЙ в logger.debug({ service, event_name, outcome, ...данные }), если лог несёт диагностическую ценность`,
|
|
1127
|
+
`- ОСТАВЬ как есть, если это бизнес-событие, аудит, безопасность, платежи, авторизация, интеграция, очередь или reconciliation`,
|
|
1120
1128
|
`- НЕ ТРОГАЙ, если это logger.warn / logger.error / logger.fatal — даже если сообщение похоже на шум`,
|
|
1129
|
+
`- Перед изменениями выведи краткий список решений: файл, паттерн/строка, действие, причина`,
|
|
1121
1130
|
``,
|
|
1122
1131
|
`⛔ НЕ ЗАПУСКАЙ npm test / vitest / playwright — это лог-правка, не изменение логики. Единственная нужная проверка: \`npm run check\` (tsc).`,
|
|
1123
1132
|
``,
|
|
1124
1133
|
`\n${LOGGING_STANDARD_INLINE}`,
|
|
1125
1134
|
].filter(Boolean).join('\n');
|
|
1126
1135
|
}
|
|
1136
|
+
function decodeJwtPayload(token) {
|
|
1137
|
+
const part = token.split('.')[1];
|
|
1138
|
+
if (!part)
|
|
1139
|
+
return null;
|
|
1140
|
+
try {
|
|
1141
|
+
const normalized = part.replace(/-/g, '+').replace(/_/g, '/');
|
|
1142
|
+
const padded = normalized + '='.repeat((4 - normalized.length % 4) % 4);
|
|
1143
|
+
return JSON.parse(Buffer.from(padded, 'base64').toString('utf-8'));
|
|
1144
|
+
}
|
|
1145
|
+
catch {
|
|
1146
|
+
return null;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
function loadCodexAccountInfo() {
|
|
1150
|
+
const result = { email: null, name: null, accountId: null, raw: '' };
|
|
1151
|
+
try {
|
|
1152
|
+
const authPath = path.join(os.homedir(), '.codex', 'auth.json');
|
|
1153
|
+
const auth = JSON.parse(fs.readFileSync(authPath, 'utf-8'));
|
|
1154
|
+
const payload = typeof auth?.tokens?.id_token === 'string'
|
|
1155
|
+
? decodeJwtPayload(auth.tokens.id_token)
|
|
1156
|
+
: null;
|
|
1157
|
+
result.email = payload?.email || payload?.https?.email || null;
|
|
1158
|
+
result.name = payload?.name || payload?.nickname || payload?.preferred_username || null;
|
|
1159
|
+
result.accountId = auth?.tokens?.account_id || payload?.sub || null;
|
|
1160
|
+
result.raw = result.email || result.name || result.accountId || '';
|
|
1161
|
+
}
|
|
1162
|
+
catch { }
|
|
1163
|
+
return result;
|
|
1164
|
+
}
|
|
1165
|
+
function buildObsPromptForTask(task, meta, obs) {
|
|
1166
|
+
if (task === 'obs-suppress-pattern') {
|
|
1167
|
+
if (!meta?.pattern)
|
|
1168
|
+
return null;
|
|
1169
|
+
return buildObsSuppressPatternPrompt(meta.pattern, meta.recommendation || 'suppress', obs.catalog);
|
|
1170
|
+
}
|
|
1171
|
+
if (task === 'obs-add-critical-logs') {
|
|
1172
|
+
if (!meta?.modulePath)
|
|
1173
|
+
return null;
|
|
1174
|
+
const v2Item = (obs.missingCriticalLogsV2 || []).find((m) => m.modulePath === meta.modulePath);
|
|
1175
|
+
return v2Item
|
|
1176
|
+
? buildObsAddCriticalLogsPromptV2(v2Item, obs.catalog)
|
|
1177
|
+
: buildObsAddCriticalLogsPrompt(meta.modulePath, obs.catalog);
|
|
1178
|
+
}
|
|
1179
|
+
if (task === 'obs-enrich-field') {
|
|
1180
|
+
if (!meta?.fieldName)
|
|
1181
|
+
return null;
|
|
1182
|
+
return buildObsEnrichFieldPrompt(meta.fieldName, obs.catalog);
|
|
1183
|
+
}
|
|
1184
|
+
if (task === 'obs-batch-recommendation') {
|
|
1185
|
+
if (!meta?.recommendationType)
|
|
1186
|
+
return null;
|
|
1187
|
+
return buildObsBatchRecommendationPrompt(meta.recommendationType, obs.catalog);
|
|
1188
|
+
}
|
|
1189
|
+
if (task === 'obs-fix-module') {
|
|
1190
|
+
const modulePath = meta?.modulePath;
|
|
1191
|
+
const catalogItem = modulePath ? obs.catalog.find(c => c.modulePath === modulePath) : null;
|
|
1192
|
+
return catalogItem ? buildObsFixModulePrompt(catalogItem.modulePath, catalogItem) : null;
|
|
1193
|
+
}
|
|
1194
|
+
if (task === 'obs-fix-selected') {
|
|
1195
|
+
const missingLogIndices = Array.isArray(meta?.missingLogIndices) ? meta.missingLogIndices : [];
|
|
1196
|
+
const indices = Array.isArray(meta?.catalogIndices) ? meta.catalogIndices : [];
|
|
1197
|
+
if (missingLogIndices.length > 0) {
|
|
1198
|
+
const selectedV2 = missingLogIndices.map(i => obs.missingCriticalLogsV2[i]).filter(Boolean);
|
|
1199
|
+
return selectedV2.length > 0 ? buildObsBatchAddCriticalLogsPrompt(selectedV2, obs.catalog) : null;
|
|
1200
|
+
}
|
|
1201
|
+
const paths = Array.isArray(meta?.catalogPaths) ? meta.catalogPaths : [];
|
|
1202
|
+
const selectedItems = paths.length > 0
|
|
1203
|
+
? paths.map(p => obs.catalog.find(c => c.modulePath === p)).filter(Boolean)
|
|
1204
|
+
: indices.map(i => obs.catalog[i]).filter(Boolean);
|
|
1205
|
+
return selectedItems.length > 0 ? buildObsFixSelectedPrompt(selectedItems, meta || {}) : null;
|
|
1206
|
+
}
|
|
1207
|
+
return null;
|
|
1208
|
+
}
|
|
1127
1209
|
function buildObsAddCriticalLogsPrompt(modulePath, catalog) {
|
|
1128
1210
|
const moduleItem = catalog.find(c => c.modulePath === modulePath);
|
|
1129
1211
|
const missingFields = moduleItem?.missingFields || [];
|
|
@@ -3302,6 +3384,34 @@ function startServer({ data: initialData, port, projectRoot }) {
|
|
|
3302
3384
|
res.end(JSON.stringify({ ...currentData, testErrors, hasPlaywright: hasPlaywright(projectRoot), e2ePlansExist, agentRuntime }));
|
|
3303
3385
|
return;
|
|
3304
3386
|
}
|
|
3387
|
+
if (url === '/api/obs-build-prompt' && req.method === 'POST') {
|
|
3388
|
+
let body = '';
|
|
3389
|
+
req.on('data', d => body += d);
|
|
3390
|
+
req.on('end', () => {
|
|
3391
|
+
try {
|
|
3392
|
+
const { task, meta } = JSON.parse(body || '{}');
|
|
3393
|
+
const obs = currentData.observability;
|
|
3394
|
+
if (!obs) {
|
|
3395
|
+
res.writeHead(400, jsonH);
|
|
3396
|
+
res.end(JSON.stringify({ error: 'Нет данных observability' }));
|
|
3397
|
+
return;
|
|
3398
|
+
}
|
|
3399
|
+
const prompt = buildObsPromptForTask(task, meta || {}, obs);
|
|
3400
|
+
if (!prompt) {
|
|
3401
|
+
res.writeHead(400, jsonH);
|
|
3402
|
+
res.end(JSON.stringify({ error: 'Не удалось собрать prompt для выбранной рекомендации' }));
|
|
3403
|
+
return;
|
|
3404
|
+
}
|
|
3405
|
+
res.writeHead(200, jsonH);
|
|
3406
|
+
res.end(JSON.stringify({ ok: true, prompt }));
|
|
3407
|
+
}
|
|
3408
|
+
catch (err) {
|
|
3409
|
+
res.writeHead(400, jsonH);
|
|
3410
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
3411
|
+
}
|
|
3412
|
+
});
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
3305
3415
|
if (url === '/api/service-map' && req.method === 'GET') {
|
|
3306
3416
|
const format = parsedUrl.searchParams.get('format') || 'json';
|
|
3307
3417
|
const sm = currentData?.serviceMap;
|
|
@@ -3634,6 +3744,27 @@ function startServer({ data: initialData, port, projectRoot }) {
|
|
|
3634
3744
|
return;
|
|
3635
3745
|
}
|
|
3636
3746
|
if (url === '/api/agent-whoami' && req.method === 'GET') {
|
|
3747
|
+
const requestedAgent = parsedUrl.searchParams.get('agent') || currentData.agent || 'claude';
|
|
3748
|
+
if (requestedAgent === 'codex') {
|
|
3749
|
+
const cmd = WIN ? 'codex.cmd login status' : 'codex login status';
|
|
3750
|
+
let out = '';
|
|
3751
|
+
const proc = (0, child_process_1.spawn)(cmd, [], { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
3752
|
+
proc.stdout?.on('data', (d) => { out += d.toString(); });
|
|
3753
|
+
proc.stderr?.on('data', (d) => { out += d.toString(); });
|
|
3754
|
+
proc.on('close', () => {
|
|
3755
|
+
const account = loadCodexAccountInfo();
|
|
3756
|
+
res.writeHead(200, jsonH);
|
|
3757
|
+
res.end(JSON.stringify({
|
|
3758
|
+
agent: 'codex',
|
|
3759
|
+
loggedIn: /logged in/i.test(out),
|
|
3760
|
+
email: account.email,
|
|
3761
|
+
name: account.name,
|
|
3762
|
+
accountId: account.accountId,
|
|
3763
|
+
raw: account.raw || out.trim().slice(0, 300),
|
|
3764
|
+
}));
|
|
3765
|
+
});
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3637
3768
|
const cmd = WIN ? 'claude.cmd auth status' : 'claude auth status';
|
|
3638
3769
|
let out = '';
|
|
3639
3770
|
const proc = (0, child_process_1.spawn)(cmd, [], { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
@@ -3646,7 +3777,7 @@ function startServer({ data: initialData, port, projectRoot }) {
|
|
|
3646
3777
|
|| out.match(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/);
|
|
3647
3778
|
const email = match ? match[1] : null;
|
|
3648
3779
|
res.writeHead(200, jsonH);
|
|
3649
|
-
res.end(JSON.stringify({ email, raw: out.trim().slice(0, 300) }));
|
|
3780
|
+
res.end(JSON.stringify({ agent: 'claude', email, raw: out.trim().slice(0, 300) }));
|
|
3650
3781
|
});
|
|
3651
3782
|
return;
|
|
3652
3783
|
}
|