plugin-agent-orchestrator 1.0.21 → 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 (180) 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 +41 -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/pages/AgentRunsPage.tsx +13 -0
  53. package/src/client-v2/pages/ExecutionHistoryPage.tsx +10 -0
  54. package/src/client-v2/pages/HarnessProfilesPage.tsx +10 -0
  55. package/src/client-v2/pages/LoopSettingsPage.tsx +10 -0
  56. package/src/client-v2/pages/RulesPage.tsx +13 -0
  57. package/src/client-v2/pages/SkillDefinitionsPage.tsx +10 -0
  58. package/src/client-v2/pages/SkillMetricsPage.tsx +10 -0
  59. package/src/client-v2/pages/TracingPage.tsx +13 -0
  60. package/src/client-v2/plugin.tsx +70 -0
  61. package/src/client-v2/skill-hub/components/ExecutionHistory.tsx +196 -0
  62. package/src/client-v2/skill-hub/components/FileLinkList.tsx +37 -0
  63. package/src/client-v2/skill-hub/components/GitSkillImport.tsx +539 -0
  64. package/src/client-v2/skill-hub/components/LoopSettings.tsx +331 -0
  65. package/src/client-v2/skill-hub/components/SkillEditor.tsx +453 -0
  66. package/src/client-v2/skill-hub/components/SkillManager.tsx +174 -0
  67. package/src/client-v2/skill-hub/components/SkillMetrics.tsx +157 -0
  68. package/src/client-v2/skill-hub/components/SkillTestPanel.tsx +135 -0
  69. package/src/client-v2/skill-hub/locale.ts +13 -0
  70. package/src/client-v2/skill-hub/tools/loopTemplates.ts +52 -0
  71. package/src/client-v2/skill-hub/utils/jsonFields.ts +41 -0
  72. package/src/client-v2/utils/jsonFields.ts +41 -0
  73. package/src/locale/en-US.json +7 -0
  74. package/src/locale/vi-VN.json +7 -0
  75. package/src/locale/zh-CN.json +27 -0
  76. package/src/server/__tests__/agent-registry-service.test.ts +147 -0
  77. package/src/server/__tests__/code-validator.test.ts +63 -0
  78. package/src/server/__tests__/skill-execute.test.ts +33 -0
  79. package/src/server/__tests__/skill-settings.test.ts +63 -0
  80. package/src/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.ts +39 -0
  81. package/src/server/plugin.ts +68 -12
  82. package/src/server/services/AgentHarness.ts +49 -22
  83. package/src/server/services/AgentLoopController.ts +17 -6
  84. package/src/server/services/AgentLoopService.ts +1 -1
  85. package/src/server/services/AgentPlannerService.ts +10 -0
  86. package/src/server/services/AgentRegistryService.ts +89 -47
  87. package/src/server/services/CircuitBreaker.ts +10 -0
  88. package/src/server/services/CodeValidator.ts +237 -159
  89. package/src/server/services/SandboxRunner.ts +203 -189
  90. package/src/server/skill-hub/plugin.ts +933 -898
  91. package/src/server/tools/delegate-task.ts +12 -9
  92. package/src/server/tools/skill-execute.ts +194 -160
  93. package/src/server/utils/ai-manager.ts +24 -0
  94. package/src/server/utils/ctx-utils.ts +14 -0
  95. package/src/server/utils/skill-settings.ts +116 -0
  96. package/dist/client/AIEmployeeSelect.d.ts +0 -11
  97. package/dist/client/AIEmployeesContext.d.ts +0 -30
  98. package/dist/client/AgentRunsTab.d.ts +0 -2
  99. package/dist/client/HarnessProfilesTab.d.ts +0 -2
  100. package/dist/client/OrchestratorSettings.d.ts +0 -3
  101. package/dist/client/RulesTab.d.ts +0 -2
  102. package/dist/client/TracingTab.d.ts +0 -2
  103. package/dist/client/hooks/useRunEventStream.d.ts +0 -22
  104. package/dist/client/index.d.ts +0 -2
  105. package/dist/client/plugin.d.ts +0 -6
  106. package/dist/client/skill-hub/components/ExecutionHistory.d.ts +0 -2
  107. package/dist/client/skill-hub/components/ExecutionProgress.d.ts +0 -20
  108. package/dist/client/skill-hub/components/GitSkillImport.d.ts +0 -7
  109. package/dist/client/skill-hub/components/LoopSettings.d.ts +0 -2
  110. package/dist/client/skill-hub/components/SkillEditor.d.ts +0 -7
  111. package/dist/client/skill-hub/components/SkillManager.d.ts +0 -2
  112. package/dist/client/skill-hub/components/SkillMetrics.d.ts +0 -2
  113. package/dist/client/skill-hub/components/SkillTestPanel.d.ts +0 -7
  114. package/dist/client/skill-hub/index.d.ts +0 -11
  115. package/dist/client/skill-hub/locale.d.ts +0 -3
  116. package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +0 -6
  117. package/dist/client/skill-hub/tools/SkillHubCard.d.ts +0 -3
  118. package/dist/client/skill-hub/tools/loopTemplates.d.ts +0 -22
  119. package/dist/client/skill-hub/tools/registerSkillLoopCards.d.ts +0 -1
  120. package/dist/client/skill-hub/utils/jsonFields.d.ts +0 -3
  121. package/dist/client/tools/PlanApprovalCard.d.ts +0 -3
  122. package/dist/client/tools/registerOrchestratorCards.d.ts +0 -1
  123. package/dist/index.d.ts +0 -2
  124. package/dist/server/collections/agent-execution-spans.d.ts +0 -9
  125. package/dist/server/collections/agent-harness-profiles.d.ts +0 -2
  126. package/dist/server/collections/agent-loop-events.d.ts +0 -2
  127. package/dist/server/collections/agent-loop-runs.d.ts +0 -2
  128. package/dist/server/collections/agent-loop-steps.d.ts +0 -2
  129. package/dist/server/collections/orchestrator-config.d.ts +0 -2
  130. package/dist/server/collections/orchestrator-logs.d.ts +0 -8
  131. package/dist/server/collections/skill-definitions.d.ts +0 -3
  132. package/dist/server/collections/skill-executions.d.ts +0 -3
  133. package/dist/server/collections/skill-loop-configs.d.ts +0 -3
  134. package/dist/server/collections/skill-worker-configs.d.ts +0 -3
  135. package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +0 -4
  136. package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +0 -4
  137. package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +0 -7
  138. package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +0 -4
  139. package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +0 -4
  140. package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +0 -7
  141. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +0 -16
  142. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +0 -7
  143. package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.d.ts +0 -7
  144. package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.d.ts +0 -12
  145. package/dist/server/migrations/20260601000000-add-token-fields.d.ts +0 -7
  146. package/dist/server/plugin.d.ts +0 -16
  147. package/dist/server/resources/agent-loop.d.ts +0 -3
  148. package/dist/server/resources/tracing.d.ts +0 -7
  149. package/dist/server/services/AgentHarness.d.ts +0 -44
  150. package/dist/server/services/AgentLoopController.d.ts +0 -218
  151. package/dist/server/services/AgentLoopRepository.d.ts +0 -20
  152. package/dist/server/services/AgentLoopService.d.ts +0 -159
  153. package/dist/server/services/AgentPlanValidator.d.ts +0 -4
  154. package/dist/server/services/AgentPlannerService.d.ts +0 -8
  155. package/dist/server/services/AgentRegistryService.d.ts +0 -21
  156. package/dist/server/services/CircuitBreaker.d.ts +0 -40
  157. package/dist/server/services/CodeValidator.d.ts +0 -32
  158. package/dist/server/services/ContextAggregator.d.ts +0 -45
  159. package/dist/server/services/ExecutionSpanService.d.ts +0 -46
  160. package/dist/server/services/FileManager.d.ts +0 -28
  161. package/dist/server/services/RunEventBus.d.ts +0 -9
  162. package/dist/server/services/SandboxRunner.d.ts +0 -41
  163. package/dist/server/services/SkillManager.d.ts +0 -6
  164. package/dist/server/services/SkillRepositoryService.d.ts +0 -22
  165. package/dist/server/services/TokenTracker.d.ts +0 -62
  166. package/dist/server/services/WorkerEnvManager.d.ts +0 -26
  167. package/dist/server/skill-hub/actions/git-import.d.ts +0 -21
  168. package/dist/server/skill-hub/mcp/McpController.d.ts +0 -15
  169. package/dist/server/skill-hub/plugin.d.ts +0 -61
  170. package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +0 -16
  171. package/dist/server/skill-hub/utils/json-fields.d.ts +0 -7
  172. package/dist/server/tools/agent-loop.d.ts +0 -235
  173. package/dist/server/tools/delegate-task.d.ts +0 -19
  174. package/dist/server/tools/external-rag-search.d.ts +0 -42
  175. package/dist/server/tools/orchestrator-plan.d.ts +0 -205
  176. package/dist/server/tools/skill-execute.d.ts +0 -36
  177. package/dist/server/types.d.ts +0 -47
  178. package/dist/server/utils/ctx-utils.d.ts +0 -30
  179. package/dist/server/utils/logging.d.ts +0 -6
  180. /package/{dist/server/index.d.ts → src/client-v2/index.tsx} +0 -0
