@dunnewold-labs/mr-manager 0.4.27 → 0.4.28
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/dist/index.mjs +44 -9
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -185,7 +185,7 @@ import { fileURLToPath } from "url";
|
|
|
185
185
|
// cli/package.json
|
|
186
186
|
var package_default = {
|
|
187
187
|
name: "@dunnewold-labs/mr-manager",
|
|
188
|
-
version: "0.4.
|
|
188
|
+
version: "0.4.28",
|
|
189
189
|
description: "Mr. Manager - Task and project management CLI",
|
|
190
190
|
bin: {
|
|
191
191
|
mr: "./dist/index.mjs"
|
|
@@ -1354,6 +1354,18 @@ If a scenario name matches the feature you're testing (by name or keyword):
|
|
|
1354
1354
|
3. Note in your test plan summary which scenario you used.
|
|
1355
1355
|
|
|
1356
1356
|
If no matching scenario exists, infer interactions from the codebase as normal.`;
|
|
1357
|
+
var SYSTEM_SECTION_QUIET_MODE = `## Quiet Mode \u2014 CRITICAL
|
|
1358
|
+
|
|
1359
|
+
You are running in **quiet mode**. This means:
|
|
1360
|
+
|
|
1361
|
+
1. **DO NOT** write any explanatory text, conversation, commentary, or summaries outside of tool calls.
|
|
1362
|
+
2. **DO NOT** describe what you are about to do or what you just did in prose.
|
|
1363
|
+
3. **ONLY** output text when using \`mr update\` for status updates (keep these to 1 short sentence each).
|
|
1364
|
+
4. All your work must happen through tool calls (Read, Edit, Write, Bash, etc.) \u2014 not through conversational output.
|
|
1365
|
+
5. When you would normally explain your reasoning or next steps, simply proceed silently with the tool calls.
|
|
1366
|
+
6. After completing work, exit immediately without a summary.
|
|
1367
|
+
|
|
1368
|
+
This mode exists to minimize output token usage. Every word of conversational text you generate costs tokens. Tool calls and file writes are the only acceptable output.`;
|
|
1357
1369
|
var SYSTEM_SECTIONS = {
|
|
1358
1370
|
"status-updates": SYSTEM_SECTION_STATUS_UPDATES,
|
|
1359
1371
|
"screenshots": SYSTEM_SECTION_SCREENSHOTS,
|
|
@@ -1362,7 +1374,8 @@ var SYSTEM_SECTIONS = {
|
|
|
1362
1374
|
"features-workflow": SYSTEM_SECTION_FEATURES_WORKFLOW,
|
|
1363
1375
|
"prd-format": SYSTEM_SECTION_PRD_FORMAT,
|
|
1364
1376
|
"prd-open-questions": SYSTEM_SECTION_PRD_OPEN_QUESTIONS,
|
|
1365
|
-
"mr-tests": SYSTEM_SECTION_MR_TESTS
|
|
1377
|
+
"mr-tests": SYSTEM_SECTION_MR_TESTS,
|
|
1378
|
+
"quiet-mode": SYSTEM_SECTION_QUIET_MODE
|
|
1366
1379
|
};
|
|
1367
1380
|
function composeSystemPrompt(sections) {
|
|
1368
1381
|
return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
|
|
@@ -2571,7 +2584,7 @@ function askYesNo(question) {
|
|
|
2571
2584
|
});
|
|
2572
2585
|
});
|
|
2573
2586
|
}
|
|
2574
|
-
function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel) {
|
|
2587
|
+
function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel, onOutputBytes) {
|
|
2575
2588
|
const jobLabel = name ?? "unknown";
|
|
2576
2589
|
console.log(`${timestamp()} ${prefix} ${paint("dim", tokenLogLine("agent", jobLabel, prompt2, systemPrompt))}`);
|
|
2577
2590
|
const { bin, args } = buildAgentArgs(agent, prompt2, "execute", sessionId, name, resumeSession, systemPrompt, maxTurns, claudeModel);
|
|
@@ -2590,12 +2603,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
|
|
|
2590
2603
|
}
|
|
2591
2604
|
child.stdout?.on("data", (data) => {
|
|
2592
2605
|
onActivity?.();
|
|
2606
|
+
onOutputBytes?.(data.length);
|
|
2593
2607
|
for (const line of data.toString().split("\n")) {
|
|
2594
2608
|
if (line) console.log(`${timestamp()} ${prefix} ${paint("dim", line)}`);
|
|
2595
2609
|
}
|
|
2596
2610
|
});
|
|
2597
2611
|
child.stderr?.on("data", (data) => {
|
|
2598
2612
|
onActivity?.();
|
|
2613
|
+
onOutputBytes?.(data.length);
|
|
2599
2614
|
for (const line of data.toString().split("\n")) {
|
|
2600
2615
|
if (line) logError(prefix, paint("dim", line));
|
|
2601
2616
|
}
|
|
@@ -2604,13 +2619,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
|
|
|
2604
2619
|
}
|
|
2605
2620
|
var watchCommand = new Command8("watch").description(
|
|
2606
2621
|
"Watch for in-progress tasks and autonomously dispatch an AI coding agent to work on them"
|
|
2607
|
-
).option("--interval <seconds>", "Polling interval in seconds", "15").option("--dry-run", "Show what would be dispatched without spawning the agent", false).option("--plan-approval", "Show the agent's plan and ask for approval before executing", false).option("--root <dir>", "Root directory filter for linked repos (default: cwd)").option("--agent <agent>", "AI agent to use: claude, codex, or gemini", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").action(async (opts) => {
|
|
2622
|
+
).option("--interval <seconds>", "Polling interval in seconds", "15").option("--dry-run", "Show what would be dispatched without spawning the agent", false).option("--plan-approval", "Show the agent's plan and ask for approval before executing", false).option("--root <dir>", "Root directory filter for linked repos (default: cwd)").option("--agent <agent>", "AI agent to use: claude, codex, or gemini", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").option("--quiet", "Run all tasks in quiet mode (agent outputs only status updates, no conversation)", false).action(async (opts) => {
|
|
2608
2623
|
const intervalMs = parseInt(opts.interval, 10) * 1e3;
|
|
2609
2624
|
const dryRun = opts.dryRun;
|
|
2610
2625
|
const planApproval = opts.planApproval;
|
|
2611
2626
|
const rootDir = opts.root ? resolve2(opts.root) : process.cwd();
|
|
2612
2627
|
const agent = opts.agent === "codex" ? "codex" : opts.agent === "gemini" ? "gemini" : "claude";
|
|
2613
2628
|
const scanAt = opts.scanAt;
|
|
2629
|
+
const globalQuietMode = opts.quiet;
|
|
2614
2630
|
const taskStallTimeoutMs = getTaskStallTimeoutMs();
|
|
2615
2631
|
const hungTaskTimeoutMinutes = Math.max(5, parseInt(process.env.MR_WATCH_HUNG_TASK_TIMEOUT_MINUTES ?? "60", 10) || 60);
|
|
2616
2632
|
const hungTaskTimeoutMs = hungTaskTimeoutMinutes * 6e4;
|
|
@@ -2631,6 +2647,7 @@ var watchCommand = new Command8("watch").description(
|
|
|
2631
2647
|
`stall-timeout=${paint("cyan", formatTimeoutMinutes(taskStallTimeoutMs))}`,
|
|
2632
2648
|
...planApproval ? [paint("yellow", "plan-approval")] : [],
|
|
2633
2649
|
...dryRun ? [paint("yellow", "dry-run")] : [],
|
|
2650
|
+
...globalQuietMode ? [paint("yellow", "quiet")] : [],
|
|
2634
2651
|
...scanAt ? [`scan-at=${paint("cyan", scanAt)}`] : [],
|
|
2635
2652
|
`hung-timeout=${paint("cyan", `${hungTaskTimeoutMinutes}m`)}`
|
|
2636
2653
|
].join(" ");
|
|
@@ -2755,8 +2772,9 @@ var watchCommand = new Command8("watch").description(
|
|
|
2755
2772
|
const legacyBranchName = `mr/${sid}/${slug}`;
|
|
2756
2773
|
const prefix = taskTag(sid);
|
|
2757
2774
|
const vcs = detectVcs(repoDir)?.provider ?? "github";
|
|
2758
|
-
|
|
2759
|
-
|
|
2775
|
+
const taskIsQuiet = task.quietMode || globalQuietMode;
|
|
2776
|
+
logDispatch(prefix, `"${paint("bold", task.title)}" ${paint("gray", repoDir)} ${paint("dim", `[${vcs}]`)}${taskIsQuiet ? ` ${paint("yellow", "[quiet]")}` : ""}`);
|
|
2777
|
+
await postTaskUpdate(task.id, `Agent dispatched${taskIsQuiet ? " (quiet mode)" : ""} \u2014 starting work on "${task.title}"`, "system");
|
|
2760
2778
|
let subtasks = [];
|
|
2761
2779
|
try {
|
|
2762
2780
|
subtasks = await api.get(`/api/tasks/${task.id}/subtasks`);
|
|
@@ -2822,6 +2840,7 @@ var watchCommand = new Command8("watch").description(
|
|
|
2822
2840
|
);
|
|
2823
2841
|
}
|
|
2824
2842
|
const prompt2 = buildExecutionPrompt(task, repoDir, subtasks, vcs, protoRefs, feedbackUpdates, existingResources, skillRefs, executionDir, startWithoutWorktree, !startWithoutWorktree && isGitRepo(repoDir) ? branchName : void 0);
|
|
2843
|
+
const taskIsQuietForEntry = task.quietMode || globalQuietMode;
|
|
2825
2844
|
const activeEntry = {
|
|
2826
2845
|
process: void 0,
|
|
2827
2846
|
title: task.title,
|
|
@@ -2829,7 +2848,9 @@ var watchCommand = new Command8("watch").description(
|
|
|
2829
2848
|
cleanupRepoDir: cleanupWorktreePath ? repoDir : void 0,
|
|
2830
2849
|
cleanupWorktreePath,
|
|
2831
2850
|
startedAt: Date.now(),
|
|
2832
|
-
lastActivityAt: Date.now()
|
|
2851
|
+
lastActivityAt: Date.now(),
|
|
2852
|
+
outputBytes: 0,
|
|
2853
|
+
quietMode: taskIsQuietForEntry
|
|
2833
2854
|
};
|
|
2834
2855
|
const touchActivity = () => {
|
|
2835
2856
|
activeEntry.lastActivityAt = Date.now();
|
|
@@ -2858,7 +2879,12 @@ var watchCommand = new Command8("watch").description(
|
|
|
2858
2879
|
const shouldResumeClaudeSession = attemptAgent === "claude" && !!task.claudeSessionId && !resumeAlreadyRetried && (hasFeedback || pausedForNetwork?.resumeSession === true);
|
|
2859
2880
|
const sessionId = attemptAgent === "claude" ? shouldResumeClaudeSession ? task.claudeSessionId : randomUUID() : void 0;
|
|
2860
2881
|
const effectiveClaudeModel = attemptAgent === "claude" ? taskClaudeModel : void 0;
|
|
2861
|
-
const
|
|
2882
|
+
const isQuiet = task.quietMode || globalQuietMode;
|
|
2883
|
+
const systemSections = isQuiet ? ["quiet-mode", ...EXECUTION_SYSTEM_SECTIONS] : [...EXECUTION_SYSTEM_SECTIONS];
|
|
2884
|
+
const executionSystemPrompt = composeSystemPrompt(systemSections);
|
|
2885
|
+
if (isQuiet) {
|
|
2886
|
+
logInfo(prefix, `${paint("yellow", "quiet mode")} \u2014 agent will suppress conversational output`);
|
|
2887
|
+
}
|
|
2862
2888
|
const child = spawnAgent(
|
|
2863
2889
|
attemptAgent,
|
|
2864
2890
|
executionDir,
|
|
@@ -2873,7 +2899,10 @@ var watchCommand = new Command8("watch").description(
|
|
|
2873
2899
|
},
|
|
2874
2900
|
executionSystemPrompt,
|
|
2875
2901
|
void 0,
|
|
2876
|
-
effectiveClaudeModel
|
|
2902
|
+
effectiveClaudeModel,
|
|
2903
|
+
(bytes) => {
|
|
2904
|
+
activeEntry.outputBytes += bytes;
|
|
2905
|
+
}
|
|
2877
2906
|
);
|
|
2878
2907
|
activeEntry.process = child;
|
|
2879
2908
|
activeEntry.currentAgent = attemptAgent;
|
|
@@ -2928,6 +2957,12 @@ var watchCommand = new Command8("watch").description(
|
|
|
2928
2957
|
}
|
|
2929
2958
|
}
|
|
2930
2959
|
finishing.add(task.id);
|
|
2960
|
+
const elapsedMs = Date.now() - activeEntry.startedAt;
|
|
2961
|
+
const modeLabel = activeEntry.quietMode ? "quiet" : "standard";
|
|
2962
|
+
const outputTokenEstimate = Math.ceil(activeEntry.outputBytes / 4);
|
|
2963
|
+
console.log(
|
|
2964
|
+
`${timestamp()} ${prefix} ${paint("dim", `[output] mode=${modeLabel} output=~${formatTokenCount(outputTokenEstimate)} elapsed=${Math.round(elapsedMs / 1e3)}s exit=${code}`)}`
|
|
2965
|
+
);
|
|
2931
2966
|
try {
|
|
2932
2967
|
if (code === 0) {
|
|
2933
2968
|
try {
|