@tangle-network/browser-agent-driver 0.24.2 → 0.26.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/brain/index.d.ts.map +1 -1
- package/dist/brain/index.js +1 -0
- package/dist/brain/index.js.map +1 -1
- package/dist/cli-preview.d.ts +59 -0
- package/dist/cli-preview.d.ts.map +1 -0
- package/dist/cli-preview.js +144 -0
- package/dist/cli-preview.js.map +1 -0
- package/dist/cli-share.d.ts +77 -0
- package/dist/cli-share.d.ts.map +1 -0
- package/dist/cli-share.js +141 -0
- package/dist/cli-share.js.map +1 -0
- package/dist/cli-ui.d.ts.map +1 -1
- package/dist/cli-ui.js +8 -4
- package/dist/cli-ui.js.map +1 -1
- package/dist/cli.js +153 -5
- package/dist/cli.js.map +1 -1
- package/dist/drivers/cursor-overlay.d.ts +18 -10
- package/dist/drivers/cursor-overlay.d.ts.map +1 -1
- package/dist/drivers/cursor-overlay.js +221 -30
- package/dist/drivers/cursor-overlay.js.map +1 -1
- package/dist/drivers/overlay-label.d.ts +33 -0
- package/dist/drivers/overlay-label.d.ts.map +1 -0
- package/dist/drivers/overlay-label.js +92 -0
- package/dist/drivers/overlay-label.js.map +1 -0
- package/dist/drivers/playwright.d.ts +22 -0
- package/dist/drivers/playwright.d.ts.map +1 -1
- package/dist/drivers/playwright.js +87 -9
- package/dist/drivers/playwright.js.map +1 -1
- package/dist/drivers/snapshot.d.ts +12 -0
- package/dist/drivers/snapshot.d.ts.map +1 -1
- package/dist/drivers/snapshot.js +17 -0
- package/dist/drivers/snapshot.js.map +1 -1
- package/dist/drivers/types.d.ts +8 -0
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/runner/fan-out.d.ts +91 -0
- package/dist/runner/fan-out.d.ts.map +1 -0
- package/dist/runner/fan-out.js +183 -0
- package/dist/runner/fan-out.js.map +1 -0
- package/dist/runner/interrupt-controller.d.ts +67 -0
- package/dist/runner/interrupt-controller.d.ts.map +1 -0
- package/dist/runner/interrupt-controller.js +142 -0
- package/dist/runner/interrupt-controller.js.map +1 -0
- package/dist/runner/overlay-narration.d.ts +83 -0
- package/dist/runner/overlay-narration.d.ts.map +1 -0
- package/dist/runner/overlay-narration.js +172 -0
- package/dist/runner/overlay-narration.js.map +1 -0
- package/dist/runner/runner.d.ts +9 -0
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +93 -0
- package/dist/runner/runner.js.map +1 -1
- package/dist/runner/stream-webhook.d.ts +70 -0
- package/dist/runner/stream-webhook.d.ts.map +1 -0
- package/dist/runner/stream-webhook.js +132 -0
- package/dist/runner/stream-webhook.js.map +1 -0
- package/dist/skills/macro-loader.d.ts +1 -1
- package/dist/skills/macro-loader.d.ts.map +1 -1
- package/dist/supervisor/policy.js +11 -0
- package/dist/supervisor/policy.js.map +1 -1
- package/dist/test-runner.d.ts +7 -0
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +3 -0
- package/dist/test-runner.js.map +1 -1
- package/dist/types.d.ts +36 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/viewer/viewer.html +264 -16
- package/package.json +2 -2
package/dist/viewer/viewer.html
CHANGED
|
@@ -658,32 +658,280 @@
|
|
|
658
658
|
});
|
|
659
659
|
}
|
|
660
660
|
|
|
661
|
-
/** Render the recording.webm video player for an agent test.
|
|
661
|
+
/** Render the recording.webm video player for an agent test.
|
|
662
|
+
* Gen 32: frame-accurate timeline scrubber — video time is synced
|
|
663
|
+
* with per-turn markers; clicking a turn jumps to that moment;
|
|
664
|
+
* the agent's reasoning for the selected turn renders below the
|
|
665
|
+
* video. Turn times are computed from cumulative turn.durationMs,
|
|
666
|
+
* which is a close proxy for wall-clock video time because the
|
|
667
|
+
* recording and the turn loop run on the same clock. */
|
|
662
668
|
function showRecording(test) {
|
|
663
669
|
const main = el('main-content');
|
|
664
670
|
if (!test?.recording) {
|
|
665
671
|
main.innerHTML = '<div class="empty-state"><h2>No recording</h2><p>This test did not produce a recording.webm.</p></div>';
|
|
666
672
|
return;
|
|
667
673
|
}
|
|
674
|
+
const turns = test.turns || [];
|
|
675
|
+
// Build cumulative start times per turn in seconds. The first turn
|
|
676
|
+
// starts at t=0; subsequent turns start at the sum of prior durations.
|
|
677
|
+
// Turns without durationMs (legacy runs) get evenly distributed.
|
|
678
|
+
const totalMs = test.durationMs || turns.reduce((s, t) => s + (t.durationMs || 0), 0);
|
|
679
|
+
let cursor = 0;
|
|
680
|
+
const turnMarkers = turns.map((t) => {
|
|
681
|
+
const start = cursor;
|
|
682
|
+
cursor += t.durationMs || (totalMs / Math.max(1, turns.length));
|
|
683
|
+
return { start, dur: t.durationMs || (totalMs / Math.max(1, turns.length)), turn: t };
|
|
684
|
+
});
|
|
685
|
+
const durationSec = Math.max(1, Math.round((totalMs || 1) / 1000));
|
|
686
|
+
const stepCount = turns.length;
|
|
687
|
+
|
|
688
|
+
// Gen 33: two-column layout — video + timeline + reasoning on the
|
|
689
|
+
// left, decision-list sidebar on the right. The decision list is
|
|
690
|
+
// the primary scrub interface: each row shows the turn number,
|
|
691
|
+
// the verb, the target, a status chip, and (on click) fork-from-
|
|
692
|
+
// this-turn affordance. Click any row = video seek + reasoning update.
|
|
668
693
|
main.innerHTML = `
|
|
669
|
-
<div style="width: 100%; max-width: 1200px;">
|
|
670
|
-
<div
|
|
671
|
-
<
|
|
672
|
-
|
|
673
|
-
|
|
694
|
+
<div style="width: 100%; max-width: 1200px; display: grid; grid-template-columns: 1fr 340px; gap: 20px; align-items: start;">
|
|
695
|
+
<div>
|
|
696
|
+
<div style="margin-bottom: 16px;">
|
|
697
|
+
<h2 style="margin: 0; font-size: 18px;">${escapeHtml(test.name || test.id)} — Recording</h2>
|
|
698
|
+
<div style="color: var(--text-muted); font-size: 12px; margin-top: 4px;">
|
|
699
|
+
${stepCount} turns · ${durationSec}s · click any decision on the right to scrub the video to that moment.
|
|
700
|
+
</div>
|
|
701
|
+
</div>
|
|
702
|
+
<div class="screenshot-wrap" style="background: #000; position: relative;">
|
|
703
|
+
<video id="rec-video" controls autoplay muted loop style="max-width: 100%; max-height: calc(100vh - 340px); display: block;" src="${escapeHtml(test.recording)}">
|
|
704
|
+
Your browser doesn't support inline video playback.
|
|
705
|
+
</video>
|
|
706
|
+
</div>
|
|
707
|
+
<!-- Timeline scrubber: thin track with a marker per turn -->
|
|
708
|
+
<div id="rec-timeline" style="margin-top: 14px; position: relative; height: 46px; padding: 0 4px;">
|
|
709
|
+
<div style="position: absolute; top: 18px; left: 4px; right: 4px; height: 6px; background: var(--border); border-radius: 3px;"></div>
|
|
710
|
+
<div id="rec-playhead" style="position: absolute; top: 15px; left: 4px; width: 2px; height: 12px; background: var(--accent, #7aa2ff); border-radius: 1px; box-shadow: 0 0 4px var(--accent, #7aa2ff); pointer-events: none;"></div>
|
|
711
|
+
<div id="rec-markers" style="position: relative; height: 46px;"></div>
|
|
712
|
+
</div>
|
|
713
|
+
<!-- Reasoning panel synced to the playhead -->
|
|
714
|
+
<div id="rec-reasoning" style="margin-top: 14px; padding: 14px 16px; background: var(--bg-panel, #141927); border: 1px solid var(--border, #2a3145); border-radius: 8px; min-height: 84px;">
|
|
715
|
+
<div style="font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent, #7aa2ff); margin-bottom: 8px;">
|
|
716
|
+
Agent reasoning · <span id="rec-turn-label">turn —</span>
|
|
717
|
+
</div>
|
|
718
|
+
<div id="rec-reasoning-body" style="font-size: 13px; line-height: 1.55; color: var(--text, #e6ebf5); white-space: pre-wrap;">
|
|
719
|
+
Press play to follow the agent's reasoning turn-by-turn.
|
|
720
|
+
</div>
|
|
721
|
+
<div id="rec-fork-panel" style="margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border, #2a3145); display: none;">
|
|
722
|
+
<div style="font-size: 10px; color: var(--text-muted); margin-bottom: 4px;">
|
|
723
|
+
Fork a new run from this decision with a different goal:
|
|
724
|
+
</div>
|
|
725
|
+
<div style="display: flex; gap: 6px; align-items: center;">
|
|
726
|
+
<input id="rec-fork-goal" type="text" placeholder="new goal…" style="flex: 1; padding: 6px 10px; background: var(--bg, #0b0f19); border: 1px solid var(--border, #2a3145); border-radius: 4px; color: var(--text, #e6ebf5); font-family: inherit; font-size: 12px;" />
|
|
727
|
+
<button id="rec-fork-button" type="button" style="padding: 6px 14px; background: var(--accent, #7aa2ff); color: #0b1220; border: none; border-radius: 4px; font-size: 12px; font-weight: 700; cursor: pointer;">
|
|
728
|
+
Copy fork cmd
|
|
729
|
+
</button>
|
|
730
|
+
</div>
|
|
731
|
+
<div id="rec-fork-hint" style="margin-top: 6px; font-size: 11px; color: var(--text-muted); font-family: 'SF Mono', Menlo, monospace; word-break: break-all;"></div>
|
|
732
|
+
</div>
|
|
674
733
|
</div>
|
|
675
734
|
</div>
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
Each click pulses a ring at the contact point when the run was captured with <code>--show-cursor</code>.
|
|
684
|
-
</div>
|
|
735
|
+
<!-- Decision sidebar -->
|
|
736
|
+
<aside id="rec-sidebar" style="background: var(--bg-panel, #141927); border: 1px solid var(--border, #2a3145); border-radius: 8px; padding: 12px; max-height: calc(100vh - 220px); overflow-y: auto;">
|
|
737
|
+
<div style="font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent, #7aa2ff); margin-bottom: 10px;">
|
|
738
|
+
${stepCount} decisions
|
|
739
|
+
</div>
|
|
740
|
+
<div id="rec-decision-list"></div>
|
|
741
|
+
</aside>
|
|
685
742
|
</div>
|
|
686
743
|
`;
|
|
744
|
+
|
|
745
|
+
const video = document.getElementById('rec-video');
|
|
746
|
+
const markers = document.getElementById('rec-markers');
|
|
747
|
+
const playhead = document.getElementById('rec-playhead');
|
|
748
|
+
const reasoningBody = document.getElementById('rec-reasoning-body');
|
|
749
|
+
const turnLabel = document.getElementById('rec-turn-label');
|
|
750
|
+
const decisionList = document.getElementById('rec-decision-list');
|
|
751
|
+
const forkPanel = document.getElementById('rec-fork-panel');
|
|
752
|
+
const forkGoalInput = document.getElementById('rec-fork-goal');
|
|
753
|
+
const forkButton = document.getElementById('rec-fork-button');
|
|
754
|
+
const forkHint = document.getElementById('rec-fork-hint');
|
|
755
|
+
|
|
756
|
+
// Render markers. Each marker is an absolutely-positioned dot with
|
|
757
|
+
// a thin stem so the viewer sees segment boundaries without clutter.
|
|
758
|
+
turnMarkers.forEach((m, i) => {
|
|
759
|
+
const pct = (m.start / Math.max(1, totalMs)) * 100;
|
|
760
|
+
const action = m.turn.action?.action ?? '?';
|
|
761
|
+
const el = document.createElement('button');
|
|
762
|
+
el.type = 'button';
|
|
763
|
+
el.className = 'rec-marker';
|
|
764
|
+
el.dataset.index = String(i);
|
|
765
|
+
el.title = `Turn ${i + 1} — ${action}`;
|
|
766
|
+
Object.assign(el.style, {
|
|
767
|
+
position: 'absolute',
|
|
768
|
+
left: `calc(${pct}% + 4px)`,
|
|
769
|
+
top: '8px',
|
|
770
|
+
width: '12px',
|
|
771
|
+
height: '28px',
|
|
772
|
+
marginLeft: '-6px',
|
|
773
|
+
background: 'transparent',
|
|
774
|
+
border: 'none',
|
|
775
|
+
padding: '0',
|
|
776
|
+
cursor: 'pointer',
|
|
777
|
+
display: 'flex',
|
|
778
|
+
flexDirection: 'column',
|
|
779
|
+
alignItems: 'center',
|
|
780
|
+
});
|
|
781
|
+
el.innerHTML = `
|
|
782
|
+
<div style="width: 10px; height: 10px; border-radius: 9999px; background: var(--bg-panel, #141927); border: 2px solid var(--accent, #7aa2ff); box-shadow: 0 0 4px rgba(122,162,255,0.5);"></div>
|
|
783
|
+
<div style="width: 1px; height: 10px; background: var(--border, #2a3145); margin-top: 2px;"></div>
|
|
784
|
+
<div style="font-size: 9px; color: var(--text-muted); margin-top: 1px;">${i + 1}</div>
|
|
785
|
+
`;
|
|
786
|
+
el.addEventListener('click', () => {
|
|
787
|
+
video.currentTime = m.start / 1000;
|
|
788
|
+
selectTurn(i);
|
|
789
|
+
});
|
|
790
|
+
markers.appendChild(el);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
// Verdict classifier mirrors the overlay narration logic — keep in
|
|
794
|
+
// sync with src/runner/overlay-narration.ts so the sidebar shows
|
|
795
|
+
// the same verdict colors as the video's baked-in badges.
|
|
796
|
+
function classifyTurn(t) {
|
|
797
|
+
const r = (t.reasoning || '') + ' ' + (t.action?.result || '');
|
|
798
|
+
if (/POSITIVE\s+MATCH/i.test(r)) return 'positive';
|
|
799
|
+
if (/\bCLEARED\b/i.test(r)) return 'cleared';
|
|
800
|
+
if (/NEEDS\s+REVIEW/i.test(r)) return 'review';
|
|
801
|
+
if (t.result?.success === false || t.verificationFailure) return 'error';
|
|
802
|
+
return 'neutral';
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
const VERDICT_COLOR = {
|
|
806
|
+
positive: '#fb7185', cleared: '#4ade80', review: '#fbbf24',
|
|
807
|
+
error: '#ef4444', neutral: 'var(--accent, #7aa2ff)'
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
// Build the decision sidebar. Each row carries turn index, action
|
|
811
|
+
// verb, target preview, a verdict chip, and a one-line reasoning
|
|
812
|
+
// summary. Click = seek video + update active state.
|
|
813
|
+
turns.forEach((t, i) => {
|
|
814
|
+
const act = t.action?.action || '?';
|
|
815
|
+
const targetRaw = t.action?.selector ?? t.action?.text ?? t.action?.key ?? t.action?.url ?? '';
|
|
816
|
+
const target = String(targetRaw).slice(0, 48);
|
|
817
|
+
const verdict = classifyTurn(t);
|
|
818
|
+
const color = VERDICT_COLOR[verdict] || VERDICT_COLOR.neutral;
|
|
819
|
+
const summary = (t.reasoning || '').replace(/\s+/g, ' ').trim().slice(0, 80);
|
|
820
|
+
const row = document.createElement('button');
|
|
821
|
+
row.type = 'button';
|
|
822
|
+
row.className = 'rec-decision';
|
|
823
|
+
row.dataset.index = String(i);
|
|
824
|
+
Object.assign(row.style, {
|
|
825
|
+
display: 'block', width: '100%', textAlign: 'left',
|
|
826
|
+
padding: '10px 12px', margin: '0 0 6px 0',
|
|
827
|
+
background: 'transparent',
|
|
828
|
+
border: '1px solid var(--border, #2a3145)', borderLeft: `3px solid ${color}`,
|
|
829
|
+
borderRadius: '6px', color: 'var(--text, #e6ebf5)',
|
|
830
|
+
cursor: 'pointer', fontFamily: 'inherit',
|
|
831
|
+
transition: 'background 120ms ease, border-color 120ms ease',
|
|
832
|
+
});
|
|
833
|
+
row.innerHTML = `
|
|
834
|
+
<div style="display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 12px;">
|
|
835
|
+
<div>
|
|
836
|
+
<span style="color: var(--text-muted); font-family: 'SF Mono', Menlo, monospace;">${i + 1}.</span>
|
|
837
|
+
<span style="color: ${color}; font-weight: 600; margin-left: 4px;">${escapeHtml(act)}</span>
|
|
838
|
+
${target ? `<span style="color: var(--text-muted); margin-left: 6px;">${escapeHtml(target)}</span>` : ''}
|
|
839
|
+
</div>
|
|
840
|
+
</div>
|
|
841
|
+
${summary ? `<div style="margin-top: 4px; font-size: 11px; color: var(--text-muted); line-height: 1.4;">${escapeHtml(summary)}</div>` : ''}
|
|
842
|
+
`;
|
|
843
|
+
row.addEventListener('mouseenter', () => { row.style.background = 'rgba(122,162,255,0.04)'; });
|
|
844
|
+
row.addEventListener('mouseleave', () => { if (!row.classList.contains('active')) row.style.background = 'transparent'; });
|
|
845
|
+
row.addEventListener('click', () => {
|
|
846
|
+
const m = turnMarkers[i];
|
|
847
|
+
if (m) video.currentTime = m.start / 1000;
|
|
848
|
+
selectTurn(i);
|
|
849
|
+
});
|
|
850
|
+
decisionList.appendChild(row);
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
function selectTurn(i) {
|
|
854
|
+
const t = turns[i];
|
|
855
|
+
if (!t) return;
|
|
856
|
+
const action = t.action?.action ?? '?';
|
|
857
|
+
const target = t.action?.selector ?? t.action?.text ?? t.action?.key ?? t.action?.url ?? '';
|
|
858
|
+
turnLabel.textContent = `turn ${i + 1} / ${turns.length} · ${action}${target ? ' · ' + String(target).slice(0, 80) : ''}`;
|
|
859
|
+
const r = (t.reasoning || '').trim();
|
|
860
|
+
reasoningBody.textContent = r || '(no reasoning captured)';
|
|
861
|
+
// Highlight the active marker
|
|
862
|
+
markers.querySelectorAll('.rec-marker').forEach((n, j) => {
|
|
863
|
+
const dot = n.firstElementChild;
|
|
864
|
+
if (!dot) return;
|
|
865
|
+
dot.style.background = j === i ? 'var(--accent, #7aa2ff)' : 'var(--bg-panel, #141927)';
|
|
866
|
+
});
|
|
867
|
+
// Highlight the active sidebar row
|
|
868
|
+
decisionList.querySelectorAll('.rec-decision').forEach((n, j) => {
|
|
869
|
+
if (j === i) {
|
|
870
|
+
n.classList.add('active');
|
|
871
|
+
n.style.background = 'rgba(122,162,255,0.10)';
|
|
872
|
+
n.style.borderColor = 'var(--accent, #7aa2ff)';
|
|
873
|
+
// Keep the active row visible when auto-advanced by video time
|
|
874
|
+
n.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
875
|
+
} else {
|
|
876
|
+
n.classList.remove('active');
|
|
877
|
+
n.style.background = 'transparent';
|
|
878
|
+
n.style.borderColor = 'var(--border, #2a3145)';
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
// Show the fork panel. Pre-fill a templated goal the user can edit.
|
|
882
|
+
const runId = test.id || test.runId || '';
|
|
883
|
+
const defaultGoal = (t.reasoning || '').split(/\.\s/)[0].slice(0, 80).replace(/^\s*["']?/, '').replace(/["']?\s*$/, '');
|
|
884
|
+
forkPanel.style.display = 'block';
|
|
885
|
+
forkGoalInput.value = defaultGoal;
|
|
886
|
+
const updateHint = () => {
|
|
887
|
+
const g = forkGoalInput.value.trim() || '<new goal>';
|
|
888
|
+
forkHint.textContent = runId
|
|
889
|
+
? `bad run --fork-run ${runId} --goal "${g.replace(/"/g, '\\"')}"`
|
|
890
|
+
: '(no run id available — fork requires memory-enabled runs)';
|
|
891
|
+
};
|
|
892
|
+
updateHint();
|
|
893
|
+
forkGoalInput.oninput = updateHint;
|
|
894
|
+
forkButton.onclick = async () => {
|
|
895
|
+
const cmd = forkHint.textContent;
|
|
896
|
+
try {
|
|
897
|
+
await navigator.clipboard.writeText(cmd);
|
|
898
|
+
const prev = forkButton.textContent;
|
|
899
|
+
forkButton.textContent = 'Copied ✓';
|
|
900
|
+
setTimeout(() => { forkButton.textContent = prev; }, 1800);
|
|
901
|
+
} catch {
|
|
902
|
+
// Clipboard blocked — select the hint text so the user can Cmd-C.
|
|
903
|
+
const range = document.createRange();
|
|
904
|
+
range.selectNodeContents(forkHint);
|
|
905
|
+
const sel = window.getSelection();
|
|
906
|
+
sel.removeAllRanges();
|
|
907
|
+
sel.addRange(range);
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
function findTurnAt(timeMs) {
|
|
913
|
+
// Binary-search not needed for typical N≤100
|
|
914
|
+
let idx = -1;
|
|
915
|
+
for (let i = 0; i < turnMarkers.length; i++) {
|
|
916
|
+
if (timeMs >= turnMarkers[i].start) idx = i;
|
|
917
|
+
else break;
|
|
918
|
+
}
|
|
919
|
+
return idx;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
video.addEventListener('timeupdate', () => {
|
|
923
|
+
const timeMs = video.currentTime * 1000;
|
|
924
|
+
const pct = Math.min(100, (timeMs / Math.max(1, totalMs)) * 100);
|
|
925
|
+
playhead.style.left = `calc(${pct}% + 4px)`;
|
|
926
|
+
const idx = findTurnAt(timeMs);
|
|
927
|
+
if (idx >= 0 && idx !== selectTurn._lastIdx) {
|
|
928
|
+
selectTurn._lastIdx = idx;
|
|
929
|
+
selectTurn(idx);
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
// Initial selection
|
|
933
|
+
if (turns.length > 0) selectTurn(0);
|
|
934
|
+
|
|
687
935
|
const aside = el('aside-panel');
|
|
688
936
|
aside.innerHTML = `
|
|
689
937
|
<div class="panel">
|
|
@@ -702,7 +950,7 @@
|
|
|
702
950
|
<div class="panel">
|
|
703
951
|
<h3>About this view</h3>
|
|
704
952
|
<div class="panel-body" style="font-size: 12px;">
|
|
705
|
-
The
|
|
953
|
+
Click a timeline marker to jump to that turn. The reasoning panel below the video updates as the video plays — each timestamp maps to the agent's own words at that moment. Cursor, click pulses, and verdict badges are baked into the video frames when the run used <code>--show-cursor</code>.
|
|
706
954
|
</div>
|
|
707
955
|
</div>
|
|
708
956
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/browser-agent-driver",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "LLM-driven browser agent for UI automation, testing, and evaluation",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -133,4 +133,4 @@
|
|
|
133
133
|
"typescript": "^5.3.0",
|
|
134
134
|
"vitest": "^4.0.18"
|
|
135
135
|
}
|
|
136
|
-
}
|
|
136
|
+
}
|