fix(ui): Various
This commit is contained in:
@@ -100,7 +100,7 @@ func SearchConfigMeta() []config.Field {
|
|||||||
Type: config.FieldTypeNumber,
|
Type: config.FieldTypeNumber,
|
||||||
DefaultValue: 1,
|
DefaultValue: 1,
|
||||||
Min: 1,
|
Min: 1,
|
||||||
Max: 10,
|
Max: 100,
|
||||||
Step: 1,
|
Step: 1,
|
||||||
HelpText: "Number of search results to return",
|
HelpText: "Number of search results to return",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,12 +6,7 @@ import ConfigForm from './ConfigForm';
|
|||||||
* Renders action configuration forms based on field group metadata
|
* Renders action configuration forms based on field group metadata
|
||||||
*/
|
*/
|
||||||
const ActionForm = ({ actions = [], onChange, onRemove, onAdd, fieldGroups = [] }) => {
|
const ActionForm = ({ actions = [], onChange, onRemove, onAdd, fieldGroups = [] }) => {
|
||||||
// Debug logging
|
|
||||||
console.log('ActionForm:', { actions, fieldGroups });
|
|
||||||
|
|
||||||
// Handle action change
|
|
||||||
const handleActionChange = (index, updatedAction) => {
|
const handleActionChange = (index, updatedAction) => {
|
||||||
console.log('Action change:', { index, updatedAction });
|
|
||||||
onChange(index, updatedAction);
|
onChange(index, updatedAction);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useNavigate, useOutletContext } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
// Import form sections
|
// Import form sections
|
||||||
import BasicInfoSection from './agent-form-sections/BasicInfoSection';
|
import BasicInfoSection from './agent-form-sections/BasicInfoSection';
|
||||||
@@ -10,6 +10,7 @@ import MemorySettingsSection from './agent-form-sections/MemorySettingsSection';
|
|||||||
import ModelSettingsSection from './agent-form-sections/ModelSettingsSection';
|
import ModelSettingsSection from './agent-form-sections/ModelSettingsSection';
|
||||||
import PromptsGoalsSection from './agent-form-sections/PromptsGoalsSection';
|
import PromptsGoalsSection from './agent-form-sections/PromptsGoalsSection';
|
||||||
import AdvancedSettingsSection from './agent-form-sections/AdvancedSettingsSection';
|
import AdvancedSettingsSection from './agent-form-sections/AdvancedSettingsSection';
|
||||||
|
import ExportSection from './agent-form-sections/ExportSection';
|
||||||
|
|
||||||
const AgentForm = ({
|
const AgentForm = ({
|
||||||
isEdit = false,
|
isEdit = false,
|
||||||
@@ -20,10 +21,9 @@ const AgentForm = ({
|
|||||||
submitButtonText,
|
submitButtonText,
|
||||||
isGroupForm = false,
|
isGroupForm = false,
|
||||||
noFormWrapper = false,
|
noFormWrapper = false,
|
||||||
metadata = null
|
metadata = null,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { showToast } = useOutletContext();
|
|
||||||
const [activeSection, setActiveSection] = useState(isGroupForm ? 'model-section' : 'basic-section');
|
const [activeSection, setActiveSection] = useState(isGroupForm ? 'model-section' : 'basic-section');
|
||||||
|
|
||||||
// Handle input changes
|
// Handle input changes
|
||||||
@@ -57,16 +57,27 @@ const AgentForm = ({
|
|||||||
|
|
||||||
// Handle navigation between sections
|
// Handle navigation between sections
|
||||||
const handleSectionChange = (section) => {
|
const handleSectionChange = (section) => {
|
||||||
|
console.log('Changing section to:', section);
|
||||||
setActiveSection(section);
|
setActiveSection(section);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle connector change (simplified)
|
||||||
|
const handleConnectorChange = (index, updatedConnector) => {
|
||||||
|
const updatedConnectors = [...formData.connectors];
|
||||||
|
updatedConnectors[index] = updatedConnector;
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
connectors: updatedConnectors
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Handle adding a connector
|
// Handle adding a connector
|
||||||
const handleAddConnector = () => {
|
const handleAddConnector = () => {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
connectors: [
|
connectors: [
|
||||||
...(formData.connectors || []),
|
...(formData.connectors || []),
|
||||||
{ name: '', config: '{}' }
|
{ type: '', config: '{}' }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -81,55 +92,6 @@ const AgentForm = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle connector name change
|
|
||||||
const handleConnectorNameChange = (index, value) => {
|
|
||||||
const updatedConnectors = [...formData.connectors];
|
|
||||||
updatedConnectors[index] = {
|
|
||||||
...updatedConnectors[index],
|
|
||||||
type: value
|
|
||||||
};
|
|
||||||
setFormData({
|
|
||||||
...formData,
|
|
||||||
connectors: updatedConnectors
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle connector config change
|
|
||||||
const handleConnectorConfigChange = (index, key, value) => {
|
|
||||||
const updatedConnectors = [...formData.connectors];
|
|
||||||
const currentConnector = updatedConnectors[index];
|
|
||||||
|
|
||||||
// Parse the current config if it's a string
|
|
||||||
let currentConfig = {};
|
|
||||||
if (typeof currentConnector.config === 'string') {
|
|
||||||
try {
|
|
||||||
currentConfig = JSON.parse(currentConnector.config);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error parsing config:', err);
|
|
||||||
currentConfig = {};
|
|
||||||
}
|
|
||||||
} else if (currentConnector.config) {
|
|
||||||
currentConfig = currentConnector.config;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the config with the new key-value pair
|
|
||||||
currentConfig = {
|
|
||||||
...currentConfig,
|
|
||||||
[key]: value
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update the connector with the stringified config
|
|
||||||
updatedConnectors[index] = {
|
|
||||||
...currentConnector,
|
|
||||||
config: JSON.stringify(currentConfig)
|
|
||||||
};
|
|
||||||
|
|
||||||
setFormData({
|
|
||||||
...formData,
|
|
||||||
connectors: updatedConnectors
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle adding an MCP server
|
// Handle adding an MCP server
|
||||||
const handleAddMCPServer = () => {
|
const handleAddMCPServer = () => {
|
||||||
setFormData({
|
setFormData({
|
||||||
@@ -231,6 +193,17 @@ const AgentForm = ({
|
|||||||
<i className="fas fa-cogs"></i>
|
<i className="fas fa-cogs"></i>
|
||||||
Advanced Settings
|
Advanced Settings
|
||||||
</li>
|
</li>
|
||||||
|
{isEdit && (
|
||||||
|
<>
|
||||||
|
<li
|
||||||
|
className={`wizard-nav-item ${activeSection === 'export-section' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleSectionChange('export-section')}
|
||||||
|
>
|
||||||
|
<i className="fas fa-file-export"></i>
|
||||||
|
Export Data
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -248,7 +221,7 @@ const AgentForm = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
|
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
|
||||||
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorNameChange={handleConnectorNameChange} handleConnectorConfigChange={handleConnectorConfigChange} metadata={metadata} />
|
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorChange={handleConnectorChange} metadata={metadata} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
|
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
|
||||||
@@ -270,6 +243,14 @@ const AgentForm = ({
|
|||||||
<div style={{ display: activeSection === 'advanced-section' ? 'block' : 'none' }}>
|
<div style={{ display: activeSection === 'advanced-section' ? 'block' : 'none' }}>
|
||||||
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
|
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isEdit && (
|
||||||
|
<>
|
||||||
|
<div style={{ display: activeSection === 'export-section' ? 'block' : 'none' }}>
|
||||||
|
<ExportSection agentName={formData.name} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<form className="agent-form" onSubmit={handleSubmit} noValidate>
|
<form className="agent-form" onSubmit={handleSubmit} noValidate>
|
||||||
@@ -283,7 +264,7 @@ const AgentForm = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
|
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
|
||||||
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorNameChange={handleConnectorNameChange} handleConnectorConfigChange={handleConnectorConfigChange} metadata={metadata} />
|
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorChange={handleConnectorChange} metadata={metadata} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
|
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
|
||||||
@@ -306,13 +287,21 @@ const AgentForm = ({
|
|||||||
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
|
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isEdit && (
|
||||||
|
<>
|
||||||
|
<div style={{ display: activeSection === 'export-section' ? 'block' : 'none' }}>
|
||||||
|
<ExportSection agentName={formData.name} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Form Controls */}
|
{/* Form Controls */}
|
||||||
<div className="form-actions">
|
<div className="form-actions" style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
|
||||||
<button type="button" className="btn btn-secondary" onClick={() => navigate('/agents')}>
|
<button type="button" className="action-btn" onClick={() => navigate('/agents')}>
|
||||||
Cancel
|
<i className="fas fa-times"></i> Cancel
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" className="btn btn-primary" disabled={loading}>
|
<button type="submit" className="action-btn" disabled={loading}>
|
||||||
{submitButtonText || (isEdit ? 'Update Agent' : 'Create Agent')}
|
<i className="fas fa-save"></i> {submitButtonText || (isEdit ? 'Update Agent' : 'Create Agent')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ const ConfigForm = ({
|
|||||||
typeField = 'type',
|
typeField = 'type',
|
||||||
addButtonText = 'Add Item'
|
addButtonText = 'Add Item'
|
||||||
}) => {
|
}) => {
|
||||||
// Debug logging
|
|
||||||
console.log(`ConfigForm for ${itemType}:`, { items, fieldGroups });
|
|
||||||
|
|
||||||
// Generate options from fieldGroups
|
// Generate options from fieldGroups
|
||||||
const typeOptions = [
|
const typeOptions = [
|
||||||
{ value: '', label: `Select a ${itemType} type` },
|
{ value: '', label: `Select a ${itemType} type` },
|
||||||
@@ -36,8 +33,6 @@ const ConfigForm = ({
|
|||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log(`${itemType} type options:`, typeOptions);
|
|
||||||
|
|
||||||
// Parse the config JSON string to an object
|
// Parse the config JSON string to an object
|
||||||
const parseConfig = (item) => {
|
const parseConfig = (item) => {
|
||||||
if (!item || !item.config) return {};
|
if (!item || !item.config) return {};
|
||||||
@@ -82,15 +77,13 @@ const ConfigForm = ({
|
|||||||
// Find the field group that matches this item's type
|
// Find the field group that matches this item's type
|
||||||
const fieldGroup = fieldGroups.find(group => group.name === itemTypeName);
|
const fieldGroup = fieldGroups.find(group => group.name === itemTypeName);
|
||||||
|
|
||||||
console.log(`Item ${index} type: ${itemTypeName}, Found field group:`, fieldGroup);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} className="config-item mb-4 card">
|
<div key={index} className="config-item mb-4 card">
|
||||||
<div className="config-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
|
<div className="config-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
|
||||||
<h4 style={{ margin: 0 }}>{itemType.charAt(0).toUpperCase() + itemType.slice(1)} #{index + 1}</h4>
|
<h4 style={{ margin: 0 }}>{itemType.charAt(0).toUpperCase() + itemType.slice(1)} #{index + 1}</h4>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="remove-btn"
|
className="action-btn delete-btn"
|
||||||
onClick={() => onRemove(index)}
|
onClick={() => onRemove(index)}
|
||||||
>
|
>
|
||||||
<i className="fas fa-times"></i>
|
<i className="fas fa-times"></i>
|
||||||
@@ -134,7 +127,7 @@ const ConfigForm = ({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="add-btn"
|
className="action-btn"
|
||||||
onClick={onAdd}
|
onClick={onAdd}
|
||||||
>
|
>
|
||||||
<i className="fas fa-plus"></i> {addButtonText}
|
<i className="fas fa-plus"></i> {addButtonText}
|
||||||
|
|||||||
@@ -9,36 +9,16 @@ function ConnectorForm({
|
|||||||
connectors = [],
|
connectors = [],
|
||||||
onAddConnector,
|
onAddConnector,
|
||||||
onRemoveConnector,
|
onRemoveConnector,
|
||||||
onConnectorNameChange,
|
onChange,
|
||||||
onConnectorConfigChange,
|
|
||||||
fieldGroups = []
|
fieldGroups = []
|
||||||
}) {
|
}) {
|
||||||
// Debug logging
|
|
||||||
console.log('ConnectorForm:', { connectors, fieldGroups });
|
|
||||||
|
|
||||||
// Handle connector change
|
|
||||||
const handleConnectorChange = (index, updatedConnector) => {
|
|
||||||
console.log('Connector change:', { index, updatedConnector });
|
|
||||||
if (updatedConnector.type !== connectors[index].type) {
|
|
||||||
onConnectorNameChange(index, updatedConnector.type);
|
|
||||||
} else {
|
|
||||||
onConnectorConfigChange(index, updatedConnector.config);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle adding a new connector
|
|
||||||
const handleAddConnector = () => {
|
|
||||||
console.log('Adding new connector');
|
|
||||||
onAddConnector();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigForm
|
<ConfigForm
|
||||||
items={connectors}
|
items={connectors}
|
||||||
fieldGroups={fieldGroups}
|
fieldGroups={fieldGroups}
|
||||||
onChange={handleConnectorChange}
|
onChange={onChange}
|
||||||
onRemove={onRemoveConnector}
|
onRemove={onRemoveConnector}
|
||||||
onAdd={handleAddConnector}
|
onAdd={onAddConnector}
|
||||||
itemType="connector"
|
itemType="connector"
|
||||||
typeField="type"
|
typeField="type"
|
||||||
addButtonText="Add Connector"
|
addButtonText="Add Connector"
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ const ConnectorsSection = ({
|
|||||||
formData,
|
formData,
|
||||||
handleAddConnector,
|
handleAddConnector,
|
||||||
handleRemoveConnector,
|
handleRemoveConnector,
|
||||||
handleConnectorNameChange,
|
handleConnectorChange,
|
||||||
handleConnectorConfigChange,
|
|
||||||
metadata
|
metadata
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@@ -23,8 +22,7 @@ const ConnectorsSection = ({
|
|||||||
connectors={formData.connectors || []}
|
connectors={formData.connectors || []}
|
||||||
onAddConnector={handleAddConnector}
|
onAddConnector={handleAddConnector}
|
||||||
onRemoveConnector={handleRemoveConnector}
|
onRemoveConnector={handleRemoveConnector}
|
||||||
onConnectorNameChange={handleConnectorNameChange}
|
onChange={handleConnectorChange}
|
||||||
onConnectorConfigChange={handleConnectorConfigChange}
|
|
||||||
fieldGroups={metadata?.connectors || []}
|
fieldGroups={metadata?.connectors || []}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
const ExportSection = ({ agentName }) => {
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('ExportSection rendered with agentName:', agentName);
|
||||||
|
}, [agentName]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="section-title">
|
||||||
|
<h2>Export Data</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="section-content">
|
||||||
|
<p className="mb-4">Export your agent configuration for backup or transfer.</p>
|
||||||
|
<a
|
||||||
|
href={`/settings/export/${agentName}`}
|
||||||
|
className="action-btn"
|
||||||
|
style={{ display: 'inline-flex', alignItems: 'center', textDecoration: 'none' }}
|
||||||
|
>
|
||||||
|
<i className="fas fa-file-export"></i> Export Configuration
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExportSection;
|
||||||
@@ -46,7 +46,7 @@ const MCPServersSection = ({
|
|||||||
<h4>MCP Server #{index + 1}</h4>
|
<h4>MCP Server #{index + 1}</h4>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="remove-btn"
|
className="action-btn delete-btn"
|
||||||
onClick={() => handleRemoveMCPServer(index)}
|
onClick={() => handleRemoveMCPServer(index)}
|
||||||
>
|
>
|
||||||
<i className="fas fa-times"></i>
|
<i className="fas fa-times"></i>
|
||||||
@@ -64,7 +64,7 @@ const MCPServersSection = ({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="add-btn"
|
className="action-btn"
|
||||||
onClick={handleAddMCPServer}
|
onClick={handleAddMCPServer}
|
||||||
>
|
>
|
||||||
<i className="fas fa-plus"></i> Add MCP Server
|
<i className="fas fa-plus"></i> Add MCP Server
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ export { default as MemorySettingsSection } from './MemorySettingsSection';
|
|||||||
export { default as PromptsGoalsSection } from './PromptsGoalsSection';
|
export { default as PromptsGoalsSection } from './PromptsGoalsSection';
|
||||||
export { default as AdvancedSettingsSection } from './AdvancedSettingsSection';
|
export { default as AdvancedSettingsSection } from './AdvancedSettingsSection';
|
||||||
export { default as FormNavSidebar } from './FormNavSidebar';
|
export { default as FormNavSidebar } from './FormNavSidebar';
|
||||||
|
export { default as ExportSection } from './ExportSection';
|
||||||
|
export { default as ControlSection } from './ControlSection';
|
||||||
|
|||||||
@@ -1,221 +1,5 @@
|
|||||||
/* Agent Form Section Styles */
|
|
||||||
|
|
||||||
.form-section {
|
|
||||||
padding: 1.5rem;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
color: #333;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-description {
|
.section-description {
|
||||||
color: #666;
|
color: #cecece;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Form Controls */
|
|
||||||
.form-controls {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 2rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-btn {
|
|
||||||
background-color: #4a6cf7;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-btn:hover {
|
|
||||||
background-color: #3a5ce5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-btn:disabled {
|
|
||||||
background-color: #a0a0a0;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error Message */
|
|
||||||
.error-message {
|
|
||||||
background-color: #f8d7da;
|
|
||||||
color: #721c24;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: #721c24;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Navigation Sidebar */
|
|
||||||
.wizard-sidebar {
|
|
||||||
width: 250px;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-nav {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-nav-item {
|
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-nav-item:hover {
|
|
||||||
background-color: #e9ecef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-nav-item.active {
|
|
||||||
background-color: #e9ecef;
|
|
||||||
border-left: 4px solid #4a6cf7;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-nav-item i {
|
|
||||||
width: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Form Layout */
|
|
||||||
.agent-form-container {
|
|
||||||
display: flex;
|
|
||||||
min-height: 80vh;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-content-area {
|
|
||||||
flex: 1;
|
|
||||||
padding: 1.5rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input Styles */
|
|
||||||
input[type="text"],
|
|
||||||
input[type="password"],
|
|
||||||
input[type="number"],
|
|
||||||
textarea,
|
|
||||||
select {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 1rem;
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
min-height: 100px;
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-label input[type="checkbox"] {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add and Remove Buttons */
|
|
||||||
.add-btn,
|
|
||||||
.remove-btn {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
color: #4a6cf7;
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-btn:hover {
|
|
||||||
color: #3a5ce5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-btn {
|
|
||||||
color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-btn:hover {
|
|
||||||
color: #c82333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Item Containers */
|
|
||||||
.action-item,
|
|
||||||
.mcp-server-item {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-header,
|
|
||||||
.mcp-server-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-header h4,
|
|
||||||
.mcp-server-header h4 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ const FormFieldDefinition = ({
|
|||||||
helpText={field.helpText || ''}
|
helpText={field.helpText || ''}
|
||||||
options={field.options || []}
|
options={field.options || []}
|
||||||
required={field.required || false}
|
required={field.required || false}
|
||||||
|
min={field.min || 0}
|
||||||
|
max={field.max || 2**31}
|
||||||
|
step={field.step || 1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
26
webui/react-ui/src/hooks/useAgent.js
vendored
26
webui/react-ui/src/hooks/useAgent.js
vendored
@@ -19,8 +19,21 @@ export function useAgent(agentName) {
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Fetch the agent configuration
|
||||||
const config = await agentApi.getAgentConfig(agentName);
|
const config = await agentApi.getAgentConfig(agentName);
|
||||||
setAgent(config);
|
|
||||||
|
// Fetch the agent status
|
||||||
|
const response = await fetch(`/api/agent/${agentName}`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch agent status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const statusData = await response.json();
|
||||||
|
|
||||||
|
// Combine configuration with active status
|
||||||
|
setAgent({
|
||||||
|
...config,
|
||||||
|
active: statusData.active
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err.message || 'Failed to fetch agent configuration');
|
setError(err.message || 'Failed to fetch agent configuration');
|
||||||
console.error('Error fetching agent:', err);
|
console.error('Error fetching agent:', err);
|
||||||
@@ -63,8 +76,13 @@ export function useAgent(agentName) {
|
|||||||
} else {
|
} else {
|
||||||
await agentApi.startAgent(agentName);
|
await agentApi.startAgent(agentName);
|
||||||
}
|
}
|
||||||
// Refresh agent data after status change
|
|
||||||
await fetchAgent();
|
// Update the agent's active status in the local state
|
||||||
|
setAgent(prevAgent => ({
|
||||||
|
...prevAgent,
|
||||||
|
active: !isActive
|
||||||
|
}));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err.message || 'Failed to toggle agent status');
|
setError(err.message || 'Failed to toggle agent status');
|
||||||
@@ -73,7 +91,7 @@ export function useAgent(agentName) {
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [agentName, fetchAgent]);
|
}, [agentName]);
|
||||||
|
|
||||||
// Delete agent
|
// Delete agent
|
||||||
const deleteAgent = useCallback(async () => {
|
const deleteAgent = useCallback(async () => {
|
||||||
|
|||||||
@@ -13,29 +13,14 @@ function AgentsList() {
|
|||||||
const fetchAgents = async () => {
|
const fetchAgents = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/agents');
|
const response = await fetch('/api/agents');
|
||||||
const html = await response.text();
|
if (!response.ok) {
|
||||||
|
throw new Error(`Server responded with status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a temporary element to parse the HTML
|
const data = await response.json();
|
||||||
const tempDiv = document.createElement('div');
|
setAgents(data.agents || []);
|
||||||
tempDiv.innerHTML = html;
|
setStatuses(data.statuses || {});
|
||||||
|
|
||||||
// Extract agent names and statuses from the HTML
|
|
||||||
const agentElements = tempDiv.querySelectorAll('[data-agent]');
|
|
||||||
const agentList = [];
|
|
||||||
const statusMap = {};
|
|
||||||
|
|
||||||
agentElements.forEach(el => {
|
|
||||||
const name = el.getAttribute('data-agent');
|
|
||||||
const status = el.getAttribute('data-active') === 'true';
|
|
||||||
if (name) {
|
|
||||||
agentList.push(name);
|
|
||||||
statusMap[name] = status;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setAgents(agentList);
|
|
||||||
setStatuses(statusMap);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching agents:', err);
|
console.error('Error fetching agents:', err);
|
||||||
setError('Failed to load agents');
|
setError('Failed to load agents');
|
||||||
@@ -47,7 +32,7 @@ function AgentsList() {
|
|||||||
// Toggle agent status (pause/start)
|
// Toggle agent status (pause/start)
|
||||||
const toggleAgentStatus = async (name, isActive) => {
|
const toggleAgentStatus = async (name, isActive) => {
|
||||||
try {
|
try {
|
||||||
const endpoint = isActive ? `/pause/${name}` : `/start/${name}`;
|
const endpoint = isActive ? `/api/agent/${name}/pause` : `/api/agent/${name}/start`;
|
||||||
const response = await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -64,8 +49,12 @@ function AgentsList() {
|
|||||||
// Show success toast
|
// Show success toast
|
||||||
const action = isActive ? 'paused' : 'started';
|
const action = isActive ? 'paused' : 'started';
|
||||||
showToast(`Agent "${name}" ${action} successfully`, 'success');
|
showToast(`Agent "${name}" ${action} successfully`, 'success');
|
||||||
|
|
||||||
|
// Refresh the agents list to ensure we have the latest data
|
||||||
|
fetchAgents();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Server responded with status: ${response.status}`);
|
const errorData = await response.json().catch(() => null);
|
||||||
|
throw new Error(errorData?.error || `Server responded with status: ${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error toggling agent status:`, err);
|
console.error(`Error toggling agent status:`, err);
|
||||||
@@ -80,7 +69,7 @@ function AgentsList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/delete/${name}`, {
|
const response = await fetch(`/api/agent/${name}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
});
|
});
|
||||||
@@ -88,11 +77,17 @@ function AgentsList() {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
// Remove from local state
|
// Remove from local state
|
||||||
setAgents(prev => prev.filter(agent => agent !== name));
|
setAgents(prev => prev.filter(agent => agent !== name));
|
||||||
|
setStatuses(prev => {
|
||||||
|
const newStatuses = { ...prev };
|
||||||
|
delete newStatuses[name];
|
||||||
|
return newStatuses;
|
||||||
|
});
|
||||||
|
|
||||||
// Show success toast
|
// Show success toast
|
||||||
showToast(`Agent "${name}" deleted successfully`, 'success');
|
showToast(`Agent "${name}" deleted successfully`, 'success');
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Server responded with status: ${response.status}`);
|
const errorData = await response.json().catch(() => null);
|
||||||
|
throw new Error(errorData?.error || `Server responded with status: ${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error deleting agent:`, err);
|
console.error(`Error deleting agent:`, err);
|
||||||
@@ -117,7 +112,7 @@ function AgentsList() {
|
|||||||
<div className="agents-container">
|
<div className="agents-container">
|
||||||
<header className="page-header">
|
<header className="page-header">
|
||||||
<h1>Manage Agents</h1>
|
<h1>Manage Agents</h1>
|
||||||
<Link to="/create" className="create-btn">
|
<Link to="/create" className="action-btn">
|
||||||
<i className="fas fa-plus"></i> Create New Agent
|
<i className="fas fa-plus"></i> Create New Agent
|
||||||
</Link>
|
</Link>
|
||||||
</header>
|
</header>
|
||||||
@@ -198,8 +193,8 @@ function AgentsList() {
|
|||||||
<div className="no-agents">
|
<div className="no-agents">
|
||||||
<h2>No Agents Found</h2>
|
<h2>No Agents Found</h2>
|
||||||
<p>Get started by creating your first agent</p>
|
<p>Get started by creating your first agent</p>
|
||||||
<Link to="/create" className="create-agent-btn">
|
<Link to="/create" className="action-btn">
|
||||||
Create Agent
|
<i className="fas fa-plus"></i> Create Agent
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useNavigate, useOutletContext } from 'react-router-dom';
|
import { useNavigate, useOutletContext } from 'react-router-dom';
|
||||||
import { agentApi } from '../utils/api';
|
import { agentApi } from '../utils/api';
|
||||||
import AgentForm from '../components/AgentForm';
|
import AgentForm from '../components/AgentForm';
|
||||||
@@ -10,6 +10,7 @@ function GroupCreate() {
|
|||||||
const [generatingProfiles, setGeneratingProfiles] = useState(false);
|
const [generatingProfiles, setGeneratingProfiles] = useState(false);
|
||||||
const [activeStep, setActiveStep] = useState(1);
|
const [activeStep, setActiveStep] = useState(1);
|
||||||
const [selectedProfiles, setSelectedProfiles] = useState([]);
|
const [selectedProfiles, setSelectedProfiles] = useState([]);
|
||||||
|
const [metadata, setMetadata] = useState(null);
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
description: '',
|
description: '',
|
||||||
model: '',
|
model: '',
|
||||||
@@ -20,6 +21,24 @@ function GroupCreate() {
|
|||||||
profiles: []
|
profiles: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch metadata on component mount
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchMetadata = async () => {
|
||||||
|
try {
|
||||||
|
// Fetch metadata from the dedicated endpoint
|
||||||
|
const response = await agentApi.getAgentConfigMetadata();
|
||||||
|
if (response) {
|
||||||
|
setMetadata(response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching metadata:', error);
|
||||||
|
// Continue without metadata, the form will use default fields
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchMetadata();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Handle form field changes
|
// Handle form field changes
|
||||||
const handleInputChange = (e) => {
|
const handleInputChange = (e) => {
|
||||||
const { name, value, type } = e.target;
|
const { name, value, type } = e.target;
|
||||||
@@ -281,6 +300,7 @@ function GroupCreate() {
|
|||||||
submitButtonText="Create Group"
|
submitButtonText="Create Group"
|
||||||
isGroupForm={true}
|
isGroupForm={true}
|
||||||
noFormWrapper={true}
|
noFormWrapper={true}
|
||||||
|
metadata={metadata}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ function Home() {
|
|||||||
try {
|
try {
|
||||||
const agents = await agentApi.getAgents();
|
const agents = await agentApi.getAgents();
|
||||||
setStats({
|
setStats({
|
||||||
agents: agents.Agents || [],
|
agents: agents.agents || [],
|
||||||
agentCount: agents.AgentCount || 0,
|
agentCount: agents.agentCount || 0,
|
||||||
actions: agents.Actions || 0,
|
actions: agents.actions || 0,
|
||||||
connectors: agents.Connectors || 0,
|
connectors: agents.connectors || 0,
|
||||||
status: agents.Status || {},
|
status: agents.statuses || {},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching dashboard data:', err);
|
console.error('Error fetching dashboard data:', err);
|
||||||
@@ -115,14 +115,14 @@ function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<h2><i className="fas fa-robot"></i> {agent}</h2>
|
<h2><i className="fas fa-robot"></i> {agent}</h2>
|
||||||
<div className="agent-actions">
|
<div className="agent-actions">
|
||||||
<Link to={`/talk/${agent}`} className="agent-action">
|
<Link to={`/talk/${agent}`} className="action-btn chat-btn">
|
||||||
Chat
|
<i className="fas fa-comment"></i> Chat
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={`/settings/${agent}`} className="agent-action">
|
<Link to={`/settings/${agent}`} className="action-btn settings-btn">
|
||||||
Settings
|
<i className="fas fa-cog"></i> Settings
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={`/status/${agent}`} className="agent-action">
|
<Link to={`/status/${agent}`} className="action-btn status-btn">
|
||||||
Status
|
<i className="fas fa-chart-line"></i> Status
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
8
webui/react-ui/src/utils/config.js
vendored
8
webui/react-ui/src/utils/config.js
vendored
@@ -20,11 +20,11 @@ export const API_CONFIG = {
|
|||||||
// Agent endpoints
|
// Agent endpoints
|
||||||
agents: '/api/agents',
|
agents: '/api/agents',
|
||||||
agentConfig: (name) => `/api/agent/${name}/config`,
|
agentConfig: (name) => `/api/agent/${name}/config`,
|
||||||
agentConfigMetadata: '/api/agent/config/metadata',
|
agentConfigMetadata: '/api/meta/agent/config',
|
||||||
createAgent: '/create',
|
createAgent: '/create',
|
||||||
deleteAgent: (name) => `/delete/${name}`,
|
deleteAgent: (name) => `/api/agent/${name}`,
|
||||||
pauseAgent: (name) => `/pause/${name}`,
|
pauseAgent: (name) => `/api/agent/${name}/pause`,
|
||||||
startAgent: (name) => `/start/${name}`,
|
startAgent: (name) => `/api/agent/${name}/start`,
|
||||||
exportAgent: (name) => `/settings/export/${name}`,
|
exportAgent: (name) => `/settings/export/${name}`,
|
||||||
importAgent: '/settings/import',
|
importAgent: '/settings/import',
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
|
|||||||
webapp.Put("/pause/:name", app.Pause(pool))
|
webapp.Put("/pause/:name", app.Pause(pool))
|
||||||
webapp.Put("/start/:name", app.Start(pool))
|
webapp.Put("/start/:name", app.Start(pool))
|
||||||
|
|
||||||
|
// JSON API endpoints for agent operations
|
||||||
|
webapp.Delete("/api/agent/:name", app.Delete(pool))
|
||||||
|
webapp.Put("/api/agent/:name/pause", app.Pause(pool))
|
||||||
|
webapp.Put("/api/agent/:name/start", app.Start(pool))
|
||||||
|
|
||||||
webapp.Post("/v1/responses", app.Responses(pool))
|
webapp.Post("/v1/responses", app.Responses(pool))
|
||||||
|
|
||||||
webapp.Get("/talk/:name", func(c *fiber.Ctx) error {
|
webapp.Get("/talk/:name", func(c *fiber.Ctx) error {
|
||||||
@@ -172,8 +177,8 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
|
|||||||
webapp.Get("/api/agent/:name/config", app.GetAgentConfig(pool))
|
webapp.Get("/api/agent/:name/config", app.GetAgentConfig(pool))
|
||||||
webapp.Put("/api/agent/:name/config", app.UpdateAgentConfig(pool))
|
webapp.Put("/api/agent/:name/config", app.UpdateAgentConfig(pool))
|
||||||
|
|
||||||
// Metadata endpoint for agent configuration fields
|
// Add endpoint for getting agent config metadata
|
||||||
webapp.Get("/api/agent/config/metadata", app.GetAgentConfigMeta())
|
webapp.Get("/api/meta/agent/config", app.GetAgentConfigMeta())
|
||||||
|
|
||||||
webapp.Post("/action/:name/run", app.ExecuteAction(pool))
|
webapp.Post("/action/:name/run", app.ExecuteAction(pool))
|
||||||
webapp.Get("/actions", app.ListActions())
|
webapp.Get("/actions", app.ListActions())
|
||||||
@@ -195,11 +200,27 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(fiber.Map{
|
return c.JSON(fiber.Map{
|
||||||
"Agents": agents,
|
"agents": agents,
|
||||||
"AgentCount": len(agents),
|
"agentCount": len(agents),
|
||||||
"Actions": len(services.AvailableActions),
|
"actions": len(services.AvailableActions),
|
||||||
"Connectors": len(services.AvailableConnectors),
|
"connectors": len(services.AvailableConnectors),
|
||||||
"Status": statuses,
|
"statuses": statuses,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// API endpoint for getting a specific agent's details
|
||||||
|
webapp.Get("/api/agent/:name", func(c *fiber.Ctx) error {
|
||||||
|
name := c.Params("name")
|
||||||
|
agent := pool.GetAgent(name)
|
||||||
|
if agent == nil {
|
||||||
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
||||||
|
"error": "Agent not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the active status to the configuration
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"active": !agent.Paused(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user