pi-recurse 0.1.2 → 0.1.4
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/package.json +4 -3
- package/skills/recurse/SKILL.md +90 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-recurse",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Recursive agent extension for Pi — spawn subagents programmatically with depth guardrails",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Tom X Nguyen",
|
|
@@ -29,12 +29,14 @@
|
|
|
29
29
|
"*.d.ts",
|
|
30
30
|
"lib/**",
|
|
31
31
|
"tests/**",
|
|
32
|
+
"skills/**",
|
|
32
33
|
"README.md",
|
|
33
34
|
"CHANGELOG.md"
|
|
34
35
|
],
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@commitlint/cli": "21.0.1",
|
|
37
38
|
"@commitlint/config-conventional": "21.0.1",
|
|
39
|
+
"@earendil-works/pi-tui": "0.84.1",
|
|
38
40
|
"@types/node": "25.9.1",
|
|
39
41
|
"@vitest/coverage-v8": "4.1.7",
|
|
40
42
|
"knip": "6.14.1",
|
|
@@ -43,8 +45,7 @@
|
|
|
43
45
|
"simple-git-hooks": "2.13.1",
|
|
44
46
|
"standard-version": "9.5.0",
|
|
45
47
|
"typescript": "6.0.3",
|
|
46
|
-
"vitest": "4.1.7"
|
|
47
|
-
"@earendil-works/pi-tui": "0.83.0"
|
|
48
|
+
"vitest": "4.1.7"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@earendil-works/pi-coding-agent": ">=0.74.0",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recurse
|
|
3
|
+
description: Use the `recurse` tool for programmatic subagent delegation. Supports single, parallel, and chain modes for large file processing, batch analysis, and sequential pipelines.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Recurse Skill
|
|
7
|
+
|
|
8
|
+
Use the `recurse` tool for programmatic subagent delegation.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- **Large files** that exceed context window → chunk and recurse
|
|
13
|
+
- **Batch analysis** of multiple files → parallel mode
|
|
14
|
+
- **Sequential pipelines** where step N depends on step N-1 → chain mode
|
|
15
|
+
- **Divide-and-conquer** refactoring → parallel tasks per file
|
|
16
|
+
|
|
17
|
+
## Mode Selection Guide
|
|
18
|
+
|
|
19
|
+
| Situation | Mode | Why |
|
|
20
|
+
|-----------|------|-----|
|
|
21
|
+
| One specific task | `single` | Simplest, direct |
|
|
22
|
+
| 10+ independent file reviews | `parallel` | Concurrent, fastest |
|
|
23
|
+
| Summary → Analysis → Plan | `chain` | Each step needs prior output |
|
|
24
|
+
| Cross-file refactoring | `parallel` with per-file tasks | Divide work, combine results |
|
|
25
|
+
|
|
26
|
+
## Example Patterns
|
|
27
|
+
|
|
28
|
+
### Parallel File Analysis
|
|
29
|
+
```typescript
|
|
30
|
+
const files = await findFiles("src/**/*.ts");
|
|
31
|
+
const results = await recurse({
|
|
32
|
+
mode: "parallel",
|
|
33
|
+
tasks: files.map(f => ({
|
|
34
|
+
id: f,
|
|
35
|
+
prompt: `Review ${f}: identify bugs, suggest improvements. Be concise.`
|
|
36
|
+
})),
|
|
37
|
+
concurrency: 4
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Aggregate
|
|
41
|
+
const issues = results.results.filter(r => r.output.includes("BUG"));
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Chain: Summarize → Analyze → Plan
|
|
45
|
+
```typescript
|
|
46
|
+
const plan = await recurse({
|
|
47
|
+
mode: "chain",
|
|
48
|
+
chain: [
|
|
49
|
+
{ id: "readme", prompt: "Summarize README.md in 3 bullet points" },
|
|
50
|
+
{ id: "risks", prompt: "Given this summary: {previous}, what are 3 implementation risks?" },
|
|
51
|
+
{ id: "mitigations", prompt: "Given these risks: {previous}, suggest mitigations for each" }
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Chunked Large File Processing
|
|
57
|
+
```typescript
|
|
58
|
+
const totalLines = await getLineCount("huge.log");
|
|
59
|
+
const chunkSize = 500;
|
|
60
|
+
const tasks = [];
|
|
61
|
+
|
|
62
|
+
for (let start = 1; start <= totalLines; start += chunkSize) {
|
|
63
|
+
const end = Math.min(start + chunkSize - 1, totalLines);
|
|
64
|
+
tasks.push({
|
|
65
|
+
id: `lines-${start}-${end}`,
|
|
66
|
+
prompt: `Extract ERROR entries from lines ${start}-${end}`,
|
|
67
|
+
context: await readLines("huge.log", start, end)
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const errors = await recurse({ mode: "parallel", tasks });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Guardrails
|
|
75
|
+
|
|
76
|
+
The extension automatically enforces limits:
|
|
77
|
+
- Max depth (default: 3)
|
|
78
|
+
- Max total calls (default: 100)
|
|
79
|
+
- Timeout (default: 600s)
|
|
80
|
+
- Budget (optional, via RLM_BUDGET)
|
|
81
|
+
|
|
82
|
+
At depth ≥ 3, the recurse tool is disabled. Work directly instead.
|
|
83
|
+
|
|
84
|
+
## Cost Awareness
|
|
85
|
+
|
|
86
|
+
Check result.stats after recurse calls:
|
|
87
|
+
```typescript
|
|
88
|
+
const result = await recurse({ mode: "parallel", tasks });
|
|
89
|
+
console.log(`Cost: $${result.stats.totalCost?.toFixed(4) || 'unknown'}`);
|
|
90
|
+
```
|