2025-10-02 21:45:59 -05:00
|
|
|
const yaml = require('js-yaml');
|
|
|
|
|
const fs = require('fs-extra');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Analyzes agent YAML files to detect which handlers are needed
|
|
|
|
|
*/
|
|
|
|
|
class AgentAnalyzer {
|
|
|
|
|
/**
|
|
|
|
|
* Analyze an agent YAML structure to determine which handlers it needs
|
|
|
|
|
* @param {Object} agentYaml - Parsed agent YAML object
|
|
|
|
|
* @returns {Object} Profile of needed handlers
|
|
|
|
|
*/
|
|
|
|
|
analyzeAgentObject(agentYaml) {
|
|
|
|
|
const profile = {
|
|
|
|
|
usedAttributes: new Set(),
|
|
|
|
|
hasPrompts: false,
|
|
|
|
|
menuItems: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Check if agent has prompts section
|
|
|
|
|
if (agentYaml.agent && agentYaml.agent.prompts) {
|
|
|
|
|
profile.hasPrompts = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Analyze menu items (support both 'menu' and legacy 'commands')
|
|
|
|
|
const menuItems = agentYaml.agent?.menu || agentYaml.agent?.commands || [];
|
|
|
|
|
|
|
|
|
|
for (const item of menuItems) {
|
|
|
|
|
// Track the menu item
|
|
|
|
|
profile.menuItems.push(item);
|
|
|
|
|
|
feat: implement granular step-file workflow architecture with multi-menu support
## Major Features Added
- **Step-file workflow architecture**: Transform monolithic workflows into granular step files for improved LLM adherence and consistency
- **Multi-menu handler system**: New `handler-multi.xml` enables grouped menu items with fuzzy matching
- **Workflow compliance checker**: Added automated compliance validation for all workflows
- **Create/edit agent workflows**: New structured workflows for agent creation and editing
## Workflow Enhancements
- **Create-workflow**: Expanded from 6 to 14 detailed steps covering tools, design, compliance
- **Granular step execution**: Each workflow step now has dedicated files for focused execution
- **New documentation**: Added CSV data standards, intent vs prescriptive spectrum, and common tools reference
## Complete Migration Status
- **4 workflows fully migrated**: `create-agent`, `edit-agent`, `create-workflow`, and `edit-workflow` now use the new granular step-file architecture
- **Legacy transformation**: `edit-workflow` includes built-in capability to transform legacy single-file workflows into the new improved granular format
- **Future cleanup**: Legacy versions will be removed in a future commit after validation
## Schema Updates
- **Multi-menu support**: Updated agent schema to support `triggers` array for grouped menu items
- **Legacy compatibility**: Maintains backward compatibility with single `trigger` field
- **Discussion enhancements**: Added conversational_knowledge recommendation for discussion agents
## File Structure Changes
- Added: `create-agent/`, `edit-agent/`, `edit-workflow/`, `workflow-compliance-check/` workflows
- Added: Documentation standards and CSV reference files
- Refactored: `create-workflow/steps/` with detailed granular step files
## Handler Improvements
- Enhanced `handler-exec.xml` with clearer execution instructions
- Improved data passing context for executed files
- Better error handling and user guidance
This architectural change significantly improves workflow execution consistency across all LLM models by breaking complex processes into manageable, focused steps. The edit-workflow transformation tool ensures smooth migration of existing workflows to the new format.
2025-11-30 15:09:23 -06:00
|
|
|
// Check for multi format items
|
|
|
|
|
if (item.multi && item.triggers) {
|
|
|
|
|
profile.usedAttributes.add('multi');
|
|
|
|
|
|
|
|
|
|
// Also check attributes in nested handlers
|
|
|
|
|
for (const triggerGroup of item.triggers) {
|
|
|
|
|
for (const [triggerName, execArray] of Object.entries(triggerGroup)) {
|
|
|
|
|
if (Array.isArray(execArray)) {
|
|
|
|
|
for (const exec of execArray) {
|
|
|
|
|
if (exec.route) {
|
|
|
|
|
// Check if route is a workflow or exec
|
|
|
|
|
if (exec.route.endsWith('.yaml') || exec.route.endsWith('.yml')) {
|
|
|
|
|
profile.usedAttributes.add('workflow');
|
|
|
|
|
} else {
|
|
|
|
|
profile.usedAttributes.add('exec');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (exec.workflow) profile.usedAttributes.add('workflow');
|
|
|
|
|
if (exec.action) profile.usedAttributes.add('action');
|
|
|
|
|
if (exec.type && ['exec', 'action', 'workflow'].includes(exec.type)) {
|
|
|
|
|
profile.usedAttributes.add(exec.type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Check for each possible attribute in legacy items
|
|
|
|
|
if (item.workflow) {
|
|
|
|
|
profile.usedAttributes.add('workflow');
|
|
|
|
|
}
|
|
|
|
|
if (item['validate-workflow']) {
|
|
|
|
|
profile.usedAttributes.add('validate-workflow');
|
|
|
|
|
}
|
|
|
|
|
if (item.exec) {
|
|
|
|
|
profile.usedAttributes.add('exec');
|
|
|
|
|
}
|
|
|
|
|
if (item.tmpl) {
|
|
|
|
|
profile.usedAttributes.add('tmpl');
|
|
|
|
|
}
|
|
|
|
|
if (item.data) {
|
|
|
|
|
profile.usedAttributes.add('data');
|
|
|
|
|
}
|
|
|
|
|
if (item.action) {
|
|
|
|
|
profile.usedAttributes.add('action');
|
|
|
|
|
}
|
2025-10-02 21:45:59 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert Set to Array for easier use
|
|
|
|
|
profile.usedAttributes = [...profile.usedAttributes];
|
|
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Analyze an agent YAML file
|
|
|
|
|
* @param {string} filePath - Path to agent YAML file
|
|
|
|
|
* @returns {Object} Profile of needed handlers
|
|
|
|
|
*/
|
|
|
|
|
async analyzeAgentFile(filePath) {
|
|
|
|
|
const content = await fs.readFile(filePath, 'utf8');
|
|
|
|
|
const agentYaml = yaml.load(content);
|
|
|
|
|
return this.analyzeAgentObject(agentYaml);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if an agent needs a specific handler
|
|
|
|
|
* @param {Object} profile - Agent profile from analyze
|
|
|
|
|
* @param {string} handlerType - Handler type to check
|
|
|
|
|
* @returns {boolean} True if handler is needed
|
|
|
|
|
*/
|
|
|
|
|
needsHandler(profile, handlerType) {
|
|
|
|
|
return profile.usedAttributes.includes(handlerType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = { AgentAnalyzer };
|