ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Спека exact-маршрута payables на дату: confirmed_balance без эвристического финала

This commit is contained in:
2026-04-12 13:46:14 +03:00
parent ca2feab893
commit 1b2ee93176
19 changed files with 2453 additions and 252 deletions
@@ -141,6 +141,24 @@ interface AutoRunsUiConfig {
hideResolvedAnnotations?: boolean;
}
type UnifiedCommentListItem =
| {
source: "autorun";
key: string;
updated_at: string;
rating: number;
autorun: AutoRunAnnotationListItem;
assistant: null;
}
| {
source: "assistant_live";
key: string;
updated_at: string;
rating: number;
autorun: null;
assistant: AssistantAnnotationRecord;
};
const DEFAULT_AUTOGEN_SETTINGS: AutoGenSettingsState = {
mode: "codex_creative",
count: 24,
@@ -557,11 +575,31 @@ export function AutoRunsHistoryPanel({
return null;
}, [assistantLiveCommentModal.messageIndex, assistantLiveConversation]);
const unifiedVisibleAnnotations = useMemo<UnifiedCommentListItem[]>(() => {
const autorunItems: UnifiedCommentListItem[] = visibleAnnotations.map((item) => ({
source: "autorun",
key: `autorun:${item.annotation_id}`,
updated_at: item.updated_at,
rating: item.rating,
autorun: item,
assistant: null
}));
const assistantItems: UnifiedCommentListItem[] = assistantLiveAnnotations.map((item) => ({
source: "assistant_live",
key: `assistant:${item.annotation_id}`,
updated_at: item.updated_at,
rating: item.rating,
autorun: null,
assistant: item
}));
return [...autorunItems, ...assistantItems].sort((left, right) => Date.parse(right.updated_at) - Date.parse(left.updated_at));
}, [assistantLiveAnnotations, visibleAnnotations]);
const annotationsAverageRating = useMemo(() => {
if (visibleAnnotations.length === 0) return null;
const avg = visibleAnnotations.reduce((acc, item) => acc + item.rating, 0) / visibleAnnotations.length;
if (unifiedVisibleAnnotations.length === 0) return null;
const avg = unifiedVisibleAnnotations.reduce((acc, item) => acc + item.rating, 0) / unifiedVisibleAnnotations.length;
return Number(avg.toFixed(2));
}, [visibleAnnotations]);
}, [unifiedVisibleAnnotations]);
const runSelectItems = useMemo(() => {
const list = [...(history?.items ?? [])];
@@ -2411,7 +2449,7 @@ export function AutoRunsHistoryPanel({
<div className="autoruns-stats-grid">
<div>
<span>Комментариев</span>
<strong>{visibleAnnotations.length}</strong>
<strong>{unifiedVisibleAnnotations.length}</strong>
</div>
<div>
<span>Средний рейтинг</span>
@@ -2419,7 +2457,9 @@ export function AutoRunsHistoryPanel({
</div>
<div>
<span>Последний</span>
<strong>{visibleAnnotations.length > 0 ? formatDateTime(visibleAnnotations[0].updated_at) : "нет данных"}</strong>
<strong>
{unifiedVisibleAnnotations.length > 0 ? formatDateTime(unifiedVisibleAnnotations[0].updated_at) : "нет данных"}
</strong>
</div>
<div>
<span>Статус</span>
@@ -2438,74 +2478,99 @@ export function AutoRunsHistoryPanel({
<div className="autoruns-comments-list">
{annotationsBusy ? <p className="muted">Загружаю комментарии...</p> : null}
{!annotationsBusy && visibleAnnotations.length === 0 ? (
{!annotationsBusy && unifiedVisibleAnnotations.length === 0 ? (
<p className="muted">
{annotations.length === 0
{annotations.length === 0 && assistantLiveAnnotations.length === 0
? "Пока нет откомментированных ответов."
: "\u041d\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u043a\u0435\u0439\u0441\u043e\u0432 \u043f\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u0444\u0438\u043b\u044c\u0442\u0440\u0443."}
</p>
) : null}
{visibleAnnotations.map((item) => (
<article
key={item.annotation_id}
className={selectedAnnotationId === item.annotation_id ? "autoruns-comment-item selected" : "autoruns-comment-item"}
onClick={() => void openAnnotationContext(item)}
role="button"
tabIndex={0}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
void openAnnotationContext(item);
}
}}
>
<div className="autoruns-comment-head">
<strong>{renderRatingDots(item.rating)}</strong>
<div className="autoruns-comment-head-actions">
<span>{formatDateTime(item.updated_at)}</span>
<button
type="button"
className={item.resolved ? "autoruns-resolve-toggle resolved" : "autoruns-resolve-toggle"}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
void toggleAnnotationResolved(item, !item.resolved);
}}
disabled={annotationResolutionBusyId === item.annotation_id}
title={
item.resolved
? "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u043d\u0435\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
: "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
}
aria-label={
item.resolved
? "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u043d\u0435\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
: "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
}
>
<CommentResolvedIcon resolved={item.resolved} />
</button>
{unifiedVisibleAnnotations.map((item) => {
if (item.source === "assistant_live") {
const annotation = item.assistant;
return (
<article key={item.key} className="autoruns-comment-item">
<div className="autoruns-comment-head">
<strong>{renderRatingDots(annotation.rating)}</strong>
<div className="autoruns-comment-head-actions">
<span>{formatDateTime(annotation.updated_at)}</span>
</div>
</div>
<div className="autoruns-run-meta">live-session: {annotation.session_id}</div>
<div className="autoruns-run-meta">msg={annotation.message_index}</div>
<div className="autoruns-run-meta">
source=assistant_live
{annotation.annotation_author ? ` | author=${annotation.annotation_author}` : ""}
</div>
{annotation.context.question_text ? <p>Q: {annotation.context.question_text}</p> : null}
{annotation.context.answer_text ? <p>A: {annotation.context.answer_text}</p> : null}
<p>{annotation.comment}</p>
</article>
);
}
const annotation = item.autorun;
return (
<article
key={item.key}
className={selectedAnnotationId === annotation.annotation_id ? "autoruns-comment-item selected" : "autoruns-comment-item"}
onClick={() => void openAnnotationContext(annotation)}
role="button"
tabIndex={0}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
void openAnnotationContext(annotation);
}
}}
>
<div className="autoruns-comment-head">
<strong>{renderRatingDots(annotation.rating)}</strong>
<div className="autoruns-comment-head-actions">
<span>{formatDateTime(annotation.updated_at)}</span>
<button
type="button"
className={annotation.resolved ? "autoruns-resolve-toggle resolved" : "autoruns-resolve-toggle"}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
void toggleAnnotationResolved(annotation, !annotation.resolved);
}}
disabled={annotationResolutionBusyId === annotation.annotation_id}
title={
annotation.resolved
? "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u043d\u0435\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
: "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
}
aria-label={
annotation.resolved
? "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u043d\u0435\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
: "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0435\u0439\u0441 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439"
}
>
<CommentResolvedIcon resolved={annotation.resolved} />
</button>
</div>
</div>
</div>
<div className="autoruns-run-meta">{item.run_id}</div>
<div className="autoruns-run-meta">
case={item.case_id} | msg={item.message_index}
</div>
<div className="autoruns-run-meta">
decision={item.manual_case_decision}
{item.annotation_author ? ` | author=${item.annotation_author}` : ""}
</div>
{item.resolved_at ? (
<div className="autoruns-run-meta">{annotation.run_id}</div>
<div className="autoruns-run-meta">
{"\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e"}: {formatDateTime(item.resolved_at)}
{item.resolved_by ? ` | by=${item.resolved_by}` : ""}
case={annotation.case_id} | msg={annotation.message_index}
</div>
) : null}
{item.context.question_text ? <p>Q: {item.context.question_text}</p> : null}
{item.context.answer_text ? <p>A: {item.context.answer_text}</p> : null}
<p>{item.comment}</p>
</article>
))}
<div className="autoruns-run-meta">
decision={annotation.manual_case_decision}
{annotation.annotation_author ? ` | author=${annotation.annotation_author}` : ""}
</div>
{annotation.resolved_at ? (
<div className="autoruns-run-meta">
{"\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e"}: {formatDateTime(annotation.resolved_at)}
{annotation.resolved_by ? ` | by=${annotation.resolved_by}` : ""}
</div>
) : null}
{annotation.context.question_text ? <p>Q: {annotation.context.question_text}</p> : null}
{annotation.context.answer_text ? <p>A: {annotation.context.answer_text}</p> : null}
<p>{annotation.comment}</p>
</article>
);
})}
</div>
{selectedAnnotation ? (
@@ -2574,7 +2639,7 @@ export function AutoRunsHistoryPanel({
>
<div className="autoruns-comment-modal">
<h3>Комментарий к ответу ассистента</h3>
<p className="muted">Комментарий сохраняется отдельно от комментариев автопрогонов.</p>
<p className="muted">Комментарий будет добавлен в общий список комментариев справа с меткой `assistant_live`.</p>
{assistantLiveCommentModalQuestion ? (
<details className="autoruns-prompt-details" open>