UNPKG

@iflow-mcp/ejmockler-brutalist

Version:

Deploy Claude, Codex & Gemini CLI agents to demolish your work before users do. Real file analysis. Brutal honesty. Now with conversation continuation & intelligent pagination.

185 lines 6.17 kB
/** * Core abstraction: ArgumentSpace * * Defines the parameter schema for a tool - what arguments it accepts. * Argument spaces are composable and reusable across tools. */ import { z } from 'zod'; /** * Standard base arguments shared by all tools */ export const BASE_ARGUMENTS = z.object({ context: z.string().optional().describe("Additional context"), models: z.object({ claude: z.string().optional(), codex: z.string().optional(), gemini: z.string().optional() }).optional().describe("Specific models per agent"), clis: z.array(z.enum(['claude', 'codex', 'gemini'])).min(1).max(3).optional() .describe("CLI agents to use (default: all available)"), force_refresh: z.boolean().optional() .describe("Ignore cache"), context_id: z.string().optional() .describe("Context ID from previous response for pagination or conversation continuation"), resume: z.boolean().optional() .describe("Continue conversation with history injection (requires context_id)"), limit: z.number().min(1000).max(100000).optional() .describe("Max chars/chunk (default: 90000)"), offset: z.number().min(0).optional() .describe("Pagination offset"), cursor: z.string().optional() .describe("Pagination cursor"), verbose: z.boolean().optional() .describe("Detailed output") }); /** * Common argument space: Filesystem-based analysis */ export const FILESYSTEM_ARGUMENT_SPACE = { id: 'filesystem', name: 'Filesystem Analysis', base: BASE_ARGUMENTS, domain: z.object({ targetPath: z.string().describe("Directory path to analyze (e.g., '/path/to/project' or '.')") }), computed: (args) => ({ workingDirectory: args.targetPath }) }; /** * Common argument space: Text-based input */ export const TEXT_INPUT_ARGUMENT_SPACE = { id: 'text_input', name: 'Text Input', base: BASE_ARGUMENTS, domain: z.object({ content: z.string().describe("Text to analyze"), targetPath: z.string().describe("Working dir (default: '.')") }), computed: (args) => ({ workingDirectory: args.targetPath || '.' }) }; /** * Argument space: Filesystem with depth control */ export const FILESYSTEM_WITH_DEPTH = { id: 'filesystem_depth', name: 'Filesystem with Depth Control', base: BASE_ARGUMENTS, domain: z.object({ targetPath: z.string().describe("Directory path to analyze (e.g., '/path/to/project')"), depth: z.number().optional().describe("Max depth (default: 3)") }), computed: (args) => ({ workingDirectory: args.targetPath, analysisDepth: args.depth || 3 }) }; /** * Argument space: Package manifest analysis */ export const PACKAGE_MANIFEST_SPACE = { id: 'package_manifest', name: 'Package Manifest', base: BASE_ARGUMENTS, domain: z.object({ targetPath: z.string().describe("Directory containing package.json (e.g., '/path/to/project')"), includeDevDeps: z.boolean().optional().describe("Include dev dependencies (default: true)") }), computed: (args) => ({ workingDirectory: args.targetPath, analyzeDevDependencies: args.includeDevDeps !== false }) }; /** * Argument space: Git repository analysis */ export const GIT_REPOSITORY_SPACE = { id: 'git_repository', name: 'Git Repository', base: BASE_ARGUMENTS, domain: z.object({ targetPath: z.string().describe("Git repository directory path (e.g., '/path/to/repo')"), commitRange: z.string().optional().describe("Commit range (default: last 20)") }), computed: (args) => ({ workingDirectory: args.targetPath, gitRange: args.commitRange || 'HEAD~20..HEAD' }) }; /** * Argument space: Test suite analysis */ export const TEST_SUITE_SPACE = { id: 'test_suite', name: 'Test Suite', base: BASE_ARGUMENTS, domain: z.object({ targetPath: z.string().describe("Project directory containing tests (e.g., '/path/to/project')"), runCoverage: z.boolean().optional().describe("Run coverage (default: true)") }), computed: (args) => ({ workingDirectory: args.targetPath, executeCoverage: args.runCoverage !== false }) }; /** * Helper to merge multiple argument spaces */ export function mergeArgumentSpaces(...spaces) { const merged = { id: spaces.map(s => s.id).join('_'), name: spaces.map(s => s.name).join(' + '), base: BASE_ARGUMENTS, domain: z.object({}) }; // Merge domain schemas for (const space of spaces) { merged.domain = merged.domain.merge(space.domain); } // Combine computed functions merged.computed = (args) => { let result = {}; for (const space of spaces) { if (space.computed) { result = { ...result, ...space.computed(args) }; } } return result; }; return merged; } /** * Helper to infer cache key fields from an argument space * * NOTE: Excludes pagination/continuation fields (context_id, resume, offset, limit, cursor, force_refresh) * as these don't affect the actual analysis content. */ export function inferCacheKeys(space) { const keys = []; // Always include these base fields if present (excludes pagination/continuation params) const baseKeys = ['context', 'models', 'clis']; keys.push(...baseKeys); // Add all domain-specific fields const domainShape = space.domain.shape; keys.push(...Object.keys(domainShape)); return keys; } /** * Helper to infer the primary argument field */ export function inferPrimaryArg(space) { const domainKeys = Object.keys(space.domain.shape); // Prefer these field names in order const preferred = ['targetPath', 'content', 'idea', 'system', 'architecture', 'research', 'product', 'infrastructure']; for (const key of preferred) { if (domainKeys.includes(key)) { return key; } } // Fallback to first domain key return domainKeys[0] || 'targetPath'; } //# sourceMappingURL=argument-space.js.map