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

This commit is contained in:
2026-04-09 16:32:19 +03:00
parent edfa09c9af
commit 99288c195d
40 changed files with 5174 additions and 853 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -4,8 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NDC AI Normalizer Playground</title>
<script type="module" crossorigin src="/assets/index-D6Y_lHrc.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BMWPMdQA.css">
<script type="module" crossorigin src="/assets/index-BDtb8kxy.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-iFxz5cXp.css">
</head>
<body>
<div id="root"></div>
+67 -20
View File
@@ -10,6 +10,7 @@ import { PromptPanel } from "./components/PromptPanel";
import { QueryPanel } from "./components/QueryPanel";
import { RuntimePanel } from "./components/RuntimePanel";
import { DEFAULT_CONNECTION, DEFAULT_PROMPTS, DEFAULT_QUERY } from "./state/defaults";
import { designConfig } from "../../../designconfig";
import type {
AssistantConversationItem,
ConnectionState,
@@ -23,7 +24,7 @@ import type {
} from "./state/types";
const SESSION_CONFIG_KEY = "ndc_normalizer_session_config_v1";
const ASSISTANT_STAGES = ["Analyzing request", "Fetching data", "Composing answer"];
const ASSISTANT_STAGES = ["Анализ запроса", "Получение данных", "Подготовка ответа"];
const DEFAULT_UI_MODE: UiMode = "assistant";
const AUTOLOAD_PROMPT_VERSION = "normalizer_v2_0_2";
const ASSISTANT_PROMPT_VERSION = "address_query_runtime_v1";
@@ -79,6 +80,9 @@ export default function App() {
const [lastError, setLastError] = useState("");
const [uiMode, setUiMode] = useState<UiMode>(DEFAULT_UI_MODE);
const [showAutorunsAssistantMode, setShowAutorunsAssistantMode] = useState(true);
const [showAutorunsDecompositionMode, setShowAutorunsDecompositionMode] = useState(true);
const [showAutorunsProgressMode, setShowAutorunsProgressMode] = useState(true);
const [assistantSessionId, setAssistantSessionId] = useState("");
const [assistantConversation, setAssistantConversation] = useState<AssistantConversationItem[]>([]);
const [assistantInput, setAssistantInput] = useState("");
@@ -87,6 +91,23 @@ export default function App() {
const [assistantError, setAssistantError] = useState("");
const presetAutoloadDoneRef = useRef(false);
useEffect(() => {
const root = document.documentElement;
const { colors } = designConfig;
root.style.setProperty("--rgb-background", colors.backgroundRgb);
root.style.setProperty("--rgb-surface-main", colors.mainSurfaceRgb);
root.style.setProperty("--rgb-surface-horizontal", colors.horizontalSurfaceRgb);
root.style.setProperty("--rgb-surface-focus", colors.focusSurfaceRgb);
root.style.setProperty("--rgb-active", colors.activeRgb);
root.style.setProperty("--rgb-active-text", colors.activeTextRgb);
root.style.setProperty("--rgb-text-main", colors.textMainRgb);
root.style.setProperty("--rgb-text-muted", colors.textMutedRgb);
root.style.setProperty("--rgb-danger", colors.dangerRgb);
root.style.setProperty("--rgb-scrollbar-track", colors.scrollbarTrackRgb);
root.style.setProperty("--rgb-scrollbar-thumb", colors.scrollbarThumbRgb);
root.style.setProperty("--rgb-scrollbar-thumb-hover", colors.scrollbarThumbHoverRgb);
}, []);
const log = (message: string) => {
setAppLogs((prev) => [withTs(message), ...prev].slice(0, 300));
};
@@ -509,12 +530,12 @@ export default function App() {
});
setAssistantSessionId(response.session_id);
setAssistantConversation(response.conversation);
setAssistantStatus("Reply is ready");
setAssistantStatus("Ответ готов");
log(`Assistant reply received: trace=${response.debug.trace_id}`);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
setAssistantError(message);
setAssistantStatus("Assistant error");
setAssistantStatus("Ошибка ассистента");
log(`Assistant error: ${message}`);
} finally {
stopTicker();
@@ -534,23 +555,46 @@ export default function App() {
}, [selectedRunId]);
return (
<main className="app-root">
<div className="hero">
<h1>NDC AI First Layer</h1>
<p>Three modes in one UI: assistant, decomposition diagnostics, and auto-run history with regression visibility.</p>
</div>
<main className={`app-root ${uiMode === "autoruns" ? "app-root-autoruns" : ""}`}>
<header className="app-topbar">
<div className="mode-switch-row">
<button type="button" className={uiMode === "assistant" ? "tab active" : "tab"} onClick={() => setUiMode("assistant")}>
Ассистент
</button>
<button type="button" className={uiMode === "decomposition" ? "tab active" : "tab"} onClick={() => setUiMode("decomposition")}>
Декомпозиция
</button>
<button type="button" className={uiMode === "autoruns" ? "tab active" : "tab"} onClick={() => setUiMode("autoruns")}>
История автопрогонов
</button>
</div>
<div className="mode-switch-row">
<button type="button" className={uiMode === "assistant" ? "tab active" : "tab"} onClick={() => setUiMode("assistant")}>
Assistant
</button>
<button type="button" className={uiMode === "decomposition" ? "tab active" : "tab"} onClick={() => setUiMode("decomposition")}>
Decomposition
</button>
<button type="button" className={uiMode === "autoruns" ? "tab active" : "tab"} onClick={() => setUiMode("autoruns")}>
AutoRun History
</button>
</div>
{uiMode === "autoruns" ? (
<div className="mode-switch-row mode-switch-row-right">
<button
type="button"
className={showAutorunsAssistantMode ? "tab active" : "tab"}
onClick={() => setShowAutorunsAssistantMode((prev) => !prev)}
>
Режим ассистента
</button>
<button
type="button"
className={showAutorunsDecompositionMode ? "tab active" : "tab"}
onClick={() => setShowAutorunsDecompositionMode((prev) => !prev)}
>
Режим декомпозиции
</button>
<button
type="button"
className={showAutorunsProgressMode ? "tab active" : "tab"}
onClick={() => setShowAutorunsProgressMode((prev) => !prev)}
>
Прогресс/регресс
</button>
</div>
) : null}
</header>
{uiMode === "assistant" ? (
<div className="layout-grid">
@@ -660,12 +704,15 @@ export default function App() {
/>
</div>
) : (
<div className="layout-grid">
<div className="layout-grid layout-grid-autoruns">
<AutoRunsHistoryPanel
connection={connection}
prompts={prompts}
assistantPromptVersion={ASSISTANT_PROMPT_VERSION}
decompositionPromptVersion={AUTOLOAD_PROMPT_VERSION}
showAssistantMode={showAutorunsAssistantMode}
showDecompositionMode={showAutorunsDecompositionMode}
showProgressMode={showAutorunsProgressMode}
onLog={log}
/>
</div>
+96
View File
@@ -1,11 +1,17 @@
import type {
AutoGenHistoryResponse,
AutoGenMode,
AutoRunAnnotationsResponse,
AutoRunAnnotationRecord,
AutoRunDetailResponse,
AutoRunDialogResponse,
AutoRunHistoryResponse,
AutoRunPostAnalysisResponse,
AssistantMessageResultState,
AssistantConversationItem,
ConnectionState,
HistoryItem,
ManualCaseDecision,
NormalizeResultState,
PromptState,
RuntimeRun
@@ -281,5 +287,95 @@ export const apiClient = {
async loadAutoRunCaseDialog(runId: string, caseId: string): Promise<AutoRunDialogResponse> {
return request(`/autoruns/history/${encodeURIComponent(runId)}/case/${encodeURIComponent(caseId)}/dialog`);
},
async loadAutoRunAnnotations(input?: {
run_id?: string;
case_id?: string;
min_rating?: number;
manual_case_decision?: ManualCaseDecision | "all";
limit?: number;
}): Promise<AutoRunAnnotationsResponse> {
const params = new URLSearchParams();
if (input?.run_id) params.set("run_id", input.run_id);
if (input?.case_id) params.set("case_id", input.case_id);
if (typeof input?.min_rating === "number") params.set("min_rating", String(input.min_rating));
if (input?.manual_case_decision) params.set("manual_case_decision", input.manual_case_decision);
if (typeof input?.limit === "number") params.set("limit", String(input.limit));
const query = params.toString();
return request(`/autoruns/annotations${query ? `?${query}` : ""}`);
},
async saveAutoRunAnnotation(input: {
run_id: string;
case_id: string;
message_index: number;
rating: number;
comment: string;
manual_case_decision: ManualCaseDecision;
annotation_author?: string;
}): Promise<{ ok: boolean; annotation: AutoRunAnnotationRecord; case_annotation_stats: { count: number; latest_at: string | null; avg_rating: number | null } | null }> {
return request("/autoruns/annotations", {
method: "POST",
body: JSON.stringify(input)
});
},
async loadAutoRunPostAnalysis(input?: {
run_id?: string;
limit_per_queue?: number;
annotation_limit?: number;
scan_limit?: number;
from?: string;
to?: string;
target?: string;
mode?: string;
use_mock?: "any" | "true" | "false";
prompt_contains?: string;
}): Promise<AutoRunPostAnalysisResponse> {
const params = new URLSearchParams();
if (input?.run_id) params.set("run_id", input.run_id);
if (typeof input?.limit_per_queue === "number") params.set("limit_per_queue", String(input.limit_per_queue));
if (typeof input?.annotation_limit === "number") params.set("annotation_limit", String(input.annotation_limit));
if (typeof input?.scan_limit === "number") params.set("scan_limit", String(input.scan_limit));
if (input?.from) params.set("from", input.from);
if (input?.to) params.set("to", input.to);
if (input?.target) params.set("target", input.target);
if (input?.mode) params.set("mode", input.mode);
if (input?.use_mock) params.set("use_mock", input.use_mock);
if (input?.prompt_contains) params.set("prompt_contains", input.prompt_contains);
const query = params.toString();
return request(`/autoruns/post-analysis${query ? `?${query}` : ""}`);
},
async loadAutoRunAutogenHistory(input?: {
mode?: AutoGenMode;
limit?: number;
}): Promise<AutoGenHistoryResponse> {
const params = new URLSearchParams();
if (input?.mode) params.set("mode", input.mode);
if (typeof input?.limit === "number") params.set("limit", String(input.limit));
const query = params.toString();
return request(`/autoruns/autogen/history${query ? `?${query}` : ""}`);
},
async generateAutoRunQuestions(input: {
mode: AutoGenMode;
count: number;
domain?: string;
persist_to_eval_cases?: boolean;
generated_by?: string;
context?: {
llm_provider?: string;
model?: string;
assistant_prompt_version?: string;
decomposition_prompt_version?: string;
prompt_fingerprint?: string;
};
}): Promise<{ ok: boolean; generation: { generation_id: string; created_at: string; mode: AutoGenMode; count: number; domain: string | null; questions: string[]; generated_by: string | null; saved_case_set_file: string | null; context: Record<string, unknown> | null } }> {
return request("/autoruns/autogen/generate", {
method: "POST",
body: JSON.stringify(input)
});
}
};
File diff suppressed because it is too large Load Diff
@@ -4,18 +4,22 @@ interface PanelFrameProps {
title: string;
subtitle?: string;
actions?: ReactNode;
className?: string;
hideHeader?: boolean;
}
export function PanelFrame({ title, subtitle, actions, children }: PropsWithChildren<PanelFrameProps>) {
export function PanelFrame({ title, subtitle, actions, className, hideHeader, children }: PropsWithChildren<PanelFrameProps>) {
return (
<section className="panel-frame">
<header className="panel-header">
<div>
<h2>{title}</h2>
{subtitle ? <p>{subtitle}</p> : null}
</div>
{actions ? <div className="panel-actions">{actions}</div> : null}
</header>
<section className={className ? `panel-frame ${className}` : "panel-frame"}>
{!hideHeader ? (
<header className="panel-header">
<div>
<h2>{title}</h2>
{subtitle ? <p>{subtitle}</p> : null}
</div>
{actions ? <div className="panel-actions">{actions}</div> : null}
</header>
) : null}
<div className="panel-body">{children}</div>
</section>
);
+149
View File
@@ -70,6 +70,17 @@ export type UiMode = "assistant" | "decomposition" | "autoruns";
export type AutoRunTarget = "normalizer" | "assistant_stage1" | "assistant_stage2" | "assistant_p0" | "unknown";
export type AutoRunTrend = "up" | "down" | "flat";
export type AutoGenMode = "qwen_seed" | "codex_creative";
export type ManualCaseDecision =
| "covered_ok"
| "covered_but_bad_answer"
| "candidate_for_implementation"
| "needs_routing_extension"
| "out_of_scope_but_answer_softly"
| "unsafe_question_limit_strictly"
| "needs_dialog_policy_fix"
| "needs_capability_registry_update"
| "bad_test_case";
export interface AutoRunDomainCoverage {
domain: string;
@@ -109,6 +120,9 @@ export interface AutoRunCaseSummary {
reply_type: string | null;
session_id: string;
dialog_available: boolean;
commented_count: number;
latest_annotation_at: string | null;
avg_rating: number | null;
checks: Record<string, unknown> | null;
metric_subscores: Record<string, unknown> | null;
}
@@ -158,15 +172,79 @@ export interface AutoRunDetailResponse {
run: AutoRunSummary;
coverage: AutoRunCoverage;
cases: AutoRunCaseSummary[];
annotations_summary?: {
total: number;
};
report: Record<string, unknown>;
}
export interface AutoRunAnnotationRecord {
annotation_id: string;
run_id: string;
case_id: string;
session_id: string;
message_index: number;
rating: number;
comment: string;
manual_case_decision: ManualCaseDecision;
annotation_author: string | null;
created_at: string;
updated_at: string;
context: {
message_id: string | null;
trace_id: string | null;
reply_type: string | null;
eval_target: AutoRunTarget | "unknown";
prompt_version: string | null;
domain: string | null;
query_class: string | null;
};
}
export interface AutoRunAnnotationListItem extends AutoRunAnnotationRecord {
run: AutoRunSummary | null;
case_summary: AutoRunCaseSummary | null;
technical_context: {
report_path: string | null;
trace_id: string | null;
reply_type: string | null;
domain: string | null;
query_class: string | null;
checks: Record<string, unknown> | null;
metric_subscores: Record<string, unknown> | null;
};
}
export interface AutoRunAnnotationsResponse {
ok: boolean;
generated_at: string;
filters_applied: {
run_id: string | null;
case_id: string | null;
min_rating: number | null;
manual_case_decision: ManualCaseDecision | "all";
limit: number;
};
stats: {
total: number;
avg_rating: number | null;
by_decision: Record<string, number>;
};
available_manual_case_decisions: ManualCaseDecision[];
manual_case_decision_schema: Record<string, unknown>;
items: AutoRunAnnotationListItem[];
}
export interface AutoRunDialogMessage {
message_id: string | null;
role: string;
text: string;
created_at: string | null;
trace_id: string | null;
reply_type: string | null;
message_index: number;
commented: boolean;
annotation: AutoRunAnnotationRecord | null;
}
export interface AutoRunDialogResponse {
@@ -178,6 +256,77 @@ export interface AutoRunDialogResponse {
messages: AutoRunDialogMessage[];
decomposition: string[];
assistant_mode: Record<string, unknown> | null;
annotations: AutoRunAnnotationRecord[];
}
export interface AutoRunPostAnalysisQueueItem {
annotation_id: string;
run_id: string;
case_id: string;
message_index: number;
rating: number;
comment: string;
manual_case_decision: ManualCaseDecision;
annotation_author: string | null;
updated_at: string;
domain: string | null;
query_class: string | null;
trace_id: string | null;
reply_type: string | null;
nearest_capability_group: {
group_code: string;
group_title: string;
maturity_status: string;
} | null;
}
export interface AutoRunPostAnalysisResponse {
ok: boolean;
generated_at: string;
filters_applied: {
run_id: string | null;
run_filters_applied: boolean;
limit_per_queue: number;
annotation_limit: number;
scan_limit: number;
};
runs_considered: AutoRunSummary[];
manual_case_decision_schema: Record<string, unknown>;
post_analysis: {
stats: {
annotations_total: number;
by_decision: Record<string, number>;
by_queue: Record<string, number>;
domains_total: number;
};
domain_summary: Array<{ domain: string; total: number }>;
queues: Record<string, AutoRunPostAnalysisQueueItem[]>;
recommended_regression_candidates: AutoRunPostAnalysisQueueItem[];
};
}
export interface AutoGenHistoryRecord {
generation_id: string;
created_at: string;
mode: AutoGenMode;
count: number;
domain: string | null;
questions: string[];
generated_by: string | null;
saved_case_set_file: string | null;
context: {
llm_provider: string | null;
model: string | null;
assistant_prompt_version: string | null;
decomposition_prompt_version: string | null;
prompt_fingerprint: string | null;
} | null;
}
export interface AutoGenHistoryResponse {
ok: boolean;
generated_at: string;
items: AutoGenHistoryRecord[];
}
export type AssistantFallbackType = "none" | "out_of_scope" | "clarification" | "partial" | "unknown";
+387 -108
View File
@@ -1,64 +1,96 @@
@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Space+Grotesk:wght@500;700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Space+Grotesk:wght@500;700&display=swap");
:root {
--bg-main: #060a08;
--bg-soft: #0e1511;
--bg-panel: rgba(15, 24, 19, 0.85);
--bg-panel-accent: rgba(38, 62, 45, 0.45);
--line: rgba(143, 255, 173, 0.3);
--line-strong: rgba(143, 255, 173, 0.72);
--text-main: #f3ffee;
--text-muted: #9bb8a5;
--lime-main: #8fffad;
--lime-press: #59db83;
--danger: #ff7e7e;
--rgb-background: 16, 16, 19;
--rgb-surface-main: 26, 26, 31;
--rgb-surface-horizontal: 32, 32, 38;
--rgb-surface-focus: 40, 40, 47;
--rgb-active: 228, 142, 92;
--rgb-active-text: 18, 18, 18;
--rgb-text-main: 240, 240, 240;
--rgb-text-muted: 166, 166, 170;
--rgb-danger: 255, 126, 126;
--rgb-scrollbar-track: 31, 31, 36;
--rgb-scrollbar-thumb: 74, 74, 82;
--rgb-scrollbar-thumb-hover: 90, 90, 100;
--bg-main: rgb(var(--rgb-background));
--bg-soft: rgb(var(--rgb-surface-main));
--bg-panel: rgb(var(--rgb-surface-main));
--bg-panel-accent: rgb(var(--rgb-surface-horizontal));
--surface-horizontal: rgb(var(--rgb-surface-horizontal));
--surface-focus: rgb(var(--rgb-surface-focus));
--line: transparent;
--line-strong: rgba(var(--rgb-active), 0.48);
--text-main: rgb(var(--rgb-text-main));
--text-muted: rgb(var(--rgb-text-muted));
--lime-main: rgb(var(--rgb-text-main));
--lime-press: rgb(var(--rgb-text-main));
--danger: rgb(var(--rgb-danger));
--radius-lg: 20px;
--radius-md: 14px;
--shadow: 0 16px 44px rgba(0, 0, 0, 0.35);
--shadow: none;
--autoruns-col-width: 360px;
}
* {
box-sizing: border-box;
scrollbar-width: thin;
scrollbar-color: rgb(var(--rgb-scrollbar-thumb)) rgb(var(--rgb-scrollbar-track));
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-track {
background: rgb(var(--rgb-scrollbar-track));
}
*::-webkit-scrollbar-thumb {
background: rgb(var(--rgb-scrollbar-thumb));
border-radius: 999px;
border: 2px solid rgb(var(--rgb-scrollbar-track));
}
*::-webkit-scrollbar-thumb:hover {
background: rgb(var(--rgb-scrollbar-thumb-hover));
}
html,
body,
#root {
margin: 0;
min-height: 100%;
min-height: 100dvh;
font-family: "Manrope", "Segoe UI", sans-serif;
background: radial-gradient(circle at 15% -10%, #1f3b2f 0%, transparent 40%),
radial-gradient(circle at 90% 10%, #1d2f24 0%, transparent 35%),
linear-gradient(165deg, var(--bg-main) 0%, #070d0a 100%);
background: var(--bg-main);
color: var(--text-main);
}
.app-root {
max-width: 1720px;
margin: 0 auto;
padding: 28px 24px 42px;
padding: 12px 16px 16px;
}
.hero {
margin-bottom: 20px;
padding: 20px 22px;
border: 1px solid var(--line);
border-radius: var(--radius-lg);
background: linear-gradient(145deg, rgba(17, 29, 22, 0.94), rgba(10, 16, 13, 0.92));
box-shadow: var(--shadow);
animation: rise 0.5s ease-out;
.app-root.app-root-autoruns {
max-width: none;
width: 100%;
min-height: 100dvh;
max-height: 100dvh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.hero h1 {
font-family: "Space Grotesk", "Manrope", sans-serif;
margin: 0 0 8px;
font-size: clamp(1.5rem, 3vw, 2.3rem);
letter-spacing: 0.04em;
}
.hero p {
margin: 0;
color: var(--text-muted);
.app-topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin: 0 0 12px;
padding: 0;
min-height: 38px;
}
.layout-grid {
@@ -67,20 +99,35 @@ body,
gap: 16px;
}
.layout-grid.layout-grid-autoruns {
min-height: 0;
flex: 1 1 auto;
grid-template-columns: minmax(0, 1fr);
}
.mode-switch-row {
display: flex;
gap: 8px;
margin: 0 0 14px;
margin: 0;
padding: 0;
}
.mode-switch-row.mode-switch-row-right {
margin-left: auto;
justify-content: flex-end;
}
.panel-frame {
grid-column: span 12;
border: 1px solid var(--line);
border: none;
border-radius: var(--radius-lg);
background: linear-gradient(165deg, var(--bg-panel), rgba(10, 17, 13, 0.88));
background: var(--bg-panel);
overflow: hidden;
box-shadow: var(--shadow);
box-shadow: none;
animation: rise 0.4s ease-out;
display: flex;
flex-direction: column;
min-height: 0;
}
.panel-header {
@@ -89,8 +136,8 @@ body,
justify-content: space-between;
gap: 14px;
padding: 14px 18px 10px;
border-bottom: 1px solid var(--line);
background: linear-gradient(90deg, var(--bg-panel-accent), transparent 70%);
border-bottom: none;
background: var(--bg-panel-accent);
}
.panel-header h2 {
@@ -106,15 +153,31 @@ body,
}
.panel-body {
padding: 14px 18px 18px;
padding: 10px 12px 12px;
min-height: 0;
}
.app-root-autoruns .autoruns-frame {
height: 100%;
}
.app-root-autoruns .autoruns-frame .panel-body {
flex: 1 1 auto;
overflow: hidden;
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 12px 12px;
background: rgb(var(--rgb-background));
}
.status-chip {
border: 1px solid var(--line);
border: none;
border-radius: 999px;
padding: 4px 10px;
color: var(--lime-main);
font-size: 0.78rem;
background: rgb(var(--rgb-surface-focus));
}
.assistant-panel-actions {
@@ -127,14 +190,14 @@ body,
.assistant-copy-btn {
background: transparent;
border-color: var(--line);
border-color: transparent;
color: var(--text-main);
box-shadow: none;
transform: none;
}
.assistant-copy-btn:hover {
background: rgba(143, 255, 173, 0.14);
background: rgb(var(--rgb-surface-focus));
filter: none;
box-shadow: none;
transform: none;
@@ -171,20 +234,22 @@ label {
input,
select,
textarea {
border: 1px solid rgba(170, 255, 194, 0.26);
border: none;
border-radius: var(--radius-md);
background: rgba(7, 13, 10, 0.92);
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
padding: 10px 12px;
outline: none;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
transition: background-color 0.18s ease;
}
input:focus,
select:focus,
textarea:focus {
border-color: var(--line-strong);
box-shadow: 0 0 0 3px rgba(143, 255, 173, 0.2);
border-color: transparent;
box-shadow: none;
outline: none;
background: rgb(var(--rgb-surface-focus));
}
textarea {
@@ -193,28 +258,28 @@ textarea {
}
button {
border: 1px solid rgba(176, 255, 199, 0.35);
border: none;
border-radius: 999px;
background: linear-gradient(180deg, #8fffad 0%, #62e286 100%);
color: #08100a;
background: rgb(var(--rgb-surface-horizontal));
color: rgb(var(--rgb-text-main));
font-weight: 700;
font-size: 0.83rem;
letter-spacing: 0.02em;
cursor: pointer;
padding: 9px 14px;
transition: transform 0.16s ease, filter 0.2s ease, box-shadow 0.18s ease;
transition: background 0.2s ease, color 0.2s ease;
outline: none;
box-shadow: none;
}
button:hover {
filter: brightness(1.04);
transform: translateY(-1px);
box-shadow: 0 8px 20px rgba(127, 255, 170, 0.32);
border-color: transparent;
background: rgb(var(--rgb-surface-focus));
}
button:disabled {
opacity: 0.5;
opacity: 0.52;
cursor: not-allowed;
transform: none;
}
.button-row {
@@ -250,14 +315,15 @@ button:disabled {
}
.tab {
background: transparent;
background: rgb(var(--rgb-surface-main));
color: var(--text-main);
border: 1px solid var(--line);
border: none;
}
.tab.active {
border-color: var(--line-strong);
background: linear-gradient(180deg, rgba(143, 255, 173, 0.25), rgba(143, 255, 173, 0.1));
border-color: transparent;
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
}
.assistant-chat-list {
@@ -266,9 +332,9 @@ button:disabled {
display: grid;
gap: 10px;
padding: 4px;
border: 1px solid rgba(156, 255, 189, 0.2);
border: none;
border-radius: var(--radius-md);
background: rgba(6, 10, 8, 0.65);
background: rgb(var(--rgb-surface-horizontal));
}
.assistant-empty {
@@ -277,19 +343,19 @@ button:disabled {
}
.assistant-msg {
border: 1px solid rgba(157, 255, 190, 0.2);
border: none;
border-radius: 12px;
background: rgba(11, 18, 14, 0.74);
background: rgb(var(--rgb-surface-main));
padding: 10px;
}
.assistant-msg.user {
border-color: rgba(110, 198, 255, 0.38);
background: rgba(13, 20, 24, 0.76);
border-color: transparent;
background: rgb(var(--rgb-surface-focus));
}
.assistant-msg.assistant {
border-color: rgba(157, 255, 190, 0.25);
border-color: transparent;
}
.assistant-msg-head {
@@ -335,11 +401,11 @@ button:disabled {
min-height: 180px;
max-height: 420px;
overflow: auto;
background: #050806;
border: 1px solid rgba(156, 255, 189, 0.2);
background: rgb(var(--rgb-surface-horizontal));
border: none;
border-radius: var(--radius-md);
padding: 12px;
color: #d6ffdf;
color: rgb(var(--rgb-text-main));
font-family: "JetBrains Mono", "Consolas", monospace;
font-size: 0.78rem;
line-height: 1.45;
@@ -352,8 +418,8 @@ button:disabled {
}
.metrics-grid div {
background: rgba(11, 18, 14, 0.7);
border: 1px solid rgba(157, 255, 190, 0.24);
background: rgba(var(--rgb-surface-main), 0.8);
border: none;
border-radius: 12px;
padding: 10px;
display: flex;
@@ -382,8 +448,8 @@ button:disabled {
width: 100%;
text-align: left;
border-radius: 12px;
border: 1px solid rgba(157, 255, 190, 0.24);
background: rgba(11, 18, 14, 0.78);
border: none;
background: rgb(var(--rgb-surface-main));
color: var(--text-main);
padding: 10px;
}
@@ -455,16 +521,32 @@ button:disabled {
}
.autoruns-columns {
display: grid;
display: flex;
gap: 12px;
width: 100%;
min-height: 0;
flex: 1 1 auto;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 4px;
}
.autoruns-col {
border: 1px solid rgba(157, 255, 190, 0.2);
flex: 0 0 var(--autoruns-col-width);
width: var(--autoruns-col-width);
height: 100%;
min-height: 0;
overflow: auto;
border: none;
border-radius: 14px;
background: rgba(8, 13, 10, 0.72);
background: rgb(var(--rgb-surface-main));
padding: 12px;
min-height: 220px;
scrollbar-gutter: stable;
}
.autoruns-col:nth-child(3) {
flex-basis: 440px;
width: 440px;
}
.autoruns-col h3 {
@@ -493,9 +575,9 @@ button:disabled {
display: flex;
justify-content: space-between;
gap: 8px;
border: 1px solid rgba(157, 255, 190, 0.14);
border: none;
border-radius: 10px;
background: rgba(10, 18, 13, 0.65);
background: rgb(var(--rgb-surface-horizontal));
padding: 8px 9px;
font-size: 0.79rem;
}
@@ -506,7 +588,7 @@ button:disabled {
.autoruns-prompt-details summary {
cursor: pointer;
color: var(--lime-main);
color: var(--text-main);
font-size: 0.8rem;
margin-bottom: 8px;
}
@@ -523,9 +605,9 @@ button:disabled {
}
.autoruns-stats-grid > div {
border: 1px solid rgba(157, 255, 190, 0.2);
border: none;
border-radius: 10px;
background: rgba(10, 18, 13, 0.7);
background: rgb(var(--rgb-surface-horizontal));
padding: 8px;
display: grid;
gap: 3px;
@@ -544,7 +626,9 @@ button:disabled {
.autoruns-run-list {
display: grid;
gap: 8px;
max-height: 760px;
max-height: none;
min-height: 0;
flex: 1 1 auto;
overflow: auto;
padding-right: 2px;
}
@@ -553,8 +637,8 @@ button:disabled {
width: 100%;
text-align: left;
border-radius: 12px;
border: 1px solid rgba(157, 255, 190, 0.23);
background: rgba(11, 18, 14, 0.75);
border: none;
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
padding: 10px;
display: grid;
@@ -589,7 +673,7 @@ button:disabled {
margin-top: 8px;
display: grid;
gap: 6px;
max-height: 170px;
max-height: 180px;
overflow: auto;
}
@@ -597,8 +681,8 @@ button:disabled {
width: 100%;
text-align: left;
border-radius: 10px;
border: 1px solid rgba(157, 255, 190, 0.22);
background: rgba(9, 14, 11, 0.72);
border: none;
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
padding: 7px 8px;
display: flex;
@@ -613,20 +697,22 @@ button:disabled {
.autoruns-dialog-view {
margin-top: 10px;
border: 1px solid rgba(157, 255, 190, 0.2);
border: none;
border-radius: 12px;
background: rgba(5, 8, 6, 0.7);
background: rgb(var(--rgb-surface-horizontal));
padding: 10px;
max-height: 570px;
max-height: none;
min-height: 0;
flex: 1 1 auto;
overflow: auto;
display: grid;
gap: 8px;
}
.autoruns-msg {
border: 1px solid rgba(157, 255, 190, 0.22);
border: none;
border-radius: 12px;
background: rgba(11, 18, 14, 0.8);
background: rgb(var(--rgb-surface-focus));
padding: 8px 10px;
display: grid;
gap: 6px;
@@ -641,6 +727,12 @@ button:disabled {
color: var(--text-muted);
}
.autoruns-msg-head-actions {
display: flex;
align-items: center;
gap: 8px;
}
.autoruns-msg p {
margin: 0;
white-space: pre-wrap;
@@ -648,14 +740,122 @@ button:disabled {
font-size: 0.84rem;
}
.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;
line-height: 1;
box-shadow: none;
transform: none;
}
.autoruns-comment-icon:hover {
border-color: var(--line-strong);
box-shadow: none;
transform: none;
}
.autoruns-comment-icon.commented {
border-color: var(--line-strong);
color: var(--lime-main);
background: rgb(var(--rgb-active));
color: rgb(var(--rgb-active-text));
}
.autoruns-msg-annotation {
display: grid;
gap: 4px;
border: none;
border-radius: 10px;
background: rgb(var(--rgb-surface-horizontal));
padding: 7px 8px;
font-size: 0.78rem;
}
.autoruns-comments-list {
display: grid;
gap: 8px;
max-height: none;
min-height: 0;
flex: 1 1 auto;
overflow: auto;
padding-right: 2px;
}
.autoruns-autogen-list {
display: grid;
gap: 8px;
max-height: none;
min-height: 0;
overflow: auto;
padding-right: 2px;
}
.autoruns-autogen-item {
border: none;
border-radius: 10px;
background: rgb(var(--rgb-surface-horizontal));
padding: 8px;
display: grid;
gap: 5px;
}
.autoruns-autogen-item header {
display: flex;
justify-content: space-between;
gap: 8px;
font-size: 0.76rem;
}
.autoruns-autogen-item p {
margin: 0;
color: var(--text-muted);
white-space: pre-wrap;
font-size: 0.8rem;
}
.autoruns-comment-item {
width: 100%;
text-align: left;
border-radius: 12px;
border: none;
background: rgb(var(--rgb-surface-horizontal));
color: var(--text-main);
padding: 9px;
display: grid;
gap: 6px;
}
.autoruns-comment-item p {
margin: 0;
white-space: pre-wrap;
color: var(--text-muted);
font-size: 0.79rem;
}
.autoruns-comment-item.selected {
border-color: var(--line-strong);
}
.autoruns-comment-head {
display: flex;
justify-content: space-between;
gap: 8px;
font-size: 0.75rem;
}
.autoruns-msg.assistant {
margin-right: 12%;
}
.autoruns-msg.user {
margin-left: 12%;
border-color: rgba(95, 179, 255, 0.35);
background: rgba(10, 18, 24, 0.75);
border-color: transparent;
background: rgb(var(--rgb-surface-focus));
}
.autoruns-decomposition-list {
@@ -666,15 +866,83 @@ button:disabled {
font-size: 0.8rem;
}
.autoruns-comment-modal-backdrop {
position: fixed;
inset: 0;
background: rgba(var(--rgb-background), 0.74);
display: grid;
place-items: center;
z-index: 1800;
padding: 12px;
}
.autoruns-comment-modal {
width: min(660px, 100%);
border: none;
border-radius: 16px;
background: rgb(var(--rgb-surface-horizontal));
box-shadow: var(--shadow);
padding: 14px;
display: grid;
gap: 10px;
}
.autoruns-comment-modal h3 {
margin: 0;
font-size: 0.95rem;
}
.autoruns-comment-quote {
margin: 0;
border: none;
border-radius: 10px;
background: rgb(var(--rgb-surface-focus));
padding: 8px;
white-space: pre-wrap;
max-height: 150px;
overflow: auto;
font-size: 0.82rem;
}
.autoruns-rating-row {
display: flex;
gap: 8px;
}
.autoruns-rating-dot {
width: 34px;
height: 34px;
border-radius: 999px;
padding: 0;
border: none;
background: rgb(var(--rgb-surface-focus));
color: var(--text-muted);
font-size: 0.95rem;
box-shadow: none;
transform: none;
}
.autoruns-rating-dot:hover {
border-color: var(--line-strong);
box-shadow: none;
transform: none;
}
.autoruns-rating-dot.active {
border-color: var(--line-strong);
color: rgb(var(--rgb-active-text));
background: rgb(var(--rgb-active));
}
.autoruns-coverage-list {
display: grid;
gap: 8px;
}
.autoruns-coverage-item {
border: 1px solid rgba(157, 255, 190, 0.2);
border: none;
border-radius: 10px;
background: rgba(11, 18, 14, 0.68);
background: rgb(var(--rgb-surface-horizontal));
padding: 8px;
}
@@ -693,27 +961,31 @@ button:disabled {
.autoruns-coverage-bar {
height: 7px;
border-radius: 999px;
background: rgba(157, 255, 190, 0.14);
background: rgb(var(--rgb-surface-focus));
overflow: hidden;
}
.autoruns-coverage-bar > div {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, #6ee0ff, #8fffad);
background: rgb(var(--rgb-active));
}
@media (max-width: 1200px) {
.metrics-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
:root {
--autoruns-col-width: 340px;
}
.autoruns-columns {
grid-template-columns: 1fr !important;
.metrics-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 920px) {
:root {
--autoruns-col-width: 320px;
}
.grid-two,
.runtime-grid {
grid-template-columns: 1fr;
@@ -731,6 +1003,10 @@ button:disabled {
}
@media (max-width: 640px) {
:root {
--autoruns-col-width: 300px;
}
.app-root {
padding: 18px 12px 24px;
}
@@ -750,3 +1026,6 @@ button:disabled {
transform: translateY(0);
}
}