import { Component, computed, input } from '@angular/core'; import { PluginToolView } from '../../utils/plugin-tool-view.util'; import { ExpandableValueComponent } from '../expandable-value/expandable-value.component'; /** Readable presentation only: the full receipt and model context stay intact. */ @Component({ selector: 'app-plugin-tool-result', standalone: true, imports: [ExpandableValueComponent], template: ` @if (view().facts.length) {
@for (fact of view().facts; track fact.key) {
{{ fact.key }}
}
} @if (view().result) {
{{ preview() }}
@if (isLong()) {
完整文本与控件树 {{ view().result.length }} 字符
{{ view().result }}
} } @if (view().rawResult) {
原始返回 payload 完整保留
{{ view().rawResult }}
} `, styles: [` :host { display: block; min-width: 0; width: 100%; user-select: text; cursor: auto; } .receipt-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr)); gap: 8px 16px; margin: 0 0 12px; } .receipt-facts div { min-width: 0; } dt { font-size: 11px; color: var(--app-text-muted, #64748b); } dd { margin: 3px 0 0; font-size: 12px; color: var(--app-text-control, #334155); overflow-wrap: anywhere; } pre { margin: 0; padding: 10px 12px; border-radius: 6px; font: 12px/1.6 Consolas, monospace; color: var(--app-text-control, #334155); background: var(--app-surface-soft, #f8fafc); white-space: pre-wrap; overflow-wrap: anywhere; } .receipt-preview { max-height: 180px; overflow: auto; } .receipt-detail { margin-top: 10px; border: 1px solid var(--app-border, #e2e8f0); border-radius: 6px; min-width: 0; } summary { padding: 9px 10px; font-size: 12px; color: var(--app-text-secondary, #475569); cursor: pointer; overflow-wrap: anywhere; } summary span { margin-left: 8px; font-size: 11px; color: var(--app-text-muted, #64748b); } summary:focus-visible { outline: 2px solid var(--app-primary-text, #1a73e8); outline-offset: 2px; } .receipt-detail pre { max-height: 400px; overflow: auto; border-top: 1px solid var(--app-border, #e2e8f0); border-radius: 0 0 6px 6px; } `] }) export class PluginToolResultComponent { view = input.required(); private readonly previewLimit = 1000; preview = computed(() => { const text = this.view().result; const excerpt = text.split('\n').slice(0, 7).join('\n').slice(0, this.previewLimit); return excerpt.length < text.length ? `${excerpt}\n…` : text; }); isLong = computed(() => this.preview() !== this.view().result); }