@dunnewold-labs/mr-manager 0.4.30 → 0.4.31
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 +90 -490
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// cli/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command28 } from "commander";
|
|
5
5
|
import { existsSync as existsSync17 } from "fs";
|
|
6
6
|
import { homedir as homedir3 } from "os";
|
|
7
7
|
import { join as join12 } from "path";
|
|
@@ -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.31",
|
|
189
189
|
description: "Mr. Manager - Task and project management CLI",
|
|
190
190
|
bin: {
|
|
191
191
|
mr: "./dist/index.mjs"
|
|
@@ -2119,9 +2119,6 @@ function protoTag(sid) {
|
|
|
2119
2119
|
function repoTag(sid) {
|
|
2120
2120
|
return paint("cyan", `[repo:${sid}]`);
|
|
2121
2121
|
}
|
|
2122
|
-
function ideaTag(sid) {
|
|
2123
|
-
return paint("magenta", `[idea:${sid}]`);
|
|
2124
|
-
}
|
|
2125
2122
|
function buildRepoCreationPrompt(project, rootDir, vcs = "github") {
|
|
2126
2123
|
const apiBase = process.env.MR_API_BASE ?? "http://localhost:3000";
|
|
2127
2124
|
const apiKey = process.env.MR_API_KEY ?? "";
|
|
@@ -2400,83 +2397,6 @@ function buildRefinementPrompt(proto, parentFiles, repoDir) {
|
|
|
2400
2397
|
`- Do NOT exit until ALL ${proto.variantCount} files have been written and verified.`
|
|
2401
2398
|
].join("\n");
|
|
2402
2399
|
}
|
|
2403
|
-
function buildIdeaPrompt(idea, repoDir) {
|
|
2404
|
-
const feedbackSection = idea.feedback ? [
|
|
2405
|
-
`## Previous Feedback`,
|
|
2406
|
-
``,
|
|
2407
|
-
`The user provided this feedback on a previous generation:`,
|
|
2408
|
-
`${idea.feedback}`,
|
|
2409
|
-
``,
|
|
2410
|
-
`Please incorporate this feedback into your new generation.`,
|
|
2411
|
-
``
|
|
2412
|
-
] : [];
|
|
2413
|
-
const existingPlanSection = idea.plan && idea.feedback ? [
|
|
2414
|
-
`## Previous Plan`,
|
|
2415
|
-
``,
|
|
2416
|
-
`Here is the plan from the previous iteration:`,
|
|
2417
|
-
`\`\`\`markdown`,
|
|
2418
|
-
idea.plan,
|
|
2419
|
-
`\`\`\``,
|
|
2420
|
-
``
|
|
2421
|
-
] : [];
|
|
2422
|
-
return [
|
|
2423
|
-
`You are a product strategist and UI designer. Your job is to take a rough idea and generate two outputs:`,
|
|
2424
|
-
`1. An implementation plan (saved as \`idea-plan.md\`)`,
|
|
2425
|
-
`2. A visual prototype (saved as \`idea-prototype.html\`)`,
|
|
2426
|
-
``,
|
|
2427
|
-
`Working directory: ${repoDir}`,
|
|
2428
|
-
``,
|
|
2429
|
-
`## Idea`,
|
|
2430
|
-
`Title: ${idea.title}`,
|
|
2431
|
-
`ID: ${idea.id}`,
|
|
2432
|
-
...idea.description ? [``, `Description: ${idea.description}`] : [],
|
|
2433
|
-
``,
|
|
2434
|
-
...feedbackSection,
|
|
2435
|
-
...existingPlanSection,
|
|
2436
|
-
`## Instructions`,
|
|
2437
|
-
``,
|
|
2438
|
-
`### Step 1: Generate the Plan`,
|
|
2439
|
-
``,
|
|
2440
|
-
`Write a comprehensive implementation plan to \`${repoDir}/idea-plan.md\` covering:`,
|
|
2441
|
-
`- **Problem statement**: What problem does this idea solve?`,
|
|
2442
|
-
`- **Proposed solution**: High-level approach`,
|
|
2443
|
-
`- **Key features**: Bulleted list of features/capabilities`,
|
|
2444
|
-
`- **Technical approach**: How it could be built (components, data model, integrations)`,
|
|
2445
|
-
`- **Implementation phases**: Phased rollout plan with milestones`,
|
|
2446
|
-
`- **Open questions**: Things that need clarification`,
|
|
2447
|
-
``,
|
|
2448
|
-
`### Step 2: Generate Follow-up Tasks`,
|
|
2449
|
-
``,
|
|
2450
|
-
`Write a JSON file to \`${repoDir}/idea-tasks.json\` containing an array of follow-up tasks that will need to be done after the project repo is created. These are setup and implementation tasks the user will need to complete. Examples: "Add environment variables (.env)", "Set up CI/CD pipeline", "Configure database", "Add authentication", etc.`,
|
|
2451
|
-
``,
|
|
2452
|
-
`Format: a JSON array of objects with "title" (short task name) and optional "notes" (additional context):`,
|
|
2453
|
-
`\`\`\`json`,
|
|
2454
|
-
`[`,
|
|
2455
|
-
` { "title": "Add environment variables (.env)", "notes": "Create .env file with required API keys and database URL" },`,
|
|
2456
|
-
` { "title": "Set up CI/CD pipeline" }`,
|
|
2457
|
-
`]`,
|
|
2458
|
-
`\`\`\``,
|
|
2459
|
-
``,
|
|
2460
|
-
`Generate 3-8 tasks that are specific to this idea. Focus on actionable setup and implementation steps.`,
|
|
2461
|
-
``,
|
|
2462
|
-
`### Step 3: Generate the Prototype`,
|
|
2463
|
-
``,
|
|
2464
|
-
`Write a self-contained HTML prototype to \`${repoDir}/idea-prototype.html\` that visually demonstrates the idea.`,
|
|
2465
|
-
`- Must be completely self-contained (inline CSS/JS, Tailwind CDN is acceptable)`,
|
|
2466
|
-
`- Should be interactive where possible (click handlers, animations, sample data)`,
|
|
2467
|
-
`- Should look polished and professional \u2014 this will be shown to stakeholders`,
|
|
2468
|
-
`- Include realistic sample data that demonstrates the feature`,
|
|
2469
|
-
``,
|
|
2470
|
-
`### Step 4: Verify`,
|
|
2471
|
-
``,
|
|
2472
|
-
`List the files in ${repoDir} and confirm \`idea-plan.md\`, \`idea-tasks.json\`, and \`idea-prototype.html\` all exist.`,
|
|
2473
|
-
``,
|
|
2474
|
-
`IMPORTANT RULES:`,
|
|
2475
|
-
`- Write EXACTLY three files: idea-plan.md, idea-tasks.json, and idea-prototype.html`,
|
|
2476
|
-
`- Do NOT upload or POST the files anywhere \u2014 the watch handler will upload them automatically`,
|
|
2477
|
-
`- Do NOT exit until both files have been written and verified`
|
|
2478
|
-
].join("\n");
|
|
2479
|
-
}
|
|
2480
2400
|
function buildAgentArgs(agent, prompt2, mode, sessionId, name, resumeSession = false, systemPrompt, maxTurns, claudeModel) {
|
|
2481
2401
|
if (agent === "codex") {
|
|
2482
2402
|
const args = [];
|
|
@@ -2719,7 +2639,7 @@ var watchCommand = new Command8("watch").description(
|
|
|
2719
2639
|
logWarn(watchTag(), `Network unavailable \u2014 pausing active tasks until connectivity returns (${reason})`);
|
|
2720
2640
|
}
|
|
2721
2641
|
for (const taskId of active.keys()) {
|
|
2722
|
-
const nonTaskPrefixes = ["proto-", "repo-", "scan-", "
|
|
2642
|
+
const nonTaskPrefixes = ["proto-", "repo-", "scan-", "test-"];
|
|
2723
2643
|
if (nonTaskPrefixes.some((prefix) => taskId.startsWith(prefix))) continue;
|
|
2724
2644
|
pauseTaskForNetwork(taskId, reason);
|
|
2725
2645
|
}
|
|
@@ -2923,28 +2843,40 @@ var watchCommand = new Command8("watch").description(
|
|
|
2923
2843
|
logWarn(prefix, `${attemptAgent} paused after network loss (${failureDetail})`);
|
|
2924
2844
|
return;
|
|
2925
2845
|
}
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
);
|
|
2934
|
-
|
|
2935
|
-
return;
|
|
2846
|
+
try {
|
|
2847
|
+
const currentTask = await api.get(`/api/tasks/${task.id}`);
|
|
2848
|
+
if (currentTask.status === "completed" || currentTask.status === "review" || currentTask.status === "error") {
|
|
2849
|
+
logWarn(prefix, `Task already in "${currentTask.status}" state after agent exit \u2014 skipping retry`);
|
|
2850
|
+
activeEntry.terminatedForError = true;
|
|
2851
|
+
}
|
|
2852
|
+
} catch {
|
|
2853
|
+
logWarn(prefix, `Could not verify task status \u2014 skipping retry to avoid stale re-dispatch`);
|
|
2854
|
+
activeEntry.terminatedForError = true;
|
|
2936
2855
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2856
|
+
if (!activeEntry.terminatedForError) {
|
|
2857
|
+
if (shouldResumeClaudeSession && !resumeAlreadyRetried) {
|
|
2858
|
+
resumeAlreadyRetried = true;
|
|
2859
|
+
logWarn(prefix, `Claude session resume failed (${failureDetail}) \u2014 retrying with fresh session`);
|
|
2860
|
+
await postTaskUpdate(
|
|
2861
|
+
task.id,
|
|
2862
|
+
`Claude session resume failed \u2014 retrying with fresh session`,
|
|
2863
|
+
"system"
|
|
2864
|
+
);
|
|
2865
|
+
await launchAttempt("claude");
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
const nextAgent = attemptOrder[attemptIndex + 1];
|
|
2869
|
+
if (nextAgent) {
|
|
2870
|
+
logWarn(prefix, `${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`);
|
|
2871
|
+
await postTaskUpdate(
|
|
2872
|
+
task.id,
|
|
2873
|
+
`${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`,
|
|
2874
|
+
"system"
|
|
2875
|
+
);
|
|
2876
|
+
attemptIndex += 1;
|
|
2877
|
+
await launchAttempt(nextAgent);
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2948
2880
|
}
|
|
2949
2881
|
}
|
|
2950
2882
|
finishing.add(task.id);
|
|
@@ -3291,7 +3223,7 @@ var watchCommand = new Command8("watch").description(
|
|
|
3291
3223
|
active.delete(key);
|
|
3292
3224
|
}
|
|
3293
3225
|
const failedAttempt = code !== 0 || spawnFailureReason !== null;
|
|
3294
|
-
if (failedAttempt) {
|
|
3226
|
+
if (failedAttempt && !activeEntry.terminatedForError) {
|
|
3295
3227
|
const nextAgent = attemptOrder[attemptIndex + 1];
|
|
3296
3228
|
if (nextAgent) {
|
|
3297
3229
|
const failureDetail = spawnFailureReason ?? `exit code ${code}`;
|
|
@@ -3401,7 +3333,7 @@ var watchCommand = new Command8("watch").description(
|
|
|
3401
3333
|
active.delete(key);
|
|
3402
3334
|
}
|
|
3403
3335
|
const failedAttempt = code !== 0 || spawnFailureReason !== null;
|
|
3404
|
-
if (failedAttempt) {
|
|
3336
|
+
if (failedAttempt && !activeEntry.terminatedForError) {
|
|
3405
3337
|
const nextAgent = attemptOrder[attemptIndex + 1];
|
|
3406
3338
|
if (nextAgent) {
|
|
3407
3339
|
const failureDetail = spawnFailureReason ?? `exit code ${code}`;
|
|
@@ -3438,158 +3370,6 @@ var watchCommand = new Command8("watch").description(
|
|
|
3438
3370
|
};
|
|
3439
3371
|
await launchAttempt(attemptOrder[attemptIndex]);
|
|
3440
3372
|
}
|
|
3441
|
-
async function dispatchIdeaJob(idea, repoDir) {
|
|
3442
|
-
const sid = shortId(idea.id);
|
|
3443
|
-
const prefix = ideaTag(sid);
|
|
3444
|
-
logDispatch(prefix, `"${paint("bold", idea.title)}"${idea.feedback ? paint("cyan", " (iteration)") : ""} ${paint("gray", repoDir)}`);
|
|
3445
|
-
for (const f of ["idea-plan.md", "idea-tasks.json", "idea-prototype.html"]) {
|
|
3446
|
-
try {
|
|
3447
|
-
unlinkSync(resolve2(repoDir, f));
|
|
3448
|
-
} catch {
|
|
3449
|
-
}
|
|
3450
|
-
}
|
|
3451
|
-
const prompt2 = buildIdeaPrompt(idea, repoDir);
|
|
3452
|
-
const key = `idea-${idea.id}`;
|
|
3453
|
-
const attemptOrder = await resolveAgentChain(agent);
|
|
3454
|
-
if (attemptOrder.length === 0) {
|
|
3455
|
-
logError(prefix, `No available agents found for fallback chain starting at ${agent}`);
|
|
3456
|
-
queued.delete(key);
|
|
3457
|
-
try {
|
|
3458
|
-
await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
|
|
3459
|
-
} catch {
|
|
3460
|
-
}
|
|
3461
|
-
return;
|
|
3462
|
-
}
|
|
3463
|
-
const activeEntry = {
|
|
3464
|
-
process: void 0,
|
|
3465
|
-
title: idea.title,
|
|
3466
|
-
repoDir,
|
|
3467
|
-
startedAt: Date.now(),
|
|
3468
|
-
lastActivityAt: Date.now()
|
|
3469
|
-
};
|
|
3470
|
-
let attemptIndex = 0;
|
|
3471
|
-
const launchAttempt = async (attemptAgent) => {
|
|
3472
|
-
let spawnFailureReason = null;
|
|
3473
|
-
const child = spawnAgent(
|
|
3474
|
-
attemptAgent,
|
|
3475
|
-
repoDir,
|
|
3476
|
-
prompt2,
|
|
3477
|
-
prefix,
|
|
3478
|
-
void 0,
|
|
3479
|
-
void 0,
|
|
3480
|
-
idea.title,
|
|
3481
|
-
false,
|
|
3482
|
-
(err) => {
|
|
3483
|
-
spawnFailureReason = err.message;
|
|
3484
|
-
}
|
|
3485
|
-
);
|
|
3486
|
-
activeEntry.process = child;
|
|
3487
|
-
activeEntry.currentAgent = attemptAgent;
|
|
3488
|
-
active.set(key, activeEntry);
|
|
3489
|
-
child.on("exit", async (code) => {
|
|
3490
|
-
if (active.get(key)?.process === child) {
|
|
3491
|
-
active.delete(key);
|
|
3492
|
-
}
|
|
3493
|
-
const failedAttempt = code !== 0 || spawnFailureReason !== null;
|
|
3494
|
-
if (failedAttempt) {
|
|
3495
|
-
const nextAgent = attemptOrder[attemptIndex + 1];
|
|
3496
|
-
if (nextAgent) {
|
|
3497
|
-
const failureDetail = spawnFailureReason ?? `exit code ${code}`;
|
|
3498
|
-
logWarn(prefix, `${attemptAgent} failed (${failureDetail}) \u2014 retrying idea generation with ${nextAgent}`);
|
|
3499
|
-
attemptIndex += 1;
|
|
3500
|
-
await launchAttempt(nextAgent);
|
|
3501
|
-
return;
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3504
|
-
finishing.add(key);
|
|
3505
|
-
try {
|
|
3506
|
-
if (code === 0) {
|
|
3507
|
-
try {
|
|
3508
|
-
let plan;
|
|
3509
|
-
let protoHtml;
|
|
3510
|
-
let followUpTasks;
|
|
3511
|
-
const planPath = resolve2(repoDir, "idea-plan.md");
|
|
3512
|
-
const tasksPath = resolve2(repoDir, "idea-tasks.json");
|
|
3513
|
-
const protoPath = resolve2(repoDir, "idea-prototype.html");
|
|
3514
|
-
try {
|
|
3515
|
-
plan = readFileSync5(planPath, "utf-8");
|
|
3516
|
-
} catch {
|
|
3517
|
-
}
|
|
3518
|
-
try {
|
|
3519
|
-
protoHtml = readFileSync5(protoPath, "utf-8");
|
|
3520
|
-
} catch {
|
|
3521
|
-
}
|
|
3522
|
-
try {
|
|
3523
|
-
const tasksRaw = readFileSync5(tasksPath, "utf-8");
|
|
3524
|
-
const parsed = JSON.parse(tasksRaw);
|
|
3525
|
-
if (Array.isArray(parsed)) {
|
|
3526
|
-
followUpTasks = parsed.filter((t) => t && typeof t === "object" && "title" in t);
|
|
3527
|
-
}
|
|
3528
|
-
} catch {
|
|
3529
|
-
}
|
|
3530
|
-
if (!plan && !protoHtml) {
|
|
3531
|
-
logError(prefix, `No output files found in ${repoDir}`);
|
|
3532
|
-
await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
|
|
3533
|
-
return;
|
|
3534
|
-
}
|
|
3535
|
-
const updateData = { status: "generated" };
|
|
3536
|
-
if (plan) updateData.plan = plan;
|
|
3537
|
-
if (followUpTasks) updateData.followUpTasks = followUpTasks;
|
|
3538
|
-
if (protoHtml) {
|
|
3539
|
-
try {
|
|
3540
|
-
const proto = await api.post("/api/prototypes", {
|
|
3541
|
-
title: `${idea.title} \u2014 Idea Prototype`,
|
|
3542
|
-
prompt: idea.description || idea.title,
|
|
3543
|
-
variantCount: 1,
|
|
3544
|
-
projectId: idea.projectId ?? null
|
|
3545
|
-
});
|
|
3546
|
-
await api.patch(`/api/prototypes/${proto.id}`, {
|
|
3547
|
-
status: "completed",
|
|
3548
|
-
files: [{ name: "idea-prototype.html", content: protoHtml }]
|
|
3549
|
-
});
|
|
3550
|
-
updateData.generatedPrototypeId = proto.id;
|
|
3551
|
-
logSuccess(prefix, `Prototype created: ${paint("gray", proto.id.slice(0, 8))}`);
|
|
3552
|
-
} catch (err) {
|
|
3553
|
-
logError(prefix, `Failed to create prototype: ${err.message}`);
|
|
3554
|
-
}
|
|
3555
|
-
}
|
|
3556
|
-
await api.patch(`/api/ideas/${idea.id}`, updateData);
|
|
3557
|
-
logSuccess(prefix, `"${paint("bold", idea.title)}" generation complete`);
|
|
3558
|
-
try {
|
|
3559
|
-
unlinkSync(planPath);
|
|
3560
|
-
} catch {
|
|
3561
|
-
}
|
|
3562
|
-
try {
|
|
3563
|
-
unlinkSync(tasksPath);
|
|
3564
|
-
} catch {
|
|
3565
|
-
}
|
|
3566
|
-
try {
|
|
3567
|
-
unlinkSync(protoPath);
|
|
3568
|
-
} catch {
|
|
3569
|
-
}
|
|
3570
|
-
} catch (err) {
|
|
3571
|
-
logError(prefix, `Failed to upload idea output: ${err.message}`);
|
|
3572
|
-
try {
|
|
3573
|
-
await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
|
|
3574
|
-
} catch {
|
|
3575
|
-
}
|
|
3576
|
-
}
|
|
3577
|
-
} else {
|
|
3578
|
-
const failureDetail = spawnFailureReason ?? `exit code ${code}`;
|
|
3579
|
-
logError(prefix, `"${paint("bold", idea.title)}" generation failed via ${attemptAgent} (${failureDetail})`);
|
|
3580
|
-
try {
|
|
3581
|
-
await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
|
|
3582
|
-
} catch {
|
|
3583
|
-
}
|
|
3584
|
-
}
|
|
3585
|
-
} finally {
|
|
3586
|
-
queued.delete(key);
|
|
3587
|
-
finishing.delete(key);
|
|
3588
|
-
}
|
|
3589
|
-
});
|
|
3590
|
-
};
|
|
3591
|
-
await launchAttempt(attemptOrder[attemptIndex]);
|
|
3592
|
-
}
|
|
3593
3373
|
function dispatchScan(scan, prefix, key) {
|
|
3594
3374
|
logDispatch(prefix, `Running scan for project ${paint("cyan", scan.projectId.slice(0, 8))}`);
|
|
3595
3375
|
const scanProc = spawn4(process.execPath, [process.argv[1], "scan", "--project", scan.projectId, "--report", scan.id], {
|
|
@@ -3726,6 +3506,7 @@ ${divider}`);
|
|
|
3726
3506
|
const running = active.get(task.id);
|
|
3727
3507
|
if (running) {
|
|
3728
3508
|
logWarn(prefix, `Task exceeded hang timeout after ${formatElapsed(Date.now() - running.startedAt)}, terminating agent\u2026`);
|
|
3509
|
+
running.terminatedForError = true;
|
|
3729
3510
|
running.process.kill("SIGTERM");
|
|
3730
3511
|
active.delete(task.id);
|
|
3731
3512
|
}
|
|
@@ -3782,7 +3563,7 @@ ${divider}`);
|
|
|
3782
3563
|
queued.delete(taskId);
|
|
3783
3564
|
}
|
|
3784
3565
|
}
|
|
3785
|
-
const nonTaskPrefixes = ["proto-", "repo-", "scan-", "
|
|
3566
|
+
const nonTaskPrefixes = ["proto-", "repo-", "scan-", "test-"];
|
|
3786
3567
|
for (const taskId of failed.keys()) {
|
|
3787
3568
|
if (nonTaskPrefixes.some((p) => taskId.startsWith(p))) continue;
|
|
3788
3569
|
if (!activeTaskIds.has(taskId)) failed.delete(taskId);
|
|
@@ -3851,6 +3632,7 @@ ${divider}`);
|
|
|
3851
3632
|
for (const [key, entry] of active) {
|
|
3852
3633
|
if (key.startsWith("proto-") && !inProgressProtoKeys.has(key)) {
|
|
3853
3634
|
logWarn(watchTag(), `Prototype ${paint("yellow", key)} no longer in_progress, terminating\u2026`);
|
|
3635
|
+
entry.terminatedForError = true;
|
|
3854
3636
|
entry.process.kill("SIGTERM");
|
|
3855
3637
|
active.delete(key);
|
|
3856
3638
|
queued.delete(key);
|
|
@@ -4064,59 +3846,6 @@ ${divider}`);
|
|
|
4064
3846
|
}
|
|
4065
3847
|
dispatchRepoCreation(project, rootDir);
|
|
4066
3848
|
}
|
|
4067
|
-
let generatingIdeas = [];
|
|
4068
|
-
try {
|
|
4069
|
-
generatingIdeas = await api.get("/api/ideas?status=generating");
|
|
4070
|
-
} catch (err) {
|
|
4071
|
-
logError(watchTag(), `Failed to fetch generating ideas: ${err.message}`);
|
|
4072
|
-
}
|
|
4073
|
-
const inProgressIdeaKeys = new Set(generatingIdeas.map((i) => `idea-${i.id}`));
|
|
4074
|
-
for (const [key, entry] of active) {
|
|
4075
|
-
if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key)) {
|
|
4076
|
-
logWarn(watchTag(), `Idea ${paint("yellow", key)} no longer generating, terminating\u2026`);
|
|
4077
|
-
entry.process.kill("SIGTERM");
|
|
4078
|
-
active.delete(key);
|
|
4079
|
-
queued.delete(key);
|
|
4080
|
-
}
|
|
4081
|
-
}
|
|
4082
|
-
for (const key of failed.keys()) {
|
|
4083
|
-
if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key)) failed.delete(key);
|
|
4084
|
-
}
|
|
4085
|
-
for (const key of queued) {
|
|
4086
|
-
if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key) && !finishing.has(key)) queued.delete(key);
|
|
4087
|
-
}
|
|
4088
|
-
const activeIdeaCount = [...active.keys()].filter((k) => k.startsWith("idea-")).length;
|
|
4089
|
-
let ideaSlots = Math.max(0, 1 - activeIdeaCount);
|
|
4090
|
-
for (const idea of generatingIdeas) {
|
|
4091
|
-
if (ideaSlots <= 0) break;
|
|
4092
|
-
const key = `idea-${idea.id}`;
|
|
4093
|
-
if (queued.has(key)) continue;
|
|
4094
|
-
if (finishing.has(key)) continue;
|
|
4095
|
-
if (failed.has(key)) continue;
|
|
4096
|
-
const sid = shortId(idea.id);
|
|
4097
|
-
const prefix = ideaTag(sid);
|
|
4098
|
-
let repoDir;
|
|
4099
|
-
if (idea.projectId) {
|
|
4100
|
-
const dir = findDirectoryForProject(config, idea.projectId, rootDir);
|
|
4101
|
-
if (!dir) {
|
|
4102
|
-
logWarn(prefix, `"${idea.title}": no linked directory found \u2014 skipping`);
|
|
4103
|
-
continue;
|
|
4104
|
-
}
|
|
4105
|
-
repoDir = dir;
|
|
4106
|
-
} else {
|
|
4107
|
-
repoDir = rootDir;
|
|
4108
|
-
}
|
|
4109
|
-
queued.add(key);
|
|
4110
|
-
ideaSlots--;
|
|
4111
|
-
if (dryRun) {
|
|
4112
|
-
logInfo(
|
|
4113
|
-
watchTag(),
|
|
4114
|
-
`${paint("yellow", "[dry-run]")} would dispatch idea "${paint("bold", idea.title)}" in ${paint("cyan", repoDir)}`
|
|
4115
|
-
);
|
|
4116
|
-
continue;
|
|
4117
|
-
}
|
|
4118
|
-
dispatchIdeaJob(idea, repoDir);
|
|
4119
|
-
}
|
|
4120
3849
|
let pendingScans = [];
|
|
4121
3850
|
try {
|
|
4122
3851
|
pendingScans = await api.get("/api/scans?status=pending&limit=5");
|
|
@@ -4741,7 +4470,7 @@ async function checkApiConnectivity() {
|
|
|
4741
4470
|
}
|
|
4742
4471
|
}
|
|
4743
4472
|
function printResults(checks) {
|
|
4744
|
-
const maxNameLen = Math.max(...checks.map((
|
|
4473
|
+
const maxNameLen = Math.max(...checks.map((c11) => c11.name.length));
|
|
4745
4474
|
let allOk = true;
|
|
4746
4475
|
for (const check of checks) {
|
|
4747
4476
|
const isOptional = check.optional ?? false;
|
|
@@ -4755,10 +4484,10 @@ function printResults(checks) {
|
|
|
4755
4484
|
}
|
|
4756
4485
|
async function autoFix(checks, agent) {
|
|
4757
4486
|
const { spawn: spawn8 } = await import("child_process");
|
|
4758
|
-
const ghInstalled = checks.find((
|
|
4759
|
-
const ghAuthed = checks.find((
|
|
4760
|
-
const mrAuthed = checks.find((
|
|
4761
|
-
const claudeCheck = checks.find((
|
|
4487
|
+
const ghInstalled = checks.find((c11) => c11.name === "GitHub CLI (gh)").ok;
|
|
4488
|
+
const ghAuthed = checks.find((c11) => c11.name === "GitHub CLI auth").ok;
|
|
4489
|
+
const mrAuthed = checks.find((c11) => c11.name === "Mr. Manager CLI auth").ok;
|
|
4490
|
+
const claudeCheck = checks.find((c11) => c11.name === "Claude Code (claude)");
|
|
4762
4491
|
if (claudeCheck && !claudeCheck.ok && agent === "claude") {
|
|
4763
4492
|
console.log(paint5("cyan", " Installing Claude Code..."));
|
|
4764
4493
|
console.log(paint5("dim", " Running: curl -fsSL https://claude.ai/install.sh | bash"));
|
|
@@ -4821,7 +4550,7 @@ var setupCommand = new Command14("setup").description("Check that all dependenci
|
|
|
4821
4550
|
console.log("");
|
|
4822
4551
|
return;
|
|
4823
4552
|
}
|
|
4824
|
-
const fixes = checks.filter((
|
|
4553
|
+
const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
|
|
4825
4554
|
if (fixes.length > 0) {
|
|
4826
4555
|
console.log(paint5("yellow", " To fix:"));
|
|
4827
4556
|
for (const fix of fixes) {
|
|
@@ -6014,10 +5743,10 @@ ${codebaseAnalysis.routes.map((r) => `- ${r}`).join("\n")}
|
|
|
6014
5743
|
${codebaseAnalysis.prismaModels.map((m) => `- ${m}`).join("\n")}
|
|
6015
5744
|
|
|
6016
5745
|
**Components:**
|
|
6017
|
-
${codebaseAnalysis.components.slice(0, 15).map((
|
|
5746
|
+
${codebaseAnalysis.components.slice(0, 15).map((c11) => `- ${c11}`).join("\n")}
|
|
6018
5747
|
|
|
6019
5748
|
**Recent Git Commits:**
|
|
6020
|
-
${codebaseAnalysis.recentCommits.slice(0, 8).map((
|
|
5749
|
+
${codebaseAnalysis.recentCommits.slice(0, 8).map((c11) => `- ${c11}`).join("\n")}
|
|
6021
5750
|
|
|
6022
5751
|
**Completed Tasks:**
|
|
6023
5752
|
${context.completedTasks.slice(0, 10).map((t) => `- ${t.title}`).join("\n") || "None"}
|
|
@@ -6464,128 +6193,8 @@ var scanCommand = new Command23("scan").description("Run a product scan on the c
|
|
|
6464
6193
|
}
|
|
6465
6194
|
});
|
|
6466
6195
|
|
|
6467
|
-
// cli/commands/idea.ts
|
|
6468
|
-
import { Command as Command24 } from "commander";
|
|
6469
|
-
var c9 = {
|
|
6470
|
-
reset: "\x1B[0m",
|
|
6471
|
-
bold: "\x1B[1m",
|
|
6472
|
-
dim: "\x1B[2m",
|
|
6473
|
-
cyan: "\x1B[36m",
|
|
6474
|
-
green: "\x1B[32m",
|
|
6475
|
-
yellow: "\x1B[33m",
|
|
6476
|
-
red: "\x1B[31m",
|
|
6477
|
-
blue: "\x1B[34m",
|
|
6478
|
-
gray: "\x1B[90m",
|
|
6479
|
-
magenta: "\x1B[35m"
|
|
6480
|
-
};
|
|
6481
|
-
function paint9(color, text) {
|
|
6482
|
-
return `${c9[color]}${text}${c9.reset}`;
|
|
6483
|
-
}
|
|
6484
|
-
function statusBadge2(status) {
|
|
6485
|
-
switch (status) {
|
|
6486
|
-
case "draft":
|
|
6487
|
-
return paint9("gray", "\u25CB draft");
|
|
6488
|
-
case "generating":
|
|
6489
|
-
return paint9("cyan", "\u27F3 generating");
|
|
6490
|
-
case "generated":
|
|
6491
|
-
return paint9("green", "\u2713 generated");
|
|
6492
|
-
case "promoted":
|
|
6493
|
-
return paint9("magenta", "\u2191 promoted");
|
|
6494
|
-
case "archived":
|
|
6495
|
-
return paint9("dim", "\u2298 archived");
|
|
6496
|
-
default:
|
|
6497
|
-
return paint9("gray", status);
|
|
6498
|
-
}
|
|
6499
|
-
}
|
|
6500
|
-
var ideaCommand = new Command24("idea").description("Manage ideas \u2014 brainstorm, generate prototypes & plans").addCommand(
|
|
6501
|
-
new Command24("list").description("List ideas for the linked project").option("--all", "Show ideas for all projects").option("--status <status>", "Filter by status").action(async (opts) => {
|
|
6502
|
-
const params = new URLSearchParams();
|
|
6503
|
-
if (!opts.all) {
|
|
6504
|
-
const projectId = getLinkedProjectId();
|
|
6505
|
-
if (projectId) {
|
|
6506
|
-
params.set("projectId", projectId);
|
|
6507
|
-
}
|
|
6508
|
-
}
|
|
6509
|
-
if (opts.status) params.set("status", opts.status);
|
|
6510
|
-
const ideas = await api.get(`/api/ideas?${params.toString()}`);
|
|
6511
|
-
if (ideas.length === 0) {
|
|
6512
|
-
console.log(paint9("gray", "No ideas found."));
|
|
6513
|
-
return;
|
|
6514
|
-
}
|
|
6515
|
-
console.log();
|
|
6516
|
-
for (const idea of ideas) {
|
|
6517
|
-
const date = new Date(idea.createdAt).toLocaleDateString();
|
|
6518
|
-
console.log(
|
|
6519
|
-
` ${paint9("bold", idea.title)} ${statusBadge2(idea.status)} ${paint9("gray", idea.id.slice(0, 8))} ${paint9("dim", date)}`
|
|
6520
|
-
);
|
|
6521
|
-
if (idea.description) {
|
|
6522
|
-
console.log(` ${paint9("dim", idea.description.slice(0, 80) + (idea.description.length > 80 ? "\u2026" : ""))}`);
|
|
6523
|
-
}
|
|
6524
|
-
console.log();
|
|
6525
|
-
}
|
|
6526
|
-
})
|
|
6527
|
-
).addCommand(
|
|
6528
|
-
new Command24("create").description("Create a new idea").argument("<title>", "Title of the idea").option("--description <desc>", "Description of the idea").option("--project <projectId>", "Project ID (defaults to linked project)").option("--generate", "Immediately start generating plan & prototype").action(async (title, opts) => {
|
|
6529
|
-
const projectId = opts.project ?? getLinkedProjectId() ?? null;
|
|
6530
|
-
const idea = await api.post("/api/ideas", {
|
|
6531
|
-
title,
|
|
6532
|
-
description: opts.description,
|
|
6533
|
-
projectId
|
|
6534
|
-
});
|
|
6535
|
-
console.log();
|
|
6536
|
-
console.log(` ${paint9("green", "\u2713")} Created idea: ${paint9("bold", idea.title)}`);
|
|
6537
|
-
console.log(` ${paint9("gray", "ID:")} ${idea.id}`);
|
|
6538
|
-
if (opts.generate) {
|
|
6539
|
-
await api.post(`/api/ideas/${idea.id}/generate`);
|
|
6540
|
-
console.log(` ${paint9("cyan", "\u27F3")} Generation will begin automatically via the watch agent.`);
|
|
6541
|
-
}
|
|
6542
|
-
console.log();
|
|
6543
|
-
})
|
|
6544
|
-
).addCommand(
|
|
6545
|
-
new Command24("generate").description("Start generating plan & prototype for an idea").argument("<id>", "Idea ID").action(async (id) => {
|
|
6546
|
-
const idea = await api.post(`/api/ideas/${id}/generate`);
|
|
6547
|
-
console.log();
|
|
6548
|
-
console.log(` ${paint9("cyan", "\u27F3")} Generating: ${paint9("bold", idea.title)}`);
|
|
6549
|
-
console.log(` ${paint9("gray", "The watch agent will pick this up shortly.")}`);
|
|
6550
|
-
console.log();
|
|
6551
|
-
})
|
|
6552
|
-
).addCommand(
|
|
6553
|
-
new Command24("feedback").description("Send feedback to iterate on an idea's generated content").argument("<id>", "Idea ID").argument("<feedback>", "Feedback text").action(async (id, feedback) => {
|
|
6554
|
-
const idea = await api.post(`/api/ideas/${id}/feedback`, { feedback });
|
|
6555
|
-
console.log();
|
|
6556
|
-
console.log(` ${paint9("cyan", "\u27F3")} Feedback sent for: ${paint9("bold", idea.title)}`);
|
|
6557
|
-
console.log(` ${paint9("gray", "The watch agent will re-generate with your feedback.")}`);
|
|
6558
|
-
console.log();
|
|
6559
|
-
})
|
|
6560
|
-
).addCommand(
|
|
6561
|
-
new Command24("promote").description("Promote an idea to a task").argument("<id>", "Idea ID").action(async (id) => {
|
|
6562
|
-
const result = await api.post(`/api/ideas/${id}/promote`);
|
|
6563
|
-
console.log();
|
|
6564
|
-
console.log(` ${paint9("green", "\u2713")} Promoted idea to task: ${paint9("bold", result.task.title)}`);
|
|
6565
|
-
console.log(` ${paint9("gray", "Task ID:")} ${result.task.id}`);
|
|
6566
|
-
console.log();
|
|
6567
|
-
})
|
|
6568
|
-
).addCommand(
|
|
6569
|
-
new Command24("spin-up").description("Spin up a new project with a GitHub repo from an idea").argument("<id>", "Idea ID").option("--name <name>", "Custom project name (defaults to idea title)").action(async (id, opts) => {
|
|
6570
|
-
const body = {};
|
|
6571
|
-
if (opts.name) body.name = opts.name;
|
|
6572
|
-
const result = await api.post(`/api/ideas/${id}/spin-up`, body);
|
|
6573
|
-
console.log();
|
|
6574
|
-
console.log(` ${paint9("green", "\u2713")} Spinning up project: ${paint9("bold", result.project.name)}`);
|
|
6575
|
-
console.log(` ${paint9("gray", "Project ID:")} ${result.project.id}`);
|
|
6576
|
-
if (result.tasks && result.tasks.length > 0) {
|
|
6577
|
-
console.log(` ${paint9("green", "\u2713")} Created ${result.tasks.length} follow-up task(s):`);
|
|
6578
|
-
for (const task of result.tasks) {
|
|
6579
|
-
console.log(` ${paint9("gray", "\u2022")} ${task.title}`);
|
|
6580
|
-
}
|
|
6581
|
-
}
|
|
6582
|
-
console.log(` ${paint9("cyan", "\u27F3")} Repo creation is queued \u2014 the watch daemon will pick it up.`);
|
|
6583
|
-
console.log();
|
|
6584
|
-
})
|
|
6585
|
-
);
|
|
6586
|
-
|
|
6587
6196
|
// cli/commands/doctor.ts
|
|
6588
|
-
import { Command as
|
|
6197
|
+
import { Command as Command24 } from "commander";
|
|
6589
6198
|
import { existsSync as existsSync15 } from "fs";
|
|
6590
6199
|
import { homedir as homedir2 } from "os";
|
|
6591
6200
|
import { join as join11 } from "path";
|
|
@@ -6633,7 +6242,7 @@ async function checkProjectLink() {
|
|
|
6633
6242
|
optional: true
|
|
6634
6243
|
};
|
|
6635
6244
|
}
|
|
6636
|
-
var doctorCommand = new
|
|
6245
|
+
var doctorCommand = new Command24("doctor").description("Diagnose Mr. Manager CLI installation and environment").action(async () => {
|
|
6637
6246
|
const banner = [
|
|
6638
6247
|
``,
|
|
6639
6248
|
paint5("cyan", ` MR DOCTOR`),
|
|
@@ -6664,7 +6273,7 @@ var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CL
|
|
|
6664
6273
|
console.log("");
|
|
6665
6274
|
return;
|
|
6666
6275
|
}
|
|
6667
|
-
const fixes = checks.filter((
|
|
6276
|
+
const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
|
|
6668
6277
|
if (fixes.length > 0) {
|
|
6669
6278
|
console.log(paint5("yellow", " To fix:"));
|
|
6670
6279
|
for (const fix of fixes) {
|
|
@@ -6676,14 +6285,14 @@ var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CL
|
|
|
6676
6285
|
});
|
|
6677
6286
|
|
|
6678
6287
|
// cli/commands/prompt-audit.ts
|
|
6679
|
-
import { Command as
|
|
6288
|
+
import { Command as Command25 } from "commander";
|
|
6680
6289
|
import { resolve as resolve8 } from "path";
|
|
6681
6290
|
import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
|
|
6682
6291
|
function auditLine(label, tokens) {
|
|
6683
6292
|
const bar = "\u2588".repeat(Math.min(60, Math.round(tokens / 200)));
|
|
6684
6293
|
return ` ${label.padEnd(30)} ${formatTokenCount(tokens).padStart(8)} ${bar}`;
|
|
6685
6294
|
}
|
|
6686
|
-
var promptAuditCommand = new
|
|
6295
|
+
var promptAuditCommand = new Command25("prompt-audit").description("Dry-run prompt construction and report estimated token counts by job type").option("--task <id>", "Audit prompts for a specific task ID").option("--all", "Audit all supported job types with representative data", false).option("--json", "Output as JSON instead of plain text", false).action(async (opts) => {
|
|
6687
6296
|
const results = [];
|
|
6688
6297
|
if (opts.task) {
|
|
6689
6298
|
try {
|
|
@@ -6843,14 +6452,6 @@ ${task.notes}` : "";
|
|
|
6843
6452
|
{ name: "instructions", tokens: 500 }
|
|
6844
6453
|
]
|
|
6845
6454
|
},
|
|
6846
|
-
{
|
|
6847
|
-
jobType: "idea",
|
|
6848
|
-
description: "Idea generation prompt",
|
|
6849
|
-
sections: [
|
|
6850
|
-
{ name: "core-prompt", tokens: 500 },
|
|
6851
|
-
{ name: "idea-desc", tokens: 200 }
|
|
6852
|
-
]
|
|
6853
|
-
},
|
|
6854
6455
|
{
|
|
6855
6456
|
jobType: "repo-creation",
|
|
6856
6457
|
description: "Repository creation prompt",
|
|
@@ -6896,8 +6497,8 @@ ${r.jobType} [${r.identifier}]`);
|
|
|
6896
6497
|
});
|
|
6897
6498
|
|
|
6898
6499
|
// cli/commands/skill.ts
|
|
6899
|
-
import { Command as
|
|
6900
|
-
var
|
|
6500
|
+
import { Command as Command26 } from "commander";
|
|
6501
|
+
var c9 = {
|
|
6901
6502
|
reset: "\x1B[0m",
|
|
6902
6503
|
bold: "\x1B[1m",
|
|
6903
6504
|
dim: "\x1B[2m",
|
|
@@ -6905,7 +6506,7 @@ var c10 = {
|
|
|
6905
6506
|
green: "\x1B[32m",
|
|
6906
6507
|
yellow: "\x1B[33m"
|
|
6907
6508
|
};
|
|
6908
|
-
var skillCommand = new
|
|
6509
|
+
var skillCommand = new Command26("skill").description("Manage skills \u2014 reusable playbooks for AI agents");
|
|
6909
6510
|
skillCommand.command("list").alias("ls").description("List all skills").option("--category <category>", "Filter by category").action(async (opts) => {
|
|
6910
6511
|
const params = new URLSearchParams();
|
|
6911
6512
|
if (opts.category) params.set("category", opts.category);
|
|
@@ -6913,17 +6514,17 @@ skillCommand.command("list").alias("ls").description("List all skills").option("
|
|
|
6913
6514
|
`/api/skills${params.toString() ? `?${params}` : ""}`
|
|
6914
6515
|
);
|
|
6915
6516
|
if (skills.length === 0) {
|
|
6916
|
-
console.log(`${
|
|
6517
|
+
console.log(`${c9.dim}No skills found.${c9.reset}`);
|
|
6917
6518
|
return;
|
|
6918
6519
|
}
|
|
6919
6520
|
for (const skill of skills) {
|
|
6920
|
-
const cat = skill.category ? ` ${
|
|
6921
|
-
const scope = skill.projectId ? ` ${
|
|
6922
|
-
console.log(` ${
|
|
6521
|
+
const cat = skill.category ? ` ${c9.dim}[${skill.category}]${c9.reset}` : "";
|
|
6522
|
+
const scope = skill.projectId ? ` ${c9.dim}(project)${c9.reset}` : ` ${c9.dim}(global)${c9.reset}`;
|
|
6523
|
+
console.log(` ${c9.cyan}${skill.name}${c9.reset}${cat}${scope}`);
|
|
6923
6524
|
if (skill.description) {
|
|
6924
|
-
console.log(` ${
|
|
6525
|
+
console.log(` ${c9.dim}${skill.description}${c9.reset}`);
|
|
6925
6526
|
}
|
|
6926
|
-
console.log(` ${
|
|
6527
|
+
console.log(` ${c9.dim}id: ${skill.id}${c9.reset}`);
|
|
6927
6528
|
}
|
|
6928
6529
|
});
|
|
6929
6530
|
skillCommand.command("create").description("Create a new skill from a markdown file or inline content").argument("<name>", "Skill name").option("-d, --description <desc>", "Short description").option("-c, --category <cat>", "Category (e.g. Deployment, Testing)").option("-f, --file <path>", "Read content from a markdown file").option("--content <text>", "Inline markdown content").option("-p, --project", "Scope to the linked project").action(async (name, opts) => {
|
|
@@ -6959,7 +6560,7 @@ skillCommand.command("create").description("Create a new skill from a markdown f
|
|
|
6959
6560
|
projectId
|
|
6960
6561
|
});
|
|
6961
6562
|
console.log(
|
|
6962
|
-
`${
|
|
6563
|
+
`${c9.green}Created skill:${c9.reset} ${c9.bold}${skill.name}${c9.reset} ${c9.dim}(${skill.id})${c9.reset}`
|
|
6963
6564
|
);
|
|
6964
6565
|
});
|
|
6965
6566
|
skillCommand.command("generate").alias("gen").description("Generate a new skill using AI from a text prompt").argument("<prompt>", "Describe the skill to generate").option("-p, --project", "Scope to the linked project").action(async (prompt2, opts) => {
|
|
@@ -6973,22 +6574,22 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
|
|
|
6973
6574
|
process.exit(1);
|
|
6974
6575
|
}
|
|
6975
6576
|
}
|
|
6976
|
-
console.log(`${
|
|
6577
|
+
console.log(`${c9.dim}Generating skill...${c9.reset}`);
|
|
6977
6578
|
try {
|
|
6978
6579
|
const skill = await api.post("/api/skills/generate", {
|
|
6979
6580
|
prompt: prompt2,
|
|
6980
6581
|
projectId
|
|
6981
6582
|
});
|
|
6982
6583
|
console.log(
|
|
6983
|
-
`${
|
|
6584
|
+
`${c9.green}Generated skill:${c9.reset} ${c9.bold}${skill.name}${c9.reset}`
|
|
6984
6585
|
);
|
|
6985
6586
|
if (skill.description) {
|
|
6986
|
-
console.log(` ${
|
|
6587
|
+
console.log(` ${c9.dim}${skill.description}${c9.reset}`);
|
|
6987
6588
|
}
|
|
6988
6589
|
if (skill.category) {
|
|
6989
|
-
console.log(` ${
|
|
6590
|
+
console.log(` ${c9.dim}Category: ${skill.category}${c9.reset}`);
|
|
6990
6591
|
}
|
|
6991
|
-
console.log(` ${
|
|
6592
|
+
console.log(` ${c9.dim}id: ${skill.id}${c9.reset}`);
|
|
6992
6593
|
} catch (err) {
|
|
6993
6594
|
console.error(`Failed to generate skill: ${err.message}`);
|
|
6994
6595
|
process.exit(1);
|
|
@@ -6996,17 +6597,17 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
|
|
|
6996
6597
|
});
|
|
6997
6598
|
|
|
6998
6599
|
// cli/commands/tests.ts
|
|
6999
|
-
import { Command as
|
|
7000
|
-
var
|
|
6600
|
+
import { Command as Command27 } from "commander";
|
|
6601
|
+
var c10 = {
|
|
7001
6602
|
reset: "\x1B[0m",
|
|
7002
6603
|
dim: "\x1B[2m",
|
|
7003
6604
|
yellow: "\x1B[33m"
|
|
7004
6605
|
};
|
|
7005
|
-
var testsCommand = new
|
|
6606
|
+
var testsCommand = new Command27("tests").description("List MR Test scenarios for the linked project").action(async () => {
|
|
7006
6607
|
const projectId = getLinkedProjectId();
|
|
7007
6608
|
if (!projectId) {
|
|
7008
6609
|
console.error(
|
|
7009
|
-
`${
|
|
6610
|
+
`${c10.yellow}No project linked to this directory.${c10.reset} Run "mr link <project-id>" first.`
|
|
7010
6611
|
);
|
|
7011
6612
|
process.exit(1);
|
|
7012
6613
|
}
|
|
@@ -7019,13 +6620,13 @@ var testsCommand = new Command28("tests").description("List MR Test scenarios fo
|
|
|
7019
6620
|
process.exit(1);
|
|
7020
6621
|
}
|
|
7021
6622
|
if (scenarios.length === 0) {
|
|
7022
|
-
console.log(`${
|
|
6623
|
+
console.log(`${c10.dim}No test scenarios found for this project.${c10.reset}`);
|
|
7023
6624
|
return;
|
|
7024
6625
|
}
|
|
7025
6626
|
for (const scenario of scenarios) {
|
|
7026
6627
|
console.log(`### ${scenario.name}`);
|
|
7027
6628
|
if (scenario.description) {
|
|
7028
|
-
console.log(`${
|
|
6629
|
+
console.log(`${c10.dim}${scenario.description}${c10.reset}`);
|
|
7029
6630
|
console.log();
|
|
7030
6631
|
}
|
|
7031
6632
|
console.log(scenario.content);
|
|
@@ -7040,7 +6641,7 @@ var userArgs = process.argv.slice(2);
|
|
|
7040
6641
|
var bypassCommands = /* @__PURE__ */ new Set(["login", "init", "auth", "help", "--help", "-h", "--version", "-V", "doctor", "setup"]);
|
|
7041
6642
|
var shouldBypass = userArgs.length > 0 && bypassCommands.has(userArgs[0]);
|
|
7042
6643
|
if (isFirstRun && !shouldBypass) {
|
|
7043
|
-
const
|
|
6644
|
+
const c11 = {
|
|
7044
6645
|
reset: "\x1B[0m",
|
|
7045
6646
|
bold: "\x1B[1m",
|
|
7046
6647
|
dim: "\x1B[2m",
|
|
@@ -7050,28 +6651,28 @@ if (isFirstRun && !shouldBypass) {
|
|
|
7050
6651
|
magenta: "\x1B[35m"
|
|
7051
6652
|
};
|
|
7052
6653
|
console.log("");
|
|
7053
|
-
console.log(`${
|
|
7054
|
-
console.log(`${
|
|
7055
|
-
console.log(`${
|
|
7056
|
-
console.log(`${
|
|
6654
|
+
console.log(`${c11.cyan} \u2554\u2566\u2557\u2566\u2550\u2557 \u2554\u2566\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2554\u2550\u2557\u2554\u2550\u2557\u2554\u2550\u2557\u2566\u2550\u2557${c11.reset}`);
|
|
6655
|
+
console.log(`${c11.magenta} \u2551\u2551\u2551\u2560\u2566\u255D \u2551\u2551\u2551\u2560\u2550\u2563\u2551\u2551\u2551\u2560\u2550\u2563\u2551 \u2566\u2551\u2563 \u2560\u2566\u255D${c11.reset}`);
|
|
6656
|
+
console.log(`${c11.cyan} \u2569 \u2569\u2569\u255A\u2550 \u2569 \u2569\u2569 \u2569\u255D\u255A\u255D\u2569 \u2569\u255A\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550${c11.reset}`);
|
|
6657
|
+
console.log(`${c11.dim} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c11.reset}`);
|
|
7057
6658
|
console.log("");
|
|
7058
|
-
console.log(`${
|
|
7059
|
-
console.log(`${
|
|
6659
|
+
console.log(`${c11.bold} Welcome to Mr. Manager!${c11.reset}`);
|
|
6660
|
+
console.log(`${c11.dim} Let's get you set up in a few quick steps.${c11.reset}`);
|
|
7060
6661
|
console.log("");
|
|
7061
|
-
console.log(` ${
|
|
7062
|
-
console.log(` ${
|
|
6662
|
+
console.log(` ${c11.yellow}Step 1:${c11.reset} Authenticate via Google OAuth`);
|
|
6663
|
+
console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr login${c11.reset}`);
|
|
7063
6664
|
console.log("");
|
|
7064
|
-
console.log(` ${
|
|
7065
|
-
console.log(` ${
|
|
6665
|
+
console.log(` ${c11.yellow}Step 2:${c11.reset} Verify your environment`);
|
|
6666
|
+
console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr setup${c11.reset}`);
|
|
7066
6667
|
console.log("");
|
|
7067
|
-
console.log(` ${
|
|
7068
|
-
console.log(` ${
|
|
6668
|
+
console.log(` ${c11.yellow}Step 3:${c11.reset} Link a repo and start watching`);
|
|
6669
|
+
console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr link${c11.reset} ${c11.dim}&&${c11.reset} ${c11.cyan}mr watch${c11.reset}`);
|
|
7069
6670
|
console.log("");
|
|
7070
|
-
console.log(`${
|
|
6671
|
+
console.log(`${c11.dim} Or run ${c11.reset}${c11.cyan}mr login${c11.reset}${c11.dim} to get started now.${c11.reset}`);
|
|
7071
6672
|
console.log("");
|
|
7072
6673
|
process.exit(0);
|
|
7073
6674
|
}
|
|
7074
|
-
var program = new
|
|
6675
|
+
var program = new Command28();
|
|
7075
6676
|
program.name("mr").description("Mr. Manager - Task and project management CLI").version(CLI_VERSION);
|
|
7076
6677
|
program.addCommand(initCommand);
|
|
7077
6678
|
program.addCommand(authCommand);
|
|
@@ -7099,7 +6700,6 @@ program.addCommand(testCommand);
|
|
|
7099
6700
|
program.addCommand(featuresCommand);
|
|
7100
6701
|
program.addCommand(noMrCommand);
|
|
7101
6702
|
program.addCommand(scanCommand);
|
|
7102
|
-
program.addCommand(ideaCommand);
|
|
7103
6703
|
program.addCommand(doctorCommand);
|
|
7104
6704
|
program.addCommand(promptAuditCommand);
|
|
7105
6705
|
program.addCommand(skillCommand);
|