207 lines
5.2 KiB
JavaScript
207 lines
5.2 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Orchestrator - Main Integration Point
|
|
*
|
|
* Ties together: Pipeline → Router → LLM → Validator → Format Locker
|
|
*/
|
|
|
|
const ContextPipeline = require('./pipeline');
|
|
const WorkflowRouter = require('./workflow-router');
|
|
const ResponseValidator = require('./validator');
|
|
const FormatLocker = require('./format-locker');
|
|
|
|
class AgentOrchestrator {
|
|
constructor(options = {}) {
|
|
this.workspace = options.workspace || '/home/jcbeasley/.openclaw/workspace';
|
|
this.verbose = options.verbose || false;
|
|
this.autoFix = options.autoFix !== false;
|
|
|
|
this.pipeline = new ContextPipeline();
|
|
this.router = new WorkflowRouter();
|
|
}
|
|
|
|
/**
|
|
* Main entry point - process user request through full pipeline
|
|
*/
|
|
async process(userInput, context = {}) {
|
|
const startTime = Date.now();
|
|
|
|
this.log('=== Starting Orchestration ===');
|
|
this.log(`Input: ${userInput.substring(0, 100)}...`);
|
|
|
|
try {
|
|
// Step 1: Build context
|
|
this.log('Step 1: Building context...');
|
|
const contextPacket = await this.buildContext(userInput, context);
|
|
|
|
// Step 2: Classify intent and route
|
|
this.log('Step 2: Classifying intent...');
|
|
const route = this.router.route(userInput, context);
|
|
|
|
// Step 3: Prepare system prompt
|
|
this.log(`Step 3: Workflow = ${route.workflow} (${(route.confidence * 100).toFixed(1)}% confidence)`);
|
|
const systemPrompt = this.buildSystemPrompt(route, contextPacket);
|
|
|
|
// Step 4: Get response (this would call LLM)
|
|
// For now, return the prompt for testing
|
|
const response = {
|
|
systemPrompt: systemPrompt,
|
|
workflow: route.workflow,
|
|
confidence: route.confidence,
|
|
context: contextPacket
|
|
};
|
|
|
|
// Step 5: Validate response
|
|
this.log('Step 4: Validating...');
|
|
const validation = this.validateResponse(response.systemPrompt, route.workflow);
|
|
|
|
// Step 6: Enforce format
|
|
this.log('Step 5: Enforcing format...');
|
|
const formatted = this.enforceFormat(response.systemPrompt, route.workflow);
|
|
|
|
const duration = Date.now() - startTime;
|
|
this.log(`=== Complete in ${duration}ms ===`);
|
|
|
|
return {
|
|
...response,
|
|
validation: validation,
|
|
format: formatted,
|
|
metadata: {
|
|
duration: duration,
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('Orchestration error:', error);
|
|
return {
|
|
error: error.message,
|
|
input: userInput,
|
|
metadata: {
|
|
duration: Date.now() - startTime,
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build context packet from all sources
|
|
*/
|
|
async buildContext(userInput, context) {
|
|
// Load rules
|
|
await this.pipeline.loadRules();
|
|
|
|
// Load preferences
|
|
await this.pipeline.loadPreferences();
|
|
|
|
// Load relevant memory
|
|
await this.pipeline.loadRelevantMemory(userInput, 5);
|
|
|
|
// Build final packet
|
|
const packet = this.pipeline.buildPacket(userInput);
|
|
|
|
// Add session context
|
|
packet.project = context.project || process.env.CURRENT_PROJECT;
|
|
packet.user = context.user || 'JC';
|
|
|
|
return packet;
|
|
}
|
|
|
|
/**
|
|
* Build combined system prompt
|
|
*/
|
|
buildSystemPrompt(route, contextPacket) {
|
|
const parts = [
|
|
'# System Instructions',
|
|
'',
|
|
contextPacket.system,
|
|
'',
|
|
'---',
|
|
'',
|
|
'# Workflow Mode',
|
|
route.systemPrompt,
|
|
'',
|
|
'---',
|
|
'',
|
|
'# Current Context',
|
|
`Project: ${contextPacket.project || 'None'}`,
|
|
`User: ${contextPacket.user || 'Unknown'}`,
|
|
'',
|
|
'---',
|
|
'',
|
|
'# Memory',
|
|
contextPacket.memory.substring(0, 1000) // Truncate for brevity
|
|
];
|
|
|
|
return parts.join('\n');
|
|
}
|
|
|
|
/**
|
|
* Validate response against rules
|
|
*/
|
|
validateResponse(response, workflow) {
|
|
const validator = new ResponseValidator(workflow);
|
|
return validator.validate(response);
|
|
}
|
|
|
|
/**
|
|
* Enforce format compliance
|
|
*/
|
|
enforceFormat(response, workflow) {
|
|
const locker = new FormatLocker(workflow);
|
|
return locker.enforceFormat(response, this.autoFix);
|
|
}
|
|
|
|
/**
|
|
* Get format prompt for LLM
|
|
*/
|
|
getFormatPrompt(workflow) {
|
|
const locker = new FormatLocker(workflow);
|
|
return locker.getFormatPrompt();
|
|
}
|
|
|
|
/**
|
|
* Log with verbosity control
|
|
*/
|
|
log(message) {
|
|
if (this.verbose) {
|
|
console.log(message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Quick classification without full processing
|
|
*/
|
|
classify(userInput) {
|
|
return this.router.classifyIntent(userInput);
|
|
}
|
|
|
|
/**
|
|
* Get workflow config
|
|
*/
|
|
getWorkflow(name) {
|
|
return this.router.getWorkflow(name);
|
|
}
|
|
}
|
|
|
|
// Export for use
|
|
module.exports = AgentOrchestrator;
|
|
|
|
// CLI usage
|
|
if (require.main === module) {
|
|
const userInput = process.argv[2] || 'implement a new feature';
|
|
const verbose = process.argv.includes('--verbose') || process.argv.includes('-v');
|
|
|
|
const orchestrator = new AgentOrchestrator({ verbose: verbose });
|
|
|
|
orchestrator.process(userInput, { project: process.env.CURRENT_PROJECT })
|
|
.then(result => {
|
|
console.log(JSON.stringify(result, null, 2));
|
|
})
|
|
.catch(err => {
|
|
console.error('Error:', err);
|
|
process.exit(1);
|
|
});
|
|
}
|