plugin-agent-orchestrator 1.0.22 → 1.0.23

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.
Files changed (96) hide show
  1. package/client-v2.d.ts +2 -0
  2. package/client-v2.js +1 -0
  3. package/dist/client/index.js +1 -1
  4. package/dist/client-v2/214.723affb37c13bf7a.js +10 -0
  5. package/dist/client-v2/264.0533912e6c5ea2d7.js +10 -0
  6. package/dist/client-v2/41.1805b2edfaa4afe2.js +10 -0
  7. package/dist/client-v2/418.5ae055abf141820e.js +10 -0
  8. package/dist/client-v2/619.d99d3c9e61c99064.js +10 -0
  9. package/dist/client-v2/70.a15d7fcec7c41768.js +10 -0
  10. package/dist/client-v2/892.72db4161511c8a16.js +10 -0
  11. package/dist/client-v2/926.87f660b670d85bcc.js +10 -0
  12. package/dist/client-v2/index.js +10 -0
  13. package/dist/externalVersion.js +7 -6
  14. package/dist/locale/en-US.json +7 -0
  15. package/dist/locale/vi-VN.json +7 -0
  16. package/dist/locale/zh-CN.json +27 -0
  17. package/dist/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.js +63 -0
  18. package/dist/server/plugin.js +32 -1
  19. package/dist/server/services/AgentHarness.js +52 -27
  20. package/dist/server/services/AgentLoopController.js +8 -2
  21. package/dist/server/services/AgentLoopService.js +1 -1
  22. package/dist/server/services/AgentRegistryService.js +53 -42
  23. package/dist/server/services/CircuitBreaker.js +7 -2
  24. package/dist/server/services/CodeValidator.js +48 -14
  25. package/dist/server/services/SandboxRunner.js +18 -14
  26. package/dist/server/skill-hub/plugin.js +44 -17
  27. package/dist/server/tools/delegate-task.js +7 -2
  28. package/dist/server/tools/skill-execute.js +33 -2
  29. package/dist/server/utils/ai-manager.js +51 -0
  30. package/dist/server/utils/ctx-utils.js +11 -0
  31. package/dist/server/utils/skill-settings.js +122 -0
  32. package/package.json +49 -45
  33. package/src/client/AIEmployeesContext.tsx +51 -14
  34. package/src/client/AgentRunsTab.tsx +767 -764
  35. package/src/client/HarnessProfilesTab.tsx +254 -247
  36. package/src/client/RulesTab.tsx +780 -716
  37. package/src/client/TracingTab.tsx +1 -0
  38. package/src/client/plugin.tsx +34 -27
  39. package/src/client/skill-hub/components/GitSkillImport.tsx +10 -3
  40. package/src/client/skill-hub/components/SkillMetrics.tsx +157 -124
  41. package/src/client/skill-hub/index.tsx +58 -51
  42. package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +132 -99
  43. package/src/client/skill-hub/tools/registerSkillLoopCards.ts +71 -58
  44. package/src/client/tools/registerOrchestratorCards.ts +17 -7
  45. package/src/client-v2/components/AIEmployeeSelect.tsx +47 -0
  46. package/src/client-v2/components/AIEmployeesContext.tsx +110 -0
  47. package/src/client-v2/components/AgentRunsTab.tsx +767 -0
  48. package/src/client-v2/components/HarnessProfilesTab.tsx +254 -0
  49. package/src/client-v2/components/RulesTab.tsx +782 -0
  50. package/src/client-v2/components/TracingTab.tsx +432 -0
  51. package/src/client-v2/hooks/useApiRequest.ts +114 -0
  52. package/src/client-v2/index.tsx +1 -0
  53. package/src/client-v2/pages/AgentRunsPage.tsx +13 -0
  54. package/src/client-v2/pages/ExecutionHistoryPage.tsx +10 -0
  55. package/src/client-v2/pages/HarnessProfilesPage.tsx +10 -0
  56. package/src/client-v2/pages/LoopSettingsPage.tsx +10 -0
  57. package/src/client-v2/pages/RulesPage.tsx +13 -0
  58. package/src/client-v2/pages/SkillDefinitionsPage.tsx +10 -0
  59. package/src/client-v2/pages/SkillMetricsPage.tsx +10 -0
  60. package/src/client-v2/pages/TracingPage.tsx +13 -0
  61. package/src/client-v2/plugin.tsx +70 -0
  62. package/src/client-v2/skill-hub/components/ExecutionHistory.tsx +196 -0
  63. package/src/client-v2/skill-hub/components/FileLinkList.tsx +37 -0
  64. package/src/client-v2/skill-hub/components/GitSkillImport.tsx +539 -0
  65. package/src/client-v2/skill-hub/components/LoopSettings.tsx +331 -0
  66. package/src/client-v2/skill-hub/components/SkillEditor.tsx +453 -0
  67. package/src/client-v2/skill-hub/components/SkillManager.tsx +174 -0
  68. package/src/client-v2/skill-hub/components/SkillMetrics.tsx +157 -0
  69. package/src/client-v2/skill-hub/components/SkillTestPanel.tsx +135 -0
  70. package/src/client-v2/skill-hub/locale.ts +13 -0
  71. package/src/client-v2/skill-hub/tools/loopTemplates.ts +52 -0
  72. package/src/client-v2/skill-hub/utils/jsonFields.ts +41 -0
  73. package/src/client-v2/utils/jsonFields.ts +41 -0
  74. package/src/locale/en-US.json +7 -0
  75. package/src/locale/vi-VN.json +7 -0
  76. package/src/locale/zh-CN.json +27 -0
  77. package/src/server/__tests__/agent-registry-service.test.ts +147 -0
  78. package/src/server/__tests__/code-validator.test.ts +63 -0
  79. package/src/server/__tests__/skill-execute.test.ts +33 -0
  80. package/src/server/__tests__/skill-settings.test.ts +63 -0
  81. package/src/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.ts +39 -0
  82. package/src/server/plugin.ts +62 -21
  83. package/src/server/services/AgentHarness.ts +49 -22
  84. package/src/server/services/AgentLoopController.ts +17 -6
  85. package/src/server/services/AgentLoopService.ts +1 -1
  86. package/src/server/services/AgentPlannerService.ts +10 -0
  87. package/src/server/services/AgentRegistryService.ts +89 -47
  88. package/src/server/services/CircuitBreaker.ts +10 -0
  89. package/src/server/services/CodeValidator.ts +237 -159
  90. package/src/server/services/SandboxRunner.ts +203 -189
  91. package/src/server/skill-hub/plugin.ts +933 -898
  92. package/src/server/tools/delegate-task.ts +12 -9
  93. package/src/server/tools/skill-execute.ts +194 -160
  94. package/src/server/utils/ai-manager.ts +24 -0
  95. package/src/server/utils/ctx-utils.ts +14 -0
  96. package/src/server/utils/skill-settings.ts +116 -0
