feat(transcript): 归档详情内回放执行/复审转录 (tsk_O9q0_u78_NPo)
- API:新增 GET /api/runs/:id/transcript,读 run.transcriptRef 指向的 jsonl,逐行解析成脱敏后的结构化消息数组。校验 runId 合法且关联任务/ 项目存在;路径只允许在 transcriptDir 下(防目录穿越)。 - 脱敏:只透传 assistant 文本 / tool_use(名+摘要参数) / tool_result(截断) / 结论 / 模型回退;命中 secret/token/env 等敏感键名的值剔除为 [已脱敏]。 - 看板 archiveModal:执行历史从"文件路径"换成可展开的消息流,按 type 分类渲染(文本/工具调用/工具结果/结论/回退),长内容折叠,复用 mdToHtml。 executor 与 reviewer/security run 并列可回放。 - Store:新增 getRun(runId)。 - 测试:transcript 解析(样例 jsonl/脱敏/截断/坏行容错/路径穿越)+ 端点 inject(合法/未知 runId/无转录/越界路径)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -826,3 +826,50 @@ li.ev-updated { --ev: var(--muted); }
|
||||
.detail-confirm-msg {
|
||||
font-size: 12px; color: var(--ink);
|
||||
}
|
||||
|
||||
/* ── 归档详情:执行历史 + 转录回放 ── */
|
||||
.run-list { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
|
||||
.run-item { border: 1px solid var(--line-soft); background: var(--panel); padding: 8px 10px; }
|
||||
.run-head { display: flex; align-items: center; gap: 10px; font-size: 12px; flex-wrap: wrap; }
|
||||
.run-head .spacer { flex: 1; }
|
||||
.run-kind { color: var(--ink); font-weight: 600; }
|
||||
.run-st { font-size: 11px; padding: 1px 6px; border: 1px solid var(--line); color: var(--muted); }
|
||||
.run-st-succeeded { color: var(--green); border-color: var(--green-dim); }
|
||||
.run-st-failed { color: var(--red); border-color: var(--red-dim); }
|
||||
.run-st-started { color: var(--cyan); border-color: var(--cyan-dim); }
|
||||
.run-time { color: var(--faint); font-size: 11px; letter-spacing: 0; }
|
||||
.run-err { margin-top: 6px; font-size: 12px; color: var(--red); }
|
||||
|
||||
.transcript { margin-top: 8px; border-top: 1px dashed var(--line-soft); padding-top: 8px; }
|
||||
.transcript-loading, .transcript-empty { color: var(--muted); font-size: 12px; }
|
||||
.transcript-err { color: var(--red); font-size: 12px; }
|
||||
|
||||
.t-stream { display: flex; flex-direction: column; gap: 8px; }
|
||||
.t-msg { font-size: 12.5px; border-left: 2px solid var(--line); padding: 2px 0 2px 10px; }
|
||||
.t-msg .doc.md { margin-top: 2px; }
|
||||
.t-text { border-left-color: var(--green-dim); }
|
||||
.t-result { border-left-color: var(--green); }
|
||||
.t-tool { border-left-color: var(--cyan-dim); }
|
||||
.t-tool-result { border-left-color: var(--amber-dim); }
|
||||
.t-tool-result.is-err { border-left-color: var(--red-dim); }
|
||||
.t-fallback { border-left-color: var(--amber); }
|
||||
.t-badge {
|
||||
display: inline-block; font-size: 10px; letter-spacing: .08em;
|
||||
padding: 1px 6px; margin-right: 8px; border: 1px solid var(--line); color: var(--muted);
|
||||
}
|
||||
.t-badge-a { color: var(--green); border-color: var(--green-dim); }
|
||||
.t-badge-r { color: var(--green); border-color: var(--green); }
|
||||
.t-badge-t { color: var(--cyan); border-color: var(--cyan-dim); }
|
||||
.t-badge-tr { color: var(--amber); border-color: var(--amber-dim); }
|
||||
.t-badge-w { color: var(--amber); border-color: var(--amber); }
|
||||
.t-tool-name { color: var(--cyan); font-weight: 600; }
|
||||
.t-fallback-txt { color: var(--amber); }
|
||||
.t-trunc { color: var(--faint); font-size: 11px; margin-top: 2px; }
|
||||
.t-pre {
|
||||
margin: 4px 0 0; padding: 6px 8px; background: var(--bg-deep); border: 1px solid var(--line-soft);
|
||||
font-size: 11.5px; white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow-y: auto;
|
||||
}
|
||||
.t-fold { margin-top: 4px; }
|
||||
.t-fold > summary { cursor: pointer; color: var(--muted); font-size: 11.5px; }
|
||||
.t-fold > summary:hover { color: var(--green); }
|
||||
.t-fold .t-pre { max-height: 480px; }
|
||||
|
||||
Reference in New Issue
Block a user