mcp-ai-agent-guidelines
Version:
A comprehensive Model Context Protocol server providing advanced tools, resources, and prompts for implementing AI agent best practices
442 lines • 18.2 kB
JavaScript
// Design Assistant - Main orchestrator/facade for the deterministic design framework
import { z } from "zod";
import { getFeatureFlags } from "../../config/feature-flags.js";
import { polyglotGateway } from "../../gateway/polyglot-gateway.js";
import { CrossCuttingCapability, OutputApproach, } from "../../strategies/output-strategy.js";
import { missingRequiredError, validationError, } from "../shared/error-factory.js";
import { handleToolError } from "../shared/error-handler.js";
import { logger } from "../shared/logger.js";
import { confirmationModule } from "./confirmation-module.js";
import { constraintManager, DEFAULT_CONSTRAINT_CONFIG, } from "./constraint-manager.js";
import { coverageEnforcer } from "./coverage-enforcer.js";
import { crossSessionConsistencyEnforcer } from "./cross-session-consistency-enforcer.js";
import { methodologySelector } from "./methodology-selector.js";
import { pivotModule } from "./pivot-module.js";
import { additionalOperationsService, artifactGenerationService, consistencyService, detectFramework, detectLanguage, generateContextAwareRecommendations, phaseManagementService, sessionManagementService, } from "./services/index.js";
const _DesignAssistantRequestSchema = z.object({
action: z.enum([
"start-session",
"advance-phase",
"validate-phase",
"evaluate-pivot",
"generate-strategic-pivot-prompt",
"generate-artifacts",
"enforce-coverage",
"enforce-consistency",
"get-status",
"load-constraints",
"select-methodology",
"enforce-cross-session-consistency",
"generate-enforcement-prompts",
"generate-constraint-documentation",
"generate-context-aware-guidance",
]),
sessionId: z.string(),
config: z.any().optional(), // DesignSessionConfig
content: z.string().optional(),
phaseId: z.string().optional(),
constraintId: z.string().optional(),
constraintConfig: z.any().optional(),
methodologySignals: z.any().optional(), // MethodologySignals
artifactTypes: z
.array(z.enum(["adr", "specification", "roadmap", "speckit"]))
.optional(),
includeTemplates: z.boolean().optional(),
includeSpace7Instructions: z.boolean().optional(),
customInstructions: z.array(z.string()).optional(),
metadata: z.record(z.unknown()).optional().default({}),
outputFormat: z
.enum(["chat", "rfc", "adr", "sdd", "togaf", "enterprise", "speckit"])
.optional(),
crossCutting: z
.array(z.enum([
"workflow",
"shell-script",
"diagram",
"config",
"issues",
"pr-template",
]))
.optional(),
});
/**
* Map outputFormat string to OutputApproach enum.
*/
function mapOutputFormat(format) {
if (!format)
return OutputApproach.CHAT;
const mapping = {
chat: OutputApproach.CHAT,
rfc: OutputApproach.RFC,
adr: OutputApproach.ADR,
sdd: OutputApproach.SDD,
togaf: OutputApproach.TOGAF,
enterprise: OutputApproach.ENTERPRISE,
speckit: OutputApproach.SPECKIT,
};
return mapping[format.toLowerCase()] ?? OutputApproach.CHAT;
}
/**
* Map crossCutting strings to CrossCuttingCapability enum.
* Validates all capabilities and throws error if any are unknown.
*/
function mapCrossCutting(capabilities) {
if (!capabilities?.length)
return [];
const mapping = {
workflow: CrossCuttingCapability.WORKFLOW,
"shell-script": CrossCuttingCapability.SHELL_SCRIPT,
diagram: CrossCuttingCapability.DIAGRAM,
config: CrossCuttingCapability.CONFIG,
issues: CrossCuttingCapability.ISSUES,
"pr-template": CrossCuttingCapability.PR_TEMPLATE,
};
const resolved = [];
const unknownCapabilities = [];
for (const rawCap of capabilities) {
const key = rawCap.toLowerCase();
const mapped = mapping[key];
if (mapped === undefined) {
unknownCapabilities.push(rawCap);
}
else {
resolved.push(mapped);
}
}
if (unknownCapabilities.length > 0) {
throw validationError(`Unknown crossCutting capabilities: ${unknownCapabilities.join(", ")}`, { unknownCapabilities, validCapabilities: Object.keys(mapping) });
}
return resolved;
}
/**
* Zod schema for validating gateway artifacts structure.
*/
const GatewayArtifactsSchema = z.object({
primary: z.object({
name: z.string(),
content: z.string(),
format: z.enum(["markdown", "json", "yaml"]),
}),
secondary: z
.array(z.object({
name: z.string(),
content: z.string(),
format: z.enum(["markdown", "json", "yaml"]),
}))
.optional(),
crossCutting: z
.array(z.object({
type: z.string(),
name: z.string(),
content: z.string(),
}))
.optional(),
});
/**
* Format gateway artifacts as DesignAssistantResponse.
* Validates artifacts structure before formatting.
*/
function formatGatewayResponse(sessionId, artifacts) {
const parseResult = GatewayArtifactsSchema.safeParse(artifacts);
if (!parseResult.success) {
throw validationError("Invalid gateway artifacts structure", {
sessionId,
issues: parseResult.error.issues,
});
}
const artifactsData = parseResult.data;
const formattedArtifacts = [
{
id: `${sessionId}-primary`,
name: artifactsData.primary.name,
type: "specification",
content: artifactsData.primary.content,
format: artifactsData.primary.format,
timestamp: new Date().toISOString(),
metadata: { source: "polyglot-gateway" },
},
];
if (artifactsData.secondary?.length) {
formattedArtifacts.push(...artifactsData.secondary.map((sec, idx) => ({
id: `${sessionId}-secondary-${idx}`,
name: sec.name,
type: "specification",
content: sec.content,
format: sec.format,
timestamp: new Date().toISOString(),
metadata: { source: "polyglot-gateway" },
})));
}
return {
success: true,
sessionId,
status: "gateway-rendered",
message: "Response rendered via PolyglotGateway",
recommendations: [
"Output formatted using new gateway strategy",
...(artifactsData.crossCutting?.length
? ["Cross-cutting artifacts included"]
: []),
],
artifacts: formattedArtifacts,
data: {
gatewayEnabled: true,
primaryFormat: artifactsData.primary.format,
secondaryCount: artifactsData.secondary?.length ?? 0,
crossCuttingCount: artifactsData.crossCutting?.length ?? 0,
},
};
}
class DesignAssistantImpl {
initialized = false;
async initialize() {
if (this.initialized)
return;
try {
// Load default constraint configuration
await constraintManager.loadConstraintsFromConfig(DEFAULT_CONSTRAINT_CONFIG);
// Initialize sub-modules
await confirmationModule.initialize();
await pivotModule.initialize();
await coverageEnforcer.initialize();
await methodologySelector.initialize();
await crossSessionConsistencyEnforcer.initialize();
this.initialized = true;
}
catch (error) {
throw validationError("Failed to initialize Design Assistant", {
originalError: error instanceof Error ? error.message : String(error),
});
}
}
// Backwards-compatible wrappers expected by tests
async createSession(config) {
await this.initialize();
const sessionId = `session-${Date.now()}`;
const resp = await this.processRequest({
action: "start-session",
sessionId,
config: {
sessionId,
context: config.context,
goal: config.goal,
requirements: config.requirements,
constraints: [],
coverageThreshold: 85,
enablePivots: true,
templateRefs: [],
outputFormats: ["markdown"],
metadata: {},
},
});
return { ...resp, sessionId };
}
async getPhaseGuidance(_sessionState, phaseId) {
await this.initialize();
return phaseManagementService.getPhaseGuidance(_sessionState, phaseId);
}
async validateConstraints(_sessionState) {
await this.initialize();
return { passed: true };
}
async generateWorkflow(_sessionState) {
await this.initialize();
return { steps: ["discovery", "requirements", "architecture"] };
}
async processRequest(request) {
try {
await this.initialize();
const { action, sessionId } = request;
// Get domain result from service layer
let domainResult;
switch (action) {
case "start-session":
if (!request.config) {
throw missingRequiredError("config", { action, sessionId });
}
domainResult = await sessionManagementService.startDesignSession(sessionId, request.config, request.constraintConfig);
break;
case "advance-phase":
domainResult = await phaseManagementService.advancePhase(sessionId, request.content, request.phaseId);
break;
case "validate-phase":
if (!request.phaseId || !request.content) {
throw missingRequiredError("phaseId/content", {
action,
sessionId,
});
}
domainResult = await phaseManagementService.validatePhase(sessionId, request.phaseId, request.content);
break;
case "evaluate-pivot":
if (!request.content) {
throw missingRequiredError("content", { action, sessionId });
}
domainResult = await additionalOperationsService.evaluatePivot(sessionId, request.content);
break;
case "generate-strategic-pivot-prompt":
if (!request.content) {
throw missingRequiredError("content", { action, sessionId });
}
domainResult =
await additionalOperationsService.generateStrategicPivotPrompt(sessionId, request.content, request.includeTemplates, request.includeSpace7Instructions, request.customInstructions);
break;
case "generate-artifacts":
domainResult = await artifactGenerationService.generateArtifacts(sessionId, request.artifactTypes || ["adr", "specification", "roadmap"]);
break;
case "enforce-coverage":
if (!request.content) {
throw missingRequiredError("content", { action, sessionId });
}
domainResult = await consistencyService.enforceCoverage(sessionId, request.content);
break;
case "enforce-consistency":
domainResult = await consistencyService.enforceConsistency(sessionId, request.constraintId, request.phaseId, request.content);
break;
case "get-status":
domainResult =
await sessionManagementService.getSessionStatus(sessionId);
break;
case "load-constraints":
if (!request.constraintConfig) {
throw missingRequiredError("constraintConfig", {
action,
sessionId,
});
}
domainResult = await additionalOperationsService.loadConstraints(request.constraintConfig);
break;
case "select-methodology":
if (!request.methodologySignals) {
throw missingRequiredError("methodologySignals", {
sessionId,
action,
});
}
domainResult = await additionalOperationsService.selectMethodology(sessionId, request.methodologySignals);
break;
case "enforce-cross-session-consistency":
domainResult =
await consistencyService.enforceCrossSessionConsistency(sessionId);
break;
case "generate-enforcement-prompts":
domainResult =
await consistencyService.generateEnforcementPrompts(sessionId);
break;
case "generate-constraint-documentation":
domainResult =
await artifactGenerationService.generateConstraintDocumentation(sessionId);
break;
case "generate-context-aware-guidance":
if (!request.content) {
throw missingRequiredError("content", { action, sessionId });
}
domainResult = await this.generateContextAwareGuidance(sessionId, request.content);
break;
default:
throw validationError(`Unknown action: ${action}`, {
action,
sessionId,
});
}
// Check if gateway rendering should be applied
const flags = getFeatureFlags();
if (flags.usePolyglotGateway && request.outputFormat) {
// Use new gateway for rendering
try {
const artifacts = polyglotGateway.render({
domainResult,
domainType: "DesignAssistantResponse",
approach: mapOutputFormat(request.outputFormat),
crossCutting: mapCrossCutting(request.crossCutting),
});
return formatGatewayResponse(sessionId, artifacts);
}
catch (gatewayError) {
// Log the error and fallback to legacy behavior
logger.warn("Gateway rendering failed, falling back to legacy", {
sessionId,
action,
outputFormat: request.outputFormat,
error: gatewayError instanceof Error
? gatewayError.message
: String(gatewayError),
});
return domainResult;
}
}
// Legacy behavior - return domain result directly
return domainResult;
}
catch (error) {
return handleToolError(error);
}
}
// Utility methods
async generateContextAwareGuidance(sessionId, codeContext) {
try {
await this.initialize();
const language = detectLanguage(codeContext);
const framework = detectFramework(codeContext);
const guidanceText = generateContextAwareRecommendations(codeContext);
return {
success: true,
sessionId,
status: "guidance-generated",
message: `Generated context-aware design guidance for ${language}${framework ? ` with ${framework} framework` : ""}`,
recommendations: [
`Detected language: ${language}`,
...(framework ? [`Detected framework: ${framework}`] : []),
"Review the detailed guidance in the artifacts",
],
artifacts: [
{
id: `guidance-${Date.now()}`,
name: "Context-Aware Design Guidance",
type: "specification",
content: guidanceText,
format: "markdown",
timestamp: new Date().toISOString(),
metadata: {
generatedAt: new Date().toISOString(),
detectedLanguage: language,
detectedFramework: framework,
},
},
],
data: {
detectedLanguage: language,
detectedFramework: framework,
guidanceLength: guidanceText.length,
},
};
}
catch (error) {
return handleToolError(error);
}
}
async getActiveSessions() {
return sessionManagementService.getActiveSessions();
}
async getConstraintSummary() {
await this.initialize();
const constraints = constraintManager.getConstraints();
const mandatory = constraintManager.getMandatoryConstraints();
const categories = [...new Set((constraints || []).map((c) => c.category))];
const thresholds = constraintManager.getCoverageThresholds();
return {
total: constraints.length,
mandatory: mandatory.length,
categories,
thresholds,
};
}
async getPhaseSequence() {
return phaseManagementService.getPhaseSequence();
}
}
// Export singleton instance
export const designAssistant = new DesignAssistantImpl();
// Module Implementation Status Sentinel
export const IMPLEMENTATION_STATUS = "IMPLEMENTED";
//# sourceMappingURL=design-assistant.js.map