plugin-agent-orchestrator 1.0.28 → 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/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/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
|
@@ -282,44 +282,44 @@ export const SkillEditor: React.FC<SkillEditorProps> = ({ skill, onClose }) => {
|
|
|
282
282
|
|
|
283
283
|
{storageType === 'plugin' && (
|
|
284
284
|
<>
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
>
|
|
310
|
-
<Select
|
|
311
|
-
placeholder={t('Choose an enabled plugin skill to attach')}
|
|
312
|
-
onChange={handleTemplateSelect}
|
|
313
|
-
allowClear
|
|
285
|
+
<Form.Item name="inputSchema" hidden>
|
|
286
|
+
<TextArea />
|
|
287
|
+
</Form.Item>
|
|
288
|
+
<Form.Item name="packages" hidden>
|
|
289
|
+
<Input />
|
|
290
|
+
</Form.Item>
|
|
291
|
+
<Form.Item
|
|
292
|
+
name="pluginSource"
|
|
293
|
+
label={t('Select Plugin Skill')}
|
|
294
|
+
rules={[{ required: true }]}
|
|
295
|
+
style={{
|
|
296
|
+
marginBottom: 24,
|
|
297
|
+
padding: 12,
|
|
298
|
+
background: '#e6f4ff',
|
|
299
|
+
borderRadius: 8,
|
|
300
|
+
border: '1px solid #91caff',
|
|
301
|
+
}}
|
|
302
|
+
extra={
|
|
303
|
+
<div style={{ fontSize: 12, color: '#1677ff', marginTop: 8 }}>
|
|
304
|
+
{t(
|
|
305
|
+
'Binding dynamically delegates execution to the plugin logic. Code, Language, and Schemas are managed externally.',
|
|
306
|
+
)}
|
|
307
|
+
</div>
|
|
308
|
+
}
|
|
314
309
|
>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
|
|
310
|
+
<Select
|
|
311
|
+
placeholder={t('Choose an enabled plugin skill to attach')}
|
|
312
|
+
onChange={handleTemplateSelect}
|
|
313
|
+
allowClear
|
|
314
|
+
>
|
|
315
|
+
{Array.isArray(templates) &&
|
|
316
|
+
templates.map((tmpl) => (
|
|
317
|
+
<Select.Option key={tmpl.name} value={tmpl.name}>
|
|
318
|
+
{tmpl.title} ({tmpl.pluginSource || tmpl.name})
|
|
319
|
+
</Select.Option>
|
|
320
|
+
))}
|
|
321
|
+
</Select>
|
|
322
|
+
</Form.Item>
|
|
323
323
|
</>
|
|
324
324
|
)}
|
|
325
325
|
|
|
@@ -417,12 +417,16 @@ export const SkillEditor: React.FC<SkillEditorProps> = ({ skill, onClose }) => {
|
|
|
417
417
|
<Form.Item
|
|
418
418
|
name="interactionSchema"
|
|
419
419
|
label={t('Interaction Schema (optional)')}
|
|
420
|
-
extra={t(
|
|
420
|
+
extra={t(
|
|
421
|
+
'If set, user is prompted to fill / confirm input before execution. Type: form | select | confirm.',
|
|
422
|
+
)}
|
|
421
423
|
>
|
|
422
424
|
<TextArea
|
|
423
425
|
rows={6}
|
|
424
426
|
style={{ fontFamily: 'monospace', fontSize: 13 }}
|
|
425
|
-
placeholder={
|
|
427
|
+
placeholder={
|
|
428
|
+
'{\n "type": "form",\n "prompt": "Confirm parameters",\n "fields": {\n "fileName": { "type": "string", "title": "File name", "required": true }\n }\n}'
|
|
429
|
+
}
|
|
426
430
|
/>
|
|
427
431
|
</Form.Item>
|
|
428
432
|
|
|
@@ -1,181 +1,194 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Card,
|
|
4
|
-
Button,
|
|
5
|
-
Space,
|
|
6
|
-
Modal,
|
|
7
|
-
Form,
|
|
8
|
-
Input,
|
|
9
|
-
Select,
|
|
10
|
-
Switch,
|
|
11
|
-
InputNumber,
|
|
12
|
-
message,
|
|
13
|
-
Popconfirm,
|
|
14
|
-
Tag,
|
|
15
|
-
List,
|
|
16
|
-
Typography,
|
|
17
|
-
Tooltip,
|
|
18
|
-
} from 'antd';
|
|
19
|
-
import { PlusOutlined, EditOutlined, DeleteOutlined, PlayCircleOutlined, BranchesOutlined } from '@ant-design/icons';
|
|
20
|
-
import { useApp } from '@nocobase/client-v2';
|
|
21
|
-
import { useT } from '../locale';
|
|
22
|
-
import { SkillEditor } from './SkillEditor';
|
|
23
|
-
import { SkillTestPanel } from './SkillTestPanel';
|
|
24
|
-
import { GitSkillImport } from './GitSkillImport';
|
|
25
|
-
|
|
26
|
-
const { TextArea } = Input;
|
|
27
|
-
|
|
28
|
-
export const SkillManager: React.FC = () => {
|
|
29
|
-
const api = useApp().apiClient;
|
|
30
|
-
const t = useT();
|
|
31
|
-
const [skills, setSkills] = useState<any[]>([]);
|
|
32
|
-
const [loading, setLoading] = useState(false);
|
|
33
|
-
const [editorVisible, setEditorVisible] = useState(false);
|
|
34
|
-
const [testVisible, setTestVisible] = useState(false);
|
|
35
|
-
const [editingSkill, setEditingSkill] = useState<any>(null);
|
|
36
|
-
const [testingSkill, setTestingSkill] = useState<any>(null);
|
|
37
|
-
const [gitImportVisible, setGitImportVisible] = useState(false);
|
|
38
|
-
|
|
39
|
-
const fetchSkills = useCallback(async () => {
|
|
40
|
-
setLoading(true);
|
|
41
|
-
try {
|
|
42
|
-
const { data } = await api.request({ url: 'skillDefinitions:list', params: { pageSize: 100 } });
|
|
43
|
-
const rawData = data?.data?.data ?? data?.data ?? [];
|
|
44
|
-
setSkills(Array.isArray(rawData) ? rawData : []);
|
|
45
|
-
} catch {
|
|
46
|
-
message.error(t('Failed to load skills'));
|
|
47
|
-
} finally {
|
|
48
|
-
setLoading(false);
|
|
49
|
-
}
|
|
50
|
-
}, [api, t]);
|
|
51
|
-
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
fetchSkills();
|
|
54
|
-
}, [fetchSkills]);
|
|
55
|
-
|
|
56
|
-
const handleCreate = () => {
|
|
57
|
-
setEditingSkill(null);
|
|
58
|
-
setEditorVisible(true);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const handleEdit = (record: any) => {
|
|
62
|
-
setEditingSkill(record);
|
|
63
|
-
setEditorVisible(true);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const handleTest = (record: any) => {
|
|
67
|
-
setTestingSkill(record);
|
|
68
|
-
setTestVisible(true);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const handleDelete = async (id: number) => {
|
|
72
|
-
try {
|
|
73
|
-
await api.request({ url: 'skillDefinitions:destroy', method: 'POST', params: { filterByTk: id } });
|
|
74
|
-
message.success(t('Deleted'));
|
|
75
|
-
fetchSkills();
|
|
76
|
-
} catch {
|
|
77
|
-
message.error(t('Failed to delete'));
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const handleToggleEnabled = async (record: any) => {
|
|
82
|
-
try {
|
|
83
|
-
await api.request({
|
|
84
|
-
url: 'skillDefinitions:update',
|
|
85
|
-
method: 'POST',
|
|
86
|
-
params: { filterByTk: record.id },
|
|
87
|
-
data: { enabled: !record.enabled },
|
|
88
|
-
});
|
|
89
|
-
fetchSkills();
|
|
90
|
-
} catch {
|
|
91
|
-
message.error(t('Failed to update'));
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const handleEditorClose = (saved?: boolean) => {
|
|
96
|
-
setEditorVisible(false);
|
|
97
|
-
setEditingSkill(null);
|
|
98
|
-
if (saved) fetchSkills();
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Table columns definition removed in favor of List rendering
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<Card
|
|
105
|
-
title={t('Skill Definitions')}
|
|
106
|
-
extra={
|
|
107
|
-
<Space>
|
|
108
|
-
<Button icon={<BranchesOutlined />} onClick={() => setGitImportVisible(true)}>
|
|
109
|
-
{t('Import from Git')}
|
|
110
|
-
</Button>
|
|
111
|
-
<Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}>
|
|
112
|
-
{t('New Skill')}
|
|
113
|
-
</Button>
|
|
114
|
-
</Space>
|
|
115
|
-
}
|
|
116
|
-
>
|
|
117
|
-
<List
|
|
118
|
-
grid={{ gutter: 16, xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }}
|
|
119
|
-
dataSource={skills}
|
|
120
|
-
loading={loading}
|
|
121
|
-
renderItem={(skill) => (
|
|
122
|
-
<List.Item>
|
|
123
|
-
<Card
|
|
124
|
-
size="small"
|
|
125
|
-
title={
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Card,
|
|
4
|
+
Button,
|
|
5
|
+
Space,
|
|
6
|
+
Modal,
|
|
7
|
+
Form,
|
|
8
|
+
Input,
|
|
9
|
+
Select,
|
|
10
|
+
Switch,
|
|
11
|
+
InputNumber,
|
|
12
|
+
message,
|
|
13
|
+
Popconfirm,
|
|
14
|
+
Tag,
|
|
15
|
+
List,
|
|
16
|
+
Typography,
|
|
17
|
+
Tooltip,
|
|
18
|
+
} from 'antd';
|
|
19
|
+
import { PlusOutlined, EditOutlined, DeleteOutlined, PlayCircleOutlined, BranchesOutlined } from '@ant-design/icons';
|
|
20
|
+
import { useApp } from '@nocobase/client-v2';
|
|
21
|
+
import { useT } from '../locale';
|
|
22
|
+
import { SkillEditor } from './SkillEditor';
|
|
23
|
+
import { SkillTestPanel } from './SkillTestPanel';
|
|
24
|
+
import { GitSkillImport } from './GitSkillImport';
|
|
25
|
+
|
|
26
|
+
const { TextArea } = Input;
|
|
27
|
+
|
|
28
|
+
export const SkillManager: React.FC = () => {
|
|
29
|
+
const api = useApp().apiClient;
|
|
30
|
+
const t = useT();
|
|
31
|
+
const [skills, setSkills] = useState<any[]>([]);
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
const [editorVisible, setEditorVisible] = useState(false);
|
|
34
|
+
const [testVisible, setTestVisible] = useState(false);
|
|
35
|
+
const [editingSkill, setEditingSkill] = useState<any>(null);
|
|
36
|
+
const [testingSkill, setTestingSkill] = useState<any>(null);
|
|
37
|
+
const [gitImportVisible, setGitImportVisible] = useState(false);
|
|
38
|
+
|
|
39
|
+
const fetchSkills = useCallback(async () => {
|
|
40
|
+
setLoading(true);
|
|
41
|
+
try {
|
|
42
|
+
const { data } = await api.request({ url: 'skillDefinitions:list', params: { pageSize: 100 } });
|
|
43
|
+
const rawData = data?.data?.data ?? data?.data ?? [];
|
|
44
|
+
setSkills(Array.isArray(rawData) ? rawData : []);
|
|
45
|
+
} catch {
|
|
46
|
+
message.error(t('Failed to load skills'));
|
|
47
|
+
} finally {
|
|
48
|
+
setLoading(false);
|
|
49
|
+
}
|
|
50
|
+
}, [api, t]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
fetchSkills();
|
|
54
|
+
}, [fetchSkills]);
|
|
55
|
+
|
|
56
|
+
const handleCreate = () => {
|
|
57
|
+
setEditingSkill(null);
|
|
58
|
+
setEditorVisible(true);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleEdit = (record: any) => {
|
|
62
|
+
setEditingSkill(record);
|
|
63
|
+
setEditorVisible(true);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const handleTest = (record: any) => {
|
|
67
|
+
setTestingSkill(record);
|
|
68
|
+
setTestVisible(true);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const handleDelete = async (id: number) => {
|
|
72
|
+
try {
|
|
73
|
+
await api.request({ url: 'skillDefinitions:destroy', method: 'POST', params: { filterByTk: id } });
|
|
74
|
+
message.success(t('Deleted'));
|
|
75
|
+
fetchSkills();
|
|
76
|
+
} catch {
|
|
77
|
+
message.error(t('Failed to delete'));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const handleToggleEnabled = async (record: any) => {
|
|
82
|
+
try {
|
|
83
|
+
await api.request({
|
|
84
|
+
url: 'skillDefinitions:update',
|
|
85
|
+
method: 'POST',
|
|
86
|
+
params: { filterByTk: record.id },
|
|
87
|
+
data: { enabled: !record.enabled },
|
|
88
|
+
});
|
|
89
|
+
fetchSkills();
|
|
90
|
+
} catch {
|
|
91
|
+
message.error(t('Failed to update'));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const handleEditorClose = (saved?: boolean) => {
|
|
96
|
+
setEditorVisible(false);
|
|
97
|
+
setEditingSkill(null);
|
|
98
|
+
if (saved) fetchSkills();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Table columns definition removed in favor of List rendering
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<Card
|
|
105
|
+
title={t('Skill Definitions')}
|
|
106
|
+
extra={
|
|
107
|
+
<Space>
|
|
108
|
+
<Button icon={<BranchesOutlined />} onClick={() => setGitImportVisible(true)}>
|
|
109
|
+
{t('Import from Git')}
|
|
110
|
+
</Button>
|
|
111
|
+
<Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}>
|
|
112
|
+
{t('New Skill')}
|
|
113
|
+
</Button>
|
|
114
|
+
</Space>
|
|
115
|
+
}
|
|
116
|
+
>
|
|
117
|
+
<List
|
|
118
|
+
grid={{ gutter: 16, xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }}
|
|
119
|
+
dataSource={skills}
|
|
120
|
+
loading={loading}
|
|
121
|
+
renderItem={(skill) => (
|
|
122
|
+
<List.Item>
|
|
123
|
+
<Card
|
|
124
|
+
size="small"
|
|
125
|
+
title={
|
|
126
|
+
<Typography.Text ellipsis title={skill.title}>
|
|
127
|
+
{skill.title}
|
|
128
|
+
</Typography.Text>
|
|
129
|
+
}
|
|
130
|
+
extra={<Tag color={skill.language === 'python' ? 'blue' : 'green'}>{skill.language}</Tag>}
|
|
131
|
+
actions={[
|
|
132
|
+
<Tooltip key="test" title={t('Test')}>
|
|
133
|
+
<PlayCircleOutlined onClick={() => handleTest(skill)} />
|
|
134
|
+
</Tooltip>,
|
|
135
|
+
<Tooltip key="edit" title={t('Edit')}>
|
|
136
|
+
<EditOutlined onClick={() => handleEdit(skill)} />
|
|
137
|
+
</Tooltip>,
|
|
138
|
+
<Popconfirm key="delete" title={t('Delete?')} onConfirm={() => handleDelete(skill.id)}>
|
|
139
|
+
<Tooltip title={t('Delete')}>
|
|
140
|
+
<DeleteOutlined style={{ color: 'red' }} />
|
|
141
|
+
</Tooltip>
|
|
142
|
+
</Popconfirm>,
|
|
143
|
+
]}
|
|
144
|
+
style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.05)', borderRadius: 8 }}
|
|
145
|
+
>
|
|
146
|
+
<Card.Meta
|
|
147
|
+
title={
|
|
148
|
+
<Typography.Text type="secondary" style={{ fontSize: 13 }}>
|
|
149
|
+
{skill.name}
|
|
150
|
+
</Typography.Text>
|
|
151
|
+
}
|
|
152
|
+
description={
|
|
153
|
+
<div
|
|
154
|
+
style={{
|
|
155
|
+
height: 60,
|
|
156
|
+
overflow: 'hidden',
|
|
157
|
+
display: '-webkit-box',
|
|
158
|
+
WebkitLineClamp: 3,
|
|
159
|
+
WebkitBoxOrient: 'vertical',
|
|
160
|
+
fontSize: 13,
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
{skill.description || t('No description')}
|
|
164
|
+
</div>
|
|
165
|
+
}
|
|
166
|
+
/>
|
|
167
|
+
<div style={{ marginTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
168
|
+
<Space size={4}>
|
|
169
|
+
<Switch checked={skill.enabled} onChange={() => handleToggleEnabled(skill)} size="small" />
|
|
170
|
+
<span style={{ fontSize: 12 }}>{skill.enabled ? t('Enabled') : t('Disabled')}</span>
|
|
171
|
+
</Space>
|
|
172
|
+
<Tag color="purple" style={{ margin: 0, fontSize: 11 }}>
|
|
173
|
+
{skill.storageType ? skill.storageType.toUpperCase() : 'DB'}
|
|
174
|
+
</Tag>
|
|
175
|
+
</div>
|
|
176
|
+
</Card>
|
|
177
|
+
</List.Item>
|
|
178
|
+
)}
|
|
179
|
+
/>
|
|
180
|
+
|
|
181
|
+
{editorVisible && <SkillEditor skill={editingSkill} onClose={handleEditorClose} />}
|
|
182
|
+
|
|
183
|
+
{testVisible && testingSkill && <SkillTestPanel skill={testingSkill} onClose={() => setTestVisible(false)} />}
|
|
184
|
+
|
|
185
|
+
<GitSkillImport
|
|
186
|
+
open={gitImportVisible}
|
|
187
|
+
onClose={(synced) => {
|
|
188
|
+
setGitImportVisible(false);
|
|
189
|
+
if (synced) fetchSkills();
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
</Card>
|
|
193
|
+
);
|
|
194
|
+
};
|