pi-antiloop 1.5.0 → 1.5.1

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
@@ -17,7 +17,7 @@
17
17
  - **Progressive intervention** — `warning` reminds the model to vary its approach; `force break` injects explicit anti-loop instructions and modifies context; `abort` stops the run entirely
18
18
  - **Configurable thresholds** — independent dials for similarity cutoff, warning/force-break/abort counts, detection window, and which strategies are on
19
19
  - **Sliding window** — only the last N messages are compared, so detection is O(N) in the window size, not in the full session
20
- - **Live footer indicator** — `🔄 antiloop(on|off)` in the footer, per spec, with the current level (`⚠️/🛑/🚨`) and consecutive count; an interactive TUI footer adds a keyboard toggle (`esc+a` by default, configurable/off) and preserves the built-in footer's pwd/branch/context/model info
20
+ - **Live footer indicator** — `🔄 antiloop(on|off)` in the footer, per spec, with the current level (`⚠️/🛑/🚨`) and consecutive count; an interactive TUI footer adds a keyboard toggle (`esc+a` by default, configurable/off, honored only while idle) and preserves the built-in footer's pwd/branch/context/model info
21
21
  - **Detection log** — timestamped history with similarity scores, filterable through the native pi menu
22
22
  - **Self-test** — `/antiloop test` runs built-in cases to verify the similarity engine is calibrated
23
23
  - **User input softens detection** — each new user message decays the consecutive counter so a fresh prompt can resolve the loop without manual reset
@@ -316,7 +316,7 @@ Persisted as JSON at `~/.pi/agent/antiloop.json`:
316
316
  | `maxHistoryEntries` | `100` | Max detection history entries |
317
317
  | `detectionWindow` | `10` | Number of recent messages to analyze |
318
318
  | `interactiveFooter` | `true` | TUI footer replaces the built-in one with an antiloop indicator + toggle shortcut (set `false` to keep the built-in footer and only the `setStatus` line) |
319
- | `toggleShortcut` | `esc+a` | Key sequence that toggles antiloop from the footer (`esc+a` or `off`). The input is never consumed, so typing is unaffected |
319
+ | `toggleShortcut` | `esc+a` | Key sequence that toggles antiloop from the footer (`esc+a` or `off`). Honored only while pi is idle (ESC is also pi's interrupt key — typing `a` right after cancelling a stuck run must not silently switch antiloop off). The input is never consumed, so typing is unaffected |
320
320
 
321
321
  ## Best Practices
322
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-antiloop",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Antiloop: detect reasoning loops and force a break (warn \u2192 force \u2192 abort) across text, tool, thinking, and structural patterns. The force break is delivered mid-run: a real break message is steered into the running agent right before its next LLM call, and if the model ignores it and keeps repeating verbatim, antiloop aborts the run \u2014 an autonomous tool loop always terminates. Tool-loop detection is result-aware: only near-identical repeated calls with the same outcome count, so sequential bash operations and retries that make progress don't false-positive. Task-stream recognition: when an extension (punched, plan, \u2026) makes the model call the SAME tool many times with DIFFERENT content \u2014 N distinct tasks of one type, e.g. appending lines or adding plan tasks \u2014 antiloop stays silent.",
5
5
  "keywords": [
6
6
  "pi-package",
package/src/index.ts CHANGED
@@ -163,6 +163,14 @@ export default function antiloopExtension(pi: ExtensionAPI) {
163
163
  ? undefined
164
164
  : ctx.ui.onTerminalInput?.((data: string) => {
165
165
  if (config.toggleShortcut === "off") return undefined;
166
+ // Only honor the toggle while idle. ESC is also pi's interrupt key:
167
+ // an 'a' typed right after cancelling a stuck run is almost always
168
+ // normal typing, not a toggle — arming while the agent runs caused
169
+ // accidental silent toggles to OFF mid-session.
170
+ if (!ctx.isIdle()) {
171
+ pendingEsc = false;
172
+ return undefined;
173
+ }
166
174
  if (data === "\x1b") {
167
175
  pendingEsc = true;
168
176
  return undefined;