АДРЕСНЫЙ РЕЖИМ - авторан история - юи + адресный рендер прогонов в реалтайме

This commit is contained in:
2026-04-09 23:48:32 +03:00
parent cf5ba1afc2
commit fd6764d412
38 changed files with 6179 additions and 777 deletions
+79 -1
View File
@@ -1,4 +1,7 @@
import type {
AsyncEvalRunStartResponse,
AsyncEvalRunStatusResponse,
AutoGenPersonalityCatalogResponse,
AutoGenHistoryResponse,
AutoGenMode,
AutoRunAnnotationsResponse,
@@ -155,6 +158,8 @@ export const apiClient = {
mode?: "standard" | "single-pass-strict";
caseSetFile?: string;
rawQuestions?: string;
evalTarget?: "normalizer" | "assistant_stage1" | "assistant_stage2" | "assistant_p0";
compareWithReportFile?: string;
}): Promise<{ ok: boolean; report: unknown }> {
return request("/eval/run", {
method: "POST",
@@ -176,11 +181,58 @@ export const apiClient = {
useMock: Boolean(input.useMock),
mode: input.mode ?? "standard",
caseSetFile: input.caseSetFile,
rawQuestions: input.rawQuestions
rawQuestions: input.rawQuestions,
eval_target: input.evalTarget,
compare_with_report_file: input.compareWithReportFile
})
});
},
async startEvalRunAsync(input: {
connection: ConnectionState;
prompts: PromptState;
promptVersion?: string;
caseIds?: string[];
useMock?: boolean;
mode?: "standard" | "single-pass-strict";
caseSetFile?: string;
rawQuestions?: string;
evalTarget?: "normalizer" | "assistant_stage1" | "assistant_stage2" | "assistant_p0";
compareWithReportFile?: string;
questions?: string[];
}): Promise<AsyncEvalRunStartResponse> {
return request("/eval/run-async/start", {
method: "POST",
body: JSON.stringify({
normalizeConfig: {
llmProvider: input.connection.llmProvider,
apiKey: input.connection.apiKey,
model: input.connection.model,
baseUrl: input.connection.baseUrl,
temperature: input.connection.temperature,
maxOutputTokens: input.connection.maxOutputTokens,
promptVersion: input.promptVersion,
systemPrompt: input.prompts.systemPrompt,
developerPrompt: input.prompts.developerPrompt,
domainPrompt: input.prompts.domainPrompt,
fewShotExamples: input.prompts.fewShotExamples
},
caseIds: input.caseIds,
useMock: Boolean(input.useMock),
mode: input.mode ?? "standard",
caseSetFile: input.caseSetFile,
rawQuestions: input.rawQuestions,
eval_target: input.evalTarget,
compare_with_report_file: input.compareWithReportFile,
questions: input.questions
})
});
},
async loadEvalRunAsyncStatus(jobId: string): Promise<AsyncEvalRunStatusResponse> {
return request(`/eval/run-async/${encodeURIComponent(jobId)}`);
},
async startRun(): Promise<{ ok: boolean; run: RuntimeRun; runId: string; sessionId: string; status: string }> {
return request("/accounting-agent/v1/runs/start", {
method: "POST",
@@ -321,6 +373,20 @@ export const apiClient = {
});
},
async updateAutoRunAnnotation(input: {
annotation_id: string;
resolved: boolean;
resolved_by?: string;
}): Promise<{ ok: boolean; annotation: AutoRunAnnotationRecord; case_annotation_stats: { count: number; latest_at: string | null; avg_rating: number | null } | null }> {
return request(`/autoruns/annotations/${encodeURIComponent(input.annotation_id)}`, {
method: "PATCH",
body: JSON.stringify({
resolved: input.resolved,
resolved_by: input.resolved_by
})
});
},
async loadAutoRunPostAnalysis(input?: {
run_id?: string;
limit_per_queue?: number;
@@ -359,12 +425,24 @@ export const apiClient = {
return request(`/autoruns/autogen/history${query ? `?${query}` : ""}`);
},
async loadAutoRunAutogenPersonalityCatalog(): Promise<AutoGenPersonalityCatalogResponse> {
return request("/autoruns/autogen/personality-catalog");
},
async generateAutoRunQuestions(input: {
mode: AutoGenMode;
count: number;
domain?: string;
persist_to_eval_cases?: boolean;
generated_by?: string;
llm?: {
llm_provider?: "openai" | "local";
api_key?: string;
model?: string;
base_url?: string;
temperature?: number;
max_output_tokens?: number;
};
context?: {
llm_provider?: string;
model?: string;
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,4 @@
import { useEffect, useState } from "react";
import { PanelFrame } from "./PanelFrame";
import type { ConnectionState } from "../state/types";
@@ -26,6 +27,46 @@ export function ConnectionPanel({
}: ConnectionPanelProps) {
const isLocal = value.llmProvider === "local";
const modelInCatalog = modelOptions.includes(value.model);
const [temperatureInput, setTemperatureInput] = useState(String(value.temperature));
const [maxOutputTokensInput, setMaxOutputTokensInput] = useState(String(value.maxOutputTokens));
useEffect(() => {
setTemperatureInput(String(value.temperature));
}, [value.temperature]);
useEffect(() => {
setMaxOutputTokensInput(String(value.maxOutputTokens));
}, [value.maxOutputTokens]);
const commitTemperatureInput = (raw: string) => {
const normalized = raw.replace(",", ".").trim();
if (!normalized) {
setTemperatureInput(String(value.temperature));
return;
}
const parsed = Number(normalized);
if (!Number.isFinite(parsed)) {
setTemperatureInput(String(value.temperature));
return;
}
onChange({ ...value, temperature: parsed });
setTemperatureInput(String(parsed));
};
const commitMaxOutputTokensInput = (raw: string) => {
const normalized = raw.trim();
if (!normalized) {
setMaxOutputTokensInput(String(value.maxOutputTokens));
return;
}
const parsed = Number.parseInt(normalized, 10);
if (!Number.isFinite(parsed) || parsed <= 0) {
setMaxOutputTokensInput(String(value.maxOutputTokens));
return;
}
onChange({ ...value, maxOutputTokens: parsed });
setMaxOutputTokensInput(String(parsed));
};
return (
<PanelFrame
@@ -108,8 +149,14 @@ export function ConnectionPanel({
<input
type="number"
step="0.1"
value={value.temperature}
onChange={(event) => onChange({ ...value, temperature: Number(event.target.value) })}
value={temperatureInput}
onChange={(event) => setTemperatureInput(event.target.value)}
onBlur={(event) => commitTemperatureInput(event.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
commitTemperatureInput((event.target as HTMLInputElement).value);
}
}}
/>
</label>
@@ -117,8 +164,14 @@ export function ConnectionPanel({
Max output tokens
<input
type="number"
value={value.maxOutputTokens}
onChange={(event) => onChange({ ...value, maxOutputTokens: Number(event.target.value) })}
value={maxOutputTokensInput}
onChange={(event) => setMaxOutputTokensInput(event.target.value)}
onBlur={(event) => commitMaxOutputTokensInput(event.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
commitMaxOutputTokensInput((event.target as HTMLInputElement).value);
}
}}
/>
</label>
</div>
+61 -1
View File
@@ -188,6 +188,9 @@ export interface AutoRunAnnotationRecord {
comment: string;
manual_case_decision: ManualCaseDecision;
annotation_author: string | null;
resolved: boolean;
resolved_at: string | null;
resolved_by: string | null;
created_at: string;
updated_at: string;
context: {
@@ -198,6 +201,8 @@ export interface AutoRunAnnotationRecord {
prompt_version: string | null;
domain: string | null;
query_class: string | null;
question_text: string | null;
answer_text: string | null;
};
}
@@ -243,6 +248,8 @@ export interface AutoRunDialogMessage {
trace_id: string | null;
reply_type: string | null;
message_index: number;
case_id?: string | null;
case_message_index?: number | null;
commented: boolean;
annotation: AutoRunAnnotationRecord | null;
}
@@ -251,7 +258,7 @@ export interface AutoRunDialogResponse {
ok: boolean;
run_id: string;
case_id: string;
source: "assistant_session" | "report_fallback" | "none";
source: "assistant_session" | "report_fallback" | "run_aggregate" | "none";
session_id: string;
messages: AutoRunDialogMessage[];
decomposition: string[];
@@ -320,6 +327,8 @@ export interface AutoGenHistoryRecord {
assistant_prompt_version: string | null;
decomposition_prompt_version: string | null;
prompt_fingerprint: string | null;
autogen_personality_id: string | null;
autogen_personality_prompt: string | null;
} | null;
}
@@ -329,6 +338,57 @@ export interface AutoGenHistoryResponse {
items: AutoGenHistoryRecord[];
}
export interface AutoGenPersonalityDefinition {
id: string;
label: string;
domain: string | null;
default_prompt: string;
source: "built_in" | "capabilities_registry";
}
export interface AutoGenPersonalityCatalogResponse {
ok: boolean;
generated_at: string;
items: AutoGenPersonalityDefinition[];
}
export interface AsyncEvalRunCase {
case_id: string;
turns_total: number;
status: "queued" | "running" | "completed" | "failed";
messages: AutoRunDialogMessage[];
}
export interface AsyncEvalRunJob {
job_id: string;
status: "queued" | "running" | "completed" | "failed";
created_at: string;
updated_at: string;
eval_target: AutoRunTarget;
run_id: string;
case_set_file: string | null;
total_cases: number;
completed_cases: number;
error: string | null;
cases: AsyncEvalRunCase[];
report_summary: {
run_id: string | null;
run_timestamp: string | null;
score_index: number | null;
cases_total: number | null;
} | null;
}
export interface AsyncEvalRunStartResponse {
ok: boolean;
job: AsyncEvalRunJob;
}
export interface AsyncEvalRunStatusResponse {
ok: boolean;
job: AsyncEvalRunJob;
}
export type AssistantFallbackType = "none" | "out_of_scope" | "clarification" | "partial" | "unknown";
export type AssistantReplyType =
| "factual"
+207 -13
View File
@@ -741,10 +741,17 @@ button:disabled {
padding: 10px;
display: grid;
gap: 5px;
transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.autoruns-run-item.selected {
border-color: var(--line-strong);
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
box-shadow: none;
}
.autoruns-run-item.selected .autoruns-run-meta {
color: rgba(var(--rgb-active-text), 0.95);
}
.autoruns-run-head,
@@ -790,7 +797,9 @@ button:disabled {
}
.autoruns-case-item.selected {
border-color: var(--line-strong);
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
box-shadow: none;
}
.autoruns-dialog-view {
@@ -831,6 +840,17 @@ button:disabled {
gap: 8px;
}
.autoruns-msg-case-tag {
display: inline-flex;
align-items: center;
border-radius: 999px;
padding: 2px 8px;
font-size: 0.7rem;
line-height: 1;
color: rgb(var(--rgb-active-text));
background: rgba(var(--rgb-active), 0.24);
}
.autoruns-msg p {
margin: 0;
white-space: pre-wrap;
@@ -840,30 +860,106 @@ button:disabled {
.autoruns-comment-icon {
border: none;
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
border-radius: 999px;
min-width: 28px;
min-height: 28px;
padding: 0 8px;
background: transparent;
color: rgb(var(--rgb-text-main));
border-radius: 0;
min-width: 20px;
min-height: 20px;
width: 20px;
height: 20px;
padding: 0;
line-height: 1;
box-shadow: none;
transform: none;
display: inline-flex;
align-items: center;
justify-content: center;
}
.autoruns-comment-icon:hover {
border-color: var(--line-strong);
background: transparent;
color: rgb(var(--rgb-active));
box-shadow: none;
transform: none;
}
.autoruns-comment-icon.commented {
border-color: var(--line-strong);
color: var(--lime-main);
color: rgb(var(--rgb-active-text));
background: transparent;
box-shadow: none;
}
.comment-icon-svg {
width: 20px;
height: 20px;
stroke: currentColor;
stroke-width: 1.75;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
.comment-icon-svg .comment-icon-dot {
fill: currentColor;
}
.comment-icon-svg.commented {
fill: rgb(var(--rgb-active));
stroke: rgb(var(--rgb-active));
}
.autoruns-comment-icon.commented .comment-icon-dot {
fill: rgb(var(--rgb-active-text));
}
.autoruns-resolve-toggle {
border: none;
background: rgb(var(--rgb-surface-focus));
color: rgb(var(--rgb-text-main));
border-radius: 999px;
width: 22px;
height: 22px;
min-width: 22px;
min-height: 22px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
box-shadow: none;
transform: none;
}
.autoruns-resolve-toggle:hover {
background: rgb(var(--rgb-surface-focus));
color: rgb(var(--rgb-active));
box-shadow: none;
transform: none;
}
.autoruns-resolve-toggle:disabled {
opacity: 0.55;
cursor: wait;
}
.autoruns-resolve-toggle.resolved {
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
}
.resolve-icon-svg {
width: 14px;
height: 14px;
fill: none;
stroke: currentColor;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
}
.resolve-icon-svg.resolved {
fill: currentColor;
}
.autoruns-msg-annotation {
display: grid;
gap: 4px;
@@ -882,6 +978,7 @@ button:disabled {
flex: 1 1 auto;
overflow: auto;
padding-right: 2px;
margin-top: 6px;
}
.autoruns-autogen-list {
@@ -900,6 +997,17 @@ button:disabled {
padding: 8px;
display: grid;
gap: 5px;
cursor: pointer;
}
.autoruns-autogen-item.selected {
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
}
.autoruns-autogen-item.selected .autoruns-run-meta,
.autoruns-autogen-item.selected p {
color: rgba(var(--rgb-active-text), 0.95);
}
.autoruns-autogen-item header {
@@ -916,6 +1024,58 @@ button:disabled {
font-size: 0.8rem;
}
.autoruns-generated-questions {
border: none;
border-radius: 10px;
background: rgb(var(--rgb-surface-horizontal));
padding: 8px;
display: grid;
gap: 8px;
}
.autoruns-generated-questions-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.autoruns-generated-questions-list {
display: grid;
gap: 6px;
max-height: 220px;
overflow: auto;
padding-right: 2px;
}
.autoruns-generated-question-item {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 8px;
border: none;
border-radius: 9px;
background: rgb(var(--rgb-surface-focus));
padding: 6px 8px;
font-size: 0.78rem;
}
.autoruns-generated-question-item span {
white-space: pre-wrap;
}
.autoruns-remove-question-btn {
flex: 0 0 auto;
border: none;
border-radius: 7px;
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
min-width: 24px;
height: 24px;
font-size: 0.75rem;
line-height: 1;
}
.autoruns-comment-item {
width: 100%;
text-align: left;
@@ -926,6 +1086,7 @@ button:disabled {
padding: 9px;
display: grid;
gap: 6px;
cursor: pointer;
}
.autoruns-comment-item p {
@@ -936,16 +1097,48 @@ button:disabled {
}
.autoruns-comment-item.selected {
border-color: var(--line-strong);
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
}
.autoruns-comment-item.selected p,
.autoruns-comment-item.selected .autoruns-run-meta,
.autoruns-comment-item.selected .muted {
color: rgba(var(--rgb-active-text), 0.94);
}
.autoruns-comment-item.selected .autoruns-resolve-toggle {
background: rgba(var(--rgb-active-text), 0.18);
color: rgb(var(--rgb-active-text));
}
.autoruns-comment-head {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
font-size: 0.75rem;
}
.autoruns-comment-head-actions {
display: inline-flex;
align-items: center;
gap: 8px;
}
.autoruns-comment-filter-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: end;
gap: 10px;
margin-bottom: 8px;
}
.autoruns-resolved-filter-toggle {
min-height: 38px;
white-space: nowrap;
}
.autoruns-msg.assistant {
margin-right: 12%;
}
@@ -1096,7 +1289,8 @@ button:disabled {
.autoruns-form-grid,
.autoruns-dialog-toolbar,
.autoruns-stats-grid {
.autoruns-stats-grid,
.autoruns-comment-filter-row {
grid-template-columns: 1fr;
}
}