aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
170 lines (147 loc) • 4.67 kB
JavaScript
/**
* L7 Star-Command Layer Processor
*
* Detects *command patterns in the user prompt and loads
* corresponding rules from the .synapse/commands domain file.
*
* Command blocks in the domain file are delimited by [*command]
* headers. Multiple star-commands in a single prompt are supported.
*
* @module core/synapse/layers/l7-star-command
* @version 1.0.0
* @created Story SYN-5 - Layer Processors L4-L7
*/
const path = require('path');
const { loadDomainFile } = require('../domain/domain-loader');
const LayerProcessor = require('./layer-processor');
/** Regex to detect star-commands in prompt */
const STAR_COMMAND_REGEX = /\*([a-z][\w-]*)/gi;
/**
* L7 Star-Command Processor
*
* Detects *command patterns in the prompt, loads the commands
* domain file, and extracts rules for matching command blocks.
* Returns null if no star-commands detected.
*
* @extends LayerProcessor
*/
class L7StarCommandProcessor extends LayerProcessor {
constructor() {
super({ name: 'star-command', layer: 7, timeout: 5 });
}
/**
* Detect star-commands and load matching rules.
*
* Detection flow:
* 1. Scan prompt for *command patterns via regex
* 2. Deduplicate detected commands
* 3. Load .synapse/commands domain file
* 4. Parse command blocks delimited by [*command]
* 5. Collect rules for detected commands
*
* @param {object} context
* @param {string} context.prompt - Current prompt text
* @param {object} context.session - Session state (SYN-2 schema)
* @param {object} context.config - Config with synapsePath and manifest
* @param {object[]} context.previousLayers - Results from previous layers
* @returns {{ rules: string[], metadata: object } | null}
*/
process(context) {
const { prompt, config } = context;
const { synapsePath } = config;
if (!prompt) {
return null;
}
// 1. Detect star-commands in prompt
const commands = this._detectCommands(prompt);
if (commands.length === 0) {
return null;
}
// 2. Load commands domain file
const commandsFilePath = path.join(synapsePath, 'commands');
const rawRules = loadDomainFile(commandsFilePath);
if (!rawRules || rawRules.length === 0) {
return null;
}
// 3. Parse command blocks from raw rules
const commandBlocks = this._parseCommandBlocks(rawRules);
// 4. Collect rules for detected commands
const allRules = [];
const matchedCommands = [];
for (const cmd of commands) {
const block = commandBlocks[cmd];
if (block && block.length > 0) {
allRules.push(...block);
matchedCommands.push(cmd);
}
}
if (allRules.length === 0) {
return null;
}
return {
rules: allRules,
metadata: {
layer: 7,
commands: matchedCommands,
},
};
}
/**
* Detect star-command patterns in prompt text.
*
* @param {string} prompt - User prompt text
* @returns {string[]} Deduplicated list of command names (lowercase)
* @private
*/
_detectCommands(prompt) {
const matches = [];
let match;
// Reset regex state
STAR_COMMAND_REGEX.lastIndex = 0;
while ((match = STAR_COMMAND_REGEX.exec(prompt)) !== null) {
matches.push(match[1].toLowerCase());
}
return [...new Set(matches)];
}
/**
* Parse command blocks from domain file rules.
*
* Format:
* [*command] COMMAND:
* 0. Rule text here
* 1. Another rule
*
* Each [*command] header starts a new block.
* Rules within a block are the lines following the header.
*
* @param {string[]} rules - Raw rules from loadDomainFile
* @returns {object} Map of command name -> rule strings
* @private
*/
_parseCommandBlocks(rules) {
const blocks = {};
let currentCommand = null;
for (const rule of rules) {
// Check if this line is a command header: [*command]
const headerMatch = rule.match(/^\[\*([a-z][\w-]*)\]/i);
if (headerMatch) {
currentCommand = headerMatch[1].toLowerCase();
if (!blocks[currentCommand]) {
blocks[currentCommand] = [];
}
// If there's content after the header on the same line, include it
const afterHeader = rule.substring(headerMatch[0].length).trim();
if (afterHeader && !afterHeader.endsWith(':')) {
blocks[currentCommand].push(afterHeader);
}
continue;
}
// Add rule to current command block
if (currentCommand && rule.trim()) {
blocks[currentCommand].push(rule.trim());
}
}
return blocks;
}
}
module.exports = L7StarCommandProcessor;