Open a cited script in the editor instead of a read-only viewer

This commit is contained in:
Gmer4Lfe
2026-08-10 21:15:45 -04:00
parent 9adf760c8e
commit 33affc5a59
2 changed files with 49 additions and 5 deletions
+35 -5
View File
@@ -194,7 +194,11 @@ function vv_ai_chat_assets(): void {
.vv-ai-think.open { display:block; }
.vv-ai-src { margin-top:9px; border-top:1px solid #1c1c1c; padding-top:7px; }
.vv-ai-src-h { font-size:9px; letter-spacing:.07em; text-transform:uppercase; color:#3a3a3a; margin-bottom:4px; }
.vv-ai-src-h { font-size:9px; letter-spacing:.07em; text-transform:uppercase; color:#3a3a3a;
margin-bottom:4px; cursor:pointer; user-select:none; }
.vv-ai-src-h:hover { color:#6a6a6a; }
.vv-ai-src-car { display:inline-block; width:10px; }
.vv-ai-src.collapsed .vv-ai-src-l { display:none; }
.vv-ai-src-i { font-size:11px; color:#5a5a5a; padding:2px 0; cursor:pointer; display:flex; gap:8px; }
.vv-ai-src-i:hover { color:#8a8a8a; }
.vv-ai-src-n { color:#3a4a6a; font-family:monospace; flex-shrink:0; }
@@ -556,7 +560,12 @@ vv_ai_profiles_script();
// path carrying a quote interpolated into an attribute is code execution, not a display bug.
function sourcesHtml(sources) {
if (!sources || !sources.length) return '';
let h = '<div class="vv-ai-src"><div class="vv-ai-src-h">Sources</div>';
// Expanded by default and collapsible by choice, never the reverse. What the model was given
// is the first thing worth seeing when an answer is wrong, and hiding it behind a click makes
// a bad retrieval look like a bad model.
let h = `<div class="vv-ai-src"><div class="vv-ai-src-h" data-src-toggle>`
+ `<span class="vv-ai-src-car">▾</span>Sources (${sources.length})</div>`
+ `<div class="vv-ai-src-l">`;
sources.forEach((s, i) => {
// A web result is a page on the internet, not a file in this install: it opens in a tab
// rather than in the source viewer, it leads with its title rather than its URL, and it
@@ -573,7 +582,7 @@ vv_ai_profiles_script();
+ `<span class="vv-ai-src-n">[${i+1}]</span><span>${esc(label)}</span>`
+ `<span class="vv-ai-src-s">${Number(s.score).toFixed(3)}</span></div>`;
});
return h + '</div>';
return h + '</div></div>';
}
function addAnswer(job) {
@@ -623,7 +632,14 @@ vv_ai_profiles_script();
if (u) window.open(u, '_blank', 'noopener,noreferrer');
return;
}
if (src && src.dataset.src) { vvAiOpen(src.dataset.src); return; }
// A page that can do something better with a source than show it gets first refusal — the
// Scheduler opens scripts in its editor, where they can actually be changed. Everything
// else falls through to the read-only viewer.
if (src && src.dataset.src) {
if (o.onOpenSource) o.onOpenSource(src.dataset.src);
else vvAiOpen(src.dataset.src);
return;
}
const cite = e.target.closest('.vv-ai-cite');
if (cite) {
const s = lastSources[Number(cite.dataset.cite) - 1];
@@ -632,9 +648,23 @@ vv_ai_profiles_script();
if (u) window.open(u, '_blank', 'noopener,noreferrer');
return;
}
if (s && s.path) vvAiOpen(s.path);
// Same routing as a source row — a citation and the row it refers to must not behave
// differently, or clicking [3] and clicking source 3 land in different places.
if (s && s.path) {
if (o.onOpenSource) o.onOpenSource(s.path);
else vvAiOpen(s.path);
}
return;
}
const stog = e.target.closest('[data-src-toggle]');
if (stog) {
const box = stog.parentElement;
box.classList.toggle('collapsed');
const car = stog.querySelector('.vv-ai-src-car');
if (car) car.textContent = box.classList.contains('collapsed') ? '▸' : '▾';
return;
}
const off = e.target.closest('[data-offer]');
if (off) { answerOffer(+off.dataset.offer, off.dataset.yes === '1'); return; }