feat(plugins): add source-aware evidence and recording timelines

This commit is contained in:
chenmingxuan committed 2026-10-16 10:20:11 +08:00
1 parent 72ff342605
commit ef7af9988e
61 files changed
+3847 -108

No files matched your search

@@ -809,6 +809,7 @@ limitations under the License.
<div class="action-card-header" (click)="toggleActionExpanded('action-' + block.id + '-' + itemIdx, $event)">
<span class="material-symbols-outlined action-icon" [class.is-failed]="isActionFailed(item.data, block.data)">{{ getActionIcon(item.data) }}</span>
<span class="action-title">{{ getActionTitle(item.data) }}</span>
<button class="evidence-source" [title]="evidenceSourceLabel(item.data) + ' · 查看对应录像'" (click)="openEvidenceVideo(item.data, block.data, $event)">{{ evidenceSourceLabel(item.data) }}</button>
@if (isActionFailed(item.data, block.data)) {
<span class="action-status-badge is-failed">
<span class="material-symbols-outlined status-icon">error</span>
@@ -1050,7 +1051,7 @@ limitations under the License.
</div>
}
<!-- Generic Tool Calls (Text format for note tools, video analyzer, and other sub-agents) -->
@if (shouldShowTool(item.data, block.data) && !isDeviceActionTool(item.data)) {
@if (shouldShowTool(item.data, block.data) && !isEvidenceTool(item.data)) {
<div class="step-generic-tool"
[class.is-running]="isToolLineRunning(item, block)"
[class.is-note-tool]="isNoteTool(item.data)"
@@ -1091,9 +1092,11 @@ limitations under the License.
</div>
</div>
}
<!-- Action Card format (For Device Actions & ADB Commands) -->
@if (shouldShowTool(item.data, block.data) && isDeviceActionTool(item.data)) {
<!-- Device actions and plugin calls share evidence cards with explicit sources. -->
@if (shouldShowTool(item.data, block.data) && isEvidenceTool(item.data)) {
<div class="step-android-action-card tool-action-card"
[class.plugin-tool-card]="getPluginToolView(item.data)"
[class.is-auxiliary]="getPluginToolView(item.data)?.auxiliary"
[class.is-running]="isItemRunning(item, block)"
[class.has-no-details]="isAdbCommandTool(item.data) ? !getAdbCommandLine(item.data) : (!getToolTargetText(item.data) && !getToolInputText(item.data) && !getToolCoords(item.data) && !getToolAnalysisText(item.data) && !getToolGenericDetails(item.data) && getToolExtraParams(item.data).length === 0)"
[class.is-failed]="isToolFailed(item.data)"
@@ -1102,6 +1105,10 @@ limitations under the License.
<div class="action-card-header" (click)="toggleActionExpanded('tool-' + block.id + '-' + itemIdx, $event)">
<span class="material-symbols-outlined action-icon" [class.is-failed]="isToolFailed(item.data)">{{ getToolIcon(item.data) }}</span>
<span class="action-title">{{ getToolTitle(item.data) }}</span>
<button class="evidence-source" [title]="evidenceSourceLabel(item.data) + ' · 查看对应证据'" (click)="openEvidenceVideo(item.data, block.data, $event)">{{ evidenceSourceLabel(item.data) }}</button>
@if (getPluginToolView(item.data); as plugin) {
<span class="plugin-call-kind">{{ plugin.kind }} · {{ plugin.status }}</span>
}
@if (isToolFailed(item.data)) {
<span class="action-status-badge is-failed">
<span class="material-symbols-outlined status-icon">error</span>
@@ -1114,7 +1121,7 @@ limitations under the License.
</span>
</div>
<!-- Compact preview body (when collapsed) -->
@if (!isActionExpanded('tool-' + block.id + '-' + itemIdx) && (isAdbCommandTool(item.data) ? getAdbCommandLine(item.data) : (getToolTargetText(item.data) || getToolInputText(item.data) || getToolCoords(item.data) || getToolAnalysisText(item.data) || getToolGenericDetails(item.data)))) {
@if (!getPluginToolView(item.data) && !isActionExpanded('tool-' + block.id + '-' + itemIdx) && (isAdbCommandTool(item.data) ? getAdbCommandLine(item.data) : (getToolTargetText(item.data) || getToolInputText(item.data) || getToolCoords(item.data) || getToolAnalysisText(item.data) || getToolGenericDetails(item.data)))) {
<div class="action-card-body">
<!-- ADB command details -->
@if (isAdbCommandTool(item.data)) {
@@ -1196,7 +1203,21 @@ limitations under the License.
</div>
}
}
@if (!isAdbCommandTool(item.data)) {
@if (getPluginToolView(item.data); as plugin) {
@for (param of plugin.args; track param.key) {
<div class="grid-item">
<span class="grid-label">{{ param.key }}</span>
<span class="grid-value code-pill">{{ param.value }}</span>
</div>
}
@if (plugin.result) {
<div class="grid-item full-width">
<span class="grid-label">实际结果</span>
<span class="grid-value plugin-result">{{ plugin.result }}</span>
</div>
}
}
@if (!isAdbCommandTool(item.data) && !getPluginToolView(item.data)) {
@if (getToolTargetText(item.data)) {
<div class="grid-item">
<span class="grid-label">目标</span>
@@ -1251,7 +1272,7 @@ limitations under the License.
}
@if (getStepPostImageUrl(block.data, item.data)) {
<div class="screenshot-column">
<span class="screenshot-label">操作后</span>
<span class="screenshot-label">{{ getPluginToolView(item.data)?.auxiliary ? '观察截图' : '操作后' }}</span>
<div class="image-wrapper" (click)="openImageModal(getStepPostImageUrl(block.data, item.data)!, null, $event)">
<div class="img-relative-box">
<img [src]="getStepPostImageUrl(block.data, item.data)" alt="操作后截图" />