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
@@ -269,6 +269,7 @@ export const TracingTab: React.FC = () => {
269
269
  dataSource={logs}
270
270
  columns={columns}
271
271
  size="middle"
272
+ scroll={{ x: 'max-content' }}
272
273
  pagination={{
273
274
  current: page,
274
275
  pageSize,
@@ -1,27 +1,34 @@
1
- import { Plugin } from '@nocobase/client';
2
- import { OrchestratorSettings } from './OrchestratorSettings';
3
- import { InteractionSchemasProvider } from './skill-hub/tools/InteractionSchemasProvider';
4
- import { registerSkillLoopCards } from './skill-hub/tools/registerSkillLoopCards';
5
- import { registerOrchestratorCards } from './tools/registerOrchestratorCards';
6
-
7
- export class PluginAgentOrchestratorClient extends Plugin {
8
- async load() {
9
- (this as any).app.use(InteractionSchemasProvider);
10
-
11
- // Register under the "AI" settings group for consistency with other AI plugins
12
- (this as any).app.pluginSettingsManager.add('ai.orchestrator', {
13
- title: 'Agent Orchestrator',
14
- icon: 'ApartmentOutlined',
15
- Component: OrchestratorSettings,
16
- });
17
-
18
- await this.registerSkillUiCards();
19
- }
20
-
21
- private async registerSkillUiCards() {
22
- await registerOrchestratorCards((this as any).app);
23
- await registerSkillLoopCards((this as any).app);
24
- }
25
- }
26
-
27
- export default PluginAgentOrchestratorClient;
1
+ import { Plugin } from '@nocobase/client';
2
+ import { OrchestratorSettings } from './OrchestratorSettings';
3
+ import { InteractionSchemasProvider } from './skill-hub/tools/InteractionSchemasProvider';
4
+ import { registerSkillLoopCards } from './skill-hub/tools/registerSkillLoopCards';
5
+ import { registerOrchestratorCards } from './tools/registerOrchestratorCards';
6
+
7
+ export class PluginAgentOrchestratorClient extends Plugin {
8
+ async load() {
9
+ (this as any).app.use(InteractionSchemasProvider);
10
+
11
+ // Register under the "AI" settings group for consistency with other AI plugins
12
+ (this as any).app.pluginSettingsManager.add('ai.orchestrator', {
13
+ title: 'Agent Orchestrator',
14
+ icon: 'ApartmentOutlined',
15
+ Component: OrchestratorSettings,
16
+ });
17
+
18
+ (this as any).app.eventBus?.addEventListener?.('auth:tokenChanged', (event: Event) => {
19
+ const token = (event as CustomEvent<{ token?: string | null }>).detail?.token;
20
+ if (token) {
21
+ registerSkillLoopCards((this as any).app);
22
+ }
23
+ });
24
+
25
+ await this.registerSkillUiCards();
26
+ }
27
+
28
+ private async registerSkillUiCards() {
29
+ await registerOrchestratorCards((this as any).app);
30
+ await registerSkillLoopCards((this as any).app);
31
+ }
32
+ }
33
+
34
+ export default PluginAgentOrchestratorClient;
@@ -178,8 +178,7 @@ export const GitSkillImport: React.FC<GitSkillImportProps> = ({ open, onClose })
178
178
  const lower = searchText.toLowerCase();
179
179
  return skills.filter(
180
180
  (s) =>
181
- (s.title || s.name || '').toLowerCase().includes(lower) ||
182
- (s.description || '').toLowerCase().includes(lower),
181
+ (s.title || s.name || '').toLowerCase().includes(lower) || (s.description || '').toLowerCase().includes(lower),
183
182
  );
184
183
  }, [skills, searchText]);
185
184
 
@@ -531,6 +530,7 @@ export const GitSkillImport: React.FC<GitSkillImportProps> = ({ open, onClose })
531
530
  selectedRowKeys: selectedSkills,
532
531
  onChange: (keys) => setSelectedSkills(keys as string[]),
533
532
  }}
533
+ scroll={{ x: 'max-content' }}
534
534
  />
535
535
  </div>
536
536
  )}
@@ -547,7 +547,14 @@ export const GitSkillImport: React.FC<GitSkillImportProps> = ({ open, onClose })
547
547
  syncResults.filter((r) => r.status === 'updated').length
