What do you want to change?
Forward willRetry to the extension-visible agent_end event too. Today AgentSession._handleAgentEvent computes willRetry and attaches it only to the internal _emit() used by session/RPC listeners — the payload passed to _emitExtensionEvent() one line earlier is the raw event, without it:
// packages/coding-agent/src/core/agent-session.ts (dist agent-session.js:346-349)
await this._emitExtensionEvent(event); // raw event, no willRetry
this._emit(event.type === "agent_end"
? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } // enriched, but only here
: event);
AgentEndEvent in extensions/types.ts has no willRetry field.
Why?
This is the same problem #4716 fixed, on the other consumer surface. #4716 gave session/RPC listeners agent_end.willRetry so they don't finalize while pi's own retry is still going to fire. Extensions have the identical problem and no signal: an agent_end handler that wants to react to a failed turn (switch model, alert, log) can't tell "pi will auto-retry this in 2-8s" from "pi has given up," so it either preempts pi's built-in retry or has to reconstruct the answer heuristically.
Two published extensions already work around this with a timer instead of a real signal, specifically because this field isn't there: cad0p/pi-fallback-provider waits 20s (longer than 3 retries' backoff) before acting; 99degree/pi-retry-fallback-model does something similar. I imagine both authors would prefer a clean signal rather than just guesswork.
How? (optional)
_willRetryAfterAgentEnd(event) is already computed once per agent_end. Reuse the same value for both emits instead of recomputing it only for _emit:
const willRetry = this._willRetryAfterAgentEnd(event);
await this._emitExtensionEvent(willRetry !== undefined ? { ...event, willRetry } : event);
this._emit(event.type === "agent_end" ? { ...event, willRetry } : event);
Add willRetry: boolean to AgentEndEvent in extensions/types.ts, mirroring the existing AgentSessionEvent.agent_end.willRetry shape from #4716.
Pure additive field, no behavior change for existing extensions. Have a local patch against 0.80.10 I can send as a PR if this gets lgtm.
What do you want to change?
Forward
willRetryto the extension-visibleagent_endevent too. TodayAgentSession._handleAgentEventcomputeswillRetryand attaches it only to the internal_emit()used by session/RPC listeners — the payload passed to_emitExtensionEvent()one line earlier is the raw event, without it:AgentEndEventinextensions/types.tshas nowillRetryfield.Why?
This is the same problem #4716 fixed, on the other consumer surface. #4716 gave session/RPC listeners
agent_end.willRetryso they don't finalize while pi's own retry is still going to fire. Extensions have the identical problem and no signal: anagent_endhandler that wants to react to a failed turn (switch model, alert, log) can't tell "pi will auto-retry this in 2-8s" from "pi has given up," so it either preempts pi's built-in retry or has to reconstruct the answer heuristically.Two published extensions already work around this with a timer instead of a real signal, specifically because this field isn't there:
cad0p/pi-fallback-providerwaits 20s (longer than 3 retries' backoff) before acting;99degree/pi-retry-fallback-modeldoes something similar. I imagine both authors would prefer a clean signal rather than just guesswork.How? (optional)
_willRetryAfterAgentEnd(event)is already computed once peragent_end. Reuse the same value for both emits instead of recomputing it only for_emit:Add
willRetry: booleantoAgentEndEventinextensions/types.ts, mirroring the existingAgentSessionEvent.agent_end.willRetryshape from #4716.Pure additive field, no behavior change for existing extensions. Have a local patch against 0.80.10 I can send as a PR if this gets
lgtm.