9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
/**
|
|
* AutoResearch Configuration — type definitions and CLI parsing.
|
|
*
|
|
* Based on Karpathy's autoresearch: constraint + mechanical metric + unbounded loop.
|
|
*/
|
|
|
|
export interface AutoResearchConfig {
|
|
/** Plain-language goal, e.g. "Increase browser pass rate to 59/59" */
|
|
goal: string;
|
|
/** Glob patterns for files the agent can modify */
|
|
scope: string[];
|
|
/** What the metric measures, e.g. "pass_count" */
|
|
metric: string;
|
|
/** Whether improvement means the number goes up or down */
|
|
direction: 'higher' | 'lower';
|
|
/** Shell command that outputs a number (the metric value) */
|
|
verify: string;
|
|
/** Optional guard command — must pass for a keep decision */
|
|
guard?: string;
|
|
/** Max iterations (undefined = unbounded) */
|
|
iterations?: number;
|
|
/** Minimum delta to count as real improvement (noise filter) */
|
|
minDelta?: number;
|
|
}
|
|
|
|
export type IterationStatus =
|
|
| 'baseline'
|
|
| 'keep'
|
|
| 'keep (reworked)'
|
|
| 'discard'
|
|
| 'crash'
|
|
| 'no-op'
|
|
| 'hook-blocked';
|
|
|
|
export interface IterationResult {
|
|
iteration: number;
|
|
commit: string;
|
|
metric: number;
|
|
delta: number;
|
|
guard: 'pass' | 'fail' | '-';
|
|
status: IterationStatus;
|
|
description: string;
|
|
}
|
|
|
|
/** Parse CLI args into a partial config (missing fields filled by preset or prompts) */
|
|
export function parseArgs(argv: string[]): Partial<AutoResearchConfig> & { preset?: string; task?: string } {
|
|
const config: Partial<AutoResearchConfig> & { preset?: string; task?: string } = {};
|
|
for (let i = 0; i < argv.length; i++) {
|
|
const arg = argv[i];
|
|
const next = argv[i + 1];
|
|
switch (arg) {
|
|
case '--preset': config.preset = next; i++; break;
|
|
case '--goal': config.goal = next; i++; break;
|
|
case '--scope': config.scope = next?.split(','); i++; break;
|
|
case '--metric': config.metric = next; i++; break;
|
|
case '--direction': config.direction = next as 'higher' | 'lower'; i++; break;
|
|
case '--verify': config.verify = next; i++; break;
|
|
case '--guard': config.guard = next; i++; break;
|
|
case '--iterations': config.iterations = parseInt(next, 10); i++; break;
|
|
case '--min-delta': config.minDelta = parseFloat(next); i++; break;
|
|
case '--task': config.task = next; i++; break;
|
|
}
|
|
}
|
|
return config;
|
|
}
|
|
|
|
/** Extract a number from command output using common patterns */
|
|
export function extractMetric(output: string): number | null {
|
|
// Try: last line that looks like a number
|
|
const lines = output.trim().split('\n');
|
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
const line = lines[i].trim();
|
|
// Match standalone numbers: "56", "95.2", "SCORE=56/59" → 56
|
|
const scoreMatch = line.match(/SCORE[=:]\s*(\d+)/i);
|
|
if (scoreMatch) return parseFloat(scoreMatch[1]);
|
|
const numMatch = line.match(/^[\d.]+$/);
|
|
if (numMatch) return parseFloat(numMatch[0]);
|
|
}
|
|
// Fallback: first number in output
|
|
const fallback = output.match(/(\d+(?:\.\d+)?)/);
|
|
return fallback ? parseFloat(fallback[1]) : null;
|
|
}
|