548
548
  } ${t('updated')}, ${syncResults.filter((r) => r.status === 'skipped').length} ${t('skipped')}`}
549
549
  />
550
- <Table dataSource={syncResults} columns={resultColumns} rowKey="folder" size="small" pagination={false} />
550
+ <Table
551
+ dataSource={syncResults}
552
+ columns={resultColumns}
553
+ rowKey="folder"
554
+ size="small"
555
+ pagination={false}
556
+ scroll={{ x: 'max-content' }}
557
+ />
551
558
  </div>
552
559
  )}
553
560
  </Modal>
@@ -1,124 +1,157 @@
1
- import React, { useState, useEffect, useCallback, useMemo } from 'react';
2
- import { Card, Table, Typography, Space, Row, Col, Statistic, Progress } from 'antd';
3
- import { SyncOutlined, CheckCircleOutlined, CloseCircleOutlined, ClockCircleOutlined } from '@ant-design/icons';
4
- import { useAPIClient } from '@nocobase/client';
5
- import { useT } from '../locale';
6
-
7
- const { Title, Text } = Typography;
8
-
9
- export const SkillMetrics: React.FC = () => {
10
- const api = useAPIClient();
11
- const t = useT();
12
- const [executions, setExecutions] = useState<any[]>([]);
13
- const [loading, setLoading] = useState(false);
14
-
15
- const fetchExecutions = useCallback(async () => {
16
- setLoading(true);
17
- try {
18
- // Fetch up to 1000 recent executions to calculate basic metrics
19
- const { data } = await api.request({
20
- url: 'skillExecutions:list',
21
- params: {
22
- pageSize: 1000,
23
- sort: ['-createdAt'],
24
- appends: ['skill'],
25
- },
26
- });
27
- const rawData = data?.data?.data ?? data?.data ?? [];
28
- setExecutions(Array.isArray(rawData) ? rawData : []);
29
- } catch {
30
- // ignore
31
- } finally {
32
- setLoading(false);
33
- }
34
- }, [api]);
35
-
36
- useEffect(() => {
37
- fetchExecutions();
38
- }, [fetchExecutions]);
39
-
40
- const metrics = useMemo(() => {
41
- const total = executions.length;
42
- const succeeded = executions.filter((e) => e.status === 'succeeded').length;
43
- const failed = executions.filter((e) => e.status === 'failed').length;
44
- const timeout = executions.filter((e) => e.status === 'timeout').length;
45
- const canceled = executions.filter((e) => e.status === 'canceled').length;
46
-
47
- // Group by skill
48
- const bySkill: Record<string, any> = {};
49
- executions.forEach((e) => {
50
- const skillName = e.skill?.title || e.skill?.name || 'Unknown';
51
- if (!bySkill[skillName]) {
52
- bySkill[skillName] = { name: skillName, total: 0, succeeded: 0, failed: 0, timeout: 0, canceled: 0, totalDuration: 0, durationCount: 0 };
53
- }
54
- bySkill[skillName].total += 1;
55
- bySkill[skillName][e.status] = (bySkill[skillName][e.status] || 0) + 1;
56
- if (e.durationMs) {
57
- bySkill[skillName].totalDuration += e.durationMs;
58
- bySkill[skillName].durationCount += 1;
59
- }
60
- });
61
-
62
- const skillData = Object.values(bySkill).map((s) => ({
63
- ...s,
64
- successRate: s.total > 0 ? (s.succeeded / s.total) * 100 : 0,
65
- avgDuration: s.durationCount > 0 ? (s.totalDuration / s.durationCount / 1000).toFixed(2) : 0,
66
- })).sort((a: any, b: any) => b.total - a.total);
67
-
68
- return { total, succeeded, failed, timeout, canceled, skillData };
69
- }, [executions]);
70
-
71
- const columns = [
72
- { title: t('Skill'), dataIndex: 'name', key: 'name', width: 200 },
73
- { title: t('Total Runs'), dataIndex: 'total', key: 'total', width: 100 },
74
- {
75
- title: t('Success Rate'),
76
- dataIndex: 'successRate',
77
- key: 'successRate',
78
- width: 150,
79
- render: (val: number) => <Progress percent={Math.round(val)} size="small" status={val === 100 ? 'success' : val > 50 ? 'active' : 'exception'} />
80
- },
81
- { title: t('Success'), dataIndex: 'succeeded', key: 'succeeded', width: 100 },
82
- { title: t('Failed'), dataIndex: 'failed', key: 'failed', width: 100 },
83
- { title: t('Timeout'), dataIndex: 'timeout', key: 'timeout', width: 100 },
84
- { title: t('Avg Duration (s)'), dataIndex: 'avgDuration', key: 'avgDuration', width: 120 },
85
- ];
86
-
87
- return (
88
- <Space direction="vertical" size="large" style={{ width: '100%', padding: '0 16px' }}>
89
- <Row gutter={16}>
90
- <Col span={6}>
91
- <Card size="small">
92
- <Statistic title="Total Executions (Recent)" value={metrics.total} prefix={<SyncOutlined />} />
93
- </Card>
94
- </Col>
95
- <Col span={6}>
96
- <Card size="small">
97
- <Statistic title="Succeeded" value={metrics.succeeded} valueStyle={{ color: '#3f8600' }} prefix={<CheckCircleOutlined />} />
98
- </Card>
99
- </Col>
100
- <Col span={6}>
101
- <Card size="small">
102
- <Statistic title="Failed" value={metrics.failed} valueStyle={{ color: '#cf1322' }} prefix={<CloseCircleOutlined />} />
103
- </Card>
104
- </Col>
105
- <Col span={6}>
106
- <Card size="small">
107
- <Statistic title="Timeout/Canceled" value={metrics.timeout + metrics.canceled} valueStyle={{ color: '#faad14' }} prefix={<ClockCircleOutlined />} />
108
- </Card>
109
- </Col>
110
- </Row>
111
-
112
- <Card title={t('Metrics by Skill (Recent)')}>
113
- <Table
114
- dataSource={metrics.skillData}
115
- columns={columns}
116
- rowKey="name"
117
- loading={loading}
118
- pagination={false}
119
- size="middle"
120
- />
121
- </Card>
122
- </Space>
123
- );
124
- };
1
+ import React, { useState, useEffect, useCallback, useMemo } from 'react';
2
+ import { Card, Table, Typography, Space, Row, Col, Statistic, Progress } from 'antd';
3
+ import { SyncOutlined, CheckCircleOutlined, CloseCircleOutlined, ClockCircleOutlined } from '@ant-design/icons';
4
+ import { useAPIClient } from '@nocobase/client';
5
+ import { useT } from '../locale';
6
+
7
+ const { Title, Text } = Typography;
8
+
9
+ export const SkillMetrics: React.FC = () => {
10
+ const api = useAPIClient();
11
+ const t = useT();
12
+ const [executions, setExecutions] = useState<any[]>([]);
13
+ const [loading, setLoading] = useState(false);
14
+
15
+ const fetchExecutions = useCallback(async () => {
16
+ setLoading(true);
17
+ try {
18
+ // Fetch up to 1000 recent executions to calculate basic metrics
19
+ const { data } = await api.request({
20
+ url: 'skillExecutions:list',
21
+ params: {
22
+ pageSize: 1000,
23
+ sort: ['-createdAt'],
24
+ appends: ['skill'],
25
+ },
26
+ });
27
+ const rawData = data?.data?.data ?? data?.data ?? [];
28
+ setExecutions(Array.isArray(rawData) ? rawData : []);
29
+ } catch {
30
+ // ignore
31
+ } finally {
32
+ setLoading(false);
33
+ }
34
+ }, [api]);
35
+
36
+ useEffect(() => {
37
+ fetchExecutions();
38
+ }, [fetchExecutions]);
39
+
40
+ const metrics = useMemo(() => {
41
+ const total = executions.length;
42
+ const succeeded = executions.filter((e) => e.status === 'succeeded').length;
43
+ const failed = executions.filter((e) => e.status === 'failed').length;
44
+ const timeout = executions.filter((e) => e.status === 'timeout').length;
45
+ const canceled = executions.filter((e) => e.status === 'canceled').length;
46
+
47
+ // Group by skill
48
+ const bySkill: Record<string, any> = {};
49
+ executions.forEach((e) => {
50
+ const skillName = e.skill?.title || e.skill?.name || 'Unknown';
51
+ if (!bySkill[skillName]) {
52
+ bySkill[skillName] = {
53
+ name: skillName,
54
+ total: 0,
55
+ succeeded: 0,
56
+ failed: 0,
57
+ timeout: 0,
58
+ canceled: 0,
59
+ totalDuration: 0,
60
+ durationCount: 0,
61
+ };
62
+ }
63
+ bySkill[skillName].total += 1;
64
+ bySkill[skillName][e.status] = (bySkill[skillName][e.status] || 0) + 1;
65
+ if (e.durationMs) {
66
+ bySkill[skillName].totalDuration += e.durationMs;
67
+ bySkill[skillName].durationCount += 1;
68
+ }
69
+ });
70
+
71
+ const skillData = Object.values(bySkill)
72
+ .map((s) => ({
73
+ ...s,
74
+ successRate: s.total > 0 ? (s.succeeded / s.total) * 100 : 0,
75
+ avgDuration: s.durationCount > 0 ? (s.totalDuration / s.durationCount / 1000).toFixed(2) : 0,
76
+ }))
77
+ .sort((a: any, b: any) => b.total - a.total);
78
+
79
+ return { total, succeeded, failed, timeout, canceled, skillData };
80
+ }, [executions]);
81
+
82
+ const columns = [
83
+ { title: t('Skill'), dataIndex: 'name', key: 'name', width: 200 },
84
+ { title: t('Total Runs'), dataIndex: 'total', key: 'total', width: 100 },
85
+ {
86
+ title: t('Success Rate'),
87
+ dataIndex: 'successRate',
88
+ key: 'successRate',
89
+ width: 150,
90
+ render: (val: number) => (
91
+ <Progress
92
+ percent={Math.round(val)}
93
+ size="small"
94
+ status={val === 100 ? 'success' : val > 50 ? 'active' : 'exception'}
95
+ />
96
+ ),
97
+ },
98
+ { title: t('Success'), dataIndex: 'succeeded', key: 'succeeded', width: 100 },
99
+ { title: t('Failed'), dataIndex: 'failed', key: 'failed', width: 100 },
100
+ { title: t('Timeout'), dataIndex: 'timeout', key: 'timeout', width: 100 },
101
+ { title: t('Avg Duration (s)'), dataIndex: 'avgDuration', key: 'avgDuration', width: 120 },
102
+ ];
103
+
104
+ return (
105
+ <Space direction="vertical" size="large" style={{ width: '100%', padding: '0 16px' }}>
106
+ <Row gutter={16}>
107
+ <Col span={6}>
108
+ <Card size="small">
109
+ <Statistic title="Total Executions (Recent)" value={metrics.total} prefix={<SyncOutlined />} />
110
+ </Card>
111
+ </Col>
112
+ <Col span={6}>
113
+ <Card size="small">
114
+ <Statistic
115
+ title="Succeeded"
116
+ value={metrics.succeeded}
117
+ valueStyle={{ color: '#3f8600' }}
118
+ prefix={<CheckCircleOutlined />}
119
+ />
120
+ </Card>
121
+ </Col>
122
+ <Col span={6}>
123
+ <Card size="small">
124
+ <Statistic
125
+ title="Failed"
126
+ value={metrics.failed}
127
+ valueStyle={{ color: '#cf1322' }}
128
+ prefix={<CloseCircleOutlined />}
129
+ />
130
+ </Card>
131
+ </Col>
132
+ <Col span={6}>
133
+ <Card size="small">
134
+ <Statistic
135
+ title="Timeout/Canceled"
136
+ value={metrics.timeout + metrics.canceled}
137
+ valueStyle={{ color: '#faad14' }}
138
+ prefix={<ClockCircleOutlined />}
139
+ />
140
+ </Card>
141
+ </Col>
142
+ </Row>
143
+
144
+ <Card title={t('Metrics by Skill (Recent)')}>
145
+ <Table
146
+ dataSource={metrics.skillData}
147
+ columns={columns}
148
+ rowKey="name"
149
+ loading={loading}
150
+ pagination={false}
151
+ size="middle"
152
+ scroll={{ x: 'max-content' }}
153
+ />
154
+ </Card>
155
+ </Space>
156
+ );
157
+ };
@@ -1,51 +1,58 @@
1
- import { Plugin } from '@nocobase/client';
2
- import { SkillManager } from './components/SkillManager';
3
- import { ExecutionHistory } from './components/ExecutionHistory';
4
- import { SkillMetrics } from './components/SkillMetrics';
5
- import { LoopSettings } from './components/LoopSettings';
6
- import { InteractionSchemasProvider } from './tools/InteractionSchemasProvider';
7
- import { registerSkillLoopCards } from './tools/registerSkillLoopCards';
8
-
9
- export class PluginSkillHubClient extends Plugin {
10
- async load() {
11
- (this as any).app.use(InteractionSchemasProvider);
12
-
13
- (this as any).app.pluginSettingsManager.add('skill-hub', {
14
- title: (this as any).t('Skill Hub'),
15
- icon: 'CodeOutlined',
16
- });
17
-
18
- (this as any).app.pluginSettingsManager.add('skill-hub.definitions', {
19
- title: (this as any).t('Skill Definitions'),
20
- Component: SkillManager,
21
- aclSnippet: 'pm.skill-hub',
22
- });
23
-
24
- (this as any).app.pluginSettingsManager.add('skill-hub.loop-settings', {
25
- title: (this as any).t('Skill Review Settings'),
26
- Component: LoopSettings,
27
- aclSnippet: 'pm.skill-hub',
28
- });
29
-
30
- (this as any).app.pluginSettingsManager.add('skill-hub.executions', {
31
- title: (this as any).t('Execution History'),
32
- Component: ExecutionHistory,
33
- aclSnippet: 'pm.skill-hub',
34
- });
35
-
36
- (this as any).app.pluginSettingsManager.add('skill-hub.metrics', {
37
- title: (this as any).t('Dashboard Metrics'),
38
- Component: SkillMetrics,
39
- aclSnippet: 'pm.skill-hub',
40
- });
41
-
42
- await this.registerSkillUiCards();
43
- }
44
-
45
- private async registerSkillUiCards() {
46
- await registerSkillLoopCards((this as any).app);
47
- }
48
- }
49
-
50
- export { SkillManager, ExecutionHistory, SkillMetrics, LoopSettings };
51
- export default PluginSkillHubClient;
1
+ import { Plugin } from '@nocobase/client';
2
+ import { SkillManager } from './components/SkillManager';
3
+ import { ExecutionHistory } from './components/ExecutionHistory';
4
+ import { SkillMetrics } from './components/SkillMetrics';
5
+ import { LoopSettings } from './components/LoopSettings';
6
+ import { InteractionSchemasProvider } from './tools/InteractionSchemasProvider';
7
+ import { registerSkillLoopCards } from './tools/registerSkillLoopCards';
8
+
9
+ export class PluginSkillHubClient extends Plugin {
10
+ async load() {
11
+ (this as any).app.use(InteractionSchemasProvider);
12
+
13
+ (this as any).app.pluginSettingsManager.add('skill-hub', {
14
+ title: (this as any).t('Skill Hub'),
15
+ icon: 'CodeOutlined',
16
+ });
17
+
18
+ (this as any).app.pluginSettingsManager.add('skill-hub.definitions', {
19
+ title: (this as any).t('Skill Definitions'),
20
+ Component: SkillManager,
21
+ aclSnippet: 'pm.skill-hub',
22
+ });
23
+
24
+ (this as any).app.pluginSettingsManager.add('skill-hub.loop-settings', {
25
+ title: (this as any).t('Skill Review Settings'),
26
+ Component: LoopSettings,
27
+ aclSnippet: 'pm.skill-hub',
28
+ });
29
+
30
+ (this as any).app.pluginSettingsManager.add('skill-hub.executions', {
31
+ title: (this as any).t('Execution History'),
32
+ Component: ExecutionHistory,
33
+ aclSnippet: 'pm.skill-hub',
34
+ });
35
+
36
+ (this as any).app.pluginSettingsManager.add('skill-hub.metrics', {
37
+ title: (this as any).t('Dashboard Metrics'),
38
+ Component: SkillMetrics,
39
+ aclSnippet: 'pm.skill-hub',
40
+ });
41
+
42
+ (this as any).app.eventBus?.addEventListener?.('auth:tokenChanged', (event: Event) => {
43
+ const token = (event as CustomEvent<{ token?: string | null }>).detail?.token;
44
+ if (token) {
45
+ this.registerSkillUiCards();
46
+ }
47
+ });
48
+
49
+ await this.registerSkillUiCards();
50
+ }
51
+
52
+ private async registerSkillUiCards() {
53
+ await registerSkillLoopCards((this as any).app);
54
+ }
55
+ }
56
+
57
+ export { SkillManager, ExecutionHistory, SkillMetrics, LoopSettings };
58
+ export default PluginSkillHubClient;