@agent-inspect/viewer 6.4.0 → 6.5.0

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/index.cjs CHANGED
@@ -4598,8 +4598,9 @@ async function runSuite(options = {}) {
4598
4598
  skipped: cases.filter((item) => item.status === "skipped").length
4599
4599
  };
4600
4600
  const finishedAt = new Date(options.nowMs ?? Date.now()).toISOString();
4601
- const ok = summary.failed === 0 && summary.errors === 0;
4602
- const status = summary.errors > 0 ? "error" : summary.failed > 0 || !ok ? "fail" : "pass";
4601
+ const allSkipped = cases.length > 0 && summary.skipped === cases.length;
4602
+ const ok = summary.failed === 0 && summary.errors === 0 && !allSkipped;
4603
+ const status = summary.errors > 0 ? "error" : allSkipped ? "fail" : summary.failed > 0 || !ok ? "fail" : "pass";
4603
4604
  return {
4604
4605
  ok,
4605
4606
  status,
@@ -4659,27 +4660,36 @@ var viewerIndexHtml = `<!DOCTYPE html>
4659
4660
  const params = new URLSearchParams(location.search);
4660
4661
  const mode = params.get("mode") || "traces";
4661
4662
 
4663
+ function escapeHtml(value) {
4664
+ return String(value ?? "")
4665
+ .replaceAll("&", "&amp;")
4666
+ .replaceAll("<", "&lt;")
4667
+ .replaceAll(">", "&gt;")
4668
+ .replaceAll('"', "&quot;")
4669
+ .replaceAll("'", "&#39;");
4670
+ }
4671
+
4662
4672
  function renderSuite(data) {
4663
4673
  const rows = data.cases.map((c) =>
4664
- '<tr><td>' + c.id + '</td><td class="' + c.status + '">' + c.status +
4665
- '</td><td>' + (c.message || '') + '</td><td>' + c.toolPath.join(' \u2192 ') +
4666
- '</td><td>' + c.observations.map((o) => o.name + ':' + o.status).join(', ') + '</td></tr>'
4674
+ '<tr><td>' + escapeHtml(c.id) + '</td><td class="' + escapeHtml(c.status) + '">' + escapeHtml(c.status) +
4675
+ '</td><td>' + escapeHtml(c.message || '') + '</td><td>' + escapeHtml(c.toolPath.join(' \u2192 ')) +
4676
+ '</td><td>' + escapeHtml(c.observations.map((o) => o.name + ':' + o.status).join(', ')) + '</td></tr>'
4667
4677
  ).join('');
4668
4678
  const failed = data.cases.filter((c) => c.status !== 'pass');
4669
4679
  const detail = failed.map((c) => {
4670
- let html = '<h3>Case ' + c.id + '</h3><ul>';
4671
- if (c.failureDiff) html += '<li>Diff errors: ' + c.failureDiff.summary.errors + '</li>';
4672
- if (c.timeline) html += '<li>Timeline steps: ' + c.timeline.entries.length + '</li>';
4673
- html += '<li>Diagnostics: ' + c.diagnostics.map((d) => d.message).join('; ') + '</li></ul>';
4680
+ let html = '<h3>Case ' + escapeHtml(c.id) + '</h3><ul>';
4681
+ if (c.failureDiff) html += '<li>Diff errors: ' + escapeHtml(c.failureDiff.summary.errors) + '</li>';
4682
+ if (c.timeline) html += '<li>Timeline steps: ' + escapeHtml(c.timeline.entries.length) + '</li>';
4683
+ html += '<li>Diagnostics: ' + escapeHtml(c.diagnostics.map((d) => d.message).join('; ')) + '</li></ul>';
4674
4684
  return html;
4675
4685
  }).join('');
4676
- return '<section><h2>Suite: ' + data.suiteName + ' (' + data.status + ')</h2>' +
4677
- '<p>Passed ' + data.summary.passed + ', failed ' + data.summary.failed + '</p>' +
4686
+ return '<section><h2>Suite: ' + escapeHtml(data.suiteName) + ' (' + escapeHtml(data.status) + ')</h2>' +
4687
+ '<p>Passed ' + escapeHtml(data.summary.passed) + ', failed ' + escapeHtml(data.summary.failed) + '</p>' +
4678
4688
  '<table><thead><tr><th>Case</th><th>Status</th><th>Message</th><th>Tool path</th><th>Observations</th></tr></thead><tbody>' +
4679
4689
  rows + '</tbody></table>' +
4680
4690
  '<section><h2>Failure detail</h2>' + (detail || '<p class="pass">No failures</p>') + '</section>' +
4681
- '<section><h2>CI artifacts</h2><p>' + (data.ciArtifactsDir || 'n/a') + '</p></section>' +
4682
- '<section><h2>Bundle export</h2><p>' + data.bundleExportHint + '</p></section>';
4691
+ '<section><h2>CI artifacts</h2><p>' + escapeHtml(data.ciArtifactsDir || 'n/a') + '</p></section>' +
4692
+ '<section><h2>Bundle export</h2><p>' + escapeHtml(data.bundleExportHint) + '</p></section>';
4683
4693
  }
4684
4694
 
4685
4695
  async function load() {
@@ -4695,8 +4705,8 @@ var viewerIndexHtml = `<!DOCTYPE html>
4695
4705
  if (mode === "workspace") {
4696
4706
  nav.innerHTML = '<a href="/api/workspace">/api/workspace</a>';
4697
4707
  const data = await fetch("/api/workspace").then((r) => r.json());
4698
- content.innerHTML = '<section><h2>Workspace: ' + (data.project || 'workspace') + '</h2>' +
4699
- '<p>Runs: ' + data.runs.length + '</p><pre>' + JSON.stringify(data, null, 2) + '</pre></section>';
4708
+ content.innerHTML = '<section><h2>Workspace: ' + escapeHtml(data.project || 'workspace') + '</h2>' +
4709
+ '<p>Runs: ' + escapeHtml(data.runs.length) + '</p><pre>' + escapeHtml(JSON.stringify(data, null, 2)) + '</pre></section>';
4700
4710
  return;
4701
4711
  }
4702
4712
  nav.innerHTML = '<a href="/api/traces">/api/traces</a> \xB7 <a href="/api/sessions">/api/sessions</a>';