@tritard/waterbrother 0.9.5 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +43 -29
- package/src/experiment.js +3 -3
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -6207,43 +6207,57 @@ async function promptLoop(agent, session, context) {
|
|
|
6207
6207
|
}
|
|
6208
6208
|
|
|
6209
6209
|
if (line === "/experiment" || line.startsWith("/experiment ")) {
|
|
6210
|
-
|
|
6210
|
+
// Parse: /experiment <goal> --metric "command" --attempts N --time M
|
|
6211
|
+
const rawArgs = line.replace("/experiment", "").trim();
|
|
6212
|
+
if (!rawArgs) {
|
|
6213
|
+
console.log('Usage: /experiment <goal> --metric "npm test" --attempts 5 --time 30');
|
|
6214
|
+
console.log(' --metric command to measure (required)');
|
|
6215
|
+
console.log(' --attempts max attempts, 0=infinite (default: 0)');
|
|
6216
|
+
console.log(' --time time limit in minutes (default: 60)');
|
|
6217
|
+
continue;
|
|
6218
|
+
}
|
|
6219
|
+
|
|
6220
|
+
// Extract flags — parse --metric value (everything until next -- flag or end)
|
|
6221
|
+
const attemptsMatch = rawArgs.match(/--attempts\s+(\d+)/);
|
|
6222
|
+
const timeMatch = rawArgs.match(/--time\s+(\d+)/);
|
|
6223
|
+
// Remove --attempts and --time first so --metric can grab the rest
|
|
6224
|
+
let cleaned = rawArgs.replace(/--attempts\s+\d+/g, "").replace(/--time\s+\d+/g, "");
|
|
6225
|
+
let metricCmd = "";
|
|
6226
|
+
const metricIdx = cleaned.indexOf("--metric");
|
|
6227
|
+
if (metricIdx !== -1) {
|
|
6228
|
+
const afterMetric = cleaned.slice(metricIdx + 8).trim();
|
|
6229
|
+
// If quoted, take the quoted content; otherwise take everything until end
|
|
6230
|
+
if (afterMetric.startsWith('"')) {
|
|
6231
|
+
const endQuote = afterMetric.indexOf('"', 1);
|
|
6232
|
+
metricCmd = endQuote > 0 ? afterMetric.slice(1, endQuote) : afterMetric.slice(1);
|
|
6233
|
+
} else {
|
|
6234
|
+
metricCmd = afterMetric;
|
|
6235
|
+
}
|
|
6236
|
+
cleaned = cleaned.slice(0, metricIdx).trim();
|
|
6237
|
+
}
|
|
6238
|
+
const goalArg = cleaned.trim();
|
|
6239
|
+
|
|
6211
6240
|
if (!goalArg) {
|
|
6212
|
-
console.log("
|
|
6241
|
+
console.log("experiment needs a goal");
|
|
6213
6242
|
continue;
|
|
6214
6243
|
}
|
|
6215
6244
|
|
|
6216
|
-
// Build charter
|
|
6217
6245
|
const charter = parseCharterFromGoal(goalArg);
|
|
6218
6246
|
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
}
|
|
6228
|
-
if (!charter.metric.command) {
|
|
6229
|
-
console.log("no metric command — experiment canceled");
|
|
6230
|
-
continue;
|
|
6231
|
-
}
|
|
6247
|
+
if (metricCmd) {
|
|
6248
|
+
charter.metric.command = metricCmd.trim();
|
|
6249
|
+
}
|
|
6250
|
+
if (attemptsMatch) {
|
|
6251
|
+
charter.budget.maxAttempts = parseInt(attemptsMatch[1], 10);
|
|
6252
|
+
}
|
|
6253
|
+
if (timeMatch) {
|
|
6254
|
+
charter.budget.maxMinutes = parseInt(timeMatch[1], 10);
|
|
6232
6255
|
}
|
|
6233
6256
|
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
if (parsed > 0) charter.budget.maxAttempts = parsed;
|
|
6239
|
-
} catch {}
|
|
6240
|
-
|
|
6241
|
-
// Ask for time budget
|
|
6242
|
-
try {
|
|
6243
|
-
const timeStr = await promptLine(`time limit in minutes [${charter.budget.maxMinutes}]: `, { input: process.stdin, output: process.stdout });
|
|
6244
|
-
const parsed = parseInt(timeStr.trim(), 10);
|
|
6245
|
-
if (parsed > 0) charter.budget.maxMinutes = parsed;
|
|
6246
|
-
} catch {}
|
|
6257
|
+
if (!charter.metric.command) {
|
|
6258
|
+
console.log('experiment needs a metric: /experiment <goal> --metric "npm test"');
|
|
6259
|
+
continue;
|
|
6260
|
+
}
|
|
6247
6261
|
|
|
6248
6262
|
const isInfinite = !charter.budget.maxAttempts || charter.budget.maxAttempts <= 0;
|
|
6249
6263
|
console.log(`────────────────────────────────────────────────────────────`);
|
package/src/experiment.js
CHANGED
|
@@ -63,12 +63,12 @@ export async function runMetric({ command, extract, cwd }) {
|
|
|
63
63
|
let stdout, stderr;
|
|
64
64
|
|
|
65
65
|
if (isWin) {
|
|
66
|
-
|
|
66
|
+
// Use PowerShell on Windows for access to proper commands
|
|
67
|
+
const result = await execFileAsync("powershell.exe", ["-NoProfile", "-Command", command], execOpts);
|
|
67
68
|
stdout = String(result.stdout || "");
|
|
68
69
|
stderr = String(result.stderr || "");
|
|
69
70
|
} else {
|
|
70
|
-
const
|
|
71
|
-
const result = await execFileAsync(parts[0], parts.slice(1), execOpts);
|
|
71
|
+
const result = await execFileAsync("/bin/sh", ["-c", command], execOpts);
|
|
72
72
|
stdout = String(result.stdout || "");
|
|
73
73
|
stderr = String(result.stderr || "");
|
|
74
74
|
}
|