feat(tasks): add skill-templated task graph execution
This commit is contained in:
@ -46,6 +46,48 @@ function timestampLabel(value?: string | null): string {
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
const latencyOrder = [
|
||||
'total_ms',
|
||||
'router_ms',
|
||||
'mcp_ms',
|
||||
'skill_assembly_ms',
|
||||
'tool_assembly_ms',
|
||||
'context_build_ms',
|
||||
'llm_ms',
|
||||
'tool_ms',
|
||||
'session_write_ms',
|
||||
];
|
||||
|
||||
function latencyLabel(key: string, locale: string): string {
|
||||
const labels: Record<string, [string, string]> = {
|
||||
total_ms: ['总耗时', 'total'],
|
||||
router_ms: ['路由', 'router'],
|
||||
mcp_ms: ['MCP', 'MCP'],
|
||||
skill_assembly_ms: ['技能', 'skills'],
|
||||
tool_assembly_ms: ['工具选择', 'tool select'],
|
||||
context_build_ms: ['上下文', 'context'],
|
||||
llm_ms: ['模型', 'LLM'],
|
||||
tool_ms: ['工具执行', 'tools'],
|
||||
session_write_ms: ['写日志', 'writes'],
|
||||
};
|
||||
const label = labels[key];
|
||||
if (!label) return key.replace(/_ms$/, '');
|
||||
return pickAppText(locale, label[0], label[1]);
|
||||
}
|
||||
|
||||
function formatLatencyMs(value: unknown): string | null {
|
||||
if (typeof value !== 'number' || !Number.isFinite(value)) return null;
|
||||
if (value >= 1000) return `${(value / 1000).toFixed(value >= 10000 ? 1 : 2)}s`;
|
||||
return `${Math.round(value)}ms`;
|
||||
}
|
||||
|
||||
function latencyEntries(latency?: Record<string, number>) {
|
||||
if (!latency) return [];
|
||||
return latencyOrder
|
||||
.map((key) => [key, formatLatencyMs(latency[key])] as const)
|
||||
.filter((entry): entry is readonly [string, string] => Boolean(entry[1]));
|
||||
}
|
||||
|
||||
export default function LogsPage() {
|
||||
const { locale } = useAppI18n();
|
||||
const [sessions, setSessions] = useState<ChatLogSession[]>([]);
|
||||
@ -142,6 +184,7 @@ export default function LogsPage() {
|
||||
<div className="space-y-3">
|
||||
{runs.map((run) => {
|
||||
const expanded = expandedRuns.has(run.run_id);
|
||||
const latencies = latencyEntries(run.latency_ms);
|
||||
return (
|
||||
<Card key={`${run.session_id}:${run.run_id}`} className="overflow-hidden">
|
||||
<button
|
||||
@ -164,6 +207,15 @@ export default function LogsPage() {
|
||||
<span className="block truncate text-xs text-muted-foreground">
|
||||
{run.sessionTitle} · {run.run_id}
|
||||
</span>
|
||||
{latencies.length ? (
|
||||
<span className="flex flex-wrap gap-1.5">
|
||||
{latencies.map(([key, value]) => (
|
||||
<Badge key={key} variant={key === 'total_ms' ? 'default' : 'outline'} className="font-mono text-[11px]">
|
||||
{latencyLabel(key, locale)} {value}
|
||||
</Badge>
|
||||
))}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
<ChevronDown className={`mt-1 h-4 w-4 shrink-0 text-muted-foreground transition-transform ${expanded ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user