@monotykamary/pi-retry 0.3.9 → 0.3.10
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 +1 -1
- package/retry.ts +34 -9
package/package.json
CHANGED
package/retry.ts
CHANGED
|
@@ -58,8 +58,18 @@ Agent.prototype.subscribe = function (this: Agent, ...args: any[]) {
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
// Monkey-patch continue() so the session's built-in retry loop cooperates
|
|
61
|
-
// with our _continueInProgress mutex
|
|
62
|
-
//
|
|
61
|
+
// with our _continueInProgress mutex AND can convert the "Cannot continue
|
|
62
|
+
// from assistant" error into a prompt([]) call when the agent was mid-task.
|
|
63
|
+
//
|
|
64
|
+
// When continue() throws "Cannot continue from message role: assistant":
|
|
65
|
+
// - stopReason "stop" → agent finished cleanly, don't continue
|
|
66
|
+
// - stopReason "aborted" → user cancelled, don't continue
|
|
67
|
+
// - stopReason "error" → pi-retry IS the error handler, fall back to prompt([])
|
|
68
|
+
// so the retry actually happens (rather than swallowing and stalling)
|
|
69
|
+
// - stopReason "toolUse" or "length" → mid-task, fall back to prompt([])
|
|
70
|
+
//
|
|
71
|
+
// This ensures the agent loop actually continues after compaction instead
|
|
72
|
+
// of swallowing the error and letting the while-loop die.
|
|
63
73
|
const _origContinue = Agent.prototype.continue as (this: Agent) => Promise<unknown>;
|
|
64
74
|
Agent.prototype.continue = function (this: Agent) {
|
|
65
75
|
const self = this;
|
|
@@ -71,15 +81,30 @@ Agent.prototype.continue = function (this: Agent) {
|
|
|
71
81
|
try {
|
|
72
82
|
return await _origContinue.call(self);
|
|
73
83
|
} catch (e: any) {
|
|
74
|
-
// After pi-retry finishes, the transcript ends with a fresh
|
|
75
|
-
// assistant message. The session's continue() sees this and
|
|
76
|
-
// would throw "Cannot continue from an assistant message".
|
|
77
|
-
// Catch it — the while-loop will poll _handlePostAgentRun()
|
|
78
|
-
// again, find no error, and exit cleanly.
|
|
79
84
|
const msg = e?.message ?? '';
|
|
80
85
|
if (msg.includes('Cannot continue from message role') ||
|
|
81
|
-
msg.includes('Cannot continue from an assistant message')
|
|
82
|
-
|
|
86
|
+
msg.includes('Cannot continue from an assistant message')) {
|
|
87
|
+
// Check stopReason — only continue if the agent was mid-task
|
|
88
|
+
const lastMsg = self.state.messages[self.state.messages.length - 1];
|
|
89
|
+
if (lastMsg?.role === 'assistant' &&
|
|
90
|
+
lastMsg.stopReason !== 'stop' &&
|
|
91
|
+
lastMsg.stopReason !== 'aborted') {
|
|
92
|
+
// Agent was mid-task (toolUse, length, or error) — fall back to prompt([])
|
|
93
|
+
if (!_continueInProgress) {
|
|
94
|
+
_continueInProgress = true;
|
|
95
|
+
try {
|
|
96
|
+
await self.prompt([]);
|
|
97
|
+
} catch {
|
|
98
|
+
// Agent already processing or other transient error
|
|
99
|
+
} finally {
|
|
100
|
+
_continueInProgress = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// For stop/aborted: return void, the session loop exits naturally
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (msg.includes('Agent is already processing')) {
|
|
83
108
|
return;
|
|
84
109
|
}
|
|
85
110
|
throw e;
|