ai-harness / src /cli /commands /run.ts
stevenkhan's picture
Initial AI Harness - production-grade model-agnostic CLI agent runtime
908562b verified
// ─── Run Command ────────────────────────────────────────────────────────────
import { createRuntime } from '../state/factory.js';
import { EventRenderer, renderMetrics } from '../renderers/index.js';
import { Runtime, type RuntimeConfig } from '../../core/runtime/index.js';
import { EventBus } from '../../core/events/index.js';
import { ToolRegistry } from '../../core/tools/index.js';
import { SkillRegistry } from '../../core/skills/index.js';
import { PolicyEngine } from '../../core/policy/index.js';
import { MetricsCollector } from '../../core/observability/index.js';
import { ArtifactStore } from '../../core/artifacts/index.js';
import { Evaluator, outputNotEmptyCheck, hasArtifactsCheck } from '../../core/evaluators/index.js';
import { readFileTool, writeFileTool, listDirTool } from '../../tools/fs/index.js';
import { shellExecTool } from '../../tools/shell/index.js';
import { webFetchTool } from '../../tools/web/index.js';
import { codingSkill } from '../../skills/coding/index.js';
import { researchSkill } from '../../skills/research/index.js';
import { docsSkill } from '../../skills/docs/index.js';
import { resolveProvider } from '../state/provider-resolver.js';
export async function runCommand(goal: string, opts: {
provider: string;
model?: string;
skills: string[];
maxTurns?: string;
budgetTokens?: string;
budgetCost?: string;
approval?: string;
verbose?: boolean;
compact?: boolean;
}): Promise<void> {
const renderer = new EventRenderer({ verbose: opts.verbose ?? false, compact: opts.compact ?? false });
// Setup
const eventBus = new EventBus();
eventBus.on((event) => renderer.render(event));
const provider = resolveProvider(opts.provider);
const model = opts.model ?? (await provider.listModels())[0]!.id;
// Tools
const tools = new ToolRegistry();
tools.register(readFileTool);
tools.register(writeFileTool);
tools.register(listDirTool);
tools.register(shellExecTool);
tools.register(webFetchTool);
// Skills
const skills = new SkillRegistry();
skills.register(codingSkill);
skills.register(researchSkill);
skills.register(docsSkill);
// Policy
const policy = new PolicyEngine({
mode: (opts.approval as any) ?? 'confirm-writes',
});
// Metrics
const metrics = new MetricsCollector();
// Artifacts
const artifacts = new ArtifactStore();
// Evaluator
const evaluator = new Evaluator();
evaluator.addCheck(outputNotEmptyCheck);
// Runtime config
const config: RuntimeConfig = {
provider,
model,
tools,
skills,
policy,
metrics,
artifacts,
evaluator,
eventBus,
systemPrompt: `You are an AI agent executing tasks autonomously. You have tools available. Complete the goal thoroughly, verify your work, and report results.`,
activeSkills: opts.skills,
maxTurns: opts.maxTurns ? parseInt(opts.maxTurns) : 20,
budgetTokens: opts.budgetTokens ? parseInt(opts.budgetTokens) : undefined,
budgetCostUsd: opts.budgetCost ? parseFloat(opts.budgetCost) : undefined,
};
// Execute
const runtime = new Runtime(config, goal);
const state = await runtime.run();
// Summary
const summary = metrics.summarize(state.id);
renderMetrics(summary);
process.exit(state.status === 'completed' ? 0 : 1);
}