@mehdisadeghi/pi-retry 0.0.0-stage → 0.12.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 +410 -2
- package/package.json +66 -4
- package/retry.ts +1056 -0
- package/src/child-retry.ts +595 -0
- package/src/config.ts +494 -0
- package/src/error-patterns.ts +262 -0
- package/src/index.ts +11 -0
- package/src/retry-logic.ts +155 -0
- package/src/session-registry.ts +253 -0
- package/vitest.config.ts +15 -0
package/README.md
CHANGED
|
@@ -1,3 +1,411 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 🔄 pi-retry
|
|
4
|
+
|
|
5
|
+
**Automatic retry for every error in [pi](https://github.com/earendil-works/pi-coding-agent)**
|
|
6
|
+
|
|
7
|
+
_400/413, connection errors, credit errors, stream exhaustion — retry them all._
|
|
8
|
+
|
|
9
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
10
|
+
[](./LICENSE)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Pi 1.0 compatibility (0.10.4)
|
|
19
|
+
|
|
20
|
+
Tested with Pi **1.0.0**. Host-provided Pi packages and TypeBox are peers (`*`), not bundled runtime dependencies; development uses exact Pi 1.0.0 pins and host-compatible TypeBox where needed.
|
|
21
|
+
|
|
22
|
+
Verified the actual `AgentSession.bindExtensions` and `_prepareRetry` lifecycle, including child retry ownership, cancellation and native nested tools. No replacement retry dispatcher is introduced.
|
|
23
|
+
|
|
24
|
+
Run `bun run test:host` for the offline real-host load, native codemode/nested-call, module-identity and reload checks. Set `PI1_HOST_PACKAGE` to an installed Pi package directory to test that host explicitly; add `PI1_HOST_ENTRY=bundle` to check the bundled CLI runtime's constructors.
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
|
|
28
|
+
This extension automatically detects and retries **all** errors, forever, until you abort. There is no error blacklist and no failure cap: invalid API keys, missing models, quota/budget exhaustion and context overflow are retried like a socket hiccup.
|
|
29
|
+
|
|
30
|
+
| Error Type | Retry Behavior | Use Case |
|
|
31
|
+
|------------|----------------|----------|
|
|
32
|
+
| **Any error** (catch-all) | **Uncapped** exponential retry | Everything, including unknown errors |
|
|
33
|
+
| HTTP 400/413 | **Uncapped** with exponential backoff | Transient context overflow that might resolve |
|
|
34
|
+
| Credit / payment errors | **Uncapped** with exponential backoff | "Not Enough Credits", insufficient balance, 402 — top up and the retry loop auto-resumes |
|
|
35
|
+
| **Quota / session-limit / budget exhaustion** | **Retried** — labelled in `/retry status` | "You've hit your limit", `insufficient_quota`, "out of budget", suspended accounts |
|
|
36
|
+
| Invalid API key / unknown model | **Retried** — no exception | The key or model may be fixed mid-loop |
|
|
37
|
+
| Context overflow | **Retried** alongside SDK compaction | Oversized payload; either path can recover the turn |
|
|
38
|
+
| Connection errors | **Uncapped** with exponential backoff | Network hiccups, connection drops, socket errors, stream exhaustion |
|
|
39
|
+
| Max tokens (`stopReason: "length"`) | **Auto-continue** indefinitely with hidden continuation turns | Model hits output token limit mid-generation |
|
|
40
|
+
| Empty / think-only stop (`stopReason: "stop"` with no text or tool calls) | **Nudge once** with a hidden continuation, then give up | Model ends its turn with no usable output (Anthropic empty responses with end_turn, thinking-only turns) |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## The Problem
|
|
45
|
+
|
|
46
|
+
By default, pi has built-in retry for some errors (rate limits, 5xx, overloaded), but:
|
|
47
|
+
|
|
48
|
+
1. **400/413 errors** are treated as context overflow → triggers compaction but NO retry
|
|
49
|
+
2. **Connection errors** sometimes get only limited retries before giving up
|
|
50
|
+
3. **Credit errors** ("Not Enough Credits") are never retried
|
|
51
|
+
4. **Stream exhaustion** ("Max outbound streams") and other provider-specific errors are never retried
|
|
52
|
+
5. **Any unknown error** from a new provider is silently ignored
|
|
53
|
+
|
|
54
|
+
## The Solution
|
|
55
|
+
|
|
56
|
+
This extension provides automatic retry for all errors with configurable exponential backoff (2s → 4s → 8s → ... → 60s by default) and keeps retrying at the maximum delay forever.
|
|
57
|
+
|
|
58
|
+
**Philosophy: retry EVERYTHING, forever.** Nothing is excluded — not an invalid API key, not a missing model, not an exhausted quota. Only a user abort (ESC), fresh input, or a session change stops the loop.
|
|
59
|
+
|
|
60
|
+
**Features:**
|
|
61
|
+
- **Catch-all retry** — Any `stopReason: "error"` is retried, regardless of error message
|
|
62
|
+
- Automatic detection of 400/413, connection, credit, and stream exhaustion errors
|
|
63
|
+
- **Auto-continuation** when the model hits its max output tokens (`stopReason: "length"`) — indefinite, no cap, hidden from the TUI
|
|
64
|
+
- **No cutoff** — Keeps retrying at the maximum backoff until success, abort, or session change, with a notification explaining why
|
|
65
|
+
- Exponential backoff with configurable base delay, cap, and multiplier
|
|
66
|
+
- **Hidden triggers** — provider-valid custom messages use `display: false`, so retries do not add TUI clutter
|
|
67
|
+
- Manual controls via unified `/retry` command
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
### Option 1: Install via pi package (Recommended)
|
|
74
|
+
|
|
75
|
+
Install directly from GitHub as a pi package:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pi install https://github.com/monotykamary/pi-retry
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Or add to your `settings.json`:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"packages": [
|
|
86
|
+
"https://github.com/monotykamary/pi-retry"
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Option 2: Global Installation
|
|
92
|
+
|
|
93
|
+
Copy the extension to pi's global extensions directory:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cp retry.ts ~/.pi/agent/extensions/
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Option 3: Project-Local Installation
|
|
100
|
+
|
|
101
|
+
Copy to your project's `.pi/extensions/` directory:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
mkdir -p .pi/extensions
|
|
105
|
+
cp retry.ts .pi/extensions/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Option 4: Quick Test
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
pi -e ./retry.ts
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Usage
|
|
117
|
+
|
|
118
|
+
Once loaded, the extension **automatically** detects and retries all errors.
|
|
119
|
+
|
|
120
|
+
### Manual Controls
|
|
121
|
+
|
|
122
|
+
| Command | Description |
|
|
123
|
+
|---------|-------------|
|
|
124
|
+
| `/retry` | Manually trigger immediate retry (auto-detects: 400/413, credit, connection, max_tokens, or any other error) |
|
|
125
|
+
| `/retry status` | Show current retry diagnostics for all error types + continuation state |
|
|
126
|
+
| `/retry reset` | Reset all retry counters and state |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
The extension reads a `piRetry` object from Pi's settings files:
|
|
133
|
+
|
|
134
|
+
- `~/.pi/agent/settings.json` applies globally.
|
|
135
|
+
- `.pi/settings.json` overrides matching global values for the current project.
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"piRetry": {
|
|
140
|
+
"baseDelayMs": 10000,
|
|
141
|
+
"maxDelayMs": 3600000,
|
|
142
|
+
"multiplier": 2
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The example above waits 10 seconds before the first retry, doubles each delay, caps the delay at one hour, and keeps retrying at that cap until you abort. Supported values are:
|
|
148
|
+
|
|
149
|
+
| Setting | Default | Description |
|
|
150
|
+
|---------|---------|-------------|
|
|
151
|
+
| `baseDelayMs` | `2000` | Delay before the first retry, in milliseconds |
|
|
152
|
+
| `maxDelayMs` | `60000` | Maximum delay between retries, in milliseconds |
|
|
153
|
+
| `multiplier` | `2` | Exponential backoff multiplier; must be at least `1` |
|
|
154
|
+
| `messageFreeRetries` | `false` | Retry errors without a hidden retry message (see below) |
|
|
155
|
+
|
|
156
|
+
`piRetry` is separate from Pi's built-in `retry` object so the two retry policies do not share ambiguous settings. The extension disables Pi's native retry scheduler while it is loaded, while preserving Pi's compaction handling, so only one retry loop owns the backoff schedule.
|
|
157
|
+
|
|
158
|
+
Settings are read when the extension starts. Restart pi or use `/reload` after editing them.
|
|
159
|
+
|
|
160
|
+
### Message-free error retries (opt-in)
|
|
161
|
+
|
|
162
|
+
By default, each error retry queues a hidden `Retry the previous request.`
|
|
163
|
+
message, which stays in the model context and the session file. With
|
|
164
|
+
`"messageFreeRetries": true`, an automatic error retry instead waits out the
|
|
165
|
+
backoff inside the original prompt, then uses Pi's `agent_before_settle`
|
|
166
|
+
boundary to omit the failed response with a `context_edit` entry and continue
|
|
167
|
+
the unchanged context. The provider receives the same request again, and the
|
|
168
|
+
omission persists when the session is resumed. The failed response stays in
|
|
169
|
+
the raw session history.
|
|
170
|
+
|
|
171
|
+
- Max-token continuations, empty-stop nudges, and manual `/retry` still use
|
|
172
|
+
hidden messages, because they need a new user turn to continue.
|
|
173
|
+
- Escape, new input, the backoff schedule, and the retry cap work as before.
|
|
174
|
+
The prompt stays busy during the backoff, so input typed then is steered
|
|
175
|
+
into the run and cancels the pending retry.
|
|
176
|
+
- Requires Pi with the `agent_before_settle` boundary (0.87.0 or later). On
|
|
177
|
+
older Pi the extension warns once and keeps hidden retry messages.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## How It Works
|
|
182
|
+
|
|
183
|
+
1. **Listen to `agent_end` event** — Fires after each agent turn completes
|
|
184
|
+
2. **Check for any error** — Examine the last assistant message for `stopReason === "error"`
|
|
185
|
+
3. **Categorize for messaging** — Classify into 400/413, credit, connection, quota, or other for `/retry status` diagnostics (labelling only; it never gates retrying)
|
|
186
|
+
4. **Retry or continue with hidden turns** — Wait with exponential backoff, then trigger a provider-valid custom user turn via `pi.sendMessage()` with `display: false` and `triggerTurn: true` (with `messageFreeRetries`, error retries omit the failed response and continue instead)
|
|
187
|
+
5. **Valid provider context** — Hidden retry and continuation messages remain in context so providers never receive a trailing assistant message
|
|
188
|
+
6. **Indefinite continuation** — Max_tokens auto-continues are uncapped; repeated `length` stops keep producing continuation turns until the model terminates normally
|
|
189
|
+
7. **Empty-stop recovery** — A `stop` turn with no usable output (only thinking, or nothing at all) gets exactly one hidden "nudge" continuation, then gives up. Matches Anthropic's documented "empty responses with `end_turn`" remedy (continuation prompt in a new user message) — retrying an empty response in place doesn't help because the model has already decided it's done.
|
|
190
|
+
8. **Lifecycle exposure** — Emits `pi-retry:started`, `pi-retry:completed`, and `pi-retry:cancelled` on Pi's shared extension event bus with a matching `retryId`, allowing status integrations to suppress intermediate completion signals
|
|
191
|
+
|
|
192
|
+
The pi's built-in `transform-messages` already strips aborted/errored assistant messages from the LLM context, so the model never sees the failed attempts.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Detected Error Patterns
|
|
197
|
+
|
|
198
|
+
### Catch-All (Any Error)
|
|
199
|
+
- **Any** assistant message with `stopReason === "error"` is retried — nothing is excluded
|
|
200
|
+
- Unknown provider errors, stream errors, unexpected failures — all handled automatically
|
|
201
|
+
|
|
202
|
+
### Retried Like Everything Else
|
|
203
|
+
These used to be treated as permanent. They are now retried too, because the cause can disappear mid-loop (a key gets refreshed, a quota window rolls over, the context gets compacted):
|
|
204
|
+
- Invalid API key / invalid authentication / revoked or missing key
|
|
205
|
+
- Model not found / unknown model / unsupported model
|
|
206
|
+
- **Quota, session-limit and budget exhaustion** — "You've hit your limit · resets …" (Claude Code, Codex, ChatGPT plans), `insufficient_quota` (OpenAI), "You have exhausted your capacity on this model" (Gemini Code Assist), `free-models-per-day` (OpenRouter), "out of budget" (LiteLLM-style proxies), suspended accounts (Kimi)
|
|
207
|
+
- **Context overflow** — "prompt is too long", "exceeds the context window", and friends
|
|
208
|
+
|
|
209
|
+
These messages are still labelled `quota` in `/retry status`, so an endless retry loop tells you whether you are waiting on billing or on the network.
|
|
210
|
+
|
|
211
|
+
### Max Tokens (stopReason: "length")
|
|
212
|
+
- The model hit its `max_tokens` / output token limit
|
|
213
|
+
- The model's response was truncated mid-generation
|
|
214
|
+
- Auto-continuation sends a provider-valid custom message hidden from the TUI
|
|
215
|
+
|
|
216
|
+
### 400/413 Errors
|
|
217
|
+
- HTTP 400 Bad Request
|
|
218
|
+
- HTTP 413 Payload Too Large
|
|
219
|
+
- "bad request" messages
|
|
220
|
+
- "payload too large" messages
|
|
221
|
+
|
|
222
|
+
### Credit / Payment Errors
|
|
223
|
+
- "Not Enough Credits"
|
|
224
|
+
- "insufficient credits"
|
|
225
|
+
- "insufficient balance"
|
|
226
|
+
- "out of credits"
|
|
227
|
+
- "Payment Required"
|
|
228
|
+
- HTTP 402 status code
|
|
229
|
+
|
|
230
|
+
### Connection Errors
|
|
231
|
+
- Connection / network errors
|
|
232
|
+
- Fetch failures
|
|
233
|
+
- Socket hang up / socket errors
|
|
234
|
+
- `ECONNRESET`, `ECONNREFUSED`, `ETIMEDOUT`, `ENOTFOUND`
|
|
235
|
+
- DNS lookup failures
|
|
236
|
+
- "Request ended without sending any chunks"
|
|
237
|
+
- Upstream connect errors
|
|
238
|
+
- TLS handshake errors
|
|
239
|
+
- Timeouts awaiting response
|
|
240
|
+
- Stream exhaustion ("Max outbound streams is 100, 100 open")
|
|
241
|
+
- Stream limit errors
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Development
|
|
246
|
+
|
|
247
|
+
### Running Tests
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Run all tests
|
|
251
|
+
npm test
|
|
252
|
+
|
|
253
|
+
# Run tests in watch mode
|
|
254
|
+
npm run test:watch
|
|
255
|
+
|
|
256
|
+
# Run tests with coverage
|
|
257
|
+
npm run test:coverage
|
|
258
|
+
|
|
259
|
+
# Type check
|
|
260
|
+
npm run typecheck
|
|
261
|
+
|
|
262
|
+
# Dead code detection
|
|
263
|
+
npm run lint:dead
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Project Structure
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
.
|
|
270
|
+
├── retry.ts # Main unified extension
|
|
271
|
+
├── src/ # Shared utilities (testable, DRY)
|
|
272
|
+
│ ├── config.ts # Settings-backed retry configuration
|
|
273
|
+
│ ├── error-patterns.ts # Error pattern matching, custom types, hasMaxTokensStop
|
|
274
|
+
│ ├── retry-logic.ts # Retry utilities (calculateDelay, RetryState, ContinuationState, etc.)
|
|
275
|
+
│ └── index.ts # Barrel exports
|
|
276
|
+
├── __tests__/ # Unit tests
|
|
277
|
+
│ └── unit/
|
|
278
|
+
│ ├── config.test.ts
|
|
279
|
+
│ ├── error-patterns.test.ts
|
|
280
|
+
│ └── retry-logic.test.ts
|
|
281
|
+
├── vitest.config.ts # Test configuration
|
|
282
|
+
└── knip.json # Dead code detection config
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Code Quality
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Run all quality checks
|
|
289
|
+
npm test # 224 tests
|
|
290
|
+
npm run typecheck # TypeScript type checking
|
|
291
|
+
npm run lint:dead # Dead code detection with knip
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Troubleshooting
|
|
297
|
+
|
|
298
|
+
### Extension not working?
|
|
299
|
+
|
|
300
|
+
Check that it's loaded in the startup header:
|
|
301
|
+
```
|
|
302
|
+
Loaded extensions: retry.ts
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Retry not triggering?
|
|
306
|
+
|
|
307
|
+
Use the status command to diagnose:
|
|
308
|
+
```
|
|
309
|
+
/retry status
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Want to see what's happening?
|
|
313
|
+
|
|
314
|
+
The extensions send notifications on retry attempts. Look at the footer status line for retry status updates, and `/retry status` for the per-category attempt counters and the last error text.
|
|
315
|
+
|
|
316
|
+
### Too many retries?
|
|
317
|
+
|
|
318
|
+
Use `/retry reset` to clear the counters, or press `Ctrl+C` to abort the session.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Comparison with @georgebashi/pi-retry
|
|
323
|
+
|
|
324
|
+
The npm package `@georgebashi/pi-retry` handles "aborted" streaming errors but explicitly excludes "connection error" (assuming pi's built-in retry handles it). This extension:
|
|
325
|
+
|
|
326
|
+
1. **Handles ALL errors** via a catch-all — no more playing whack-a-mole with new error patterns
|
|
327
|
+
2. **Handles connection errors** that pi might not retry sufficiently
|
|
328
|
+
3. **Handles 400/413 errors** without compaction
|
|
329
|
+
4. **Handles credit errors** and stream exhaustion
|
|
330
|
+
|
|
331
|
+
They can work together for maximum coverage:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
pi install npm:@georgebashi/pi-retry
|
|
335
|
+
# Plus install this extension
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Limitations
|
|
341
|
+
|
|
342
|
+
- Pi's native retry scheduler is disabled while this extension is loaded so native and extension retries cannot interleave; Pi's compaction check still runs normally
|
|
343
|
+
- Error messages remain in the session history (but are invisible to the LLM)
|
|
344
|
+
- Every error class is retried, so a permanent-looking failure (invalid API key, exhausted quota, genuinely oversized context) keeps firing at the maximum backoff until the cause is fixed
|
|
345
|
+
- Escape aborts the loop; fresh input or `/new` also stops it
|
|
346
|
+
- **Warning**: Retrying 400/413 without reducing context may fail repeatedly if the payload is genuinely too large — run `/compact`
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Related
|
|
351
|
+
|
|
352
|
+
- [Pi Coding Agent Extensions Docs](https://github.com/badlogic/pi/tree/main/packages/coding-agent/docs/extensions.md)
|
|
353
|
+
- [@georgebashi/pi-retry](https://github.com/georgebashi/pi-retry) — Handles "aborted" streaming errors
|
|
354
|
+
- [Issue #252: Connection error with no retry](https://github.com/badlogic/pi-mono/issues/252)
|
|
355
|
+
|
|
356
|
+
## License
|
|
357
|
+
|
|
358
|
+
MIT
|
|
359
|
+
|
|
360
|
+
## Subagent retry policies
|
|
361
|
+
|
|
362
|
+
Sessions that should retry with a different policy can be selected by matching
|
|
363
|
+
their effective system prompt. This is user configuration: the extension ships
|
|
364
|
+
no built-in marker or identity check for any specific subagent tool.
|
|
365
|
+
|
|
366
|
+
```json
|
|
367
|
+
{
|
|
368
|
+
"piRetry": {
|
|
369
|
+
"subagents": {
|
|
370
|
+
"enabled": true,
|
|
371
|
+
"match": {
|
|
372
|
+
"systemPromptRegex": [
|
|
373
|
+
{
|
|
374
|
+
"pattern": "^<active_agent name=\"[^\"\\r\\n]+\"/>$",
|
|
375
|
+
"flags": "m"
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
"baseDelayMs": 1000,
|
|
380
|
+
"maxDelayMs": 10000
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Semantics:
|
|
387
|
+
|
|
388
|
+
- Sessions whose effective system prompt matches any listed rule use the
|
|
389
|
+
inline child policy; rules combine with OR.
|
|
390
|
+
- Omitted child fields inherit from the effective top-level policy, field by
|
|
391
|
+
field. Project matcher lists replace global ones.
|
|
392
|
+
- A matching rule with `enabled: false` leaves pi's native retry scheduler
|
|
393
|
+
untouched; a missing, empty, malformed, or nonmatching configuration keeps
|
|
394
|
+
the ordinary `pi-retry` takeover.
|
|
395
|
+
- Unmatched sessions in print or JSON mode (`pi -p`, `pi --mode json`, and SDK
|
|
396
|
+
hosts that bind extensions without a mode, such as pi-subagents children)
|
|
397
|
+
retry inline with the top-level policy, inside the original prompt. These
|
|
398
|
+
hosts read the result as soon as `prompt()` settles, so a detached retry
|
|
399
|
+
would arrive too late. A matcher is only needed for a different child policy
|
|
400
|
+
or for `enabled: false`.
|
|
401
|
+
- Patterns are compiled when settings resolve. Invalid syntax, unsupported or
|
|
402
|
+
duplicate flags, and malformed groups warn and become no-match instead of
|
|
403
|
+
matching everything.
|
|
404
|
+
- The extension must also be loaded in the target session (for pi-subagents
|
|
405
|
+
that means listing it in the child's `subagentOnlyExtensions`), not only in
|
|
406
|
+
the parent.
|
|
407
|
+
|
|
408
|
+
The example pattern above matches the `<active_agent name="…"/>` line that
|
|
409
|
+
`pi-subagents` prefixes to native child system prompts; substitute your own
|
|
410
|
+
marker if you select child sessions differently. Keep the `m` flag: some
|
|
411
|
+
children have a `<sub_agent_context>` block before that line.
|
package/package.json
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mehdisadeghi/pi-retry",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Extension suite for pi coding agent that handles 400/413 errors and connection errors with automatic retry",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Tom X Nguyen",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/monotykamary/pi-retry.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/monotykamary/pi-retry#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/monotykamary/pi-retry/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"pi-package",
|
|
18
|
+
"pi",
|
|
19
|
+
"pi-coding-agent",
|
|
20
|
+
"extension",
|
|
21
|
+
"retry",
|
|
22
|
+
"error-handling",
|
|
23
|
+
"http-400",
|
|
24
|
+
"http-413",
|
|
25
|
+
"connection-error",
|
|
26
|
+
"network-error",
|
|
27
|
+
"infinite-retry",
|
|
28
|
+
"cli"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"*.ts",
|
|
32
|
+
"src/",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test:host": "node scripts/pi1-host.mjs",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"test:coverage": "vitest run --coverage",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"lint:dead": "knip --no-gitignore"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@earendil-works/pi-agent-core": "*",
|
|
45
|
+
"@earendil-works/pi-ai": "*",
|
|
46
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
47
|
+
"@earendil-works/pi-tui": "*"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@earendil-works/pi-agent-core": "1.3.0",
|
|
51
|
+
"@earendil-works/pi-ai": "1.3.0",
|
|
52
|
+
"@earendil-works/pi-coding-agent": "1.3.0",
|
|
53
|
+
"@earendil-works/pi-tui": "1.3.0",
|
|
54
|
+
"@types/node": "25.9.1",
|
|
55
|
+
"@vitest/coverage-v8": "4.1.7",
|
|
56
|
+
"knip": "6.14.1",
|
|
57
|
+
"typescript": "6.0.3",
|
|
58
|
+
"vitest": "4.1.7"
|
|
59
|
+
},
|
|
60
|
+
"pi": {
|
|
61
|
+
"extensions": [
|
|
62
|
+
"./retry.ts"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"overrides": {
|
|
66
|
+
"brace-expansion": "5.0.12"
|
|
67
|
+
}
|
|
68
|
+
}
|