pi-extensions 0.1.30 → 0.1.32
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 +3 -3
- package/files-widget/CHANGELOG.md +5 -0
- package/files-widget/README.md +2 -0
- package/files-widget/TODO.md +2 -2
- package/files-widget/input-utils.ts +19 -10
- package/files-widget/viewer.ts +46 -9
- package/package.json +3 -3
- package/pi-ralph-wiggum/CHANGELOG.md +33 -0
- package/{ralph-wiggum → pi-ralph-wiggum}/README.md +3 -3
- package/{ralph-wiggum → pi-ralph-wiggum}/SKILL.md +1 -1
- package/{ralph-wiggum → pi-ralph-wiggum}/index.ts +23 -0
- package/{ralph-wiggum → pi-ralph-wiggum}/package.json +3 -3
- package/ralph-wiggum/CHANGELOG.md +0 -21
- /package/{ralph-wiggum → pi-ralph-wiggum}/LICENSE +0 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Personal extensions for the [Pi coding agent](https://github.com/badlogic/pi-mon
|
|
|
8
8
|
|-----------|-------------|
|
|
9
9
|
| [/readfiles](files-widget/) | In-terminal file browser and viewer widget. Navigate files, view diffs, select code, send comments to agent - without leaving Pi, and without interrupting your agent |
|
|
10
10
|
| [tab-status](tab-status/) | Manage as many parallel sessions as your mind can handle. Terminal tab indicators for <br>✅ done / 🚧 stuck / 🛑 timed out |
|
|
11
|
-
| [ralph-wiggum](ralph-wiggum/) | Run arbitrarily-long tasks without diluting model attention. Flat version without subagents like [ralph-loop](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ralph-loop) |
|
|
11
|
+
| [pi-ralph-wiggum](pi-ralph-wiggum/) | Run arbitrarily-long tasks without diluting model attention. Flat version without subagents like [ralph-loop](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ralph-loop) |
|
|
12
12
|
| [agent-guidance](agent-guidance/) | Switch between Claude/Codex/Gemini with model-specific guidance (CLAUDE.md, CODEX.md, GEMINI.md) |
|
|
13
13
|
| [/usage](usage-extension/) | 📊 Usage statistics dashboard. See cost, tokens, and messages by provider/model across Today, This Week, Last Week, and All Time — with a compact view for narrow terminals |
|
|
14
14
|
| [/paste](raw-paste/) | Paste editable text, not [paste #1 +21 lines]. Running `/paste` with optional keybinding |
|
|
@@ -21,7 +21,7 @@ Personal extensions for the [Pi coding agent](https://github.com/badlogic/pi-mon
|
|
|
21
21
|
|-------|-------------|
|
|
22
22
|
| [extending-pi](extending-pi/) | Guide for extending Pi — decide between skills, extensions, prompt templates, themes, or packages. |
|
|
23
23
|
| ↳ [skill-creator](extending-pi/skill-creator/) | Detailed guidance for creating Pi skills. |
|
|
24
|
-
| [ralph-wiggum](ralph-wiggum/) | Skill instructions for long-running development loops. |
|
|
24
|
+
| [pi-ralph-wiggum](pi-ralph-wiggum/) | Skill instructions for long-running development loops. |
|
|
25
25
|
|
|
26
26
|
## Install (pi package manager)
|
|
27
27
|
|
|
@@ -56,7 +56,7 @@ If you keep a local clone, add extensions to your `~/.pi/agent/settings.json`:
|
|
|
56
56
|
"~/pi-extensions/arcade/picman.ts",
|
|
57
57
|
"~/pi-extensions/arcade/tetris.ts",
|
|
58
58
|
"~/pi-extensions/arcade/mario-not/mario-not.ts",
|
|
59
|
-
"~/pi-extensions/ralph-wiggum",
|
|
59
|
+
"~/pi-extensions/pi-ralph-wiggum",
|
|
60
60
|
"~/pi-extensions/agent-guidance/agent-guidance.ts",
|
|
61
61
|
"~/pi-extensions/raw-paste",
|
|
62
62
|
"~/pi-extensions/code-actions",
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this extension will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- Make the inline comment editor multiline with wrapped footer rendering, `Enter` for a new line, and `Ctrl+Enter`/`Ctrl+D` to send.
|
|
9
|
+
|
|
5
10
|
## [0.1.16] - 2026-04-19
|
|
6
11
|
|
|
7
12
|
### Fixed
|
package/files-widget/README.md
CHANGED
|
@@ -117,6 +117,8 @@ If missing, `/review` or `/diff` will show a clear install prompt.
|
|
|
117
117
|
- `n` / `N`: next/prev match
|
|
118
118
|
- `v`: select mode (line selection)
|
|
119
119
|
- `c`: comment on selected lines (inline prompt)
|
|
120
|
+
- `Enter`: new line in the comment editor
|
|
121
|
+
- `Ctrl+Enter` or `Ctrl+D`: send the comment (`Alt+Enter` also works when supported)
|
|
120
122
|
- `]` / `[`: next/prev changed file
|
|
121
123
|
- `+` / `-`: increase/decrease viewer height
|
|
122
124
|
- `q`: back to browser
|
package/files-widget/TODO.md
CHANGED
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
|
|
67
67
|
### Comment Dialog
|
|
68
68
|
- [x] `c` to open comment input
|
|
69
|
-
- [
|
|
70
|
-
- [x] `Enter`
|
|
69
|
+
- [x] Multi-line text input
|
|
70
|
+
- [x] `Enter` for newline and `Ctrl+Enter` / `Ctrl+D` to confirm
|
|
71
71
|
- [x] `Esc` to cancel
|
|
72
72
|
|
|
73
73
|
### Send to Agent
|
|
@@ -4,17 +4,22 @@ const CONTROL_CHARS = /[\u0000-\u0008\u000B-\u001F\u007F]/g;
|
|
|
4
4
|
const BRACKETED_PASTE_START = "\u001b[200~";
|
|
5
5
|
const BRACKETED_PASTE_END = "\u001b[201~";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
interface SanitizeTextInputOptions {
|
|
8
|
+
preserveNewlines?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function sanitizeTextInput(data: string, options: SanitizeTextInputOptions = {}): string {
|
|
8
12
|
const normalized = decodeKittyPrintable(data) ?? data;
|
|
9
13
|
if (!normalized || normalized.includes("\u001b")) {
|
|
10
14
|
return "";
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
.replace(/\
|
|
16
|
-
.replace(/\t/g, " ")
|
|
17
|
-
|
|
17
|
+
const withNewlines = normalized.replace(/\r\n?/g, "\n");
|
|
18
|
+
const withoutTabs = options.preserveNewlines
|
|
19
|
+
? withNewlines.replace(/\t/g, " ")
|
|
20
|
+
: withNewlines.replace(/\n/g, " ").replace(/\t/g, " ");
|
|
21
|
+
|
|
22
|
+
return withoutTabs.replace(CONTROL_CHARS, "");
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
function getPendingStartSuffix(data: string): string {
|
|
@@ -33,7 +38,11 @@ export interface TextInputBuffer {
|
|
|
33
38
|
reset(): void;
|
|
34
39
|
}
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
interface TextInputBufferOptions {
|
|
42
|
+
preserveNewlines?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function createTextInputBuffer(options: TextInputBufferOptions = {}): TextInputBuffer {
|
|
37
46
|
let isInPaste = false;
|
|
38
47
|
let pasteBuffer = "";
|
|
39
48
|
let pendingStart = "";
|
|
@@ -52,14 +61,14 @@ export function createTextInputBuffer(): TextInputBuffer {
|
|
|
52
61
|
const pendingSuffix = getPendingStartSuffix(combined);
|
|
53
62
|
const completeText = pendingSuffix ? combined.slice(0, combined.length - pendingSuffix.length) : combined;
|
|
54
63
|
pendingStart = pendingSuffix;
|
|
55
|
-
return sanitizeTextInput(completeText);
|
|
64
|
+
return sanitizeTextInput(completeText, options);
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
const beforePaste = combined.slice(0, startIndex);
|
|
59
68
|
const afterStart = combined.slice(startIndex + BRACKETED_PASTE_START.length);
|
|
60
69
|
isInPaste = true;
|
|
61
70
|
pasteBuffer = "";
|
|
62
|
-
return sanitizeTextInput(beforePaste) + push(afterStart);
|
|
71
|
+
return sanitizeTextInput(beforePaste, options) + push(afterStart);
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
pasteBuffer += combined;
|
|
@@ -73,7 +82,7 @@ export function createTextInputBuffer(): TextInputBuffer {
|
|
|
73
82
|
isInPaste = false;
|
|
74
83
|
pasteBuffer = "";
|
|
75
84
|
|
|
76
|
-
return sanitizeTextInput(pastedText) + push(remaining);
|
|
85
|
+
return sanitizeTextInput(pastedText, options) + push(remaining);
|
|
77
86
|
};
|
|
78
87
|
|
|
79
88
|
return {
|
package/files-widget/viewer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { Key, matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
|
2
|
+
import { Key, matchesKey, truncateToWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";
|
|
3
3
|
import { readFileSync, statSync } from "node:fs";
|
|
4
4
|
import { relative } from "node:path";
|
|
5
5
|
|
|
@@ -14,6 +14,8 @@ import type { FileNode } from "./types";
|
|
|
14
14
|
import { isUntrackedStatus } from "./utils";
|
|
15
15
|
import { createTextInputBuffer } from "./input-utils";
|
|
16
16
|
|
|
17
|
+
const COMMENT_EDITOR_MAX_VISIBLE_LINES = 4;
|
|
18
|
+
|
|
17
19
|
export interface CommentPayload {
|
|
18
20
|
relPath: string;
|
|
19
21
|
lineRange: string;
|
|
@@ -61,7 +63,8 @@ export function createViewer(
|
|
|
61
63
|
theme: Theme,
|
|
62
64
|
requestComment: (payload: CommentPayload, comment: string) => void
|
|
63
65
|
): ViewerController {
|
|
64
|
-
const
|
|
66
|
+
const searchInput = createTextInputBuffer();
|
|
67
|
+
const commentInput = createTextInputBuffer({ preserveNewlines: true });
|
|
65
68
|
|
|
66
69
|
const state: ViewerState = {
|
|
67
70
|
file: null,
|
|
@@ -98,7 +101,8 @@ export function createViewer(
|
|
|
98
101
|
|
|
99
102
|
function setMode(mode: ViewerMode): void {
|
|
100
103
|
if (mode !== state.mode) {
|
|
101
|
-
|
|
104
|
+
searchInput.reset();
|
|
105
|
+
commentInput.reset();
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
state.mode = mode;
|
|
@@ -264,6 +268,38 @@ export function createViewer(
|
|
|
264
268
|
return truncateToWidth(header, width);
|
|
265
269
|
}
|
|
266
270
|
|
|
271
|
+
function renderCommentEditor(width: number): string[] {
|
|
272
|
+
const contentWidth = Math.max(1, width - 2);
|
|
273
|
+
const wrappedLines: string[] = [];
|
|
274
|
+
const logicalLines = state.commentText.split("\n");
|
|
275
|
+
|
|
276
|
+
for (const line of logicalLines) {
|
|
277
|
+
if (line.length === 0) {
|
|
278
|
+
wrappedLines.push("");
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
wrappedLines.push(...wrapTextWithAnsi(line, contentWidth));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (wrappedLines.length === 0) {
|
|
285
|
+
wrappedLines.push("");
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const lastIndex = wrappedLines.length - 1;
|
|
289
|
+
wrappedLines[lastIndex] = `${wrappedLines[lastIndex]}█`;
|
|
290
|
+
|
|
291
|
+
const overflow = Math.max(0, wrappedLines.length - COMMENT_EDITOR_MAX_VISIBLE_LINES);
|
|
292
|
+
const visibleLines = wrappedLines.slice(-COMMENT_EDITOR_MAX_VISIBLE_LINES);
|
|
293
|
+
if (overflow > 0 && visibleLines.length > 0) {
|
|
294
|
+
visibleLines[0] = `…${visibleLines[0]}`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return [
|
|
298
|
+
truncateToWidth(theme.fg("accent", "Comment:"), width),
|
|
299
|
+
...visibleLines.map(line => truncateToWidth(` ${line}`, width)),
|
|
300
|
+
];
|
|
301
|
+
}
|
|
302
|
+
|
|
267
303
|
function renderFooter(width: number): string[] {
|
|
268
304
|
const lines: string[] = [];
|
|
269
305
|
const pct = state.content.length > 0
|
|
@@ -271,14 +307,13 @@ export function createViewer(
|
|
|
271
307
|
: 0;
|
|
272
308
|
|
|
273
309
|
if (state.mode === "comment") {
|
|
274
|
-
|
|
275
|
-
lines.push(truncateToWidth(prompt, width));
|
|
310
|
+
lines.push(...renderCommentEditor(width));
|
|
276
311
|
lines.push(theme.fg("borderMuted", "─".repeat(width)));
|
|
277
312
|
}
|
|
278
313
|
|
|
279
314
|
let help: string;
|
|
280
315
|
if (state.mode === "comment") {
|
|
281
|
-
help = theme.fg("dim", "Enter: send Esc: cancel");
|
|
316
|
+
help = theme.fg("dim", "Enter: newline Ctrl+Enter/Ctrl+D: send Esc: cancel");
|
|
282
317
|
} else if (state.mode === "select") {
|
|
283
318
|
help = theme.fg("dim", "j/k: extend c: comment Esc: cancel");
|
|
284
319
|
} else if (state.mode === "search") {
|
|
@@ -363,19 +398,21 @@ export function createViewer(
|
|
|
363
398
|
if (!state.file) return { type: "none" };
|
|
364
399
|
|
|
365
400
|
if (state.mode === "comment") {
|
|
366
|
-
if (matchesKey(data,
|
|
401
|
+
if (matchesKey(data, "ctrl+enter") || matchesKey(data, "ctrl+d") || matchesKey(data, "alt+enter")) {
|
|
367
402
|
const comment = state.commentText.trim();
|
|
368
403
|
if (comment) {
|
|
369
404
|
sendComment(comment);
|
|
370
405
|
} else {
|
|
371
406
|
setMode("normal");
|
|
372
407
|
}
|
|
408
|
+
} else if (matchesKey(data, Key.enter) || matchesKey(data, "shift+enter")) {
|
|
409
|
+
state.commentText += "\n";
|
|
373
410
|
} else if (matchesKey(data, Key.escape)) {
|
|
374
411
|
setMode("normal");
|
|
375
412
|
} else if (matchesKey(data, Key.backspace)) {
|
|
376
413
|
state.commentText = state.commentText.slice(0, -1);
|
|
377
414
|
} else {
|
|
378
|
-
const text =
|
|
415
|
+
const text = commentInput.push(data);
|
|
379
416
|
if (text) {
|
|
380
417
|
state.commentText += text;
|
|
381
418
|
}
|
|
@@ -392,7 +429,7 @@ export function createViewer(
|
|
|
392
429
|
state.searchQuery = state.searchQuery.slice(0, -1);
|
|
393
430
|
updateSearchMatches();
|
|
394
431
|
} else {
|
|
395
|
-
const text =
|
|
432
|
+
const text = searchInput.push(data);
|
|
396
433
|
if (text) {
|
|
397
434
|
state.searchQuery += text;
|
|
398
435
|
updateSearchMatches();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extensions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"keywords": [
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"./code-actions/index.ts",
|
|
18
18
|
"./files-widget/index.ts",
|
|
19
19
|
"./raw-paste/index.ts",
|
|
20
|
-
"./ralph-wiggum/index.ts",
|
|
20
|
+
"./pi-ralph-wiggum/index.ts",
|
|
21
21
|
"./tab-status/tab-status.ts",
|
|
22
22
|
"./usage-extension/index.ts"
|
|
23
23
|
],
|
|
24
24
|
"skills": [
|
|
25
25
|
"./extending-pi/SKILL.md",
|
|
26
26
|
"./extending-pi/skill-creator/SKILL.md",
|
|
27
|
-
"./ralph-wiggum/SKILL.md"
|
|
27
|
+
"./pi-ralph-wiggum/SKILL.md"
|
|
28
28
|
]
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 - 2026-04-19
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **BREAKING:** SKILL.md `name` renamed `ralph-wiggum` → `pi-ralph-wiggum` to match the parent directory (both in the repo and after `pi install npm:@tmustier/pi-ralph-wiggum`). This removes the `[Skill conflicts]` warning pi emitted on every startup, but it also changes the skill's public identifier — explicit invocations must now use `/skill:pi-ralph-wiggum` instead of `/skill:ralph-wiggum`. Thanks to @ishanmalik for reporting ([#12](https://github.com/tmustier/pi-extensions/issues/12)).
|
|
7
|
+
- Repo directory renamed `ralph-wiggum/` → `pi-ralph-wiggum/` as part of the same fix. Git-source users referencing `~/pi-extensions/ralph-wiggum/…` in their pi config should update the path to `~/pi-extensions/pi-ralph-wiggum/…`. The npm package name (`@tmustier/pi-ralph-wiggum`) is unchanged.
|
|
8
|
+
- Renamed the README's `Install` section to `Installation` so it matches the skill validator's expectations.
|
|
9
|
+
|
|
10
|
+
## 0.1.7 - 2026-04-19
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Ralph loops no longer silently stop after auto-compaction or `/compact`. On session reload, `currentLoop` is now rehydrated from the on-disk state (most-recently-updated active loop wins on ties), so `ralph_done`, `agent_end`, and `before_agent_start` continue to function. Thanks to @elecnix for the detailed report and proposed fix ([#11](https://github.com/tmustier/pi-extensions/issues/11)).
|
|
14
|
+
|
|
15
|
+
## 0.1.5 - 2026-02-03
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Add preview image metadata for the extension listing.
|
|
19
|
+
|
|
20
|
+
## 0.1.4 - 2026-02-02
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- **BREAKING:** Updated tool execute signatures for Pi v0.51.0 compatibility (`signal` parameter now comes before `onUpdate`)
|
|
24
|
+
- **BREAKING:** Changed `before_agent_start` handler to use `systemPrompt` instead of deprecated `systemPromptAppend` (Pi v0.39.0+)
|
|
25
|
+
|
|
26
|
+
## 0.1.3 - 2026-01-26
|
|
27
|
+
- Added note clarifying this is a flat version without subagents.
|
|
28
|
+
|
|
29
|
+
## 0.1.1 - 2026-01-25
|
|
30
|
+
- Clarified that agents must write the task file themselves (tool does not auto-create it).
|
|
31
|
+
|
|
32
|
+
## 0.1.0 - 2026-01-13
|
|
33
|
+
- Initial release.
|
|
@@ -10,7 +10,7 @@ This one is cool because:
|
|
|
10
10
|
|
|
11
11
|
**Note: This is a flat version without subagents, similar to the [Anthropic plugins implementation](https://github.com/anthropics/claude-code-plugins/tree/main/ralph-loop).**
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Installation
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
pi install npm:@tmustier/pi-ralph-wiggum
|
|
@@ -27,8 +27,8 @@ Then filter to just this extension in `~/.pi/agent/settings.json`:
|
|
|
27
27
|
"packages": [
|
|
28
28
|
{
|
|
29
29
|
"source": "git:github.com/tmustier/pi-extensions",
|
|
30
|
-
"extensions": ["ralph-wiggum/index.ts"],
|
|
31
|
-
"skills": ["ralph-wiggum/SKILL.md"]
|
|
30
|
+
"extensions": ["pi-ralph-wiggum/index.ts"],
|
|
31
|
+
"skills": ["pi-ralph-wiggum/SKILL.md"]
|
|
32
32
|
}
|
|
33
33
|
]
|
|
34
34
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: ralph-wiggum
|
|
2
|
+
name: pi-ralph-wiggum
|
|
3
3
|
description: Long-running iterative development loops with pacing control and verifiable progress. Use when tasks require multiple iterations, many discrete steps, or periodic reflection with clear checkpoints; avoid for simple one-shot tasks or quick fixes.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -92,6 +92,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
function safeMtimeMs(filePath: string): number {
|
|
96
|
+
try {
|
|
97
|
+
return fs.statSync(filePath).mtimeMs;
|
|
98
|
+
} catch {
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
function tryRemoveDir(dirPath: string): boolean {
|
|
96
104
|
try {
|
|
97
105
|
if (fs.existsSync(dirPath)) {
|
|
@@ -784,6 +792,21 @@ Examples:
|
|
|
784
792
|
|
|
785
793
|
pi.on("session_start", async (_event, ctx) => {
|
|
786
794
|
const active = listLoops(ctx).filter((l) => l.status === "active");
|
|
795
|
+
|
|
796
|
+
// Rehydrate currentLoop from disk. The module is re-initialized on
|
|
797
|
+
// session reload (including auto-compaction and /compact), which would
|
|
798
|
+
// otherwise leave `currentLoop` null and silently break ralph_done,
|
|
799
|
+
// agent_end, and before_agent_start. Pick the most-recently-updated
|
|
800
|
+
// active loop when there are multiple, using the state file mtime.
|
|
801
|
+
if (!currentLoop && active.length > 0) {
|
|
802
|
+
const mostRecent = active.reduce((best, candidate) => {
|
|
803
|
+
const bestMtime = safeMtimeMs(getPath(ctx, best.name, ".state.json"));
|
|
804
|
+
const candidateMtime = safeMtimeMs(getPath(ctx, candidate.name, ".state.json"));
|
|
805
|
+
return candidateMtime > bestMtime ? candidate : best;
|
|
806
|
+
});
|
|
807
|
+
currentLoop = mostRecent.name;
|
|
808
|
+
}
|
|
809
|
+
|
|
787
810
|
if (active.length > 0 && ctx.hasUI) {
|
|
788
811
|
const lines = active.map(
|
|
789
812
|
(l) => ` • ${l.name} (iteration ${l.iteration}${l.maxIterations > 0 ? `/${l.maxIterations}` : ""})`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tmustier/pi-ralph-wiggum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Long-running agent loops for iterative development in Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Thomas Mustier",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "git+https://github.com/tmustier/pi-extensions.git",
|
|
13
|
-
"directory": "ralph-wiggum"
|
|
13
|
+
"directory": "pi-ralph-wiggum"
|
|
14
14
|
},
|
|
15
15
|
"bugs": "https://github.com/tmustier/pi-extensions/issues",
|
|
16
|
-
"homepage": "https://github.com/tmustier/pi-extensions/tree/main/ralph-wiggum",
|
|
16
|
+
"homepage": "https://github.com/tmustier/pi-extensions/tree/main/pi-ralph-wiggum",
|
|
17
17
|
"pi": {
|
|
18
18
|
"extensions": [
|
|
19
19
|
"index.ts"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.1.5 - 2026-02-03
|
|
4
|
-
|
|
5
|
-
### Added
|
|
6
|
-
- Add preview image metadata for the extension listing.
|
|
7
|
-
|
|
8
|
-
## 0.1.4 - 2026-02-02
|
|
9
|
-
|
|
10
|
-
### Changed
|
|
11
|
-
- **BREAKING:** Updated tool execute signatures for Pi v0.51.0 compatibility (`signal` parameter now comes before `onUpdate`)
|
|
12
|
-
- **BREAKING:** Changed `before_agent_start` handler to use `systemPrompt` instead of deprecated `systemPromptAppend` (Pi v0.39.0+)
|
|
13
|
-
|
|
14
|
-
## 0.1.3 - 2026-01-26
|
|
15
|
-
- Added note clarifying this is a flat version without subagents.
|
|
16
|
-
|
|
17
|
-
## 0.1.1 - 2026-01-25
|
|
18
|
-
- Clarified that agents must write the task file themselves (tool does not auto-create it).
|
|
19
|
-
|
|
20
|
-
## 0.1.0 - 2026-01-13
|
|
21
|
-
- Initial release.
|
|
File without changes
|