merge: maestro/tsk_O9q0_u78_NPo [tsk_O9q0_u78_NPo]

This commit is contained in:
maestro
2026-06-13 11:35:20 +08:00
6 changed files with 512 additions and 6 deletions
+63 -6
View File
@@ -589,12 +589,18 @@ function renderArchiveModal(t, runs, events) {
.join('');
const runRows = runs.length ? `<div class="gate-doc-label">执行历史(${runs.length} 次 run</div>
<dl class="result-kv">${runs.map((x) => kv(
`${RUN_KIND[x.kind] || esc(x.kind)} · ${RUN_ST[x.status] || esc(x.status)}`,
`${fmtFull(x.startedAt)}${x.endedAt ? fmtFull(x.endedAt) : '—'} · 时长 ${fmtDuration(x.startedAt, x.endedAt)}` +
(x.error ? `<br>错误:${esc(x.error)}` : '') +
(x.transcriptRef ? `<br><span class="t-id">转录 ${esc(x.transcriptRef)}</span>` : ''),
)).join('')}</dl>` : '';
<div class="run-list">${runs.map((x) => `
<div class="run-item">
<div class="run-head">
<span class="run-kind">${RUN_KIND[x.kind] || esc(x.kind)}</span>
<span class="run-st run-st-${esc(x.status)}">${RUN_ST[x.status] || esc(x.status)}</span>
<span class="run-time">${fmtFull(x.startedAt)}${x.endedAt ? fmtFull(x.endedAt) : ''} · ${fmtDuration(x.startedAt, x.endedAt)}</span>
<span class="spacer"></span>
${x.transcriptRef ? `<button class="btn btn-xs btn-ghost" data-action="run-transcript" data-id="${esc(x.id)}">▶ 查看转录</button>` : ''}
</div>
${x.error ? `<div class="run-err">错误:${esc(x.error)}</div>` : ''}
${x.transcriptRef ? `<div class="transcript" id="transcript-${esc(x.id)}" hidden></div>` : ''}
</div>`).join('')}</div>` : '';
const resultBlock = r ? `${reviewReportBlocks(r)}
<div class="gate-doc-label">执行结果</div>
@@ -651,6 +657,41 @@ function renderArchiveModal(t, runs, events) {
</div>`;
}
// 过长内容折叠为 <details>,短内容直接 <pre>
function foldable(text, truncated, threshold = 400) {
const body = esc(text) + (truncated ? esc('\n…(已截断)') : '');
if ((text || '').length <= threshold) return `<pre class="t-pre">${body}</pre>`;
return `<details class="t-fold"><summary>展开(${(text || '').length} 字符)</summary><pre class="t-pre">${body}</pre></details>`;
}
// 结构化转录消息流 → HTML(按 type 分类;文本/结论复用 mdToHtml,工具调用/结果折叠)
function renderTranscript(messages) {
if (!messages || !messages.length) return '<div class="transcript-empty">(无可展示的转录内容)</div>';
return `<div class="t-stream">${messages.map((m) => {
if (m.type === 'text') {
return `<div class="t-msg t-text"><span class="t-badge t-badge-a">assistant</span>
<div class="doc md">${mdToHtml(m.text || '')}</div>${m.truncated ? '<div class="t-trunc">…(已截断)</div>' : ''}</div>`;
}
if (m.type === 'result') {
return `<div class="t-msg t-result"><span class="t-badge t-badge-r">结论</span>
<div class="doc md">${mdToHtml(m.text || '')}</div>${m.truncated ? '<div class="t-trunc"></div>' : ''}</div>`;
}
if (m.type === 'fallback') {
return `<div class="t-msg t-fallback"><span class="t-badge t-badge-w">模型回退</span>
<span class="t-fallback-txt">${esc(m.from)}${esc(m.to)}</span></div>`;
}
if (m.type === 'tool_use') {
return `<div class="t-msg t-tool"><span class="t-badge t-badge-t">工具调用</span>
<span class="t-tool-name">${esc(m.name)}</span>${m.input ? foldable(m.input, m.truncated) : ''}</div>`;
}
if (m.type === 'tool_result') {
return `<div class="t-msg t-tool-result${m.isError ? ' is-err' : ''}">
<span class="t-badge t-badge-tr">工具结果${m.isError ? ' · 报错' : ''}</span>${foldable(m.text || '', m.truncated)}</div>`;
}
return '';
}).join('')}</div>`;
}
// ── 渲染:全局预览(全屏读方案 + 就地裁决) ──
function renderPreview() {
const root = $('#previewRoot');
@@ -1237,6 +1278,22 @@ document.addEventListener('click', (ev) => {
case 'archive-detail':
openArchiveDetail(id);
break;
case 'run-transcript': {
ev.stopPropagation();
const box = document.getElementById(`transcript-${id}`);
if (!box) break;
if (!box.hidden) { box.hidden = true; el.textContent = '▶ 查看转录'; break; }
box.hidden = false;
el.textContent = '▼ 收起转录';
if (!box.dataset.loaded) {
box.innerHTML = '<div class="transcript-loading">加载中…</div>';
api(`/api/runs/${id}/transcript`)
.then((data) => { box.dataset.loaded = '1'; box.innerHTML = renderTranscript(data.messages); })
.catch((e) => { box.innerHTML = `<div class="transcript-err">${esc(e.message)}</div>`; });
}
break;
}
case 'archive-modal-close':
$('#archiveModalRoot').hidden = true;
$('#archiveModalRoot').innerHTML = '';