pi-better-goal 0.10.2 → 0.10.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/README.md CHANGED
@@ -14,7 +14,7 @@ Use `pi-better-goal` when a Pi session should keep an explicit objective visible
14
14
 
15
15
  - `/goal` runtime for starting, pausing, resuming, completing, and clearing the current objective.
16
16
  - `/goal settings` opens an interactive settings page in the TUI. Select a row with Up/Down and toggle with Space/Enter; changes save immediately, and Escape closes the page. All three controls default to `on`. Automatic continuation controls idle and background-drain wakes; conversational resume controls the agent's Escape-pause resume tool; **Pause on Esc** controls whether editor Escape pauses the active goal. Goal kickoff, `/goal resume`, and `alt+g` remain available with these controls off. For scripts or non-interactive sessions, use `/goal settings auto-continue on|off`, `/goal settings conversational-resume on|off`, and `/goal settings pause-on-escape on|off`; bare `/goal settings` prints the saved values outside the TUI.
17
- - `escape` pauses the active goal by default, and it stays paused while you talk to the agent. With **Pause on Esc** off, observed editor Escape leaves the goal active while preserving native streaming interruption and menu/dialog cancellation. Automatic continuation remains independent. Hosts without terminal/focus inspection and unknown custom editors retain generic abort-to-pause behavior because they cannot identify Escape reliably. With conversational resume enabled, say "go" (the agent then calls `goal_resume`), or use `/goal resume` or `alt+g`. `/goal pause` resumes only through `/goal resume` or `alt+g`. The status line shows the available resume path, and paused goals are never poked. On a macOS terminal without Option-as-Meta, `alt+g` types `©`; use `/goal resume` there.
17
+ - `escape` pauses the active goal by default, and it stays paused while you talk to the agent. With **Pause on Esc** off, observed editor Escape leaves the goal active while preserving native streaming interruption and menu/dialog cancellation. Automatic continuation remains independent. Hosts without terminal/focus inspection and unknown custom editors retain generic abort-to-pause behavior because they cannot identify Escape reliably. With conversational resume enabled, say "go" (the agent then calls `goal_resume`), or use `/goal resume` or `alt+g`. `/goal pause` resumes only through `/goal resume` or `alt+g`. Paused goals are never poked. On a macOS terminal without Option-as-Meta, `alt+g` types `©`; use `/goal resume` there.
18
18
  - Background work that finishes while an `ask_user_question` is pending is handed to the agent right after the answer.
19
19
  - A compact goal widget that does not replace Pi's footer.
