mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-30 05:16:52 +08:00
feat(agent): add task-oriented run logs and execution details
This commit is contained in:
@@ -27,6 +27,7 @@ import PipelineDetailContent from '@/app/home/pipelines/PipelineDetailContent';
|
||||
import PluginProcessorDetailContent from './PluginProcessorDetailContent';
|
||||
import AgentCreateContent from './components/AgentCreateContent';
|
||||
import AgentDebugPanel from './components/AgentDebugPanel';
|
||||
import AgentMonitoringTab from './components/AgentMonitoringTab';
|
||||
import AgentFormComponent, {
|
||||
AgentFormHandle,
|
||||
RunnerStatus,
|
||||
@@ -281,6 +282,21 @@ export default function AgentDetailContent({
|
||||
) : undefined
|
||||
}
|
||||
unsavedLabel={t('pipelines.unsavedChanges')}
|
||||
monitoring={
|
||||
currentWorkspace?.permissions.includes('resource.view')
|
||||
? {
|
||||
label: t('pipelines.monitoring.title'),
|
||||
workbenchLabel: t('pipelines.monitoring.workbench'),
|
||||
content: (
|
||||
<AgentMonitoringTab
|
||||
key={id}
|
||||
agentId={id}
|
||||
platformTools={platformTools}
|
||||
/>
|
||||
),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<EntityBasicInfoDialog
|
||||
|
||||
@@ -0,0 +1,549 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Brain, ChevronRight, RefreshCw, Wrench } from 'lucide-react';
|
||||
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||
import type {
|
||||
AgentPlatformTool,
|
||||
ProcessorRun,
|
||||
ProcessorRunEvent,
|
||||
} from '@/app/infra/entities/api';
|
||||
import { extractI18nObject } from '@/i18n/I18nProvider';
|
||||
import { eventPatternLabel } from '@/app/home/components/event-patterns/event-pattern-groups';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleTrigger,
|
||||
CollapsibleContent,
|
||||
} from '@/components/ui/collapsible';
|
||||
import { executionSteps } from './debug-execution';
|
||||
import { ProcessorPayload } from './PluginProcessorTrace';
|
||||
import {
|
||||
formatRunDuration,
|
||||
processorRunDuration,
|
||||
} from './processor-run-timing';
|
||||
|
||||
const activeStatuses = new Set([
|
||||
'created',
|
||||
'pending',
|
||||
'queued',
|
||||
'claimed',
|
||||
'running',
|
||||
'waiting',
|
||||
]);
|
||||
const failedStatuses = new Set(['failed', 'timeout']);
|
||||
const json = (value: unknown) =>
|
||||
typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
||||
const textClass =
|
||||
'whitespace-pre-wrap break-words [overflow-wrap:anywhere] text-sm';
|
||||
|
||||
export default function AgentMonitoringTab({
|
||||
agentId,
|
||||
platformTools,
|
||||
}: {
|
||||
agentId: string;
|
||||
platformTools: AgentPlatformTool[];
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [runs, setRuns] = useState<ProcessorRun[]>([]);
|
||||
const [total, setTotal] = useState<number>();
|
||||
const [cursor, setCursor] = useState<number | null>(null);
|
||||
const [selectedId, setSelectedId] = useState<string>();
|
||||
const [selected, setSelected] = useState<ProcessorRun>();
|
||||
const [events, setEvents] = useState<ProcessorRunEvent[]>([]);
|
||||
const [eventCursor, setEventCursor] = useState<number | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [loadingTrace, setLoadingTrace] = useState(false);
|
||||
const [listError, setListError] = useState(false);
|
||||
const [traceError, setTraceError] = useState(false);
|
||||
const [paging, setPaging] = useState(false);
|
||||
const [traceRevision, setTraceRevision] = useState(0);
|
||||
const generation = useRef(0);
|
||||
const listBusy = useRef(false);
|
||||
const listInitialized = useRef(false);
|
||||
const traceBusy = useRef(false);
|
||||
const alive = useRef(true);
|
||||
useEffect(() => {
|
||||
alive.current = true;
|
||||
return () => {
|
||||
alive.current = false;
|
||||
generation.current += 1;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
if (listBusy.current) return;
|
||||
listBusy.current = true;
|
||||
try {
|
||||
const page = await httpClient.getProcessorRuns(agentId);
|
||||
if (!alive.current) return;
|
||||
setRuns((current) => {
|
||||
const merged = new Map(page.items.map((run) => [run.run_id, run]));
|
||||
current.forEach((run) => {
|
||||
if (!merged.has(run.run_id)) merged.set(run.run_id, run);
|
||||
});
|
||||
return [...merged.values()];
|
||||
});
|
||||
if (!listInitialized.current) {
|
||||
setCursor(page.has_more ? page.next_cursor : null);
|
||||
listInitialized.current = true;
|
||||
}
|
||||
setTotal(page.total);
|
||||
setSelectedId((current) => current ?? page.items[0]?.run_id);
|
||||
setListError(false);
|
||||
} catch {
|
||||
if (alive.current) setListError(true);
|
||||
} finally {
|
||||
listBusy.current = false;
|
||||
if (alive.current) setLoading(false);
|
||||
}
|
||||
}, [agentId]);
|
||||
|
||||
useEffect(() => {
|
||||
void refresh();
|
||||
const timer = window.setInterval(() => {
|
||||
if (!document.hidden) void refresh();
|
||||
}, 5000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [refresh]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedId) return;
|
||||
const version = ++generation.current;
|
||||
setEvents([]);
|
||||
setSelected(undefined);
|
||||
setEventCursor(null);
|
||||
setLoadingTrace(true);
|
||||
setPaging(false);
|
||||
setTraceError(false);
|
||||
traceBusy.current = false;
|
||||
void httpClient
|
||||
.getProcessorRunEvents(agentId, selectedId)
|
||||
.then((page) => {
|
||||
if (generation.current !== version) return;
|
||||
setSelected(page.run);
|
||||
setEvents(page.items);
|
||||
setEventCursor(page.has_more ? page.next_cursor : null);
|
||||
})
|
||||
.catch(() => {
|
||||
if (generation.current === version) setTraceError(true);
|
||||
})
|
||||
.finally(() => {
|
||||
if (generation.current === version) setLoadingTrace(false);
|
||||
});
|
||||
return () => {
|
||||
generation.current += 1;
|
||||
};
|
||||
}, [agentId, selectedId, traceRevision]);
|
||||
|
||||
const nextEvents = useCallback(async () => {
|
||||
if (!selectedId || traceBusy.current || loadingTrace) return;
|
||||
const version = generation.current;
|
||||
traceBusy.current = true;
|
||||
setPaging(true);
|
||||
try {
|
||||
const page = await httpClient.getProcessorRunEvents(
|
||||
agentId,
|
||||
selectedId,
|
||||
eventCursor ?? events.at(-1)?.sequence,
|
||||
);
|
||||
if (generation.current !== version) return;
|
||||
setSelected(page.run);
|
||||
setEvents((current) => [
|
||||
...new Map(
|
||||
[...current, ...page.items].map((event) => [event.sequence, event]),
|
||||
).values(),
|
||||
]);
|
||||
setEventCursor(page.has_more ? page.next_cursor : null);
|
||||
setTraceError(false);
|
||||
} catch {
|
||||
if (generation.current === version) setTraceError(true);
|
||||
} finally {
|
||||
if (generation.current === version) {
|
||||
traceBusy.current = false;
|
||||
setPaging(false);
|
||||
}
|
||||
}
|
||||
}, [agentId, selectedId, eventCursor, events, loadingTrace]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!selected ||
|
||||
!activeStatuses.has(selected.status) ||
|
||||
eventCursor !== null
|
||||
)
|
||||
return;
|
||||
const timer = window.setInterval(() => {
|
||||
if (!document.hidden) void nextEvents();
|
||||
}, 3000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [selected, eventCursor, nextEvents]);
|
||||
|
||||
async function moreRuns() {
|
||||
if (cursor === null || listBusy.current) return;
|
||||
listBusy.current = true;
|
||||
setLoading(true);
|
||||
try {
|
||||
const page = await httpClient.getProcessorRuns(agentId, cursor);
|
||||
if (!alive.current) return;
|
||||
setRuns((current) => [
|
||||
...new Map(
|
||||
[...current, ...page.items].map((run) => [run.run_id, run]),
|
||||
).values(),
|
||||
]);
|
||||
setCursor(page.has_more ? page.next_cursor : null);
|
||||
setListError(false);
|
||||
} catch {
|
||||
if (alive.current) setListError(true);
|
||||
} finally {
|
||||
listBusy.current = false;
|
||||
if (alive.current) setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const labels = Object.fromEntries(
|
||||
platformTools.map((tool) => [tool.name, extractI18nObject(tool.label)]),
|
||||
);
|
||||
const steps = executionSteps(events);
|
||||
const duration = selected ? processorRunDuration(selected) : null;
|
||||
const failureReason =
|
||||
selected?.status_reason ||
|
||||
events.findLast((event) => event.type === 'run.failed')?.data.error;
|
||||
const models = [
|
||||
...new Set(
|
||||
events.flatMap((event) => {
|
||||
const message = event.data.message ?? event.data.chunk;
|
||||
return message &&
|
||||
typeof message === 'object' &&
|
||||
'model' in message &&
|
||||
typeof message.model === 'string' &&
|
||||
message.model
|
||||
? [message.model]
|
||||
: [];
|
||||
}),
|
||||
),
|
||||
];
|
||||
const stateLabel = (run: ProcessorRun) =>
|
||||
t(
|
||||
`agents.eventProcessor.status_${({ created: 'pending', claimed: 'queued' } as Record<string, string>)[run.status] ?? run.status}`,
|
||||
{
|
||||
defaultValue: run.status,
|
||||
},
|
||||
);
|
||||
const debugRun = (run: ProcessorRun) =>
|
||||
run.binding_id?.startsWith('debug:') || run.metadata.source === 'webui';
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex min-h-0 flex-1 flex-col gap-4"
|
||||
data-testid="agent-monitoring"
|
||||
>
|
||||
<div className="flex shrink-0 items-center justify-between gap-3">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('agents.monitoring.description')}
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
void refresh();
|
||||
setTraceRevision((value) => value + 1);
|
||||
}}
|
||||
>
|
||||
<RefreshCw className="size-4" />
|
||||
{t('monitoring.refreshData')}
|
||||
</Button>
|
||||
</div>
|
||||
{listError && (
|
||||
<Alert variant="destructive">
|
||||
<AlertDescription>{t('monitoring.loadError')}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<div className="grid min-h-0 flex-1 gap-4 lg:grid-cols-[minmax(16rem,0.8fr)_minmax(0,2fr)]">
|
||||
<section
|
||||
className="flex min-h-0 min-w-0 flex-col gap-2"
|
||||
aria-label={t('agents.eventProcessor.runs')}
|
||||
>
|
||||
<p className="text-sm font-medium">
|
||||
{t('agents.eventProcessor.runs')}
|
||||
{total !== undefined && (
|
||||
<span className="ml-2 text-muted-foreground">{total}</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="max-h-72 min-h-0 overflow-y-auto rounded-md border lg:max-h-none lg:flex-1">
|
||||
{runs.map((run) => (
|
||||
<Button
|
||||
key={run.run_id}
|
||||
variant="ghost"
|
||||
aria-pressed={selectedId === run.run_id}
|
||||
onClick={() => setSelectedId(run.run_id)}
|
||||
className="h-auto w-full flex-col items-stretch gap-2 rounded-none border-b p-3 text-left font-normal last:border-b-0 aria-pressed:bg-accent"
|
||||
>
|
||||
<span className="flex items-center justify-between gap-2">
|
||||
<span className="truncate font-medium">
|
||||
{eventPatternLabel(run.metadata.event_type ?? '', t)}
|
||||
</span>
|
||||
<Badge
|
||||
variant={
|
||||
failedStatuses.has(run.status) ? 'destructive' : 'outline'
|
||||
}
|
||||
>
|
||||
{stateLabel(run)}
|
||||
</Badge>
|
||||
</span>
|
||||
{run.metadata.input?.text && (
|
||||
<span className="truncate text-sm">
|
||||
{run.metadata.input.text}
|
||||
</span>
|
||||
)}
|
||||
<span className="flex items-center justify-between gap-2 text-xs text-muted-foreground">
|
||||
<time>
|
||||
{new Date(run.created_at * 1000).toLocaleString()}
|
||||
</time>
|
||||
{debugRun(run) && (
|
||||
<Badge variant="secondary">{t('agents.debugTab')}</Badge>
|
||||
)}
|
||||
{processorRunDuration(run) !== null && (
|
||||
<span>{formatRunDuration(processorRunDuration(run)!)}</span>
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
))}
|
||||
{!runs.length && (
|
||||
<p className="p-4 text-sm text-muted-foreground">
|
||||
{loading ? t('common.loading') : t('agents.monitoring.empty')}
|
||||
</p>
|
||||
)}
|
||||
{cursor !== null && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="w-full"
|
||||
disabled={loading}
|
||||
onClick={() => void moreRuns()}
|
||||
>
|
||||
{t('agents.eventProcessor.loadMore')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
aria-label={t('agents.monitoring.execution')}
|
||||
className="min-h-0 min-w-0 space-y-4 overflow-y-auto lg:pr-2"
|
||||
>
|
||||
{loadingTrace ? (
|
||||
<p role="status">{t('common.loading')}</p>
|
||||
) : (
|
||||
selected && (
|
||||
<>
|
||||
<div className="space-y-2 border-b pb-3">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="font-medium">
|
||||
{eventPatternLabel(selected.metadata.event_type ?? '', t)}
|
||||
</h2>
|
||||
<Badge
|
||||
variant={
|
||||
failedStatuses.has(selected.status)
|
||||
? 'destructive'
|
||||
: 'outline'
|
||||
}
|
||||
>
|
||||
{stateLabel(selected)}
|
||||
</Badge>
|
||||
{debugRun(selected) && (
|
||||
<Badge variant="secondary">{t('agents.debugTab')}</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
|
||||
<time>
|
||||
{new Date(selected.created_at * 1000).toLocaleString()}
|
||||
</time>
|
||||
{duration !== null && (
|
||||
<span>
|
||||
{t('monitoring.llmCalls.duration')}:{' '}
|
||||
{formatRunDuration(duration)}
|
||||
</span>
|
||||
)}
|
||||
{models.length > 0 && <span>{models.join(', ')}</span>}
|
||||
{selected.usage?.total_tokens != null && (
|
||||
<span>
|
||||
{t('monitoring.llmCalls.totalTokens')}:{' '}
|
||||
{selected.usage.total_tokens.toLocaleString()}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="break-all text-xs text-muted-foreground">
|
||||
{selected.runner_id}
|
||||
</p>
|
||||
</div>
|
||||
{failedStatuses.has(selected.status) && failureReason && (
|
||||
<Alert variant="destructive">
|
||||
<AlertDescription className={textClass}>
|
||||
{json(failureReason)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<Card className="gap-2 py-3">
|
||||
<CardHeader className="px-3">
|
||||
<CardTitle className="text-sm">
|
||||
{t('agents.monitoring.input')}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 px-3">
|
||||
{selected.metadata.input?.text && (
|
||||
<p className={textClass}>
|
||||
{selected.metadata.input.text}
|
||||
</p>
|
||||
)}
|
||||
{(selected.metadata.input ??
|
||||
selected.metadata.input_event) != null ? (
|
||||
<ProcessorPayload
|
||||
title={t('agents.monitoring.eventData')}
|
||||
value={
|
||||
selected.metadata.input_event
|
||||
? {
|
||||
...selected.metadata.input,
|
||||
event: selected.metadata.input_event,
|
||||
}
|
||||
: selected.metadata.input
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('agents.monitoring.inputUnavailable')}
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<h3 className="text-sm font-medium">
|
||||
{t('agents.monitoring.execution')}
|
||||
</h3>
|
||||
{steps.map((step, index) => (
|
||||
<Card key={index} className="gap-2 py-3">
|
||||
<CardHeader className="px-3">
|
||||
<CardTitle className="flex min-w-0 items-center gap-2 text-sm">
|
||||
{step.kind === 'tool' ? (
|
||||
<>
|
||||
<Wrench className="size-4 shrink-0" />
|
||||
<span className="break-all">
|
||||
{labels[step.name] || step.name}
|
||||
</span>
|
||||
<Badge
|
||||
variant={
|
||||
step.status === 'failed'
|
||||
? 'destructive'
|
||||
: 'outline'
|
||||
}
|
||||
>
|
||||
{t(
|
||||
`agents.debugTool${step.status === 'running' ? (activeStatuses.has(selected.status) || eventCursor !== null ? 'Running' : 'Interrupted') : step.result && typeof step.result === 'object' && 'mock' in step.result && step.result.mock === true ? (step.status === 'failed' ? 'MockFailed' : 'Simulated') : step.status === 'failed' ? 'Failed' : 'Completed'}`,
|
||||
)}
|
||||
</Badge>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Brain className="size-4" />
|
||||
{t('agents.debugTextOutput')}
|
||||
</>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 px-3">
|
||||
{step.kind === 'message' ? (
|
||||
<>
|
||||
{step.text && (
|
||||
<p className={textClass}>{step.text}</p>
|
||||
)}
|
||||
{step.reasoning && (
|
||||
<ProcessorPayload
|
||||
title={t('agents.debugReasoning')}
|
||||
value={step.reasoning}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{step.error && (
|
||||
<p className={`${textClass} text-destructive`}>
|
||||
{step.error}
|
||||
</p>
|
||||
)}
|
||||
<ProcessorPayload
|
||||
title={t('agents.debugToolArguments')}
|
||||
value={step.parameters}
|
||||
/>
|
||||
{step.result !== undefined && (
|
||||
<ProcessorPayload
|
||||
title={t('agents.debugToolResult')}
|
||||
value={step.result}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
{events
|
||||
.filter((event) => event.type === 'processor.log')
|
||||
.map((event) => (
|
||||
<Alert
|
||||
key={event.sequence}
|
||||
variant={
|
||||
event.data.level === 'error' ? 'destructive' : 'default'
|
||||
}
|
||||
>
|
||||
<AlertDescription className={textClass}>
|
||||
{String(event.data.text ?? '')}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
))}
|
||||
{eventCursor !== null && (
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={paging}
|
||||
onClick={() => void nextEvents()}
|
||||
>
|
||||
{t('agents.eventProcessor.loadMore')}
|
||||
</Button>
|
||||
)}
|
||||
<Collapsible>
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button variant="ghost" className="group">
|
||||
<ChevronRight className="size-4 group-data-[state=open]:rotate-90" />
|
||||
{t('agents.monitoring.rawEvents')}
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<pre
|
||||
className={`${textClass} rounded-md bg-muted p-3 font-mono text-xs`}
|
||||
>
|
||||
{json({
|
||||
run_id: selected.run_id,
|
||||
usage: selected.usage,
|
||||
events,
|
||||
})}
|
||||
</pre>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
{traceError && (
|
||||
<Alert variant="destructive">
|
||||
<AlertDescription>
|
||||
{t('monitoring.loadError')}
|
||||
<Button
|
||||
variant="link"
|
||||
onClick={() => setTraceRevision((value) => value + 1)}
|
||||
>
|
||||
{t('common.retry')}
|
||||
</Button>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -196,6 +196,13 @@ export interface RunnerDescriptor {
|
||||
|
||||
export interface ProcessorRun {
|
||||
run_id: string;
|
||||
binding_id?: string;
|
||||
runner_id?: string;
|
||||
usage?: {
|
||||
prompt_tokens?: number | null;
|
||||
completion_tokens?: number | null;
|
||||
total_tokens?: number | null;
|
||||
} | null;
|
||||
status: string;
|
||||
status_reason?: string;
|
||||
created_at: number;
|
||||
@@ -204,7 +211,13 @@ export interface ProcessorRun {
|
||||
created_at_ms?: number | null;
|
||||
started_at_ms?: number | null;
|
||||
finished_at_ms?: number | null;
|
||||
metadata: { event_type?: string; input_event?: unknown; delivery?: unknown };
|
||||
metadata: {
|
||||
event_type?: string;
|
||||
source?: string;
|
||||
input?: { text?: string; contents?: unknown[]; attachments?: unknown[] };
|
||||
input_event?: unknown;
|
||||
delivery?: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ProcessorRunEvent {
|
||||
@@ -215,6 +228,7 @@ export interface ProcessorRunEvent {
|
||||
|
||||
export interface ProcessorRunPage {
|
||||
items: ProcessorRun[];
|
||||
total?: number;
|
||||
next_cursor: number | null;
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
@@ -787,6 +787,17 @@ const enUS = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'Follow each task from its triggering event through model output and tool execution.',
|
||||
empty:
|
||||
'No runs yet. Trigger a platform event or run a debug test to see it here.',
|
||||
input: 'Triggering input',
|
||||
eventData: 'Event data',
|
||||
execution: 'Execution steps',
|
||||
rawEvents: 'Raw run events',
|
||||
inputUnavailable: 'Input was not recorded for this run.',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'Plugin processor configurations',
|
||||
configTab: 'Configuration',
|
||||
@@ -825,6 +836,7 @@ const enUS = {
|
||||
loadMore: 'Load more',
|
||||
activation:
|
||||
'Install a plugin, create a processor configuration, then bind a bot.',
|
||||
status_timeout: 'Timed out',
|
||||
status_pending: 'Pending',
|
||||
status_running: 'Running',
|
||||
status_completed: 'Completed',
|
||||
|
||||
@@ -611,6 +611,17 @@ const esES = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'Consulta el evento, la salida del modelo y las herramientas de cada tarea.',
|
||||
empty:
|
||||
'Sin ejecuciones. Activa un evento o ejecuta una prueba de depuración.',
|
||||
input: 'Entrada inicial',
|
||||
eventData: 'Datos del evento',
|
||||
execution: 'Pasos de ejecución',
|
||||
rawEvents: 'Eventos sin procesar',
|
||||
inputUnavailable: 'No se registró la entrada de esta ejecución.',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'Configuraciones de procesadores de plugins',
|
||||
configTab: 'Configuración',
|
||||
@@ -649,6 +660,7 @@ const esES = {
|
||||
loadMore: 'Cargar más',
|
||||
activation:
|
||||
'Instala un plugin, crea una configuración de procesador y vincula un bot.',
|
||||
status_timeout: 'Tiempo agotado',
|
||||
status_pending: 'Pendiente',
|
||||
status_running: 'En ejecución',
|
||||
status_completed: 'Completado',
|
||||
|
||||
@@ -800,6 +800,17 @@ const jaJP = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'各タスクのトリガーイベント、モデル出力、ツール実行を確認します。',
|
||||
empty:
|
||||
'実行記録はありません。プラットフォームイベントまたはデバッグテストを実行してください。',
|
||||
input: 'トリガー入力',
|
||||
eventData: 'イベントデータ',
|
||||
execution: '実行過程',
|
||||
rawEvents: '生の実行イベント',
|
||||
inputUnavailable: 'この実行の入力は記録されていません。',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'プラグインプロセッサー設定',
|
||||
configTab: '設定',
|
||||
@@ -839,6 +850,7 @@ const jaJP = {
|
||||
loadMore: 'さらに読み込む',
|
||||
activation:
|
||||
'プラグインをインストールし、プロセッサー設定を作成してボットに紐付けます。',
|
||||
status_timeout: 'タイムアウト',
|
||||
status_pending: '待機中',
|
||||
status_running: '実行中',
|
||||
status_completed: '完了',
|
||||
|
||||
@@ -606,6 +606,17 @@ const ruRU = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'Просмотр события, ответа модели и вызовов инструментов для каждой задачи.',
|
||||
empty:
|
||||
'Запусков пока нет. Вызовите событие платформы или запустите отладку.',
|
||||
input: 'Входные данные',
|
||||
eventData: 'Данные события',
|
||||
execution: 'Ход выполнения',
|
||||
rawEvents: 'Исходные события',
|
||||
inputUnavailable: 'Входные данные этого запуска не записаны.',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'Конфигурации обработчиков плагинов',
|
||||
configTab: 'Настройки',
|
||||
@@ -643,6 +654,7 @@ const ruRU = {
|
||||
loadMore: 'Загрузить ещё',
|
||||
activation:
|
||||
'Установите плагин, создайте конфигурацию обработчика и привяжите бота.',
|
||||
status_timeout: 'Время истекло',
|
||||
status_pending: 'Ожидание',
|
||||
status_running: 'Выполняется',
|
||||
status_completed: 'Завершено',
|
||||
|
||||
@@ -591,6 +591,16 @@ const thTH = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'ดูเหตุการณ์เริ่มต้น ผลลัพธ์โมเดล และการเรียกเครื่องมือของแต่ละงาน',
|
||||
empty: 'ยังไม่มีการทำงาน เริ่มเหตุการณ์หรือทดสอบการดีบักเพื่อดูบันทึก',
|
||||
input: 'ข้อมูลเริ่มต้น',
|
||||
eventData: 'ข้อมูลเหตุการณ์',
|
||||
execution: 'ขั้นตอนการทำงาน',
|
||||
rawEvents: 'เหตุการณ์ดิบ',
|
||||
inputUnavailable: 'ไม่มีการบันทึกข้อมูลเริ่มต้นของการทำงานนี้',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'การตั้งค่าตัวประมวลผลปลั๊กอิน',
|
||||
configTab: 'การตั้งค่า',
|
||||
@@ -627,6 +637,7 @@ const thTH = {
|
||||
destination: 'ปลายทางการส่ง',
|
||||
loadMore: 'โหลดเพิ่มเติม',
|
||||
activation: 'ติดตั้งปลั๊กอิน สร้างการตั้งค่าตัวประมวลผล แล้วเชื่อมโยงบอท',
|
||||
status_timeout: 'หมดเวลา',
|
||||
status_pending: 'รอดำเนินการ',
|
||||
status_running: 'กำลังทำงาน',
|
||||
status_completed: 'เสร็จสิ้น',
|
||||
|
||||
@@ -601,6 +601,16 @@ const viVN = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description:
|
||||
'Xem sự kiện kích hoạt, đầu ra mô hình và quá trình gọi công cụ của mỗi tác vụ.',
|
||||
empty: 'Chưa có lượt chạy. Kích hoạt sự kiện hoặc chạy thử gỡ lỗi.',
|
||||
input: 'Đầu vào kích hoạt',
|
||||
eventData: 'Dữ liệu sự kiện',
|
||||
execution: 'Quá trình thực thi',
|
||||
rawEvents: 'Sự kiện gốc',
|
||||
inputUnavailable: 'Đầu vào của lượt chạy này chưa được ghi lại.',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: 'Cấu hình bộ xử lý plugin',
|
||||
configTab: 'Cấu hình',
|
||||
@@ -637,6 +647,7 @@ const viVN = {
|
||||
destination: 'Đích gửi',
|
||||
loadMore: 'Tải thêm',
|
||||
activation: 'Cài plugin, tạo cấu hình bộ xử lý rồi liên kết bot.',
|
||||
status_timeout: 'Hết thời gian',
|
||||
status_pending: 'Đang chờ',
|
||||
status_running: 'Đang chạy',
|
||||
status_completed: 'Hoàn tất',
|
||||
|
||||
@@ -748,6 +748,15 @@ const zhHans = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description: '查看每次任务的触发事件、模型输出和工具执行过程。',
|
||||
empty: '暂无运行记录。触发平台事件或运行调试后,可在这里查看。',
|
||||
input: '触发输入',
|
||||
eventData: '事件数据',
|
||||
execution: '执行过程',
|
||||
rawEvents: '原始运行事件',
|
||||
inputUnavailable: '这次运行未记录输入内容。',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: '插件处理器配置',
|
||||
configTab: '配置',
|
||||
@@ -783,6 +792,7 @@ const zhHans = {
|
||||
destination: '投递目标',
|
||||
loadMore: '加载更多',
|
||||
activation: '安装插件,创建处理器配置,再绑定机器人。',
|
||||
status_timeout: '已超时',
|
||||
status_pending: '待执行',
|
||||
status_running: '运行中',
|
||||
status_completed: '已完成',
|
||||
|
||||
@@ -573,6 +573,15 @@ const zhHant = {
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
monitoring: {
|
||||
description: '查看每次任務的觸發事件、模型輸出和工具執行過程。',
|
||||
empty: '尚無執行紀錄。觸發平台事件或執行除錯後,可在此查看。',
|
||||
input: '觸發輸入',
|
||||
eventData: '事件資料',
|
||||
execution: '執行過程',
|
||||
rawEvents: '原始執行事件',
|
||||
inputUnavailable: '此次執行未記錄輸入內容。',
|
||||
},
|
||||
eventProcessor: {
|
||||
configurations: '外掛處理器設定',
|
||||
configTab: '設定',
|
||||
@@ -608,6 +617,7 @@ const zhHant = {
|
||||
destination: '傳送目標',
|
||||
loadMore: '載入更多',
|
||||
activation: '安裝外掛、建立處理器設定,再綁定機器人。',
|
||||
status_timeout: '已逾時',
|
||||
status_pending: '待執行',
|
||||
status_running: '執行中',
|
||||
status_completed: '已完成',
|
||||
|
||||
Reference in New Issue
Block a user