pi-goal-x 0.30.3 → 0.30.5
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/extensions/goal-events.ts +14 -4
- package/extensions/goal-format.ts +24 -5
- package/package.json +1 -1
|
@@ -174,7 +174,10 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
174
174
|
core.accountProgress(ctx, { completedTurnTokens: tokens });
|
|
175
175
|
|
|
176
176
|
if (isAbortedAssistantMessage(message)) {
|
|
177
|
-
|
|
177
|
+
// Pause only on a genuine user abort (signal fired). A provider- or
|
|
178
|
+
// transport-side abort without the signal routes into recovery via
|
|
179
|
+
// agent_end instead of stranding the goal.
|
|
180
|
+
if (ctx.signal?.aborted) core.pauseActiveGoal(ctx);
|
|
178
181
|
return;
|
|
179
182
|
}
|
|
180
183
|
// Provider failures are not completed work: do not turn one failed turn
|
|
@@ -266,7 +269,9 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
266
269
|
});
|
|
267
270
|
|
|
268
271
|
pi.on("message_end", async (event, ctx) => {
|
|
269
|
-
|
|
272
|
+
// Signal-aware: see turn_end — only user aborts pause; provider-side
|
|
273
|
+
// aborts are handled by agent_end's recovery path.
|
|
274
|
+
if (isAbortedAssistantMessage(event.message) && ctx.signal?.aborted) core.pauseActiveGoal(ctx);
|
|
270
275
|
const raw = asRecord(event.message);
|
|
271
276
|
if (raw?.role === "custom" && raw.customType === GOAL_EVENT_ENTRY && raw.display !== false) {
|
|
272
277
|
return { message: { ...event.message, display: false } as typeof event.message };
|
|
@@ -494,14 +499,19 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
494
499
|
if (!core.state.goal || core.state.goal.status !== "active" || !core.state.goal.autoContinue) return;
|
|
495
500
|
if (endedGoalId && core.state.goal.id !== endedGoalId) return;
|
|
496
501
|
if (!core.reconcileFocusedGoalFromDisk(ctx)) return;
|
|
497
|
-
|
|
502
|
+
// A genuine user abort pauses the goal. An assistant message with
|
|
503
|
+
// stopReason "aborted" WITHOUT a user abort signal is a provider- or
|
|
504
|
+
// transport-side termination (e.g. after Pi exhausts its retries) —
|
|
505
|
+
// pausing there stranded goals during outages, so it routes into the
|
|
506
|
+
// same bounded recovery as classified transient errors instead.
|
|
507
|
+
if (ctx.signal?.aborted) {
|
|
498
508
|
core.pauseActiveGoal(ctx);
|
|
499
509
|
return;
|
|
500
510
|
}
|
|
501
511
|
// Provider failures are not completed work: persist and refresh the
|
|
502
512
|
// display, but never queue a continuation for a run whose messages
|
|
503
513
|
// include an assistant error (danim47c pattern).
|
|
504
|
-
if (hasNetworkErrorAssistantMessage(event.messages)) {
|
|
514
|
+
if (hasNetworkErrorAssistantMessage(event.messages) || hasAbortedAssistantMessage(event.messages)) {
|
|
505
515
|
core.persist(ctx);
|
|
506
516
|
core.updateUI(ctx);
|
|
507
517
|
networkErrorRecoveryAfterSettleFor = core.state.goal.id;
|
|
@@ -228,16 +228,20 @@ export function isErrorAssistantMessage(message: unknown): boolean {
|
|
|
228
228
|
|
|
229
229
|
/**
|
|
230
230
|
* Transient provider failures are safe for goal-level recovery backoff:
|
|
231
|
-
* Pi-declared network errors plus HTTP 5xx-style outages surfaced by
|
|
232
|
-
* providers (503 server_error, "Endpoint is unavailable",
|
|
233
|
-
* gateway failures). Deliberately excludes
|
|
234
|
-
*
|
|
231
|
+
* Pi-declared network errors plus HTTP 429/5xx-style outages surfaced by
|
|
232
|
+
* providers (429 rate limits, 503 server_error, "Endpoint is unavailable",
|
|
233
|
+
* overloaded, gateway failures). Deliberately excludes auth and
|
|
234
|
+
* malformed-request failures (and quota/billing text), which retrying
|
|
235
|
+
* cannot fix.
|
|
235
236
|
*/
|
|
236
237
|
const TRANSIENT_PROVIDER_ERROR_RE = new RegExp(
|
|
237
238
|
[
|
|
238
239
|
"\\bnetwork[_\\s-]?error\\b",
|
|
239
240
|
"\\bserver[_\\s]?error\\b",
|
|
240
|
-
"\\b(?:502|503|504|529)\\b",
|
|
241
|
+
"\\b(?:429|502|503|504|529)\\b",
|
|
242
|
+
"\\brate[_\\s-]?limited\\b",
|
|
243
|
+
"\\brate[_\\s-]?limit\\b",
|
|
244
|
+
"\\btoo many requests\\b",
|
|
241
245
|
"\\bservice unavailable\\b",
|
|
242
246
|
"\\bbad gateway\\b",
|
|
243
247
|
"\\bgateway timeout\\b",
|
|
@@ -248,6 +252,19 @@ const TRANSIENT_PROVIDER_ERROR_RE = new RegExp(
|
|
|
248
252
|
"i",
|
|
249
253
|
);
|
|
250
254
|
|
|
255
|
+
/** Quota/billing exhaustion is deterministic; retrying cannot fix it. */
|
|
256
|
+
const NON_TRANSIENT_PROVIDER_ERROR_RE = new RegExp(
|
|
257
|
+
[
|
|
258
|
+
"\\binsufficient[_\\s]?quota\\b",
|
|
259
|
+
"\\bout of budget\\b",
|
|
260
|
+
"\\bquota exceeded\\b",
|
|
261
|
+
"\\bbilling\\b",
|
|
262
|
+
"GoUsageLimitError",
|
|
263
|
+
"FreeUsageLimitError",
|
|
264
|
+
].join("|"),
|
|
265
|
+
"i",
|
|
266
|
+
);
|
|
267
|
+
|
|
251
268
|
/** A transient provider failure is safe for the bounded goal backoff. */
|
|
252
269
|
export function isNetworkErrorAssistantMessage(message: unknown): boolean {
|
|
253
270
|
if (!isErrorAssistantMessage(message)) return false;
|
|
@@ -255,6 +272,8 @@ export function isNetworkErrorAssistantMessage(message: unknown): boolean {
|
|
|
255
272
|
const details = [raw?.rawStopReason, raw?.errorMessage]
|
|
256
273
|
.filter((value): value is string => typeof value === "string")
|
|
257
274
|
.join(" ");
|
|
275
|
+
// Quota/billing exhaustion is deterministic and must never be retried.
|
|
276
|
+
if (NON_TRANSIENT_PROVIDER_ERROR_RE.test(details)) return false;
|
|
258
277
|
return TRANSIENT_PROVIDER_ERROR_RE.test(details);
|
|
259
278
|
}
|
|
260
279
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-x",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.5",
|
|
4
4
|
"description": "Goal mode extension for pi: durable long-running objectives, five model tools, structured tasks, independent completion audit, Sisyphus mode, auto-continue, and a status overlay.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "pi-goal-x contributors",
|