viberadar 0.3.211 → 0.3.213

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.
@@ -1786,9 +1786,6 @@ let loadVusDraft = 10;
1786
1786
  let loadDurationDraft = '30s';
1787
1787
  let loadDataDirDraft = '';
1788
1788
  let loadResultDirDraft = '';
1789
- let loadExecutionModeDraft = 'auto';
1790
- let loadVusEnvNameDraft = 'SMOKE_VUS';
1791
- let loadDurationEnvNameDraft = 'SMOKE_DURATION';
1792
1789
  let loadView = 'library'; // 'library' | 'editor'
1793
1790
 
1794
1791
  function toggleObsHint(id) {
@@ -7766,25 +7763,16 @@ function applyLoadConfigToFields(cfg) {
7766
7763
  loadDurationDraft = cfg.duration || loadDurationDraft;
7767
7764
  loadDataDirDraft = cfg.dataDir || loadDataDirDraft;
7768
7765
  loadResultDirDraft = cfg.resultDir || loadResultDirDraft;
7769
- loadExecutionModeDraft = cfg.executionMode || loadExecutionModeDraft;
7770
- loadVusEnvNameDraft = cfg.vusEnvName || loadVusEnvNameDraft;
7771
- loadDurationEnvNameDraft = cfg.durationEnvName || loadDurationEnvNameDraft;
7772
7766
  const baseEl = document.getElementById('loadBaseUrl');
7773
7767
  const vusEl = document.getElementById('loadVus');
7774
7768
  const durEl = document.getElementById('loadDuration');
7775
7769
  const dataEl = document.getElementById('loadDataDir');
7776
7770
  const resultEl = document.getElementById('loadResultDir');
7777
- const modeEl = document.getElementById('loadExecutionMode');
7778
- const vusEnvEl = document.getElementById('loadVusEnvName');
7779
- const durationEnvEl = document.getElementById('loadDurationEnvName');
7780
7771
  if (baseEl) baseEl.value = loadBaseUrlDraft;
7781
7772
  if (vusEl) vusEl.value = loadVusDraft;
7782
7773
  if (durEl) durEl.value = loadDurationDraft;
7783
7774
  if (dataEl) dataEl.value = loadDataDirDraft;
7784
7775
  if (resultEl) resultEl.value = loadResultDirDraft;
7785
- if (modeEl) modeEl.value = loadExecutionModeDraft;
7786
- if (vusEnvEl) vusEnvEl.value = loadVusEnvNameDraft;
7787
- if (durationEnvEl) durationEnvEl.value = loadDurationEnvNameDraft;
7788
7776
  }
7789
7777
 
7790
7778
  function renderLoad(c) {
@@ -7819,7 +7807,7 @@ function renderLoad(c) {
7819
7807
  const cards = loadSavedScripts.map(s => `
7820
7808
  <div class="load-library-card" data-sname="${escapeHtml(s.name)}">
7821
7809
  <div class="load-library-card-name">${escapeHtml(s.name)}</div>
7822
- <div class="load-library-card-meta">${escapeHtml(s.date)} · ${s.vus || 10} VU · ${escapeHtml(s.duration || '30s')}</div>
7810
+ <div class="load-library-card-meta">${escapeHtml(s.date)} · ${s.vus || 10} VU · ${escapeHtml(s.duration || '30s')}${s.dataDir ? ' · data: ' + escapeHtml(s.dataDir) : ''}</div>
7823
7811
  </div>`).join('');
7824
7812
  const runRows = loadRuns.slice(0, 12).map(r => {
7825
7813
  const summary = r.summary || {};
@@ -7828,7 +7816,7 @@ function renderLoad(c) {
7828
7816
  return `<div class="load-run-item" data-run-id="${escapeHtml(r.runId)}">
7829
7817
  <div class="load-run-main">
7830
7818
  <div class="load-run-name">${escapeHtml(r.scriptName || 'Без названия')}</div>
7831
- <div class="load-run-meta">${formatLoadRunDate(r.createdAt || r.startTime)} · ${cfg.vus || '—'} VU · ${escapeHtml(cfg.duration || '—')} · ${loadStatusLabel(r.status)}</div>
7819
+ <div class="load-run-meta">${formatLoadRunDate(r.createdAt || r.startTime)} · ${cfg.vus || '—'} VU · ${escapeHtml(cfg.duration || '—')} · ${escapeHtml(cfg.executionMode || 'auto')} · ${loadStatusLabel(r.status)}</div>
7832
7820
  </div>
7833
7821
  <div class="load-run-kpi" title="${escapeHtml(cfg.resultPath || '')}">${summary.rps != null ? Number(summary.rps || 0).toFixed(1) : '—'} RPS</div>
7834
7822
  <div class="load-run-kpi">p95 ${summary.p95Duration != null ? Math.round(summary.p95Duration || 0) + 'ms' : '—'}</div>
@@ -7846,12 +7834,12 @@ function renderLoad(c) {
7846
7834
  </div>
7847
7835
 
7848
7836
  ${loadSavedScripts.length === 0
7849
- ? `<div class="load-library-empty">
7850
- <div style="font-size:32px;margin-bottom:12px">📋</div>
7851
- <div style="font-size:14px;font-weight:500;margin-bottom:6px">Нет сохранённых тестов</div>
7852
- <div style="font-size:12px;color:var(--muted);margin-bottom:16px">Создай первый тест напиши k6 скрипт или сгенерируй через AI</div>
7853
- <button class="load-btn load-btn-run" onclick="loadNewTest()">+ Создать первый тест</button>
7854
- </div>`
7837
+ ? `<div class="load-library-empty">
7838
+ <div style="font-size:32px;margin-bottom:12px">📋</div>
7839
+ <div style="font-size:14px;font-weight:500;margin-bottom:6px">Нет сохранённых тестов</div>
7840
+ <div style="font-size:12px;color:var(--muted);margin-bottom:16px">Вставь готовый k6-скрипт и укажи папку с data-файлами при необходимости</div>
7841
+ <button class="load-btn load-btn-run" onclick="loadNewTest()">+ Создать первый тест</button>
7842
+ </div>`
7855
7843
  : `<div class="load-library-grid">${cards}</div>`
7856
7844
  }
7857
7845
 
@@ -7875,8 +7863,8 @@ function renderLoad(c) {
7875
7863
  const features = (D && D.features) || [];
7876
7864
  const featureOptions = features.map(f =>
7877
7865
  `<option value="${f.key}">${f.label || f.key}</option>`
7878
- ).join('');
7879
-
7866
+ ).join('');
7867
+
7880
7868
  if (!loadScriptDraft) {
7881
7869
  loadScriptDraft = buildDefaultScript({ baseUrl: loadBaseUrlDraft, vus: loadVusDraft, duration: loadDurationDraft, endpoints: ['/'] });
7882
7870
  }
@@ -7899,8 +7887,8 @@ function renderLoad(c) {
7899
7887
 
7900
7888
  <div class="load-section">
7901
7889
  <div class="load-section-title">Конфигурация ${loadK6Version ? `<span style="color:var(--dim);font-weight:400">${escapeHtml(loadK6Version)}</span>` : ''}</div>
7902
- <div class="load-config-row">
7903
- <div class="load-config-field" style="flex:1;min-width:200px">
7890
+ <div class="load-config-row">
7891
+ <div class="load-config-field" style="flex:1;min-width:200px">
7904
7892
  <label>Base URL</label>
7905
7893
  <input id="loadBaseUrl" type="text" value="${escapeHtml(loadBaseUrlDraft)}" placeholder="http://localhost:5000" />
7906
7894
  </div>
@@ -7910,29 +7898,10 @@ function renderLoad(c) {
7910
7898
  </div>
7911
7899
  <div class="load-config-field">
7912
7900
  <label>Duration</label>
7913
- <input id="loadDuration" type="text" value="${escapeHtml(loadDurationDraft)}" style="width:80px" placeholder="30s" />
7901
+ <input id="loadDuration" type="text" value="${escapeHtml(loadDurationDraft)}" style="width:90px" placeholder="30s" />
7914
7902
  </div>
7915
7903
  </div>
7916
- <div class="load-config-hint">VUs и Duration применяются через CLI k6 и переопределяют значения из <code>export const options</code>. Base URL доступен в скрипте как <code>__ENV.BASE_URL</code>.</div>
7917
- <div class="load-config-row" style="margin-top:8px">
7918
- <div class="load-config-field">
7919
- <label>Execution</label>
7920
- <select id="loadExecutionMode" style="width:150px">
7921
- <option value="auto" ${loadExecutionModeDraft === 'auto' ? 'selected' : ''}>Auto</option>
7922
- <option value="cli" ${loadExecutionModeDraft === 'cli' ? 'selected' : ''}>CLI override</option>
7923
- <option value="script" ${loadExecutionModeDraft === 'script' ? 'selected' : ''}>Script scenarios</option>
7924
- </select>
7925
- </div>
7926
- <div class="load-config-field">
7927
- <label>VUs env</label>
7928
- <input id="loadVusEnvName" type="text" value="${escapeHtml(loadVusEnvNameDraft)}" style="width:130px" placeholder="SMOKE_VUS" />
7929
- </div>
7930
- <div class="load-config-field">
7931
- <label>Duration env</label>
7932
- <input id="loadDurationEnvName" type="text" value="${escapeHtml(loadDurationEnvNameDraft)}" style="width:150px" placeholder="SMOKE_DURATION" />
7933
- </div>
7934
- </div>
7935
- <div class="load-config-hint">Auto: если скрипт содержит <code>options.scenarios</code>, VibeRadar не передаёт <code>--vus/--duration</code>, а кладёт значения в env-переменные, например <code>SMOKE_VUS</code> и <code>SMOKE_DURATION</code>.</div>
7904
+ <div class="load-config-hint">Если в скрипте есть <code>options.scenarios</code>, VibeRadar не ломает stages через CLI, а передаёт значения как <code>__ENV.LOAD_VUS</code>/<code>__ENV.LOAD_DURATION</code> и совместимые <code>SMOKE_*</code>/<code>AUTH_*</code>. Если scenarios нет, будут использованы CLI <code>--vus</code>/<code>--duration</code>.</div>
7936
7905
  <div class="load-config-row" style="margin-top:8px">
7937
7906
  <div class="load-config-field" style="flex:1;min-width:260px">
7938
7907
  <label>Data dir / file <span style="color:var(--dim);font-weight:400">(для <code>open('./users.csv')</code> и локальных lib)</span></label>
@@ -7949,30 +7918,12 @@ function renderLoad(c) {
7949
7918
  <label>Bearer Token <span style="color:var(--dim);font-weight:400;font-size:11px">(→ <code style="background:var(--bg2);padding:1px 4px;border-radius:3px">__ENV.TOKEN</code>)</span></label>
7950
7919
  <input id="loadToken" type="password" placeholder="Вставь Bearer-токен (необязательно)" style="font-family:monospace;font-size:12px" oninput="localStorage.setItem('vr_load_token', this.value)" />
7951
7920
  </div>
7952
- ${featureOptions ? `<div class="load-config-field">
7953
- <label>Фича (шаблон)</label>
7954
- <select id="loadFeature" style="width:150px">
7955
- <option value="">— выбрать —</option>
7956
- ${featureOptions}
7957
- </select>
7958
- </div>` : ''}
7959
- </div>
7960
- <div class="load-btns">
7961
- <button class="load-btn" onclick="loadGenerateScript()">⚙ Сгенерировать скрипт</button>
7962
- <button class="load-btn load-btn-run" id="loadRunBtn" onclick="runLoadTest()" ${isRunning ? 'disabled' : ''}>▶ Запустить</button>
7963
- <button class="load-btn load-btn-stop" id="loadStopBtn" onclick="stopLoadTest()" ${!isRunning ? 'disabled' : ''}>■ Стоп</button>
7964
- </div>
7965
- </div>
7966
-
7967
- <div class="load-section">
7968
- <div class="load-section-title">🤖 AI генерация скрипта</div>
7969
- <div style="font-size:11px;color:var(--muted);margin-bottom:6px">Опиши сценарий — агент найдёт эндпоинты в коде и сгенерирует k6-скрипт</div>
7970
- <div class="load-ai-prompt-wrap">
7971
- <textarea class="load-ai-prompt" id="loadAiPrompt" placeholder="Например: загрузка аудио .mp3 на /api/transcribe с полем language=ru, нужна авторизация Bearer-токеном, тестировать 20 VU 1 минуту&#10;&#10;Или: чат с RAG — POST /api/chat с body {message, knowledge_base_id, workspace_id}, stream:false">${escapeHtml(loadAiPromptDraft)}</textarea>
7972
- <button class="load-btn load-btn-ai" id="loadAiGenBtn" onclick="loadAiGenerateScript()" ${agentRunning ? 'disabled' : ''}>🤖 Сгенерировать<br>через AI</button>
7973
- </div>
7974
- <div class="load-ai-status" id="loadAiStatus">${loadAiGenerating ? '⏳ Агент генерирует скрипт… следи в терминале ↓' : ''}</div>
7975
- </div>
7921
+ </div>
7922
+ <div class="load-btns">
7923
+ <button class="load-btn load-btn-run" id="loadRunBtn" onclick="runLoadTest()" ${isRunning ? 'disabled' : ''}>▶ Запустить</button>
7924
+ <button class="load-btn load-btn-stop" id="loadStopBtn" onclick="stopLoadTest()" ${!isRunning ? 'disabled' : ''}>■ Стоп</button>
7925
+ </div>
7926
+ </div>
7976
7927
 
7977
7928
  <div class="load-section">
7978
7929
  <div class="load-section-title">k6 скрипт <span style="font-weight:400;color:var(--dim)">(редактируемый)</span></div>
@@ -8035,32 +7986,11 @@ function renderLoad(c) {
8035
7986
  const durationInput = document.getElementById('loadDuration');
8036
7987
  const dataInput = document.getElementById('loadDataDir');
8037
7988
  const resultInput = document.getElementById('loadResultDir');
8038
- const modeInput = document.getElementById('loadExecutionMode');
8039
- const vusEnvInput = document.getElementById('loadVusEnvName');
8040
- const durationEnvInput = document.getElementById('loadDurationEnvName');
8041
7989
  if (baseInput) baseInput.addEventListener('input', () => { loadBaseUrlDraft = baseInput.value || 'http://localhost:5000'; });
8042
7990
  if (vusInput) vusInput.addEventListener('input', () => { loadVusDraft = parseInt(vusInput.value || '10', 10) || 10; });
8043
7991
  if (durationInput) durationInput.addEventListener('input', () => { loadDurationDraft = durationInput.value || '30s'; });
8044
7992
  if (dataInput) dataInput.addEventListener('input', () => { loadDataDirDraft = dataInput.value || ''; });
8045
7993
  if (resultInput) resultInput.addEventListener('input', () => { loadResultDirDraft = resultInput.value || ''; });
8046
- if (modeInput) modeInput.addEventListener('change', () => { loadExecutionModeDraft = modeInput.value || 'auto'; });
8047
- if (vusEnvInput) vusEnvInput.addEventListener('input', () => { loadVusEnvNameDraft = vusEnvInput.value || 'SMOKE_VUS'; });
8048
- if (durationEnvInput) durationEnvInput.addEventListener('input', () => { loadDurationEnvNameDraft = durationEnvInput.value || 'SMOKE_DURATION'; });
8049
-
8050
- // Feature selector auto-generates script
8051
- const featSel = document.getElementById('loadFeature');
8052
- if (featSel) {
8053
- featSel.addEventListener('change', () => {
8054
- const fk = featSel.value;
8055
- if (!fk) return;
8056
- const script = generateScriptFromFeature(fk);
8057
- if (script) {
8058
- loadScriptDraft = script;
8059
- const ta2 = document.getElementById('loadScriptEditor');
8060
- if (ta2) ta2.value = script;
8061
- }
8062
- });
8063
- }
8064
7994
 
8065
7995
  // Draw charts if we have data
8066
7996
  if (loadBuckets && loadBuckets.length > 0) {
@@ -8085,9 +8015,6 @@ function loadOpenScript(name) {
8085
8015
  if (s.duration) loadDurationDraft = s.duration;
8086
8016
  loadDataDirDraft = s.dataDir || loadDataDirDraft;
8087
8017
  loadResultDirDraft = s.resultDir || loadResultDirDraft;
8088
- loadExecutionModeDraft = s.executionMode || loadExecutionModeDraft;
8089
- loadVusEnvNameDraft = s.vusEnvName || loadVusEnvNameDraft;
8090
- loadDurationEnvNameDraft = s.durationEnvName || loadDurationEnvNameDraft;
8091
8018
  loadView = 'editor';
8092
8019
  renderContent();
8093
8020
  }
@@ -8118,19 +8045,12 @@ async function runLoadTest() {
8118
8045
  const scriptName = (document.getElementById('loadScriptName')?.value || loadScriptNameDraft || 'Новый тест').trim();
8119
8046
  const dataDir = (document.getElementById('loadDataDir')?.value || loadDataDirDraft || '').trim();
8120
8047
  const resultDir = (document.getElementById('loadResultDir')?.value || loadResultDirDraft || '').trim();
8121
- const executionModeRaw = (document.getElementById('loadExecutionMode')?.value || loadExecutionModeDraft || 'auto').trim();
8122
- const executionMode = executionModeRaw === 'auto' ? undefined : executionModeRaw;
8123
- const vusEnvName = (document.getElementById('loadVusEnvName')?.value || loadVusEnvNameDraft || 'SMOKE_VUS').trim();
8124
- const durationEnvName = (document.getElementById('loadDurationEnvName')?.value || loadDurationEnvNameDraft || 'SMOKE_DURATION').trim();
8125
8048
  loadBaseUrlDraft = baseUrl;
8126
8049
  loadVusDraft = vus;
8127
8050
  loadDurationDraft = duration;
8128
8051
  loadScriptNameDraft = scriptName;
8129
8052
  loadDataDirDraft = dataDir;
8130
8053
  loadResultDirDraft = resultDir;
8131
- loadExecutionModeDraft = executionModeRaw;
8132
- loadVusEnvNameDraft = vusEnvName;
8133
- loadDurationEnvNameDraft = durationEnvName;
8134
8054
 
8135
8055
  loadLogLines = [];
8136
8056
  loadBuckets = [];
@@ -8142,7 +8062,7 @@ async function runLoadTest() {
8142
8062
  const r = await fetch('/api/load/run', {
8143
8063
  method: 'POST',
8144
8064
  headers: { 'Content-Type': 'application/json' },
8145
- body: JSON.stringify({ script, vus, duration, baseUrl, scriptName, dataDir, resultDir, executionMode, vusEnvName, durationEnvName, envVars }),
8065
+ body: JSON.stringify({ script, vus, duration, baseUrl, scriptName, dataDir, resultDir, envVars }),
8146
8066
  });
8147
8067
  const d = await r.json();
8148
8068
  if (!r.ok) { alert('Ошибка запуска: ' + (d.error || r.status)); return; }
@@ -8344,23 +8264,17 @@ async function loadSaveScript() {
8344
8264
  const duration = (document.getElementById('loadDuration')?.value || loadDurationDraft || '30s').trim();
8345
8265
  const dataDir = (document.getElementById('loadDataDir')?.value || loadDataDirDraft || '').trim();
8346
8266
  const resultDir = (document.getElementById('loadResultDir')?.value || loadResultDirDraft || '').trim();
8347
- const executionMode = (document.getElementById('loadExecutionMode')?.value || loadExecutionModeDraft || 'auto').trim();
8348
- const vusEnvName = (document.getElementById('loadVusEnvName')?.value || loadVusEnvNameDraft || 'SMOKE_VUS').trim();
8349
- const durationEnvName = (document.getElementById('loadDurationEnvName')?.value || loadDurationEnvNameDraft || 'SMOKE_DURATION').trim();
8350
8267
  loadScriptNameDraft = name;
8351
8268
  loadBaseUrlDraft = baseUrl;
8352
8269
  loadVusDraft = vus;
8353
8270
  loadDurationDraft = duration;
8354
8271
  loadDataDirDraft = dataDir;
8355
8272
  loadResultDirDraft = resultDir;
8356
- loadExecutionModeDraft = executionMode;
8357
- loadVusEnvNameDraft = vusEnvName;
8358
- loadDurationEnvNameDraft = durationEnvName;
8359
8273
  try {
8360
8274
  const r = await fetch('/api/load/scripts', {
8361
8275
  method: 'POST',
8362
8276
  headers: { 'Content-Type': 'application/json' },
8363
- body: JSON.stringify({ name, script, baseUrl, vus, duration, dataDir, resultDir, executionMode, vusEnvName, durationEnvName }),
8277
+ body: JSON.stringify({ name, script, baseUrl, vus, duration, dataDir, resultDir }),
8364
8278
  });
8365
8279
  if (!r.ok) { const d = await r.json().catch(() => ({})); alert('Ошибка: ' + (d.error || r.status)); return; }
8366
8280
  await loadRefreshScripts();
@@ -8380,9 +8294,6 @@ async function loadLoadScript(name) {
8380
8294
  if (s.duration) loadDurationDraft = s.duration;
8381
8295
  loadDataDirDraft = s.dataDir || loadDataDirDraft;
8382
8296
  loadResultDirDraft = s.resultDir || loadResultDirDraft;
8383
- loadExecutionModeDraft = s.executionMode || loadExecutionModeDraft;
8384
- loadVusEnvNameDraft = s.vusEnvName || loadVusEnvNameDraft;
8385
- loadDurationEnvNameDraft = s.durationEnvName || loadDurationEnvNameDraft;
8386
8297
  const ta = document.getElementById('loadScriptEditor');
8387
8298
  if (ta) { ta.value = s.script; ta.style.borderColor = 'var(--blue)'; setTimeout(() => { ta.style.borderColor = ''; }, 1500); }
8388
8299
  const nameEl = document.getElementById('loadScriptName');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viberadar",
3
- "version": "0.3.211",
3
+ "version": "0.3.213",
4
4
  "description": "Live module map with test coverage for vibecoding projects",
5
5
  "main": "./dist/cli.js",
6
6
  "bin": {