plugin-agent-orchestrator 1.0.27 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/client/index.js +1 -1
- package/dist/client-v2/{214.723affb37c13bf7a.js → 214.79650a549273f163.js} +1 -1
- package/dist/client-v2/264.718a107e43fc163c.js +10 -0
- package/dist/client-v2/373.f5d5292e53c4e832.js +10 -0
- package/dist/client-v2/{41.1805b2edfaa4afe2.js → 41.ba6e080cc0488143.js} +1 -1
- package/dist/client-v2/418.29e713f79131eece.js +10 -0
- package/dist/client-v2/619.bd3c5698b40705c3.js +10 -0
- package/dist/client-v2/677.a991ce0250ff5c77.js +10 -0
- package/dist/client-v2/{70.a15d7fcec7c41768.js → 70.bda9518881c05360.js} +1 -1
- package/dist/client-v2/925.f5370de8f6632d65.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/externalVersion.js +7 -10
- package/dist/locale/en-US.json +94 -25
- package/dist/locale/vi-VN.json +94 -25
- package/dist/locale/zh-CN.json +94 -25
- package/dist/server/collections/agent-execution-spans.js +37 -0
- package/dist/server/collections/agent-harness-profiles.js +2 -2
- package/dist/server/collections/agent-memory-contexts.js +125 -0
- package/dist/server/collections/orchestrator-logs.js +2 -2
- package/dist/server/migrations/20260425000000-add-interaction-schema.js +3 -1
- package/dist/server/migrations/20260427000000-change-packages-to-text.js +3 -1
- package/dist/server/migrations/20260427000001-change-other-json-to-text.js +6 -2
- package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.js +21 -19
- package/dist/server/migrations/20260621000000-native-policy-profile-defaults.js +193 -0
- package/dist/server/plugin.js +128 -74
- package/dist/server/resources/agent-monitor.js +454 -0
- package/dist/server/services/AgentHarness.js +24 -499
- package/dist/server/services/AgentMemoryContextService.js +216 -0
- package/dist/server/services/ExecutionSpanService.js +2 -2
- package/dist/server/services/NativeSubAgentObserver.js +413 -0
- package/dist/server/skill-hub/mcp/McpController.js +16 -5
- package/dist/server/skill-hub/plugin.js +81 -5
- package/dist/server/skill-hub/tasks/SkillExecutionTask.js +9 -3
- package/dist/server/tools/delegate-task.js +11 -589
- package/dist/server/utils/skill-settings.js +18 -1
- package/package.json +47 -49
- package/src/client/AIEmployeesContext.tsx +5 -18
- package/src/client/AgentRunsTab.tsx +2 -771
- package/src/client/HarnessProfilesTab.tsx +2 -257
- package/src/client/OrchestratorSettings.tsx +97 -106
- package/src/client/RulesTab.tsx +2 -788
- package/src/client/plugin.tsx +0 -2
- package/src/client/skill-hub/components/ExecutionHistory.tsx +200 -202
- package/src/client/skill-hub/components/ExecutionProgress.tsx +51 -55
- package/src/client/skill-hub/components/LoopSettings.tsx +331 -331
- package/src/client/skill-hub/components/SkillEditor.tsx +43 -39
- package/src/client/skill-hub/components/SkillManager.tsx +194 -181
- package/src/client/skill-hub/components/SkillTestPanel.tsx +141 -145
- package/src/client/skill-hub/locale.ts +16 -16
- package/src/client/skill-hub/tools/SkillHubCard.tsx +104 -109
- package/src/client/skill-hub/tools/loopTemplates.ts +52 -52
- package/src/client/skill-hub/utils/jsonFields.ts +7 -3
- package/src/client-v2/components/AIEmployeesContext.tsx +3 -16
- package/src/client-v2/components/AgentRunsTab.tsx +182 -455
- package/src/client-v2/components/HarnessProfilesTab.tsx +34 -31
- package/src/client-v2/components/RulesTab.tsx +2 -782
- package/src/client-v2/components/TracingTab.tsx +1 -1
- package/src/client-v2/hooks/useApiRequest.ts +8 -1
- package/src/client-v2/pages/RulesPage.tsx +2 -2
- package/src/client-v2/plugin.tsx +3 -3
- package/src/locale/en-US.json +94 -25
- package/src/locale/vi-VN.json +94 -25
- package/src/locale/zh-CN.json +94 -25
- package/src/server/__tests__/native-sub-agent-observer.test.ts +246 -0
- package/src/server/__tests__/skill-settings.test.ts +6 -6
- package/src/server/__tests__/smoke.test.ts +1 -0
- package/src/server/collections/agent-execution-spans.ts +37 -0
- package/src/server/collections/agent-harness-profiles.ts +59 -59
- package/src/server/collections/agent-loop-events.ts +71 -71
- package/src/server/collections/agent-loop-steps.ts +144 -144
- package/src/server/collections/agent-memory-contexts.ts +95 -0
- package/src/server/collections/orchestrator-logs.ts +4 -4
- package/src/server/collections/skill-definitions.ts +111 -111
- package/src/server/collections/skill-executions.ts +106 -106
- package/src/server/collections/skill-loop-configs.ts +65 -65
- package/src/server/migrations/20260423000000-add-progress-fields.ts +14 -14
- package/src/server/migrations/20260425000000-add-interaction-schema.ts +3 -1
- package/src/server/migrations/20260427000000-change-packages-to-text.ts +4 -2
- package/src/server/migrations/20260427000001-change-other-json-to-text.ts +9 -5
- package/src/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.ts +30 -30
- package/src/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.ts +145 -142
- package/src/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.ts +2 -2
- package/src/server/migrations/20260621000000-native-policy-profile-defaults.ts +193 -0
- package/src/server/plugin.ts +151 -94
- package/src/server/resources/agent-monitor.ts +482 -0
- package/src/server/services/AgentHarness.ts +38 -623
- package/src/server/services/AgentMemoryContextService.ts +256 -0
- package/src/server/services/AgentPlanValidator.ts +73 -73
- package/src/server/services/ExecutionSpanService.ts +6 -2
- package/src/server/services/FileManager.ts +144 -144
- package/src/server/services/NativeSubAgentObserver.ts +507 -0
- package/src/server/services/SkillManager.ts +583 -583
- package/src/server/services/SkillRepositoryService.ts +5 -7
- package/src/server/services/TokenTracker.ts +3 -3
- package/src/server/services/WorkerEnvManager.ts +1 -2
- package/src/server/skill-hub/actions/git-import.ts +5 -7
- package/src/server/skill-hub/mcp/McpController.ts +41 -14
- package/src/server/skill-hub/plugin.ts +89 -6
- package/src/server/skill-hub/tasks/SkillExecutionTask.ts +470 -460
- package/src/server/skill-hub/utils/json-fields.ts +1 -1
- package/src/server/tools/delegate-task.ts +13 -847
- package/src/server/utils/skill-settings.ts +24 -6
- package/dist/client-v2/264.0533912e6c5ea2d7.js +0 -10
- package/dist/client-v2/418.5ae055abf141820e.js +0 -10
- package/dist/client-v2/619.d99d3c9e61c99064.js +0 -10
- package/dist/client-v2/892.72db4161511c8a16.js +0 -10
- package/dist/client-v2/926.87f660b670d85bcc.js +0 -10
- package/src/client/tools/PlanApprovalCard.tsx +0 -176
- package/src/client/tools/registerOrchestratorCards.ts +0 -17
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
Empty,
|
|
10
10
|
Form,
|
|
11
11
|
message,
|
|
12
|
-
Popconfirm,
|
|
13
12
|
Select,
|
|
14
13
|
Space,
|
|
15
14
|
Spin,
|
|
@@ -18,101 +17,41 @@ import {
|
|
|
18
17
|
Timeline,
|
|
19
18
|
Typography,
|
|
20
19
|
} from 'antd';
|
|
21
|
-
import {
|
|
22
|
-
BranchesOutlined,
|
|
23
|
-
CheckCircleOutlined,
|
|
24
|
-
ClockCircleOutlined,
|
|
25
|
-
CloseCircleOutlined,
|
|
26
|
-
EyeOutlined,
|
|
27
|
-
PauseCircleOutlined,
|
|
28
|
-
PlayCircleOutlined,
|
|
29
|
-
RedoOutlined,
|
|
30
|
-
ReloadOutlined,
|
|
31
|
-
StopOutlined,
|
|
32
|
-
} from '@ant-design/icons';
|
|
20
|
+
import { CheckCircleOutlined, CloseCircleOutlined, EyeOutlined, ReloadOutlined, SyncOutlined } from '@ant-design/icons';
|
|
33
21
|
import { useApiClient as useAPIClient, useRequest } from '../hooks/useApiRequest';
|
|
34
22
|
import { useAIEmployees } from './AIEmployeesContext';
|
|
35
|
-
import {
|
|
23
|
+
import { useT } from '../skill-hub/locale';
|
|
36
24
|
|
|
37
25
|
const { Paragraph, Text } = Typography;
|
|
38
26
|
|
|
39
27
|
type FilterState = {
|
|
40
28
|
leader?: string;
|
|
29
|
+
subAgent?: string;
|
|
41
30
|
status?: string;
|
|
42
31
|
};
|
|
43
32
|
|
|
44
|
-
const terminalRunStatuses = new Set(['succeeded', 'failed', 'rejected', 'canceled']);
|
|
45
|
-
|
|
46
33
|
function statusColor(status?: string) {
|
|
47
34
|
switch (status) {
|
|
48
|
-
case 'succeeded':
|
|
49
35
|
case 'success':
|
|
50
36
|
return 'success';
|
|
51
|
-
case 'failed':
|
|
52
37
|
case 'error':
|
|
53
38
|
return 'error';
|
|
54
|
-
case 'waiting_user':
|
|
55
|
-
case 'waiting_plan_approval':
|
|
56
|
-
case 'needs_replan':
|
|
57
|
-
return 'warning';
|
|
58
|
-
case 'approved':
|
|
59
39
|
case 'running':
|
|
60
|
-
case 'planning':
|
|
61
40
|
return 'processing';
|
|
62
|
-
case 'rejected':
|
|
63
|
-
case 'canceled':
|
|
64
|
-
case 'skipped':
|
|
65
|
-
return 'default';
|
|
66
41
|
default:
|
|
67
42
|
return 'default';
|
|
68
43
|
}
|
|
69
44
|
}
|
|
70
45
|
|
|
71
46
|
function statusIcon(status?: string) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return <CheckCircleOutlined />;
|
|
76
|
-
case 'failed':
|
|
77
|
-
case 'error':
|
|
78
|
-
return <CloseCircleOutlined />;
|
|
79
|
-
case 'waiting_user':
|
|
80
|
-
case 'waiting_plan_approval':
|
|
81
|
-
case 'needs_replan':
|
|
82
|
-
return <PauseCircleOutlined />;
|
|
83
|
-
case 'approved':
|
|
84
|
-
case 'running':
|
|
85
|
-
case 'planning':
|
|
86
|
-
return <ClockCircleOutlined />;
|
|
87
|
-
default:
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function timelineColor(status?: string) {
|
|
93
|
-
switch (status) {
|
|
94
|
-
case 'succeeded':
|
|
95
|
-
case 'success':
|
|
96
|
-
return 'green';
|
|
97
|
-
case 'failed':
|
|
98
|
-
case 'error':
|
|
99
|
-
return 'red';
|
|
100
|
-
case 'waiting_user':
|
|
101
|
-
case 'waiting_plan_approval':
|
|
102
|
-
case 'needs_replan':
|
|
103
|
-
return 'orange';
|
|
104
|
-
case 'approved':
|
|
105
|
-
case 'running':
|
|
106
|
-
case 'planning':
|
|
107
|
-
return 'blue';
|
|
108
|
-
default:
|
|
109
|
-
return 'gray';
|
|
110
|
-
}
|
|
47
|
+
if (status === 'success') return <CheckCircleOutlined />;
|
|
48
|
+
if (status === 'error') return <CloseCircleOutlined />;
|
|
49
|
+
return undefined;
|
|
111
50
|
}
|
|
112
51
|
|
|
113
52
|
function StatusTag({ status }: { status?: string }) {
|
|
114
53
|
return (
|
|
115
|
-
<Tag
|
|
54
|
+
<Tag color={statusColor(status)} icon={statusIcon(status)}>
|
|
116
55
|
{status || '-'}
|
|
117
56
|
</Tag>
|
|
118
57
|
);
|
|
@@ -122,17 +61,14 @@ function formatDate(value?: string) {
|
|
|
122
61
|
return value ? new Date(value).toLocaleString() : '-';
|
|
123
62
|
}
|
|
124
63
|
|
|
125
|
-
function
|
|
126
|
-
if (!
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (diff >= 60000) return `${Math.round(diff / 60000)}m`;
|
|
131
|
-
if (diff >= 1000) return `${(diff / 1000).toFixed(1)}s`;
|
|
132
|
-
return `${diff}ms`;
|
|
64
|
+
function formatDurationMs(value?: number) {
|
|
65
|
+
if (!value) return '-';
|
|
66
|
+
if (value >= 60000) return `${Math.round(value / 60000)}m`;
|
|
67
|
+
if (value >= 1000) return `${(value / 1000).toFixed(1)}s`;
|
|
68
|
+
return `${value}ms`;
|
|
133
69
|
}
|
|
134
70
|
|
|
135
|
-
function formatJson(value:
|
|
71
|
+
function formatJson(value: unknown) {
|
|
136
72
|
if (value === undefined || value === null || value === '') return '';
|
|
137
73
|
if (typeof value === 'string') return value;
|
|
138
74
|
try {
|
|
@@ -142,25 +78,7 @@ function formatJson(value: any) {
|
|
|
142
78
|
}
|
|
143
79
|
}
|
|
144
80
|
|
|
145
|
-
function
|
|
146
|
-
if (file?.downloadUrl) return file.downloadUrl;
|
|
147
|
-
if (!execution?.id || !file?.name) return '';
|
|
148
|
-
return `/api/skillHub:download?execId=${execution.id}&filename=${encodeURIComponent(file.name)}`;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function renderSkillFileLink(execution: any, file: any, index: number) {
|
|
152
|
-
const url = buildSkillFileUrl(execution, file);
|
|
153
|
-
const label = file.name || file.path || `file-${index + 1}`;
|
|
154
|
-
return url ? (
|
|
155
|
-
<a key={index} href={url} target="_blank" rel="noreferrer">
|
|
156
|
-
{label}
|
|
157
|
-
</a>
|
|
158
|
-
) : (
|
|
159
|
-
<Text key={index}>{label}</Text>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function TextBlock({ value, rows = 10 }: { value: any; rows?: number }) {
|
|
81
|
+
function TextBlock({ value, rows = 8 }: { value: unknown; rows?: number }) {
|
|
164
82
|
const text = formatJson(value);
|
|
165
83
|
if (!text) return <Text type="secondary">-</Text>;
|
|
166
84
|
return (
|
|
@@ -175,18 +93,19 @@ function TextBlock({ value, rows = 10 }: { value: any; rows?: number }) {
|
|
|
175
93
|
|
|
176
94
|
export const AgentRunsTab: React.FC = () => {
|
|
177
95
|
const api = useAPIClient();
|
|
96
|
+
const t = useT();
|
|
178
97
|
const { employees, employeeMap } = useAIEmployees();
|
|
179
98
|
const [filters, setFilters] = useState<FilterState>({});
|
|
180
99
|
const [page, setPage] = useState(1);
|
|
181
100
|
const [pageSize, setPageSize] = useState(20);
|
|
182
101
|
const [selectedRun, setSelectedRun] = useState<any>(null);
|
|
183
|
-
const [detail, setDetail] = useState<any>(null);
|
|
184
102
|
const [detailLoading, setDetailLoading] = useState(false);
|
|
185
|
-
const [
|
|
103
|
+
const [syncLoading, setSyncLoading] = useState(false);
|
|
186
104
|
|
|
187
105
|
const requestParams = useMemo(() => {
|
|
188
|
-
const filter:
|
|
106
|
+
const filter: Record<string, string> = {};
|
|
189
107
|
if (filters.leader) filter.leaderUsername = filters.leader;
|
|
108
|
+
if (filters.subAgent) filter.subAgentUsername = filters.subAgent;
|
|
190
109
|
if (filters.status) filter.status = filters.status;
|
|
191
110
|
return {
|
|
192
111
|
sort: ['-createdAt'],
|
|
@@ -198,7 +117,7 @@ export const AgentRunsTab: React.FC = () => {
|
|
|
198
117
|
|
|
199
118
|
const { data, loading, refresh } = useRequest(
|
|
200
119
|
{
|
|
201
|
-
url: '
|
|
120
|
+
url: 'agentMonitor:list',
|
|
202
121
|
params: requestParams,
|
|
203
122
|
},
|
|
204
123
|
{
|
|
@@ -225,20 +144,6 @@ export const AgentRunsTab: React.FC = () => {
|
|
|
225
144
|
[employees],
|
|
226
145
|
);
|
|
227
146
|
|
|
228
|
-
const fetchDetail = async (runId: string | number, seed?: any) => {
|
|
229
|
-
setSelectedRun(seed || selectedRun || { id: runId });
|
|
230
|
-
setDetailLoading(true);
|
|
231
|
-
try {
|
|
232
|
-
const res = await api.request({
|
|
233
|
-
url: 'agentLoops:get',
|
|
234
|
-
params: { filterByTk: runId },
|
|
235
|
-
});
|
|
236
|
-
setDetail((res as any)?.data?.data || (res as any)?.data || null);
|
|
237
|
-
} finally {
|
|
238
|
-
setDetailLoading(false);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
147
|
const updateFilter = (patch: Partial<FilterState>) => {
|
|
243
148
|
setFilters((prev) => ({ ...prev, ...patch }));
|
|
244
149
|
setPage(1);
|
|
@@ -249,230 +154,175 @@ export const AgentRunsTab: React.FC = () => {
|
|
|
249
154
|
setPage(1);
|
|
250
155
|
};
|
|
251
156
|
|
|
252
|
-
const
|
|
253
|
-
|
|
157
|
+
const fetchDetail = async (record: any) => {
|
|
158
|
+
setSelectedRun(record);
|
|
159
|
+
setDetailLoading(true);
|
|
254
160
|
try {
|
|
255
|
-
await api.request({
|
|
256
|
-
url:
|
|
257
|
-
|
|
258
|
-
data: action === 'cancel' ? { runId } : { runId, stepId: detail?.run?.currentStepId, approved: true },
|
|
161
|
+
const res = await api.request({
|
|
162
|
+
url: 'agentMonitor:get',
|
|
163
|
+
params: { filterByTk: record.id },
|
|
259
164
|
});
|
|
260
|
-
|
|
261
|
-
refresh();
|
|
262
|
-
await fetchDetail(runId);
|
|
263
|
-
} catch (error: any) {
|
|
264
|
-
message.error(error?.message || `Failed to ${action} run`);
|
|
165
|
+
setSelectedRun((res as any)?.data?.data?.data || (res as any)?.data?.data || record);
|
|
265
166
|
} finally {
|
|
266
|
-
|
|
167
|
+
setDetailLoading(false);
|
|
267
168
|
}
|
|
268
169
|
};
|
|
269
170
|
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
setActionLoading(true);
|
|
171
|
+
const syncNativeRuns = async () => {
|
|
172
|
+
setSyncLoading(true);
|
|
273
173
|
try {
|
|
274
|
-
await api.request({
|
|
275
|
-
url: '
|
|
276
|
-
method: '
|
|
277
|
-
data: {
|
|
174
|
+
const res = await api.request({
|
|
175
|
+
url: 'agentMonitor:sync',
|
|
176
|
+
method: 'post',
|
|
177
|
+
data: { limit: 500 },
|
|
278
178
|
});
|
|
279
|
-
|
|
179
|
+
const result = (res as any)?.data?.data || {};
|
|
180
|
+
message.success(t('Synced {{count}} native runs', { count: result.created || 0 }));
|
|
280
181
|
refresh();
|
|
281
|
-
if (runId) await fetchDetail(runId);
|
|
282
182
|
} catch (error: any) {
|
|
283
|
-
message
|
|
183
|
+
const text = error?.response?.data?.errors?.[0]?.message || error?.message || t('Sync failed');
|
|
184
|
+
message.error(text);
|
|
284
185
|
} finally {
|
|
285
|
-
|
|
186
|
+
setSyncLoading(false);
|
|
286
187
|
}
|
|
287
188
|
};
|
|
288
189
|
|
|
190
|
+
const hasFilters = Boolean(filters.leader || filters.subAgent || filters.status);
|
|
191
|
+
const trace = Array.isArray(selectedRun?.trace) ? selectedRun.trace : [];
|
|
192
|
+
const toolMessages = Array.isArray(selectedRun?.toolMessages) ? selectedRun.toolMessages : [];
|
|
193
|
+
const nativeMessages = Array.isArray(selectedRun?.nativeMessages) ? selectedRun.nativeMessages : [];
|
|
194
|
+
|
|
289
195
|
const columns = [
|
|
290
196
|
{
|
|
291
|
-
title: 'Time',
|
|
197
|
+
title: t('Time'),
|
|
292
198
|
dataIndex: 'createdAt',
|
|
293
199
|
key: 'createdAt',
|
|
294
200
|
width: 170,
|
|
295
201
|
render: formatDate,
|
|
296
202
|
},
|
|
297
203
|
{
|
|
298
|
-
title: 'Leader',
|
|
204
|
+
title: t('Leader'),
|
|
299
205
|
dataIndex: 'leaderUsername',
|
|
300
206
|
key: 'leaderUsername',
|
|
301
207
|
width: 160,
|
|
302
208
|
render: (username: string) => <Tag color="blue">{employeeMap.get(username) || username || '-'}</Tag>,
|
|
303
209
|
},
|
|
304
210
|
{
|
|
305
|
-
title: '
|
|
306
|
-
dataIndex: '
|
|
307
|
-
key: '
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
211
|
+
title: t('Sub-Agent'),
|
|
212
|
+
dataIndex: 'subAgentUsername',
|
|
213
|
+
key: 'subAgentUsername',
|
|
214
|
+
width: 160,
|
|
215
|
+
render: (username: string) => <Tag color="green">{employeeMap.get(username) || username || '-'}</Tag>,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
title: t('Task'),
|
|
219
|
+
dataIndex: 'task',
|
|
220
|
+
key: 'task',
|
|
221
|
+
render: (task: string) => (
|
|
222
|
+
<Text ellipsis style={{ maxWidth: 360 }}>
|
|
223
|
+
{task || '-'}
|
|
311
224
|
</Text>
|
|
312
225
|
),
|
|
313
226
|
},
|
|
314
227
|
{
|
|
315
|
-
title: 'Status',
|
|
228
|
+
title: t('Status'),
|
|
316
229
|
dataIndex: 'status',
|
|
317
230
|
key: 'status',
|
|
318
|
-
width:
|
|
231
|
+
width: 110,
|
|
319
232
|
render: (status: string) => <StatusTag status={status} />,
|
|
320
233
|
},
|
|
321
234
|
{
|
|
322
|
-
title: '
|
|
323
|
-
dataIndex: '
|
|
324
|
-
key: '
|
|
325
|
-
width:
|
|
326
|
-
render:
|
|
235
|
+
title: t('Duration'),
|
|
236
|
+
dataIndex: 'durationMs',
|
|
237
|
+
key: 'durationMs',
|
|
238
|
+
width: 100,
|
|
239
|
+
render: formatDurationMs,
|
|
327
240
|
},
|
|
328
241
|
{
|
|
329
|
-
title: '
|
|
330
|
-
|
|
242
|
+
title: t('Context'),
|
|
243
|
+
dataIndex: 'memoryContextApplied',
|
|
244
|
+
key: 'memoryContextApplied',
|
|
331
245
|
width: 100,
|
|
332
|
-
render: (
|
|
246
|
+
render: (applied: boolean) => (applied ? <Tag color="purple">memory</Tag> : <Text type="secondary">-</Text>),
|
|
333
247
|
},
|
|
334
248
|
{
|
|
335
249
|
title: '',
|
|
336
250
|
key: 'actions',
|
|
337
251
|
width: 90,
|
|
338
|
-
render: (_:
|
|
339
|
-
<Button type="link" size="small" icon={<EyeOutlined />} onClick={() => fetchDetail(record
|
|
340
|
-
Detail
|
|
252
|
+
render: (_: unknown, record: any) => (
|
|
253
|
+
<Button type="link" size="small" icon={<EyeOutlined />} onClick={() => fetchDetail(record)}>
|
|
254
|
+
{t('Detail')}
|
|
341
255
|
</Button>
|
|
342
256
|
),
|
|
343
257
|
},
|
|
344
258
|
];
|
|
345
259
|
|
|
346
|
-
const steps = Array.isArray(detail?.steps) ? detail.steps : [];
|
|
347
|
-
const events = Array.isArray(detail?.events) ? detail.events : [];
|
|
348
|
-
const spans = Array.isArray(detail?.spans) ? detail.spans : [];
|
|
349
|
-
const skillExecutions = Array.isArray(detail?.skillExecutions) ? detail.skillExecutions : [];
|
|
350
|
-
const run = detail?.run || selectedRun;
|
|
351
|
-
const hasFilters = Boolean(filters.leader || filters.status);
|
|
352
|
-
|
|
353
|
-
const stepColumns = [
|
|
354
|
-
{
|
|
355
|
-
title: '#',
|
|
356
|
-
dataIndex: 'index',
|
|
357
|
-
key: 'index',
|
|
358
|
-
width: 56,
|
|
359
|
-
render: (value: number) => Number(value ?? 0) + 1,
|
|
360
|
-
},
|
|
361
|
-
{
|
|
362
|
-
title: 'Status',
|
|
363
|
-
dataIndex: 'status',
|
|
364
|
-
key: 'status',
|
|
365
|
-
width: 130,
|
|
366
|
-
render: (status: string) => <StatusTag status={status} />,
|
|
367
|
-
},
|
|
368
|
-
{
|
|
369
|
-
title: 'Type',
|
|
370
|
-
dataIndex: 'type',
|
|
371
|
-
key: 'type',
|
|
372
|
-
width: 110,
|
|
373
|
-
render: (type: string) => <Tag>{type}</Tag>,
|
|
374
|
-
},
|
|
375
|
-
{
|
|
376
|
-
title: 'Step',
|
|
377
|
-
key: 'step',
|
|
378
|
-
render: (_: any, record: any) => (
|
|
379
|
-
<Space direction="vertical" size={2} style={{ width: '100%' }}>
|
|
380
|
-
<Text strong>{record.title || record.planKey}</Text>
|
|
381
|
-
{record.description && <Text type="secondary">{record.description}</Text>}
|
|
382
|
-
{record.target && <Text code>{record.target}</Text>}
|
|
383
|
-
</Space>
|
|
384
|
-
),
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
title: 'Depends',
|
|
388
|
-
dataIndex: 'dependsOn',
|
|
389
|
-
key: 'dependsOn',
|
|
390
|
-
width: 130,
|
|
391
|
-
render: (dependsOn: string[]) =>
|
|
392
|
-
Array.isArray(dependsOn) && dependsOn.length ? dependsOn.map((key) => <Tag key={key}>{key}</Tag>) : '-',
|
|
393
|
-
},
|
|
394
|
-
{
|
|
395
|
-
title: 'Attempts',
|
|
396
|
-
key: 'attempts',
|
|
397
|
-
width: 90,
|
|
398
|
-
render: (_: any, record: any) => `${record.attempt || 0}/${record.maxAttempts || 0}`,
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
title: '',
|
|
402
|
-
key: 'actions',
|
|
403
|
-
width: 90,
|
|
404
|
-
render: (_: any, record: any) =>
|
|
405
|
-
record.status === 'failed' && Number(record.attempt || 0) < Number(record.maxAttempts || 0) ? (
|
|
406
|
-
<Button
|
|
407
|
-
type="link"
|
|
408
|
-
size="small"
|
|
409
|
-
icon={<RedoOutlined />}
|
|
410
|
-
loading={actionLoading}
|
|
411
|
-
onClick={() => retryStep(record.id)}
|
|
412
|
-
>
|
|
413
|
-
Retry
|
|
414
|
-
</Button>
|
|
415
|
-
) : null,
|
|
416
|
-
},
|
|
417
|
-
];
|
|
418
|
-
|
|
419
260
|
return (
|
|
420
261
|
<div>
|
|
421
262
|
<Alert
|
|
422
263
|
type="info"
|
|
423
264
|
showIcon
|
|
424
265
|
style={{ marginBottom: 16 }}
|
|
425
|
-
message=
|
|
266
|
+
message={t('Native Agent Runs')}
|
|
426
267
|
description={
|
|
427
268
|
<Text type="secondary">
|
|
428
|
-
|
|
429
|
-
|
|
269
|
+
{t(
|
|
270
|
+
'Native plugin-ai sub-agent dispatches captured by the orchestrator observer. Execution still runs through AIEmployee/SubAgentsDispatcher.',
|
|
271
|
+
)}
|
|
430
272
|
</Text>
|
|
431
273
|
}
|
|
432
274
|
/>
|
|
433
275
|
|
|
434
276
|
<Card bordered={false}>
|
|
435
277
|
<Form layout="inline" style={{ marginBottom: 16, rowGap: 8, flexWrap: 'wrap' }}>
|
|
436
|
-
<Form.Item label=
|
|
278
|
+
<Form.Item label={t('Leader')}>
|
|
437
279
|
<Select
|
|
438
280
|
allowClear
|
|
439
281
|
showSearch
|
|
440
282
|
optionFilterProp="label"
|
|
441
|
-
placeholder=
|
|
283
|
+
placeholder={t('Any leader')}
|
|
442
284
|
style={{ minWidth: 180 }}
|
|
443
285
|
options={employeeOptions}
|
|
444
286
|
value={filters.leader}
|
|
445
287
|
onChange={(value) => updateFilter({ leader: value })}
|
|
446
288
|
/>
|
|
447
289
|
</Form.Item>
|
|
448
|
-
<Form.Item label=
|
|
290
|
+
<Form.Item label={t('Sub-Agent')}>
|
|
449
291
|
<Select
|
|
450
292
|
allowClear
|
|
451
|
-
|
|
452
|
-
|
|
293
|
+
showSearch
|
|
294
|
+
optionFilterProp="label"
|
|
295
|
+
placeholder={t('Any sub-agent')}
|
|
296
|
+
style={{ minWidth: 180 }}
|
|
297
|
+
options={employeeOptions}
|
|
298
|
+
value={filters.subAgent}
|
|
299
|
+
onChange={(value) => updateFilter({ subAgent: value })}
|
|
300
|
+
/>
|
|
301
|
+
</Form.Item>
|
|
302
|
+
<Form.Item label={t('Status')}>
|
|
303
|
+
<Select
|
|
304
|
+
allowClear
|
|
305
|
+
placeholder={t('Any status')}
|
|
306
|
+
style={{ minWidth: 140 }}
|
|
453
307
|
value={filters.status}
|
|
454
308
|
onChange={(value) => updateFilter({ status: value })}
|
|
455
309
|
options={[
|
|
456
|
-
{ label: '
|
|
457
|
-
{ label: '
|
|
458
|
-
{ label: '
|
|
459
|
-
{ label: 'Running', value: 'running' },
|
|
460
|
-
{ label: 'Waiting user', value: 'waiting_user' },
|
|
461
|
-
{ label: 'Needs replan', value: 'needs_replan' },
|
|
462
|
-
{ label: 'Succeeded', value: 'succeeded' },
|
|
463
|
-
{ label: 'Failed', value: 'failed' },
|
|
464
|
-
{ label: 'Rejected', value: 'rejected' },
|
|
465
|
-
{ label: 'Canceled', value: 'canceled' },
|
|
310
|
+
{ label: t('Running'), value: 'running' },
|
|
311
|
+
{ label: t('Success'), value: 'success' },
|
|
312
|
+
{ label: t('Error'), value: 'error' },
|
|
466
313
|
]}
|
|
467
314
|
/>
|
|
468
315
|
</Form.Item>
|
|
469
316
|
<Form.Item>
|
|
470
317
|
<Space>
|
|
471
318
|
<Button onClick={resetFilters} disabled={!hasFilters}>
|
|
472
|
-
Reset
|
|
319
|
+
{t('Reset')}
|
|
473
320
|
</Button>
|
|
474
321
|
<Button icon={<ReloadOutlined />} onClick={refresh}>
|
|
475
|
-
Refresh
|
|
322
|
+
{t('Refresh')}
|
|
323
|
+
</Button>
|
|
324
|
+
<Button icon={<SyncOutlined />} onClick={syncNativeRuns} loading={syncLoading}>
|
|
325
|
+
{t('Sync')}
|
|
476
326
|
</Button>
|
|
477
327
|
</Space>
|
|
478
328
|
</Form.Item>
|
|
@@ -490,272 +340,149 @@ export const AgentRunsTab: React.FC = () => {
|
|
|
490
340
|
total,
|
|
491
341
|
showSizeChanger: true,
|
|
492
342
|
pageSizeOptions: [10, 20, 50, 100],
|
|
493
|
-
showTotal: (count) =>
|
|
343
|
+
showTotal: (count) => t('{{count}} runs', { count }),
|
|
494
344
|
onChange: (nextPage, nextSize) => {
|
|
495
345
|
setPage(nextPage);
|
|
496
346
|
if (nextSize && nextSize !== pageSize) setPageSize(nextSize);
|
|
497
347
|
},
|
|
498
348
|
}}
|
|
499
349
|
locale={{
|
|
500
|
-
emptyText:
|
|
350
|
+
emptyText: (
|
|
351
|
+
<Empty description={hasFilters ? t('No runs match the current filters') : t('No native runs yet')} />
|
|
352
|
+
),
|
|
501
353
|
}}
|
|
502
354
|
/>
|
|
503
355
|
</Card>
|
|
504
356
|
|
|
505
|
-
<Drawer
|
|
506
|
-
|
|
507
|
-
width={980}
|
|
508
|
-
onClose={() => {
|
|
509
|
-
setSelectedRun(null);
|
|
510
|
-
setDetail(null);
|
|
511
|
-
}}
|
|
512
|
-
open={!!selectedRun}
|
|
513
|
-
>
|
|
514
|
-
{run && (
|
|
357
|
+
<Drawer title={t('Native Run Detail')} width={960} onClose={() => setSelectedRun(null)} open={!!selectedRun}>
|
|
358
|
+
{selectedRun && (
|
|
515
359
|
<Spin spinning={detailLoading}>
|
|
516
360
|
<Space direction="vertical" size={16} style={{ width: '100%' }}>
|
|
517
|
-
<Space wrap>
|
|
518
|
-
<Button icon={<ReloadOutlined />} onClick={() => fetchDetail(run.id)} loading={detailLoading}>
|
|
519
|
-
Refresh
|
|
520
|
-
</Button>
|
|
521
|
-
{run.status === 'waiting_user' && (
|
|
522
|
-
<Button
|
|
523
|
-
type="primary"
|
|
524
|
-
icon={<PlayCircleOutlined />}
|
|
525
|
-
loading={actionLoading}
|
|
526
|
-
onClick={() => runAction('resume', run.id)}
|
|
527
|
-
>
|
|
528
|
-
Resume
|
|
529
|
-
</Button>
|
|
530
|
-
)}
|
|
531
|
-
{!terminalRunStatuses.has(run.status) && (
|
|
532
|
-
<Popconfirm title="Cancel this run?" onConfirm={() => runAction('cancel', run.id)}>
|
|
533
|
-
<Button danger icon={<StopOutlined />} loading={actionLoading}>
|
|
534
|
-
Cancel run
|
|
535
|
-
</Button>
|
|
536
|
-
</Popconfirm>
|
|
537
|
-
)}
|
|
538
|
-
</Space>
|
|
539
|
-
|
|
540
361
|
<Descriptions bordered size="small" column={2}>
|
|
541
|
-
<Descriptions.Item label=
|
|
542
|
-
<StatusTag status={
|
|
362
|
+
<Descriptions.Item label={t('Status')}>
|
|
363
|
+
<StatusTag status={selectedRun.status} />
|
|
364
|
+
</Descriptions.Item>
|
|
365
|
+
<Descriptions.Item label={t('Harness')}>{selectedRun.harnessTag || 'default'}</Descriptions.Item>
|
|
366
|
+
<Descriptions.Item label={t('Leader')}>
|
|
367
|
+
<Tag color="blue">
|
|
368
|
+
{employeeMap.get(selectedRun.leaderUsername) || selectedRun.leaderUsername || '-'}
|
|
369
|
+
</Tag>
|
|
370
|
+
</Descriptions.Item>
|
|
371
|
+
<Descriptions.Item label={t('Sub-Agent')}>
|
|
372
|
+
<Tag color="green">
|
|
373
|
+
{employeeMap.get(selectedRun.subAgentUsername) || selectedRun.subAgentUsername || '-'}
|
|
374
|
+
</Tag>
|
|
543
375
|
</Descriptions.Item>
|
|
544
|
-
<Descriptions.Item label=
|
|
545
|
-
<
|
|
376
|
+
<Descriptions.Item label={t('Parent session')}>
|
|
377
|
+
<Text code>{selectedRun.parentSessionId || '-'}</Text>
|
|
546
378
|
</Descriptions.Item>
|
|
547
|
-
<Descriptions.Item label=
|
|
548
|
-
<Text code>{
|
|
379
|
+
<Descriptions.Item label={t('Sub session')}>
|
|
380
|
+
<Text code>{selectedRun.subSessionId || '-'}</Text>
|
|
549
381
|
</Descriptions.Item>
|
|
550
|
-
<Descriptions.Item label=
|
|
551
|
-
<Text code>{
|
|
382
|
+
<Descriptions.Item label={t('Tool call')}>
|
|
383
|
+
<Text code>{selectedRun.toolCallId || '-'}</Text>
|
|
552
384
|
</Descriptions.Item>
|
|
553
|
-
<Descriptions.Item label=
|
|
554
|
-
<Descriptions.Item label=
|
|
555
|
-
|
|
556
|
-
<Descriptions.Item label="Harness">{run.metadata?.harnessTag || '-'}</Descriptions.Item>
|
|
557
|
-
<Descriptions.Item label="Duration">
|
|
558
|
-
{formatDuration(run.startedAt || run.createdAt, run.endedAt)}
|
|
385
|
+
<Descriptions.Item label={t('Duration')}>{formatDurationMs(selectedRun.durationMs)}</Descriptions.Item>
|
|
386
|
+
<Descriptions.Item label={t('Started')}>
|
|
387
|
+
{formatDate(selectedRun.startedAt || selectedRun.createdAt)}
|
|
559
388
|
</Descriptions.Item>
|
|
560
|
-
<Descriptions.Item label=
|
|
561
|
-
<Descriptions.Item label="Ended">{formatDate(run.endedAt)}</Descriptions.Item>
|
|
389
|
+
<Descriptions.Item label={t('Ended')}>{formatDate(selectedRun.endedAt)}</Descriptions.Item>
|
|
562
390
|
</Descriptions>
|
|
563
391
|
|
|
564
|
-
<Card title=
|
|
565
|
-
<TextBlock value={
|
|
566
|
-
</Card>
|
|
567
|
-
|
|
568
|
-
<Card title="Plan" size="small" extra={<BranchesOutlined />}>
|
|
569
|
-
<Table
|
|
570
|
-
rowKey="id"
|
|
571
|
-
size="small"
|
|
572
|
-
dataSource={steps}
|
|
573
|
-
columns={stepColumns}
|
|
574
|
-
pagination={false}
|
|
575
|
-
scroll={{ x: 'max-content' }}
|
|
576
|
-
expandable={{
|
|
577
|
-
expandedRowRender: (record: any) => (
|
|
578
|
-
<Space direction="vertical" size={12} style={{ width: '100%' }}>
|
|
579
|
-
<Card size="small" title="Input">
|
|
580
|
-
<TextBlock value={record.input} rows={8} />
|
|
581
|
-
</Card>
|
|
582
|
-
<Card size="small" title="Output">
|
|
583
|
-
<TextBlock value={record.output} rows={8} />
|
|
584
|
-
</Card>
|
|
585
|
-
{record.approval && Object.keys(record.approval).length > 0 && (
|
|
586
|
-
<Card size="small" title="Approval">
|
|
587
|
-
<TextBlock value={record.approval} rows={8} />
|
|
588
|
-
</Card>
|
|
589
|
-
)}
|
|
590
|
-
{record.error && (
|
|
591
|
-
<Card size="small" title="Error" style={{ borderColor: '#ffa39e' }}>
|
|
592
|
-
<TextBlock value={record.error} rows={8} />
|
|
593
|
-
</Card>
|
|
594
|
-
)}
|
|
595
|
-
</Space>
|
|
596
|
-
),
|
|
597
|
-
}}
|
|
598
|
-
locale={{ emptyText: <Empty description="No plan steps" /> }}
|
|
599
|
-
/>
|
|
392
|
+
<Card title={t('Task')} size="small">
|
|
393
|
+
<TextBlock value={selectedRun.task || selectedRun.input?.question} rows={6} />
|
|
600
394
|
</Card>
|
|
601
395
|
|
|
602
|
-
<Card title=
|
|
603
|
-
{
|
|
396
|
+
<Card title={t('Execution Flow')} size="small">
|
|
397
|
+
{trace.length ? (
|
|
604
398
|
<Timeline
|
|
605
|
-
items={
|
|
606
|
-
key:
|
|
607
|
-
color:
|
|
399
|
+
items={trace.map((item: any) => ({
|
|
400
|
+
key: item.id,
|
|
401
|
+
color: item.status === 'error' ? 'red' : item.status === 'running' ? 'blue' : 'green',
|
|
608
402
|
children: (
|
|
609
403
|
<Space direction="vertical" size={2} style={{ width: '100%' }}>
|
|
610
404
|
<Space wrap>
|
|
611
|
-
<Text strong>{
|
|
612
|
-
<
|
|
613
|
-
|
|
405
|
+
<Text strong>{item.title || item.type}</Text>
|
|
406
|
+
<Tag>{item.type}</Tag>
|
|
407
|
+
<StatusTag status={item.status} />
|
|
408
|
+
{item.toolName && <Text code>{item.toolName}</Text>}
|
|
409
|
+
{item.durationMs ? <Text type="secondary">{formatDurationMs(item.durationMs)}</Text> : null}
|
|
614
410
|
</Space>
|
|
615
|
-
<Text type="secondary">{formatDate(
|
|
616
|
-
{
|
|
411
|
+
<Text type="secondary">{formatDate(item.at)}</Text>
|
|
412
|
+
{item.content ? <TextBlock value={item.content} rows={4} /> : null}
|
|
617
413
|
</Space>
|
|
618
414
|
),
|
|
619
415
|
}))}
|
|
620
416
|
/>
|
|
621
417
|
) : (
|
|
622
|
-
<Empty description=
|
|
418
|
+
<Empty description={t('No execution flow captured')} />
|
|
623
419
|
)}
|
|
624
420
|
</Card>
|
|
625
421
|
|
|
626
422
|
<Collapse
|
|
627
423
|
items={[
|
|
628
424
|
{
|
|
629
|
-
key: '
|
|
630
|
-
label:
|
|
631
|
-
children:
|
|
425
|
+
key: 'toolMessages',
|
|
426
|
+
label: t('Native tool messages ({{count}})', { count: toolMessages.length }),
|
|
427
|
+
children: toolMessages.length ? (
|
|
632
428
|
<Table
|
|
633
|
-
rowKey=
|
|
429
|
+
rowKey={(record: any) => `${record.sessionId}:${record.toolCallId}`}
|
|
634
430
|
size="small"
|
|
635
|
-
dataSource={spans}
|
|
636
431
|
pagination={false}
|
|
432
|
+
dataSource={toolMessages}
|
|
637
433
|
scroll={{ x: 'max-content' }}
|
|
638
434
|
columns={[
|
|
435
|
+
{ title: t('Session'), dataIndex: 'sessionId', key: 'sessionId' },
|
|
436
|
+
{ title: t('Tool'), dataIndex: 'toolName', key: 'toolName' },
|
|
639
437
|
{
|
|
640
|
-
title: '
|
|
641
|
-
dataIndex: 'type',
|
|
642
|
-
key: 'type',
|
|
643
|
-
width: 110,
|
|
644
|
-
render: (value: string) => <Tag>{value}</Tag>,
|
|
645
|
-
},
|
|
646
|
-
{
|
|
647
|
-
title: 'Status',
|
|
438
|
+
title: t('Status'),
|
|
648
439
|
dataIndex: 'status',
|
|
649
440
|
key: 'status',
|
|
650
|
-
|
|
651
|
-
render: (value: string) => <StatusTag status={value} />,
|
|
652
|
-
},
|
|
653
|
-
{ title: 'Title', dataIndex: 'title', key: 'title' },
|
|
654
|
-
{
|
|
655
|
-
title: 'Tool',
|
|
656
|
-
dataIndex: 'toolName',
|
|
657
|
-
key: 'toolName',
|
|
658
|
-
render: (value: string) => (value ? <Text code>{value}</Text> : '-'),
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
title: 'Duration',
|
|
662
|
-
dataIndex: 'durationMs',
|
|
663
|
-
key: 'durationMs',
|
|
664
|
-
width: 100,
|
|
665
|
-
render: (value: number) => (value ? `${value}ms` : '-'),
|
|
441
|
+
render: (value: string) => <StatusTag status={value === 'error' ? 'error' : value} />,
|
|
666
442
|
},
|
|
443
|
+
{ title: t('Invoke'), dataIndex: 'invokeStatus', key: 'invokeStatus' },
|
|
667
444
|
{
|
|
668
|
-
title: '
|
|
669
|
-
dataIndex: '
|
|
670
|
-
key: '
|
|
671
|
-
|
|
672
|
-
render: (value: any) => value || '-',
|
|
445
|
+
title: t('Content'),
|
|
446
|
+
dataIndex: 'content',
|
|
447
|
+
key: 'content',
|
|
448
|
+
render: (value: unknown) => <TextBlock value={value} rows={3} />,
|
|
673
449
|
},
|
|
674
450
|
]}
|
|
675
451
|
/>
|
|
676
452
|
) : (
|
|
677
|
-
<Empty description=
|
|
453
|
+
<Empty description={t('No native tool messages')} />
|
|
678
454
|
),
|
|
679
455
|
},
|
|
680
456
|
{
|
|
681
|
-
key: '
|
|
682
|
-
label:
|
|
683
|
-
children:
|
|
684
|
-
<Space direction="vertical" size={
|
|
685
|
-
{
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
<StatusTag status={execution.status} />
|
|
695
|
-
{execution.agentLoopStepId && (
|
|
696
|
-
<Text type="secondary">step #{execution.agentLoopStepId}</Text>
|
|
697
|
-
)}
|
|
698
|
-
</Space>
|
|
699
|
-
}
|
|
700
|
-
>
|
|
701
|
-
<Space direction="vertical" size={8} style={{ width: '100%' }}>
|
|
702
|
-
<Descriptions size="small" column={2}>
|
|
703
|
-
<Descriptions.Item label="Duration">
|
|
704
|
-
{execution.durationMs ? `${execution.durationMs}ms` : '-'}
|
|
705
|
-
</Descriptions.Item>
|
|
706
|
-
<Descriptions.Item label="Created">
|
|
707
|
-
{formatDate(execution.createdAt)}
|
|
708
|
-
</Descriptions.Item>
|
|
709
|
-
</Descriptions>
|
|
710
|
-
<Collapse
|
|
711
|
-
size="small"
|
|
712
|
-
items={[
|
|
713
|
-
{
|
|
714
|
-
key: 'stdout',
|
|
715
|
-
label: 'stdout',
|
|
716
|
-
children: <TextBlock value={execution.stdout} rows={10} />,
|
|
717
|
-
},
|
|
718
|
-
{
|
|
719
|
-
key: 'stderr',
|
|
720
|
-
label: 'stderr',
|
|
721
|
-
children: <TextBlock value={execution.stderr} rows={10} />,
|
|
722
|
-
},
|
|
723
|
-
{
|
|
724
|
-
key: 'files',
|
|
725
|
-
label: `files (${files.length})`,
|
|
726
|
-
children: files.length ? (
|
|
727
|
-
<Space direction="vertical">
|
|
728
|
-
{files.map((file: any, index: number) =>
|
|
729
|
-
renderSkillFileLink(execution, file, index),
|
|
730
|
-
)}
|
|
731
|
-
</Space>
|
|
732
|
-
) : (
|
|
733
|
-
<Empty description="No files" />
|
|
734
|
-
),
|
|
735
|
-
},
|
|
736
|
-
]}
|
|
737
|
-
/>
|
|
738
|
-
</Space>
|
|
739
|
-
</Card>
|
|
740
|
-
);
|
|
741
|
-
})}
|
|
457
|
+
key: 'messages',
|
|
458
|
+
label: t('Native messages ({{count}})', { count: nativeMessages.length }),
|
|
459
|
+
children: nativeMessages.length ? (
|
|
460
|
+
<Space direction="vertical" size={8} style={{ width: '100%' }}>
|
|
461
|
+
{nativeMessages.map((item: any) => (
|
|
462
|
+
<Card
|
|
463
|
+
key={`${item.sessionId}:${item.messageId}`}
|
|
464
|
+
size="small"
|
|
465
|
+
title={`${item.role} #${item.messageId}`}
|
|
466
|
+
>
|
|
467
|
+
<TextBlock value={item.content || item.metadata} rows={6} />
|
|
468
|
+
</Card>
|
|
469
|
+
))}
|
|
742
470
|
</Space>
|
|
743
471
|
) : (
|
|
744
|
-
<Empty description=
|
|
472
|
+
<Empty description={t('No native messages loaded')} />
|
|
745
473
|
),
|
|
746
474
|
},
|
|
475
|
+
{
|
|
476
|
+
key: 'metadata',
|
|
477
|
+
label: t('Monitor metadata'),
|
|
478
|
+
children: <TextBlock value={selectedRun.metadata} rows={10} />,
|
|
479
|
+
},
|
|
747
480
|
]}
|
|
748
481
|
/>
|
|
749
482
|
|
|
750
|
-
{(
|
|
751
|
-
<Card title=
|
|
752
|
-
{
|
|
753
|
-
<Paragraph style={{ whiteSpace: 'pre-wrap', marginBottom: 12 }}>
|
|
754
|
-
<Text strong>Summary: </Text>
|
|
755
|
-
{run.summary}
|
|
756
|
-
</Paragraph>
|
|
757
|
-
)}
|
|
758
|
-
<TextBlock value={run.finalAnswer} rows={16} />
|
|
483
|
+
{(selectedRun.output || selectedRun.error) && (
|
|
484
|
+
<Card title={selectedRun.error ? t('Error') : t('Result')} size="small">
|
|
485
|
+
<TextBlock value={selectedRun.error || selectedRun.output} rows={12} />
|
|
759
486
|
</Card>
|
|
760
487
|
)}
|
|
761
488
|
</Space>
|