pi-review-loop 0.2.1 → 0.3.0
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/README.md +9 -11
- package/index.ts +76 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,18 +44,8 @@ The pattern is the same: keep reviewing until there's genuinely nothing left to
|
|
|
44
44
|
|
|
45
45
|
## Install
|
|
46
46
|
|
|
47
|
-
**npm** (recommended):
|
|
48
|
-
|
|
49
47
|
```bash
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The extension is automatically copied to `~/.pi/agent/extensions/pi-review-loop/`.
|
|
54
|
-
|
|
55
|
-
**Or clone directly:**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
git clone https://github.com/nicobailon/pi-review-loop ~/.pi/agent/extensions/pi-review-loop
|
|
48
|
+
pi install npm:pi-review-loop
|
|
59
49
|
```
|
|
60
50
|
|
|
61
51
|
Restart pi to load the extension. On activation, you'll see status in the footer:
|
|
@@ -253,9 +243,13 @@ The loop exits when:
|
|
|
253
243
|
| Command | Description |
|
|
254
244
|
|---------|-------------|
|
|
255
245
|
| `/review-start` | Activate and send review prompt immediately |
|
|
246
|
+
| `/review-start "focus on X"` | Start review with custom focus appended to prompt |
|
|
247
|
+
| `/review-plan` | Activate and review plans/specs/PRDs (uses `double-check-plan` template) |
|
|
248
|
+
| `/review-plan "focus on X"` | Review plan with custom focus appended to prompt |
|
|
256
249
|
| `/review-exit` | Exit review mode |
|
|
257
250
|
| `/review-max <n>` | Set max iterations (session only) |
|
|
258
251
|
| `/review-auto [on\|off]` | Toggle auto-trigger from keywords (session only) |
|
|
252
|
+
| `/review-auto "focus on X"` | Enable auto-trigger AND start review with custom focus |
|
|
259
253
|
| `/review-status` | Show current state |
|
|
260
254
|
|
|
261
255
|
## Tool API
|
|
@@ -272,6 +266,9 @@ review_loop({ start: true })
|
|
|
272
266
|
// Start with custom max iterations
|
|
273
267
|
review_loop({ start: true, maxIterations: 5 })
|
|
274
268
|
|
|
269
|
+
// Start with custom focus
|
|
270
|
+
review_loop({ start: true, focus: "focus on error handling and edge cases" })
|
|
271
|
+
|
|
275
272
|
// Stop review mode
|
|
276
273
|
review_loop({ stop: true })
|
|
277
274
|
|
|
@@ -290,6 +287,7 @@ review_loop({ autoTrigger: false })
|
|
|
290
287
|
"currentIteration": 2,
|
|
291
288
|
"maxIterations": 7,
|
|
292
289
|
"autoTrigger": false,
|
|
290
|
+
"focus": "focus on error handling",
|
|
293
291
|
"message": "Review mode active: iteration 2/7"
|
|
294
292
|
}
|
|
295
293
|
```
|
package/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
6
6
|
let settings: ReviewerLoopSettings = loadSettings();
|
|
7
7
|
let reviewModeActive = false;
|
|
8
8
|
let currentIteration = 0;
|
|
9
|
+
let customPromptSuffix = "";
|
|
9
10
|
|
|
10
11
|
function updateStatus(ctx: ExtensionContext) {
|
|
11
12
|
if (reviewModeActive) {
|
|
@@ -18,9 +19,25 @@ export default function (pi: ExtensionAPI) {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
function buildReviewPrompt(promptConfig: { type: "inline" | "file" | "template"; value: string }): string {
|
|
23
|
+
const basePrompt = getReviewPrompt(promptConfig);
|
|
24
|
+
if (customPromptSuffix) {
|
|
25
|
+
return `${basePrompt}\n\n**Additional focus:** ${customPromptSuffix}`;
|
|
26
|
+
}
|
|
27
|
+
return basePrompt;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseCustomText(args: string): string {
|
|
31
|
+
// Match quoted strings: "text" or 'text' (must use matching quotes)
|
|
32
|
+
const match = args.match(/^"(.+)"$/s) || args.match(/^'(.+)'$/s) ||
|
|
33
|
+
args.match(/"(.+?)"/s) || args.match(/'(.+?)'/s);
|
|
34
|
+
return match ? match[1].trim() : "";
|
|
35
|
+
}
|
|
36
|
+
|
|
21
37
|
function exitReviewMode(ctx: ExtensionContext, reason: string) {
|
|
22
38
|
reviewModeActive = false;
|
|
23
39
|
currentIteration = 0;
|
|
40
|
+
customPromptSuffix = "";
|
|
24
41
|
updateStatus(ctx);
|
|
25
42
|
ctx.ui.notify(`Review mode ended: ${reason}`, "info");
|
|
26
43
|
}
|
|
@@ -103,19 +120,33 @@ export default function (pi: ExtensionAPI) {
|
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
updateStatus(ctx);
|
|
106
|
-
pi.sendUserMessage(
|
|
123
|
+
pi.sendUserMessage(buildReviewPrompt(settings.reviewPromptConfig), {
|
|
107
124
|
deliverAs: "followUp",
|
|
108
125
|
});
|
|
109
126
|
});
|
|
110
127
|
|
|
111
128
|
pi.registerCommand("review-start", {
|
|
112
|
-
description: "Activate review loop and send review prompt immediately",
|
|
113
|
-
handler: async (
|
|
129
|
+
description: "Activate review loop and send review prompt immediately. Optional: add custom focus with quotes.",
|
|
130
|
+
handler: async (args, ctx) => {
|
|
114
131
|
if (reviewModeActive) {
|
|
115
132
|
ctx.ui.notify("Review mode is already active", "info");
|
|
116
133
|
} else {
|
|
134
|
+
customPromptSuffix = parseCustomText(args);
|
|
117
135
|
enterReviewMode(ctx);
|
|
118
|
-
pi.sendUserMessage(
|
|
136
|
+
pi.sendUserMessage(buildReviewPrompt(settings.reviewPromptConfig));
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
pi.registerCommand("review-plan", {
|
|
142
|
+
description: "Activate review loop for plans/specs/PRDs. Optional: add custom focus with quotes.",
|
|
143
|
+
handler: async (args, ctx) => {
|
|
144
|
+
if (reviewModeActive) {
|
|
145
|
+
ctx.ui.notify("Review mode is already active", "info");
|
|
146
|
+
} else {
|
|
147
|
+
customPromptSuffix = parseCustomText(args);
|
|
148
|
+
enterReviewMode(ctx);
|
|
149
|
+
pi.sendUserMessage(buildReviewPrompt({ type: "template", value: "double-check-plan" }));
|
|
119
150
|
}
|
|
120
151
|
},
|
|
121
152
|
});
|
|
@@ -162,17 +193,36 @@ export default function (pi: ExtensionAPI) {
|
|
|
162
193
|
});
|
|
163
194
|
|
|
164
195
|
pi.registerCommand("review-auto", {
|
|
165
|
-
description: "Toggle auto-trigger
|
|
196
|
+
description: "Toggle auto-trigger, or start review with custom focus: /review-auto \"focus on X\"",
|
|
166
197
|
handler: async (args, ctx) => {
|
|
167
|
-
const arg = args.trim()
|
|
168
|
-
|
|
198
|
+
const arg = args.trim();
|
|
199
|
+
const argLower = arg.toLowerCase();
|
|
200
|
+
|
|
201
|
+
// Check for quoted custom text first
|
|
202
|
+
const customText = parseCustomText(arg);
|
|
203
|
+
if (customText) {
|
|
204
|
+
// Custom text provided: enable auto-trigger and start review with custom focus
|
|
205
|
+
settings.autoTrigger = true;
|
|
206
|
+
customPromptSuffix = customText;
|
|
207
|
+
if (reviewModeActive) {
|
|
208
|
+
ctx.ui.notify(`Auto-trigger enabled, focus updated for next iteration`, "info");
|
|
209
|
+
} else {
|
|
210
|
+
enterReviewMode(ctx);
|
|
211
|
+
pi.sendUserMessage(buildReviewPrompt(settings.reviewPromptConfig));
|
|
212
|
+
ctx.ui.notify(`Auto-trigger enabled, review started with custom focus`, "info");
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Standard on/off/toggle behavior
|
|
218
|
+
if (argLower === "on" || argLower === "true" || argLower === "1") {
|
|
169
219
|
settings.autoTrigger = true;
|
|
170
|
-
} else if (
|
|
220
|
+
} else if (argLower === "off" || argLower === "false" || argLower === "0") {
|
|
171
221
|
settings.autoTrigger = false;
|
|
172
222
|
} else if (arg === "") {
|
|
173
223
|
settings.autoTrigger = !settings.autoTrigger;
|
|
174
224
|
} else {
|
|
175
|
-
ctx.ui.notify("Usage: /review-auto [on|off]", "error");
|
|
225
|
+
ctx.ui.notify("Usage: /review-auto [on|off] or /review-auto \"custom focus\"", "error");
|
|
176
226
|
return;
|
|
177
227
|
}
|
|
178
228
|
ctx.ui.notify(
|
|
@@ -208,6 +258,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
208
258
|
minimum: 1,
|
|
209
259
|
})
|
|
210
260
|
),
|
|
261
|
+
focus: Type.Optional(
|
|
262
|
+
Type.String({
|
|
263
|
+
description: "Custom focus/instructions to append to the review prompt (e.g., \"focus on error handling\")",
|
|
264
|
+
})
|
|
265
|
+
),
|
|
211
266
|
}),
|
|
212
267
|
|
|
213
268
|
async execute(_toolCallId, params, _onUpdate, ctx) {
|
|
@@ -225,6 +280,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
225
280
|
);
|
|
226
281
|
}
|
|
227
282
|
|
|
283
|
+
// Update custom focus if provided
|
|
284
|
+
if (typeof params.focus === "string") {
|
|
285
|
+
customPromptSuffix = params.focus.trim();
|
|
286
|
+
}
|
|
287
|
+
|
|
228
288
|
// Mode: start > stop > status
|
|
229
289
|
if (params.start) {
|
|
230
290
|
if (reviewModeActive) {
|
|
@@ -237,6 +297,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
237
297
|
currentIteration,
|
|
238
298
|
maxIterations: settings.maxIterations,
|
|
239
299
|
autoTrigger: settings.autoTrigger,
|
|
300
|
+
focus: customPromptSuffix || undefined,
|
|
240
301
|
message: "Review mode is already active",
|
|
241
302
|
}),
|
|
242
303
|
},
|
|
@@ -245,7 +306,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
245
306
|
}
|
|
246
307
|
|
|
247
308
|
enterReviewMode(ctx);
|
|
248
|
-
pi.sendUserMessage(
|
|
309
|
+
pi.sendUserMessage(buildReviewPrompt(settings.reviewPromptConfig));
|
|
249
310
|
|
|
250
311
|
return {
|
|
251
312
|
content: [
|
|
@@ -256,7 +317,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
256
317
|
currentIteration,
|
|
257
318
|
maxIterations: settings.maxIterations,
|
|
258
319
|
autoTrigger: settings.autoTrigger,
|
|
259
|
-
|
|
320
|
+
focus: customPromptSuffix || undefined,
|
|
321
|
+
message: customPromptSuffix
|
|
322
|
+
? `Review mode started with custom focus. Review prompt sent.`
|
|
323
|
+
: "Review mode started. Review prompt sent.",
|
|
260
324
|
}),
|
|
261
325
|
},
|
|
262
326
|
],
|
|
@@ -309,6 +373,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
309
373
|
currentIteration,
|
|
310
374
|
maxIterations: settings.maxIterations,
|
|
311
375
|
autoTrigger: settings.autoTrigger,
|
|
376
|
+
focus: customPromptSuffix || undefined,
|
|
312
377
|
message: reviewModeActive
|
|
313
378
|
? `Review mode active: iteration ${currentIteration}/${settings.maxIterations}`
|
|
314
379
|
: "Review mode inactive",
|