20
20
  - Background activity tracking for subagents and other registered providers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-goal",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "Pi extension for goal tracking with background-aware continuation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -374,7 +374,7 @@ export default function (pi: ExtensionAPI): void {
374
374
  * Chat `notify` appends lines above the Working/bash status region. While the
375
375
  * agent is streaming, that height change desyncs Pi main-screen differential
376
376
  * rendering and stacks "Working..." / "Elapsed Xs" into scrollback. Keep
377
- * mid-stream feedback out of the transcript; use the footer status instead.
377
+ * mid-stream non-error feedback out of the transcript.
378
378
  */
379
379
  const notifyGoal = (
380
380
  ctx: ExtensionContext,
@@ -385,11 +385,6 @@ export default function (pi: ExtensionAPI): void {
385
385
  return;
386
386
  }
387
387
  if (isForegroundBusy(ctx) && type !== "error") {
388
- try {
389
- ctx.ui.setStatus(EXTENSION_NAME, message);
390
- } catch {
391
- // Footer status is best-effort only.
392
- }
393
388
  return;
394
389
  }
395
390
  ctx.ui.notify(message, type);
@@ -424,7 +419,6 @@ export default function (pi: ExtensionAPI): void {
424
419
  clearIdleContinuation();
425
420
  syncPollingState();
426
421
  syncResumeTool(goal);
427
- applyStatus(ctx);
428
422
  // Force a full redraw when the dock height changes (absent ↔ visible clock).
429
423
  refreshGoalWidget?.(!wasVisible || !isGoalClockVisible(goal));
430
424
  };
@@ -443,7 +437,6 @@ export default function (pi: ExtensionAPI): void {
443
437
  clearIdleContinuation();
444
438
  syncPollingState();
445
439
  syncResumeTool(null);
446
- applyStatus(ctx);
447
440
  refreshGoalWidget?.(wasVisible);
448
441
  };
449
442
 
@@ -726,41 +719,9 @@ export default function (pi: ExtensionAPI): void {
726
719
  pi.events.emit(EVENT_TERMINAL_ATTENTION, snapshot);
727
720
  if (execution !== executionGeneration) return null;
728
721
  }
729
- applyStatus(ctx);
730
-
731
722
  return snapshot;
732
723
  };
733
724
 
734
- /** Footer status from the goal state and the latest activity snapshot. */
735
- const statusText = (ctx: ExtensionContext, snapshot: ActivitySnapshot | null): string | undefined => {
736
- const goal = getGoal(ctx);
737
- let waitingOnAnswer = 0;
738
- if (snapshot) {
739
- for (const activeAtStart of pendingQuestions.values()) {
740
- waitingOnAnswer += finishedSinceQuestion(activeAtStart, snapshot).length;
741
- }
742
- }
743
- if (waitingOnAnswer > 0) return `${waitingOnAnswer} background done; waiting on your answer`;
744
- if (goal?.status === "paused") return pausedGoalStatus(goal, preferences.conversationalResume);
745
- if (snapshot?.backgroundRunning) return undefined;
746
- const continuation = goal ? currentContinuationState(ctx, goal.goalId) : null;
747
- if (continuation?.blocked) return "waiting: no progress";
748
- const goalStall = observeGoalStall(goal, continuation, {
749
- foregroundRunning,
750
- backgroundRunning: snapshot?.backgroundRunning ?? false,
751
- });
752
- return goalStall?.state === "stalled" ? "goal stalled" : undefined;
753
- };
754
-
755
- function applyStatus(ctx: ExtensionContext): void {
756
- if (!ctx.hasUI) return;
757
- try {
758
- ctx.ui.setStatus(EXTENSION_NAME, statusText(ctx, latestSnapshot));
759
- } catch {
760
- // UI status is best-effort only.
761
- }
762
- }
763
-
764
725
  /**
765
726
  * `goal_resume` is in the model's tool list only while an escape-paused goal
766
727
  * waits. Pi activates newly registered tools by default, so this also removes
@@ -890,7 +851,7 @@ export default function (pi: ExtensionAPI): void {
890
851
  const fg = typeof theme?.fg === "function"
891
852
  ? (color: string, value: string) => theme.fg(color as never, value)
892
853
  : undefined;
893
- return [renderGoalClockLine(goal, width, undefined, fg), ""];
854
+ return [renderGoalClockLine(goal, width, undefined, fg)];
894
855
  },
895
856
  };
896
857
  },
@@ -918,7 +879,6 @@ export default function (pi: ExtensionAPI): void {
918
879
  preferences = writeGoalPreference(key, enabled);
919
880
  if (previous.autoContinue !== preferences.autoContinue) clearIdleContinuation();
920
881
  syncResumeTool(getGoal(ctx));
921
- applyStatus(ctx);
922
882
  if (!previous.autoContinue && preferences.autoContinue) {
923
883
  const snapshot = await publishSnapshot(ctx);
924
884
  const goal = getGoal(ctx);
@@ -1578,7 +1538,6 @@ export default function (pi: ExtensionAPI): void {
1578
1538
  if (blocked) {
1579
1539
  refreshGoalWidget?.();
1580
1540
  if (ctx.hasUI) {
1581
- ctx.ui.setStatus(EXTENSION_NAME, "waiting: no progress");
1582
1541
  ctx.ui.notify(
1583
1542
  `Goal automatic continuation is waiting after ${noProgressRetries} identical retries (${evidence.summary}). Use /goal resume or alt+g to resume it.`,
1584
1543
  "warning",
@@ -1630,7 +1589,6 @@ export default function (pi: ExtensionAPI): void {
1630
1589
  latestSnapshot = null;
1631
1590
  collectionPending = false;
1632
1591
  try {
1633
- ctx.ui.setStatus(EXTENSION_NAME, undefined);
1634
1592
  ctx.ui.setWidget(EXTENSION_NAME, undefined);
1635
1593
  } catch {
1636
1594
  // Best-effort cleanup.