feat: implement channel runtime connectors

This commit is contained in:
2026-06-03 16:22:44 +08:00
parent ee972441f5
commit c3d84b904a
105 changed files with 15621 additions and 322 deletions

View File

@ -24,6 +24,7 @@ import { Card, CardContent } from '@/components/ui/card';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
import type { TaskRuntimeStatus } from '@/lib/task-runtime';
import { containedJsonTextClass, containedLongTextClass, containedPreservedLongTextClass } from '@/lib/text-wrapping';
import type { TaskTimelineCard as TaskTimelineCardView, TaskTimelineCardType } from '@/types';
import { TaskAcceptanceControls, type TaskFeedbackItem, type TaskFeedbackType } from './TaskAcceptanceCard';
@ -146,14 +147,14 @@ function TaskResultHistory({ card }: { card: TaskTimelineCardView }) {
const versions = historyVersions(card.details);
return (
<details className="mt-3 rounded-md border border-border bg-muted/20 px-3 py-2 text-sm">
<details className="mt-3 min-w-0 max-w-full overflow-hidden rounded-md border border-border bg-muted/20 px-3 py-2 text-sm">
<summary className="flex cursor-pointer select-none items-center justify-between gap-3 font-medium">
<span>{pickAppText(locale, '展开历史版本', 'Show previous versions')}</span>
<ChevronDown className="h-4 w-4 text-muted-foreground" />
</summary>
<div className="mt-3 space-y-3">
{versions.map((version, index) => (
<div key={String(version.runId || index)} className="rounded-md border border-border bg-background p-3">
<div key={String(version.runId || index)} className="min-w-0 max-w-full overflow-hidden rounded-md border border-border bg-background p-3">
<div className="flex flex-wrap items-center justify-between gap-2">
<div className="text-sm font-medium">
{pickAppText(locale, `${index + 1} 轮结果`, `Version ${index + 1}`)}
@ -162,9 +163,9 @@ function TaskResultHistory({ card }: { card: TaskTimelineCardView }) {
{renderHistoryStatus(version, locale)}
</Badge>
</div>
{version.result ? <p className="mt-2 whitespace-pre-wrap text-sm leading-6 text-muted-foreground">{String(version.result)}</p> : null}
{version.result ? <p className={`mt-2 text-sm leading-6 text-muted-foreground ${containedPreservedLongTextClass}`}>{String(version.result)}</p> : null}
{version.comment ? (
<div className="mt-3 rounded-md bg-muted/35 p-2 text-xs text-muted-foreground">
<div className={`mt-3 rounded-md bg-muted/35 p-2 text-xs text-muted-foreground ${containedLongTextClass}`}>
{pickAppText(locale, '修改意见', 'Revision note')}: {String(version.comment)}
</div>
) : null}
@ -181,7 +182,7 @@ export function TaskTimelineCard({ card, resultAcceptance, reviewTargetId }: Pro
const shouldRenderResultAcceptance = Boolean(card.type === 'result' && resultAcceptance && card.runId === resultAcceptance.runId);
return (
<Card id={shouldRenderResultAcceptance ? reviewTargetId : undefined} className="rounded-md scroll-mt-28">
<Card id={shouldRenderResultAcceptance ? reviewTargetId : undefined} className="scroll-mt-28 overflow-hidden rounded-md">
<CardContent className="p-4">
<div className="flex gap-3">
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted">
@ -197,7 +198,7 @@ export function TaskTimelineCard({ card, resultAcceptance, reviewTargetId }: Pro
</Badge>
</div>
<div className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground">
{card.actorName ? <span>{card.actorName}</span> : null}
{card.actorName ? <span className={containedLongTextClass}>{card.actorName}</span> : null}
<span>{formatTaskRuntimeTime(card.createdAt, locale)}</span>
{card.runId ? <span className="font-mono">{card.runId.slice(0, 8)}</span> : null}
</div>
@ -213,7 +214,7 @@ export function TaskTimelineCard({ card, resultAcceptance, reviewTargetId }: Pro
) : null}
</div>
{card.summary ? <p className="mt-3 whitespace-pre-wrap text-sm leading-6 text-muted-foreground">{card.summary}</p> : null}
{card.summary ? <p className={`mt-3 text-sm leading-6 text-muted-foreground ${containedPreservedLongTextClass}`}>{card.summary}</p> : null}
{shouldRenderResultAcceptance ? (
<div className="mt-4 border-t border-border pt-4">
@ -222,11 +223,11 @@ export function TaskTimelineCard({ card, resultAcceptance, reviewTargetId }: Pro
) : null}
{card.type === 'result_history' ? <TaskResultHistory card={card} /> : card.details ? (
<details className="mt-3 rounded-md border border-border bg-muted/20 px-3 py-2 text-xs">
<details className="mt-3 min-w-0 max-w-full overflow-hidden rounded-md border border-border bg-muted/20 px-3 py-2 text-xs">
<summary className="cursor-pointer select-none font-medium text-muted-foreground">
{pickAppText(locale, '详情 JSON', 'Details JSON')}
</summary>
<pre className="mt-2 max-h-72 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-5 text-muted-foreground">
<pre className={`mt-2 max-h-72 overflow-auto text-[11px] leading-5 text-muted-foreground ${containedJsonTextClass}`}>
{detailsJson(card.details)}
</pre>
</details>