@@ -0,0 +1,331 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Card,
5
+ Form,
6
+ Input,
7
+ List,
8
+ message,
9
+ Modal,
10
+ Popconfirm,
11
+ Select,
12
+ Space,
13
+ Switch,
14
+ Tag,
15
+ Tooltip,
16
+ Typography,
17
+ } from 'antd';
18
+ import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
19
+ import { useApiClient as useAPIClient } from '../../hooks/useApiRequest';
20
+ import { useT } from '../locale';
21
+ import { formatJsonText, parseJsonText, stringifyJsonText } from '../utils/jsonFields';
22
+ import { getLoopTemplate, LOOP_TEMPLATES } from '../tools/loopTemplates';
23
+
24
+ const { TextArea } = Input;
25
+
26
+ const extractList = (data: any) => {
27
+ const value = data?.data?.data ?? data?.data ?? data ?? [];
28
+ return Array.isArray(value) ? value : [];
29
+ };
30
+
31
+ export const LoopSettings: React.FC = () => {
32
+ const api = useAPIClient();
33
+ const t = useT();
34
+ const [form] = Form.useForm();
35
+ const [skills, setSkills] = useState<any[]>([]);
36
+ const [configs, setConfigs] = useState<any[]>([]);
37
+ const [loading, setLoading] = useState(false);
38
+ const [editorVisible, setEditorVisible] = useState(false);
39
+ const [editingConfig, setEditingConfig] = useState<any>(null);
40
+
41
+ const skillsById = useMemo(() => new Map(skills.map((skill) => [String(skill.id), skill])), [skills]);
42
+
43
+ const fetchData = useCallback(async () => {
44
+ setLoading(true);
45
+ try {
46
+ const [skillsResponse, configsResponse] = await Promise.all([
47
+ api.request({
48
+ url: 'skillDefinitions:list',
49
+ params: {
50
+ filter: { enabled: true },
51
+ fields: ['id', 'name', 'title', 'language', 'autoCall'],
52
+ pageSize: 500,
53
+ },
54
+ }),
55
+ api.request({
56
+ url: 'skillLoopConfigs:list',
57
+ params: {
58
+ fields: ['id', 'skillId', 'enabled', 'title', 'templateKey', 'prompt', 'schema', 'config', 'updatedAt'],
59
+ sort: ['-updatedAt'],
60
+ pageSize: 500,
61
+ },
62
+ }),
63
+ ]);
64
+ setSkills(extractList(skillsResponse.data));
65
+ setConfigs(extractList(configsResponse.data));
66
+ } catch {
67
+ message.error(t('Failed to load skill review settings'));
68
+ } finally {
69
+ setLoading(false);
70
+ }
71
+ }, [api, t]);
72
+
73
+ useEffect(() => {
74
+ fetchData();
75
+ }, [fetchData]);
76
+
77
+ const openCreate = () => {
78
+ const template = getLoopTemplate('confirm');
79
+ setEditingConfig(null);
80
+ form.resetFields();
81
+ form.setFieldsValue({
82
+ enabled: true,
83
+ templateKey: template.key,
84
+ prompt: template.schema.prompt,
85
+ schema: formatJsonText(template.schema),
86
+ config: '',
87
+ });
88
+ setEditorVisible(true);
89
+ };
90
+
91
+ const openEdit = (record: any) => {
92
+ const template = getLoopTemplate(record.templateKey);
93
+ setEditingConfig(record);
94
+ form.setFieldsValue({
95
+ ...record,
96
+ templateKey: record.templateKey || template.key,
97
+ prompt: record.prompt || template.schema.prompt,
98
+ schema: formatJsonText(record.schema || template.schema),
99
+ config: formatJsonText(record.config, null),
100
+ });
101
+ setEditorVisible(true);
102
+ };
103
+
104
+ const closeEditor = () => {
105
+ setEditorVisible(false);
106
+ setEditingConfig(null);
107
+ form.resetFields();
108
+ };
109
+
110
+ // client-v2 has no aiManager.toolsManager, so loop cards cannot be (re)registered
111
+ // here — the v1 client plugin owns card registration. We only broadcast the
112
+ // change event so any listening v1 surface refreshes.
113
+ const notifyLoopSettingsChanged = useCallback(() => {
114
+ window.dispatchEvent(new Event('skill-hub-loop-settings-changed'));
115
+ }, []);
116
+
117
+ const handleTemplateChange = (templateKey: string) => {
118
+ const template = getLoopTemplate(templateKey);
119
+ form.setFieldsValue({
120
+ prompt: template.schema.prompt,
121
+ schema: formatJsonText(template.schema),
122
+ });
123
+ };
124
+
125
+ const handleSave = async () => {
126
+ try {
127
+ const values = await form.validateFields();
128
+ const schema = parseJsonText<any>(values.schema, undefined);
129
+ if (!schema || typeof schema !== 'object') {
130
+ message.error(t('Invalid JSON in Review Schema'));
131
+ return;
132
+ }
133
+
134
+ const config = parseJsonText<any>(values.config, undefined);
135
+ if (values.config && config === undefined) {
136
+ message.error(t('Invalid JSON in Review Config'));
137
+ return;
138
+ }
139
+
140
+ const schemaWithPrompt = {
141
+ ...schema,
142
+ prompt: values.prompt || schema.prompt,
143
+ };
144
+ const data = {
145
+ ...values,
146
+ schema: stringifyJsonText(schemaWithPrompt),
147
+ config: values.config ? stringifyJsonText(config) : null,
148
+ };
149
+
150
+ if (editingConfig) {
151
+ await api.request({
152
+ url: 'skillLoopConfigs:update',
153
+ method: 'POST',
154
+ params: { filterByTk: editingConfig.id },
155
+ data,
156
+ });
157
+ } else {
158
+ await api.request({
159
+ url: 'skillLoopConfigs:create',
160
+ method: 'POST',
161
+ data,
162
+ });
163
+ }
164
+
165
+ message.success(t(editingConfig ? 'Skill review setting updated' : 'Skill review setting created'));
166
+ closeEditor();
167
+ fetchData();
168
+ notifyLoopSettingsChanged();
169
+ } catch (err: any) {
170
+ if (err?.errorFields) return;
171
+ message.error(t('Failed to save skill review setting'));
172
+ }
173
+ };
174
+
175
+ const handleDelete = async (id: number) => {
176
+ try {
177
+ await api.request({ url: 'skillLoopConfigs:destroy', method: 'POST', params: { filterByTk: id } });
178
+ message.success(t('Deleted'));
179
+ fetchData();
180
+ notifyLoopSettingsChanged();
181
+ } catch {
182
+ message.error(t('Failed to delete'));
183
+ }
184
+ };
185
+
186
+ const handleToggleEnabled = async (record: any) => {
187
+ try {
188
+ await api.request({
189
+ url: 'skillLoopConfigs:update',
190
+ method: 'POST',
191
+ params: { filterByTk: record.id },
192
+ data: { enabled: !record.enabled },
193
+ });
194
+ fetchData();
195
+ notifyLoopSettingsChanged();
196
+ } catch {
197
+ message.error(t('Failed to update'));
198
+ }
199
+ };
200
+
201
+ return (
202
+ <Card
203
+ title={t('Skill Review Settings')}
204
+ extra={
205
+ <Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
206
+ {t('New Review')}
207
+ </Button>
208
+ }
209
+ >
210
+ <List
211
+ loading={loading}
212
+ dataSource={configs}
213
+ grid={{ gutter: 16, xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }}
214
+ renderItem={(config) => {
215
+ const skill = skillsById.get(String(config.skillId));
216
+ const template = getLoopTemplate(config.templateKey);
217
+ return (
218
+ <List.Item>
219
+ <Card
220
+ size="small"
221
+ title={
222
+ <Typography.Text ellipsis>
223
+ {config.title || skill?.title || skill?.name || t('Unknown skill')}
224
+ </Typography.Text>
225
+ }
226
+ extra={
227
+ <Tag color={config.enabled ? 'green' : 'default'}>
228
+ {config.enabled ? t('Enabled') : t('Disabled')}
229
+ </Tag>
230
+ }
231
+ actions={[
232
+ <Tooltip key="edit" title={t('Edit')}>
233
+ <EditOutlined onClick={() => openEdit(config)} />
234
+ </Tooltip>,
235
+ <Popconfirm key="delete" title={t('Delete?')} onConfirm={() => handleDelete(config.id)}>
236
+ <Tooltip title={t('Delete')}>
237
+ <DeleteOutlined style={{ color: 'red' }} />
238
+ </Tooltip>
239
+ </Popconfirm>,
240
+ ]}
241
+ style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.05)', borderRadius: 8 }}
242
+ >
243
+ <Space direction="vertical" size={8} style={{ width: '100%' }}>
244
+ <Typography.Text type="secondary" style={{ fontSize: 13 }}>
245
+ {skill?.name || `skillId=${config.skillId}`}
246
+ </Typography.Text>
247
+ <Tag color="blue" style={{ width: 'fit-content' }}>
248
+ {template.title}
249
+ </Tag>
250
+ <Typography.Paragraph
251
+ type="secondary"
252
+ ellipsis={{ rows: 2 }}
253
+ style={{ minHeight: 44, marginBottom: 0, fontSize: 13 }}
254
+ >
255
+ {config.prompt || template.schema.prompt}
256
+ </Typography.Paragraph>
257
+ <Space size={4}>
258
+ <Switch checked={config.enabled} onChange={() => handleToggleEnabled(config)} size="small" />
259
+ <span style={{ fontSize: 12 }}>{config.enabled ? t('Enabled') : t('Disabled')}</span>
260
+ </Space>
261
+ </Space>
262
+ </Card>
263
+ </List.Item>
264
+ );
265
+ }}
266
+ />
267
+
268
+ <Modal
269
+ open={editorVisible}
270
+ title={editingConfig ? t('Edit Skill Review Setting') : t('New Skill Review Setting')}
271
+ onCancel={closeEditor}
272
+ onOk={handleSave}
273
+ width={760}
274
+ destroyOnClose
275
+ >
276
+ <Form form={form} layout="vertical">
277
+ <Form.Item name="enabled" valuePropName="checked" label={t('Enabled')}>
278
+ <Switch />
279
+ </Form.Item>
280
+
281
+ <Form.Item name="skillId" label={t('Skill')} rules={[{ required: true }]}>
282
+ <Select
283
+ showSearch
284
+ optionFilterProp="label"
285
+ placeholder={t('Select a skill')}
286
+ options={skills.map((skill) => ({
287
+ value: skill.id,
288
+ label: `${skill.title || skill.name} (${skill.name})`,
289
+ }))}
290
+ />
291
+ </Form.Item>
292
+
293
+ <Form.Item name="title" label={t('Title')}>
294
+ <Input placeholder={t('Optional display title')} />
295
+ </Form.Item>
296
+
297
+ <Form.Item name="templateKey" label={t('Review Template')} rules={[{ required: true }]}>
298
+ <Select onChange={handleTemplateChange}>
299
+ {LOOP_TEMPLATES.map((template) => (
300
+ <Select.Option key={template.key} value={template.key}>
301
+ {template.title} - {template.description}
302
+ </Select.Option>
303
+ ))}
304
+ </Select>
305
+ </Form.Item>
306
+
307
+ <Form.Item name="prompt" label={t('Prompt')} rules={[{ required: true }]}>
308
+ <TextArea rows={3} />
309
+ </Form.Item>
310
+
311
+ <Form.Item
312
+ name="schema"
313
+ label={t('Review Schema (JSON)')}
314
+ rules={[{ required: true }]}
315
+ extra={t('Standard interaction schema. Supported types: confirm, form, select.')}
316
+ >
317
+ <TextArea rows={10} style={{ fontFamily: 'monospace', fontSize: 13 }} />
318
+ </Form.Item>
319
+
320
+ <Form.Item name="config" label={t('Review Config (optional JSON)')}>
321
+ <TextArea
322
+ rows={4}
323
+ style={{ fontFamily: 'monospace', fontSize: 13 }}
324
+ placeholder={'{\n "maxRetries": 1\n}'}
325
+ />
326
+ </Form.Item>
327
+ </Form>
328
+ </Modal>
329
+ </Card>
330
+ );
331
+ };