@monotykamary/pi-retry 0.6.3 → 0.6.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 +3 -3
- package/retry.ts +30 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monotykamary/pi-retry",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Extension suite for pi coding agent that handles 400/413 errors and connection errors with automatic retry",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Tom X Nguyen",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
37
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
36
|
+
"@earendil-works/pi-agent-core": "^0.80.7",
|
|
37
|
+
"@earendil-works/pi-coding-agent": "^0.80.7",
|
|
38
38
|
"@types/node": "25.9.1",
|
|
39
39
|
"@vitest/coverage-v8": "4.1.7",
|
|
40
40
|
"knip": "6.14.1",
|
package/retry.ts
CHANGED
|
@@ -168,6 +168,8 @@ let _userAborted = false;
|
|
|
168
168
|
// automatic retry) race through waitForIdle() and both call prompt([]),
|
|
169
169
|
// producing "Agent is already processing".
|
|
170
170
|
let _continueInProgress = false;
|
|
171
|
+
// Session generation that owns the retry mutex and its Escape handler.
|
|
172
|
+
let _continueGeneration: number | null = null;
|
|
171
173
|
|
|
172
174
|
// Timestamp of the last completed triggerInvisibleContinue().
|
|
173
175
|
// Used by the continue() monkey-patch to avoid double continuation when
|
|
@@ -179,6 +181,8 @@ let _lastInvisibleContinueTime = 0;
|
|
|
179
181
|
// when it changes — this handles /new and other session switches.
|
|
180
182
|
let _sessionGeneration = 0;
|
|
181
183
|
|
|
184
|
+
let _terminalInputUnsubscribe: (() => void) | null = null;
|
|
185
|
+
|
|
182
186
|
// Interruptible sleep: polls _userAborted and _sessionGeneration every
|
|
183
187
|
// 100ms. Returns true if interrupted (abort or session change), false if
|
|
184
188
|
// the full delay elapsed normally.
|
|
@@ -501,7 +505,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
501
505
|
});
|
|
502
506
|
|
|
503
507
|
// Initialize
|
|
504
|
-
pi.on("session_start", async () => {
|
|
508
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
505
509
|
// Bump the generation counter so any in-flight retry loop from a
|
|
506
510
|
// previous session exits on its next checkpoint (within 100ms during
|
|
507
511
|
// backoff sleep, or immediately after prompt([]) returns).
|
|
@@ -513,11 +517,29 @@ export default function (pi: ExtensionAPI) {
|
|
|
513
517
|
stateOther.reset();
|
|
514
518
|
stateContinuation.reset();
|
|
515
519
|
// Do NOT reset _continueInProgress here — the in-flight loop's
|
|
516
|
-
// finally block
|
|
517
|
-
//
|
|
518
|
-
// break the mutex invariant and could allow a second loop to start.
|
|
520
|
+
// finally block releases its owner token. Resetting it here could allow
|
|
521
|
+
// a second loop to start before the old one has settled.
|
|
519
522
|
_lastInvisibleContinueTime = 0;
|
|
520
523
|
_userAborted = false;
|
|
524
|
+
|
|
525
|
+
_terminalInputUnsubscribe?.();
|
|
526
|
+
_terminalInputUnsubscribe = null;
|
|
527
|
+
|
|
528
|
+
if (ctx.mode === "tui") {
|
|
529
|
+
_terminalInputUnsubscribe = ctx.ui.onTerminalInput(data => {
|
|
530
|
+
if (
|
|
531
|
+
data !== "\x1b" ||
|
|
532
|
+
!_continueInProgress ||
|
|
533
|
+
_continueGeneration !== _sessionGeneration
|
|
534
|
+
) {
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
_userAborted = true;
|
|
539
|
+
ctx.abort();
|
|
540
|
+
return { consume: true };
|
|
541
|
+
});
|
|
542
|
+
}
|
|
521
543
|
});
|
|
522
544
|
|
|
523
545
|
// Retry loop driver — the core of pi-retry.
|
|
@@ -548,6 +570,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
548
570
|
// Capture the current session generation. If /new fires while we're
|
|
549
571
|
// looping, _sessionGeneration will increment and the loop will exit.
|
|
550
572
|
const myGeneration = _sessionGeneration;
|
|
573
|
+
_continueGeneration = myGeneration;
|
|
551
574
|
|
|
552
575
|
try {
|
|
553
576
|
// Wait for the current run to finish (activeRun resolves in
|
|
@@ -602,11 +625,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
602
625
|
// Error again — loop back for another attempt.
|
|
603
626
|
}
|
|
604
627
|
} finally {
|
|
605
|
-
//
|
|
606
|
-
|
|
607
|
-
// mutex — resetting it here would clobber that.
|
|
608
|
-
if (_sessionGeneration === myGeneration) {
|
|
628
|
+
// Release the mutex only if this loop still owns it.
|
|
629
|
+
if (_continueGeneration === myGeneration) {
|
|
609
630
|
_continueInProgress = false;
|
|
631
|
+
_continueGeneration = null;
|
|
610
632
|
}
|
|
611
633
|
_lastInvisibleContinueTime = Date.now();
|
|
612
634
|
}
|