Skip to main content
Glama
agent.tsโ€ข5.95 kB
/** * Iris MCP Module: agent * Returns canned prompt text for specialized agent roles */ import { getChildLogger } from "../utils/logger.js"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; import { TemplateRenderer } from "../agents/template-renderer.js"; import { ContextDiscovery, getAgentPatterns } from "../agents/context-discovery.js"; import { getGitDiff, findTemplate } from "../agents/template-utils.js"; import { readFileSync } from "fs"; const logger = getChildLogger("action:agent"); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const TEMPLATES_DIR = join(__dirname, "..", "..", "templates", "base"); // Supported agent types export const AGENT_TYPES = [ "tech-writer", "unit-tester", "integration-tester", "code-reviewer", "debugger", "refactorer", "changeloger", "error-handler", "example-writer", "logger", ] as const; export type AgentType = (typeof AGENT_TYPES)[number]; export interface AgentInput { /** Type of agent to get prompt for (e.g., 'tech-writer', 'unit-tester') */ agentType: string; /** Optional context to interpolate into the template */ context?: Record<string, any>; /** Optional project path for context discovery (Phase 2) */ projectPath?: string; /** Include git diff in context (Phase 3) */ includeGitDiff?: boolean; } export interface AgentOutput { /** The agent type requested */ agentType: string; /** The canned prompt text for this agent */ prompt: string; /** Whether the agent type is valid/supported */ valid: boolean; /** Available agent types */ availableAgents: readonly string[]; } /** * Validates if an agent type is supported */ function isValidAgentType(type: string): type is AgentType { return AGENT_TYPES.includes(type as AgentType); } /** * Get bundled template directory */ function getBundledTemplatesDir(): string { return TEMPLATES_DIR; } /** * Register all bundled templates as partials */ async function registerBundledPartials(renderer: TemplateRenderer): Promise<void> { // Register all bundled templates as partials so they can be included for (const agentType of AGENT_TYPES) { try { const templatePath = join(TEMPLATES_DIR, `${agentType}.hbs`); const templateContent = readFileSync(templatePath, "utf-8"); renderer.registerPartial(`base/${agentType}`, templateContent); } catch (error) { logger.warn({ agentType, error }, "Failed to register partial"); } } } export async function agent(input: AgentInput): Promise<AgentOutput> { const { agentType, context = {}, projectPath, includeGitDiff = false } = input; logger.info( { agentType, hasContext: Object.keys(context).length > 0, hasProjectPath: !!projectPath, includeGitDiff, }, "Getting agent prompt", ); if (!isValidAgentType(agentType)) { logger.warn( { requestedType: agentType, availableTypes: AGENT_TYPES, }, "Invalid agent type requested", ); return { agentType, prompt: `Invalid agent type "${agentType}". Available types: ${AGENT_TYPES.join(", ")}`, valid: false, availableAgents: AGENT_TYPES, }; } try { // Build context for template rendering let templateContext = { ...context }; // Phase 2: Auto-discover project context if projectPath provided if (projectPath) { logger.debug({ projectPath }, "Running context discovery"); const discovery = new ContextDiscovery(projectPath); const projectContext = await discovery.discover(); // Get agent-specific file patterns const agentPatterns = getAgentPatterns(agentType); // Merge discovered context with user-provided context // User-provided context takes precedence templateContext = { ...projectContext, writePatterns: projectContext.writePatterns.length > 0 ? projectContext.writePatterns : agentPatterns.writePatterns, readOnlyPatterns: projectContext.readOnlyPatterns.length > 0 ? projectContext.readOnlyPatterns : agentPatterns.readOnlyPatterns, ...context, // User context overrides discovered context }; logger.info( { projectName: templateContext.projectName, framework: templateContext.framework, hasTypeScript: templateContext.hasTypeScript, }, "Context discovery complete", ); // Phase 3: Add git diff if requested if (includeGitDiff) { logger.debug("Including git diff in context"); const gitDiff = await getGitDiff(projectPath); if (gitDiff) { templateContext.gitDiff = gitDiff; logger.info({ diffLength: gitDiff.length }, "Git diff added to context"); } } } // Phase 3: Template hierarchy - find template with lookup order const templatePath = await findTemplate( agentType, projectPath, getBundledTemplatesDir(), ); logger.debug({ templatePath }, "Template resolved"); // Create renderer and register partials (Phase 3) const renderer = new TemplateRenderer(); await registerBundledPartials(renderer); // Render template with context const prompt = renderer.render(templatePath, templateContext); logger.info( { agentType, templatePath, promptLength: prompt.length, contextKeys: Object.keys(templateContext).length, hasGitDiff: !!templateContext.gitDiff, }, "Agent prompt rendered successfully", ); return { agentType, prompt, valid: true, availableAgents: AGENT_TYPES, }; } catch (error) { logger.error( { err: error instanceof Error ? error : new Error(String(error)), agentType, }, "Failed to get agent prompt", ); throw error; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jenova-marie/iris-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server