@monotykamary/pi-retry 0.3.6 → 0.3.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monotykamary/pi-retry",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
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",
package/retry.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  hasConnectionError,
7
7
  hasRetryableError,
8
8
  isNonRetryableError,
9
+ isSilencedError,
9
10
  hasMaxTokensStop,
10
11
  isAssistantMessage,
11
12
  getLastAssistantMessage,
@@ -191,7 +192,8 @@ export default function (pi: ExtensionAPI) {
191
192
  }
192
193
 
193
194
  // Log non-retryable errors so the user knows why we didn't retry
194
- if (isNonRetryableError(lastAssistant)) {
195
+ // (silenced errors are neither retried nor shown)
196
+ if (isNonRetryableError(lastAssistant) && !isSilencedError(lastAssistant)) {
195
197
  const errorMsg = lastAssistant.errorMessage || "Unknown error";
196
198
  ctx.ui.notify(`Non-retryable error (not retried): ${errorMsg.substring(0, 100)}`, "error");
197
199
  }
@@ -355,10 +357,16 @@ export default function (pi: ExtensionAPI) {
355
357
  // finishRun() after agent_end listeners return).
356
358
  await _agent.waitForIdle();
357
359
 
358
- // Fire-and-forget with .catch() as final safety net.
359
- // The continue() monkey-patch means the session can't collide
360
- // with us even if it tries — but .catch() is belt-and-suspenders.
361
- _agent.prompt([]).catch(() => {});
360
+ try {
361
+ // Await so _continueInProgress stays true for the full retry.
362
+ // The session's continue() is blocked (monkey-patch) and the
363
+ // session's _runAgentPrompt stays alive, keeping the UI
364
+ // "Working…" until the agent is actually done.
365
+ await _agent.prompt([]);
366
+ } catch {
367
+ // Ignore — if prompt throws, something else is driving.
368
+ // The session will handle it or report the error.
369
+ }
362
370
  } finally {
363
371
  _continueInProgress = false;
364
372
  }
@@ -75,6 +75,12 @@ const NON_RETRYABLE_PATTERNS = [
75
75
  /no\s*such\s*model/i,
76
76
  /model\s*does\s*not\s*exist/i,
77
77
  /unsupported\s*model/i,
78
+ /cannot continue from message role/i,
79
+ ];
80
+
81
+ // Errors that are non-retryable AND should be silently ignored (no notification)
82
+ const SILENCED_PATTERNS = [
83
+ /cannot continue from message role/i,
78
84
  ];
79
85
 
80
86
  // ── Type guard ──
@@ -124,6 +130,17 @@ export function isNonRetryableError(message: AgentMessage): boolean {
124
130
  return NON_RETRYABLE_PATTERNS.some(p => p.test(message.errorMessage));
125
131
  }
126
132
 
133
+ /**
134
+ * Returns true for errors that are non-retryable and should be silently
135
+ * ignored (no UI notification). These are provider-level refusals that
136
+ * the user cannot act on and that would only add noise.
137
+ */
138
+ export function isSilencedError(message: AgentMessage): boolean {
139
+ if (!isAssistantMessage(message)) return false;
140
+ if (message.stopReason !== "error" || !message.errorMessage) return false;
141
+ return SILENCED_PATTERNS.some(p => p.test(message.errorMessage));
142
+ }
143
+
127
144
  // ── Categorisation (for UI messages) ──
128
145
 
129
146
  export function getErrorCategory(errorMessage: string): '400-413' | 'credit' | 'connection' | 'builtin' | 'other' {