@@ -0,0 +1,70 @@
1
+ import { Plugin, Application } from '@nocobase/client-v2';
2
+
3
+ export class PluginAgentOrchestratorClient extends Plugin<Record<string, never>, Application> {
4
+ async load() {
5
+ this.pluginSettingsManager.addMenuItem({
6
+ key: 'ai.orchestrator',
7
+ title: this.t('Agent Orchestrator'),
8
+ icon: 'ApartmentOutlined',
9
+ });
10
+
11
+ this.pluginSettingsManager.addPageTabItem({
12
+ menuKey: 'ai.orchestrator',
13
+ key: 'index',
14
+ title: this.t('Orchestration Rules'),
15
+ componentLoader: () => import('./pages/RulesPage'),
16
+ sort: -1,
17
+ });
18
+
19
+ this.pluginSettingsManager.addPageTabItem({
20
+ menuKey: 'ai.orchestrator',
21
+ key: 'tracing',
22
+ title: this.t('Execution Tracing'),
23
+ componentLoader: () => import('./pages/TracingPage'),
24
+ });
25
+
26
+ this.pluginSettingsManager.addPageTabItem({
27
+ menuKey: 'ai.orchestrator',
28
+ key: 'agent-runs',
29
+ title: this.t('Agent Runs'),
30
+ componentLoader: () => import('./pages/AgentRunsPage'),
31
+ });
32
+
33
+ this.pluginSettingsManager.addPageTabItem({
34
+ menuKey: 'ai.orchestrator',
35
+ key: 'harness-profiles',
36
+ title: this.t('Harness Profiles'),
37
+ componentLoader: () => import('./pages/HarnessProfilesPage'),
38
+ });
39
+
40
+ this.pluginSettingsManager.addPageTabItem({
41
+ menuKey: 'ai.orchestrator',
42
+ key: 'skill-definitions',
43
+ title: this.t('Skill Hub Definitions'),
44
+ componentLoader: () => import('./pages/SkillDefinitionsPage'),
45
+ });
46
+
47
+ this.pluginSettingsManager.addPageTabItem({
48
+ menuKey: 'ai.orchestrator',
49
+ key: 'skill-executions',
50
+ title: this.t('Execution History'),
51
+ componentLoader: () => import('./pages/ExecutionHistoryPage'),
52
+ });
53
+
54
+ this.pluginSettingsManager.addPageTabItem({
55
+ menuKey: 'ai.orchestrator',
56
+ key: 'skill-loop-settings',
57
+ title: this.t('Skill Review Settings'),
58
+ componentLoader: () => import('./pages/LoopSettingsPage'),
59
+ });
60
+
61
+ this.pluginSettingsManager.addPageTabItem({
62
+ menuKey: 'ai.orchestrator',
63
+ key: 'skill-metrics',
64
+ title: this.t('Metrics'),
65
+ componentLoader: () => import('./pages/SkillMetricsPage'),
66
+ });
67
+ }
68
+ }
69
+
70
+ export default PluginAgentOrchestratorClient;
@@ -0,0 +1,196 @@
1
+ import React, { useState, useEffect, useCallback } from 'react';
2
+ import { Card, Table, Tag, Button, Typography, Space, Tooltip, Popconfirm, message } from 'antd';
3
+ import { ReloadOutlined, DeleteOutlined } from '@ant-design/icons';
4
+ import { useApiClient as useAPIClient } from '../../hooks/useApiRequest';
5
+ import { useT } from '../locale';
6
+ import { parseJsonText } from '../utils/jsonFields';
7
+ import { FileLinkList } from './FileLinkList';
8
+
9
+ const STATUS_COLORS: Record<string, string> = {
10
+ pending: 'default',
11
+ running: 'processing',
12
+ succeeded: 'success',
13
+ failed: 'error',
14
+ canceled: 'warning',
15
+ timeout: 'error',
16
+ };
17
+
18
+ export const ExecutionHistory: React.FC = () => {
19
+ const api = useAPIClient();
20
+ const t = useT();
21
+ const [executions, setExecutions] = useState<any[]>([]);
22
+ const [loading, setLoading] = useState(false);
23
+ const [page, setPage] = useState(1);
24
+ const [total, setTotal] = useState(0);
25
+ const pageSize = 20;
26
+
27
+ const fetchExecutions = useCallback(async () => {
28
+ setLoading(true);
29
+ try {
30
+ const { data } = await api.request({
31
+ url: 'skillExecutions:list',
32
+ params: {
33
+ page,
34
+ pageSize,
35
+ sort: ['-createdAt'],
36
+ appends: ['skill', 'triggeredBy'],
37
+ },
38
+ });
39
+ const rawData = data?.data?.data ?? data?.data ?? [];
40
+ setExecutions(Array.isArray(rawData) ? rawData : []);
41
+ setTotal(data?.meta?.count || 0);
42
+ } catch {
43
+ // ignore
44
+ } finally {
45
+ setLoading(false);
46
+ }
47
+ }, [api, page]);
48
+
49
+ useEffect(() => {
50
+ fetchExecutions();
51
+ }, [fetchExecutions]);
52
+
53
+ const handleDelete = async (id: number) => {
54
+ try {
55
+ await api.request({
56
+ url: `skillExecutions:destroy`,
57
+ method: 'POST',
58
+ params: {
59
+ filterByTk: id,
60
+ },
61
+ });
62
+ message.success(t('Deleted successfully'));
63
+ fetchExecutions();
64
+ } catch (err: any) {
65
+ message.error(err?.response?.data?.errors?.[0]?.message || t('Delete failed'));
66
+ }
67
+ };
68
+
69
+ const columns = [
70
+ {
71
+ title: 'ID',
72
+ dataIndex: 'id',
73
+ key: 'id',
74
+ width: 80,
75
+ },
76
+ {
77
+ title: t('Skill'),
78
+ dataIndex: ['skill', 'title'],
79
+ key: 'skill',
80
+ width: 180,
81
+ },
82
+ {
83
+ title: t('Status'),
84
+ dataIndex: 'status',
85
+ key: 'status',
86
+ width: 120,
87
+ render: (status: string) => <Tag color={STATUS_COLORS[status] || 'default'}>{status}</Tag>,
88
+ },
89
+ {
90
+ title: t('Duration'),
91
+ dataIndex: 'durationMs',
92
+ key: 'duration',
93
+ width: 100,
94
+ render: (ms: number) => (ms ? `${(ms / 1000).toFixed(1)}s` : '-'),
95
+ },
96
+ {
97
+ title: t('Files'),
98
+ dataIndex: 'outputFiles',
99
+ key: 'files',
100
+ width: 250,
101
+ render: (files: any[], record: any) => {
102
+ const parsed = parseJsonText<any[]>(files, []);
103
+ if (!Array.isArray(parsed) || !parsed.length) return '-';
104
+ const formattedFiles = parsed.map((f) => ({
105
+ name: f.name,
106
+ url: `/api/skillHub:download?execId=${record.id}&filename=${encodeURIComponent(f.name)}`,
107
+ }));
108
+ return <FileLinkList files={formattedFiles} />;
109
+ },
110
+ },
111
+ {
112
+ title: t('Triggered By'),
113
+ dataIndex: ['triggeredBy', 'nickname'],
114
+ key: 'triggeredBy',
115
+ width: 120,
116
+ render: (v: string) => v || '-',
117
+ },
118
+ {
119
+ title: t('Created At'),
120
+ dataIndex: 'createdAt',
121
+ key: 'createdAt',
122
+ width: 180,
123
+ render: (v: string) => (v ? new Date(v).toLocaleString() : '-'),
124
+ },
125
+ {
126
+ title: t('Output'),
127
+ key: 'output',
128
+ width: 200,
129
+ render: (_: any, record: any) => (
130
+ <Space direction="vertical" size={0}>
131
+ {record.stdout && (
132
+ <Tooltip title={record.stdout}>
133
+ <Typography.Text style={{ fontSize: 12, maxWidth: 200 }} ellipsis>
134
+ {record.stdout}
135
+ </Typography.Text>
136
+ </Tooltip>
137
+ )}
138
+ {record.stderr && (
139
+ <Tooltip title={record.stderr}>
140
+ <Typography.Text type="danger" style={{ fontSize: 12, maxWidth: 200 }} ellipsis>
141
+ {record.stderr}
142
+ </Typography.Text>
143
+ </Tooltip>
144
+ )}
145
+ </Space>
146
+ ),
147
+ },
148
+ {
149
+ title: t('Actions'),
150
+ key: 'actions',
151
+ width: 80,
152
+ fixed: 'right' as const,
153
+ render: (_: any, record: any) => (
154
+ <Space size="middle">
155
+ <Popconfirm
156
+ title={t('Are you sure to delete this execution history and its files?')}
157
+ onConfirm={() => handleDelete(record.id)}
158
+ okText={t('Yes')}
159
+ cancelText={t('No')}
160
+ >
161
+ <Button type="text" danger icon={<DeleteOutlined />} size="small" />
162
+ </Popconfirm>
163
+ </Space>
164
+ ),
165
+ },
166
+ ];
167
+
168
+ return (
169
+ <Card
170
+ title={t('Execution History')}
171
+ extra={
172
+ <Space>
173
+ <Button icon={<ReloadOutlined />} onClick={fetchExecutions} loading={loading}>
174
+ {t('Refresh')}
175
+ </Button>
176
+ </Space>
177
+ }
178
+ >
179
+ <Table
180
+ dataSource={executions}
181
+ columns={columns}
182
+ rowKey="id"
183
+ loading={loading}
184
+ size="middle"
185
+ pagination={{
186
+ current: page,
187
+ pageSize,
188
+ total,
189
+ onChange: setPage,
190
+ showTotal: (count) => `Total: ${count}`,
191
+ }}
192
+ scroll={{ x: 1200 }}
193
+ />
194
+ </Card>
195
+ );
196
+ };
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { Space, Typography } from 'antd';
3
+ import { PaperClipOutlined } from '@ant-design/icons';
4
+
5
+ export interface FileLinkItem {
6
+ name: string;
7
+ url?: string;
8
+ downloadUrl?: string;
9
+ }
10
+
11
+ /**
12
+ * client-v2 replacement for the v1 `Upload.ReadPretty` file list, which is not
13
+ * exported by `@nocobase/client-v2`. Renders a simple vertical list of download
14
+ * links; non-resolvable entries fall back to plain text.
15
+ */
16
+ export const FileLinkList: React.FC<{ files: FileLinkItem[] }> = ({ files }) => {
17
+ if (!Array.isArray(files) || files.length === 0) {
18
+ return <Typography.Text type="secondary">-</Typography.Text>;
19
+ }
20
+ return (
21
+ <Space direction="vertical" size={2} style={{ width: '100%' }}>
22
+ {files.map((file, index) => {
23
+ const url = file.downloadUrl || file.url;
24
+ const label = file.name || `file-${index + 1}`;
25
+ return url ? (
26
+ <a key={`${label}-${index}`} href={url} target="_blank" rel="noreferrer">
27
+ <PaperClipOutlined /> {label}
28
+ </a>
29
+ ) : (
30
+ <Typography.Text key={`${label}-${index}`}>
31
+ <PaperClipOutlined /> {label}
32
+ </Typography.Text>
33
+ );
34
+ })}
35
+ </Space>
36
+ );
37
+ };