ralph-mcp 1.0.9 → 1.0.11
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.
|
@@ -5,7 +5,8 @@ import { execSync } from "child_process";
|
|
|
5
5
|
import { parsePrdFile } from "../utils/prd-parser.js";
|
|
6
6
|
import { createWorktree } from "../utils/worktree.js";
|
|
7
7
|
import { generateAgentPrompt } from "../utils/agent.js";
|
|
8
|
-
import {
|
|
8
|
+
import { detectPackageManager, getInstallCommand, } from "../utils/package-manager.js";
|
|
9
|
+
import { areDependenciesSatisfied, findExecutionByBranch, insertExecution, insertUserStories, updateExecution, } from "../store/state.js";
|
|
9
10
|
export const batchStartInputSchema = z.object({
|
|
10
11
|
prdPaths: z.array(z.string()).describe("Array of paths to PRD markdown files"),
|
|
11
12
|
projectRoot: z.string().optional().describe("Project root directory (defaults to cwd)"),
|
|
@@ -20,7 +21,7 @@ export const batchStartInputSchema = z.object({
|
|
|
20
21
|
.string()
|
|
21
22
|
.optional()
|
|
22
23
|
.describe("Path to a file (e.g., CLAUDE.md) to inject into the agent prompt"),
|
|
23
|
-
preheat: z.boolean().default(true).describe("Run
|
|
24
|
+
preheat: z.boolean().default(true).describe("Run install command serially before starting agents (avoids store lock)"),
|
|
24
25
|
});
|
|
25
26
|
/**
|
|
26
27
|
* Topological sort to determine execution order based on dependencies.
|
|
@@ -53,23 +54,30 @@ function topologicalSort(prds) {
|
|
|
53
54
|
return result;
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
56
|
-
* Run
|
|
57
|
+
* Run install command in a worktree directory.
|
|
57
58
|
*/
|
|
58
|
-
function preheatWorktree(worktreePath) {
|
|
59
|
+
function preheatWorktree(worktreePath, installCmd) {
|
|
60
|
+
const cmd = `${installCmd.command} ${installCmd.args.join(" ")}`;
|
|
59
61
|
try {
|
|
60
|
-
execSync(
|
|
62
|
+
execSync(cmd, {
|
|
61
63
|
cwd: worktreePath,
|
|
62
64
|
stdio: "pipe",
|
|
63
65
|
timeout: 300000, // 5 minutes
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
68
|
catch (error) {
|
|
67
|
-
// Try
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
// Try fallback if available
|
|
70
|
+
if (installCmd.fallbackArgs.length > 0) {
|
|
71
|
+
const fallbackCmd = `${installCmd.command} ${installCmd.fallbackArgs.join(" ")}`;
|
|
72
|
+
execSync(fallbackCmd, {
|
|
73
|
+
cwd: worktreePath,
|
|
74
|
+
stdio: "pipe",
|
|
75
|
+
timeout: 300000,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
83
|
export async function batchStart(input) {
|
|
@@ -78,6 +86,9 @@ export async function batchStart(input) {
|
|
|
78
86
|
const contextPath = input.contextInjectionPath
|
|
79
87
|
? resolve(projectRoot, input.contextInjectionPath)
|
|
80
88
|
: undefined;
|
|
89
|
+
// Detect package manager
|
|
90
|
+
const pm = detectPackageManager(projectRoot);
|
|
91
|
+
const installCmd = getInstallCommand(pm);
|
|
81
92
|
const skipped = [];
|
|
82
93
|
const prdInfos = [];
|
|
83
94
|
// Phase 1: Parse all PRDs and create execution records
|
|
@@ -159,13 +170,13 @@ export async function batchStart(input) {
|
|
|
159
170
|
}
|
|
160
171
|
// Phase 2: Topological sort for preheat order
|
|
161
172
|
const sortedPrds = topologicalSort(prdInfos);
|
|
162
|
-
// Phase 3: Preheat worktrees serially (avoids
|
|
173
|
+
// Phase 3: Preheat worktrees serially (avoids store lock contention)
|
|
163
174
|
let preheatCompleted = false;
|
|
164
175
|
if (input.preheat && input.worktree) {
|
|
165
176
|
for (const prd of sortedPrds) {
|
|
166
177
|
if (prd.worktreePath) {
|
|
167
178
|
try {
|
|
168
|
-
preheatWorktree(prd.worktreePath);
|
|
179
|
+
preheatWorktree(prd.worktreePath, installCmd);
|
|
169
180
|
}
|
|
170
181
|
catch (error) {
|
|
171
182
|
console.error(`Preheat failed for ${prd.branch}:`, error);
|
|
@@ -184,6 +195,11 @@ export async function batchStart(input) {
|
|
|
184
195
|
if (depStatus.satisfied) {
|
|
185
196
|
const agentPrompt = generateAgentPrompt(prd.branch, "", // description not stored in prdInfo
|
|
186
197
|
prd.worktreePath || projectRoot, prd.stories, contextPath);
|
|
198
|
+
// Mark as running immediately since we're returning the prompt
|
|
199
|
+
await updateExecution(prd.executionId, {
|
|
200
|
+
status: "running",
|
|
201
|
+
updatedAt: new Date(),
|
|
202
|
+
});
|
|
187
203
|
readyToStart.push({
|
|
188
204
|
branch: prd.branch,
|
|
189
205
|
agentPrompt,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
|
|
2
|
+
export interface InstallCommand {
|
|
3
|
+
command: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
fallbackArgs: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function detectPackageManager(projectRoot: string): PackageManager;
|
|
8
|
+
export declare function getInstallCommand(pm: PackageManager): InstallCommand;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
export function detectPackageManager(projectRoot) {
|
|
4
|
+
if (existsSync(join(projectRoot, "pnpm-lock.yaml"))) {
|
|
5
|
+
return "pnpm";
|
|
6
|
+
}
|
|
7
|
+
if (existsSync(join(projectRoot, "yarn.lock"))) {
|
|
8
|
+
return "yarn";
|
|
9
|
+
}
|
|
10
|
+
if (existsSync(join(projectRoot, "bun.lockb"))) {
|
|
11
|
+
return "bun";
|
|
12
|
+
}
|
|
13
|
+
// Default to npm if package-lock.json exists or as fallback
|
|
14
|
+
return "npm";
|
|
15
|
+
}
|
|
16
|
+
export function getInstallCommand(pm) {
|
|
17
|
+
switch (pm) {
|
|
18
|
+
case "pnpm":
|
|
19
|
+
return {
|
|
20
|
+
command: "pnpm",
|
|
21
|
+
args: ["install", "--frozen-lockfile"],
|
|
22
|
+
fallbackArgs: ["install"],
|
|
23
|
+
};
|
|
24
|
+
case "yarn":
|
|
25
|
+
return {
|
|
26
|
+
command: "yarn",
|
|
27
|
+
args: ["install", "--frozen-lockfile"],
|
|
28
|
+
fallbackArgs: ["install"],
|
|
29
|
+
};
|
|
30
|
+
case "bun":
|
|
31
|
+
return {
|
|
32
|
+
command: "bun",
|
|
33
|
+
args: ["install", "--frozen-lockfile"],
|
|
34
|
+
fallbackArgs: ["install"],
|
|
35
|
+
};
|
|
36
|
+
case "npm":
|
|
37
|
+
default:
|
|
38
|
+
return {
|
|
39
|
+
command: "npm",
|
|
40
|
+
args: ["ci"],
|
|
41
|
+
fallbackArgs: ["install"],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
CHANGED