ralph-mcp 1.1.0 → 1.1.1
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.js +49 -0
- package/dist/tools/reset-stagnation.d.ts +24 -0
- package/dist/tools/reset-stagnation.js +40 -0
- package/dist/tools/retry.d.ts +26 -0
- package/dist/tools/retry.js +65 -0
- package/dist/tools/status.d.ts +1 -0
- package/dist/tools/status.js +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ import { update, updateInputSchema } from "./tools/update.js";
|
|
|
10
10
|
import { stop, stopInputSchema } from "./tools/stop.js";
|
|
11
11
|
import { merge, mergeInputSchema, mergeQueueAction, mergeQueueInputSchema } from "./tools/merge.js";
|
|
12
12
|
import { setAgentId, setAgentIdInputSchema } from "./tools/set-agent-id.js";
|
|
13
|
+
import { resetStagnationTool, resetStagnationInputSchema } from "./tools/reset-stagnation.js";
|
|
14
|
+
import { retry, retryInputSchema } from "./tools/retry.js";
|
|
13
15
|
const server = new Server({
|
|
14
16
|
name: "ralph",
|
|
15
17
|
version: "1.0.0",
|
|
@@ -120,6 +122,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
120
122
|
type: "string",
|
|
121
123
|
description: "Implementation notes",
|
|
122
124
|
},
|
|
125
|
+
filesChanged: {
|
|
126
|
+
type: "number",
|
|
127
|
+
description: "Number of files changed (for stagnation detection)",
|
|
128
|
+
},
|
|
129
|
+
error: {
|
|
130
|
+
type: "string",
|
|
131
|
+
description: "Error message if stuck (for stagnation detection)",
|
|
132
|
+
},
|
|
123
133
|
},
|
|
124
134
|
required: ["branch", "storyId", "passes"],
|
|
125
135
|
},
|
|
@@ -258,6 +268,39 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
258
268
|
required: ["prdPaths"],
|
|
259
269
|
},
|
|
260
270
|
},
|
|
271
|
+
{
|
|
272
|
+
name: "ralph_reset_stagnation",
|
|
273
|
+
description: "Reset stagnation counters for an execution. Use after manual intervention to allow the agent to continue.",
|
|
274
|
+
inputSchema: {
|
|
275
|
+
type: "object",
|
|
276
|
+
properties: {
|
|
277
|
+
branch: {
|
|
278
|
+
type: "string",
|
|
279
|
+
description: "Branch name (e.g., ralph/task1-agent)",
|
|
280
|
+
},
|
|
281
|
+
resumeExecution: {
|
|
282
|
+
type: "boolean",
|
|
283
|
+
description: "Also set status back to 'running' if currently 'failed' (default: true)",
|
|
284
|
+
default: true,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
required: ["branch"],
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: "ralph_retry",
|
|
292
|
+
description: "Retry a failed PRD execution. Resets stagnation counters and generates a new agent prompt to continue from where it left off.",
|
|
293
|
+
inputSchema: {
|
|
294
|
+
type: "object",
|
|
295
|
+
properties: {
|
|
296
|
+
branch: {
|
|
297
|
+
type: "string",
|
|
298
|
+
description: "Branch name (e.g., ralph/task1-agent)",
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
required: ["branch"],
|
|
302
|
+
},
|
|
303
|
+
},
|
|
261
304
|
],
|
|
262
305
|
};
|
|
263
306
|
});
|
|
@@ -294,6 +337,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
294
337
|
case "ralph_batch_start":
|
|
295
338
|
result = await batchStart(batchStartInputSchema.parse(args));
|
|
296
339
|
break;
|
|
340
|
+
case "ralph_reset_stagnation":
|
|
341
|
+
result = await resetStagnationTool(resetStagnationInputSchema.parse(args));
|
|
342
|
+
break;
|
|
343
|
+
case "ralph_retry":
|
|
344
|
+
result = await retry(retryInputSchema.parse(args));
|
|
345
|
+
break;
|
|
297
346
|
default:
|
|
298
347
|
throw new Error(`Unknown tool: ${name}`);
|
|
299
348
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const resetStagnationInputSchema: z.ZodObject<{
|
|
3
|
+
branch: z.ZodString;
|
|
4
|
+
resumeExecution: z.ZodDefault<z.ZodBoolean>;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
branch: string;
|
|
7
|
+
resumeExecution: boolean;
|
|
8
|
+
}, {
|
|
9
|
+
branch: string;
|
|
10
|
+
resumeExecution?: boolean | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
export type ResetStagnationInput = z.infer<typeof resetStagnationInputSchema>;
|
|
13
|
+
export interface ResetStagnationResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
branch: string;
|
|
16
|
+
message: string;
|
|
17
|
+
previousStatus: string;
|
|
18
|
+
newStatus: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reset stagnation counters for an execution.
|
|
22
|
+
* Use this after manual intervention to allow the agent to continue.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resetStagnationTool(input: ResetStagnationInput): Promise<ResetStagnationResult>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { findExecutionByBranch, resetStagnation, updateExecution, } from "../store/state.js";
|
|
3
|
+
export const resetStagnationInputSchema = z.object({
|
|
4
|
+
branch: z.string().describe("Branch name (e.g., ralph/task1-agent)"),
|
|
5
|
+
resumeExecution: z
|
|
6
|
+
.boolean()
|
|
7
|
+
.default(true)
|
|
8
|
+
.describe("Also set status back to 'running' if currently 'failed'"),
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Reset stagnation counters for an execution.
|
|
12
|
+
* Use this after manual intervention to allow the agent to continue.
|
|
13
|
+
*/
|
|
14
|
+
export async function resetStagnationTool(input) {
|
|
15
|
+
const exec = await findExecutionByBranch(input.branch);
|
|
16
|
+
if (!exec) {
|
|
17
|
+
throw new Error(`No execution found for branch: ${input.branch}`);
|
|
18
|
+
}
|
|
19
|
+
const previousStatus = exec.status;
|
|
20
|
+
// Reset stagnation counters
|
|
21
|
+
await resetStagnation(exec.id);
|
|
22
|
+
// Optionally resume execution
|
|
23
|
+
let newStatus = previousStatus;
|
|
24
|
+
if (input.resumeExecution && previousStatus === "failed") {
|
|
25
|
+
await updateExecution(exec.id, {
|
|
26
|
+
status: "running",
|
|
27
|
+
updatedAt: new Date(),
|
|
28
|
+
});
|
|
29
|
+
newStatus = "running";
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
success: true,
|
|
33
|
+
branch: input.branch,
|
|
34
|
+
message: previousStatus === "failed" && input.resumeExecution
|
|
35
|
+
? "Stagnation counters reset and execution resumed"
|
|
36
|
+
: "Stagnation counters reset",
|
|
37
|
+
previousStatus,
|
|
38
|
+
newStatus,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const retryInputSchema: z.ZodObject<{
|
|
3
|
+
branch: z.ZodString;
|
|
4
|
+
}, "strip", z.ZodTypeAny, {
|
|
5
|
+
branch: string;
|
|
6
|
+
}, {
|
|
7
|
+
branch: string;
|
|
8
|
+
}>;
|
|
9
|
+
export type RetryInput = z.infer<typeof retryInputSchema>;
|
|
10
|
+
export interface RetryResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
branch: string;
|
|
13
|
+
message: string;
|
|
14
|
+
previousStatus: string;
|
|
15
|
+
agentPrompt: string | null;
|
|
16
|
+
progress: {
|
|
17
|
+
completed: number;
|
|
18
|
+
total: number;
|
|
19
|
+
percentage: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Retry a failed PRD execution.
|
|
24
|
+
* Resets stagnation counters and generates a new agent prompt.
|
|
25
|
+
*/
|
|
26
|
+
export declare function retry(input: RetryInput): Promise<RetryResult>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { findExecutionByBranch, listUserStoriesByExecutionId, resetStagnation, updateExecution, } from "../store/state.js";
|
|
3
|
+
import { generateAgentPrompt } from "../utils/agent.js";
|
|
4
|
+
export const retryInputSchema = z.object({
|
|
5
|
+
branch: z.string().describe("Branch name (e.g., ralph/task1-agent)"),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* Retry a failed PRD execution.
|
|
9
|
+
* Resets stagnation counters and generates a new agent prompt.
|
|
10
|
+
*/
|
|
11
|
+
export async function retry(input) {
|
|
12
|
+
const exec = await findExecutionByBranch(input.branch);
|
|
13
|
+
if (!exec) {
|
|
14
|
+
throw new Error(`No execution found for branch: ${input.branch}`);
|
|
15
|
+
}
|
|
16
|
+
const previousStatus = exec.status;
|
|
17
|
+
// Only allow retry for failed or stopped executions
|
|
18
|
+
if (previousStatus !== "failed" && previousStatus !== "stopped") {
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
branch: input.branch,
|
|
22
|
+
message: `Cannot retry execution with status '${previousStatus}'. Only 'failed' or 'stopped' executions can be retried.`,
|
|
23
|
+
previousStatus,
|
|
24
|
+
agentPrompt: null,
|
|
25
|
+
progress: { completed: 0, total: 0, percentage: 0 },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// Reset stagnation counters
|
|
29
|
+
await resetStagnation(exec.id);
|
|
30
|
+
// Set status back to running
|
|
31
|
+
await updateExecution(exec.id, {
|
|
32
|
+
status: "running",
|
|
33
|
+
updatedAt: new Date(),
|
|
34
|
+
});
|
|
35
|
+
// Get stories and generate new agent prompt
|
|
36
|
+
const stories = await listUserStoriesByExecutionId(exec.id);
|
|
37
|
+
const completed = stories.filter((s) => s.passes).length;
|
|
38
|
+
const total = stories.length;
|
|
39
|
+
const agentPrompt = generateAgentPrompt(exec.branch, exec.description, exec.worktreePath || exec.projectRoot, stories.map((s) => ({
|
|
40
|
+
storyId: s.storyId,
|
|
41
|
+
title: s.title,
|
|
42
|
+
description: s.description,
|
|
43
|
+
acceptanceCriteria: s.acceptanceCriteria,
|
|
44
|
+
priority: s.priority,
|
|
45
|
+
passes: s.passes,
|
|
46
|
+
})), undefined, // contextPath - would need to re-read from PRD
|
|
47
|
+
{
|
|
48
|
+
loopCount: 0, // Reset loop context for fresh start
|
|
49
|
+
consecutiveNoProgress: 0,
|
|
50
|
+
consecutiveErrors: 0,
|
|
51
|
+
lastError: null,
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
success: true,
|
|
55
|
+
branch: input.branch,
|
|
56
|
+
message: `Execution retried. ${total - completed} stories remaining.`,
|
|
57
|
+
previousStatus,
|
|
58
|
+
agentPrompt,
|
|
59
|
+
progress: {
|
|
60
|
+
completed,
|
|
61
|
+
total,
|
|
62
|
+
percentage: total > 0 ? Math.round((completed / total) * 100) : 0,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
package/dist/tools/status.d.ts
CHANGED
package/dist/tools/status.js
CHANGED
|
@@ -50,6 +50,7 @@ export async function status(input) {
|
|
|
50
50
|
completed: executionStatuses.filter((e) => e.status === "completed").length,
|
|
51
51
|
failed: executionStatuses.filter((e) => e.status === "failed").length,
|
|
52
52
|
pending: executionStatuses.filter((e) => e.status === "pending").length,
|
|
53
|
+
atRisk: executionStatuses.filter((e) => e.consecutiveNoProgress >= 2 || e.consecutiveErrors >= 3).length,
|
|
53
54
|
};
|
|
54
55
|
return {
|
|
55
56
|
executions: executionStatuses,
|
package/package.json
CHANGED