pi-hodor

A pi extension that automatically continues after transient stream and connection errors.

Package details

extension

Install pi-hodor from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-hodor
Package
pi-hodor
Version
0.3.0
Published
Apr 22, 2026
Downloads
582/mo · 166/wk
Author
vurihuang
License
MIT
Types
extension
Size
22.7 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-hodor

npm version npm downloads license

pi-hodor is a pi extension that automatically sends a follow-up retry message when an assistant response stops in a retryable way.

It is useful when model output is interrupted by provider-side failures such as ECONNRESET, ETIMEDOUT, premature stream closure, or partial JSON responses. It can also continue when the assistant stops because it hit a length limit, when it ends with a normal stop but only emitted thinking content and never produced user-visible text or tool calls, when it ends with a silent stop immediately after a user message without producing any visible follow-up, when it ends with a silent stop immediately after a tool result without producing any visible follow-up, or when an automatic retry message such as continue is followed by another silent stop. Instead of stopping and waiting for manual intervention, the extension detects these cases and sends a configurable retry message such as continue.

Features

  • Watches assistant messages that end with retryable stop reasons
  • Automatically continues on stopReason === "length"
  • Automatically continues on stopReason === "stop" when the assistant emitted only thinking content
  • Automatically continues on silent stopReason === "stop" immediately after a user message when the assistant emitted no visible output
  • Automatically continues on silent stopReason === "stop" immediately after a tool result when the assistant emitted no visible output
  • Automatically continues again when its own retry message is followed by another silent stopReason === "stop"
  • Matches stopReason === "error" text against configurable substring patterns
  • Automatically sends a configurable retry message when a match is found
  • Prevents runaway loops with a configurable retry limit
  • Optionally shows UI notifications when an auto-retry happens
  • Supports project-level and global config overrides without modifying the packaged files

Installation

Install from npm:

pi install npm:pi-hodor

Or from git:

pi install git:github.com/vurihuang/pi-hodor

Restart pi after installation so the extension is loaded.

Load it for a single run

pi -e npm:pi-hodor

Install from a local path

pi install /absolute/path/to/pi-hodor

Load from a local path for one session

pi -e /absolute/path/to/pi-hodor

Verify installation

After restarting pi, the extension is active automatically.

You can confirm it is loaded by triggering a transient stream error during normal use, or by checking that the extension has been installed from npm and is available in your pi package list.

Usage

Once the extension is loaded, there is nothing else to trigger manually.

When pi receives an assistant message that matches one of these conditions, pi-hodor automatically sends the configured retry message:

  1. it ends with stopReason === "error" and its text matches one of the configured error patterns
  2. it ends with stopReason === "length" and autoContinueOnLength is enabled
  3. it ends with stopReason === "stop", emitted thinking content, and emitted neither text nor tool calls, and autoContinueOnThinkingOnlyStop is enabled
  4. it ends with stopReason === "stop", emitted no visible output, the previous message was a user message, and autoContinueOnSilentStopAfterTool is enabled
  5. it ends with stopReason === "stop", emitted no visible output, the previous message was a toolResult, and autoContinueOnSilentStopAfterTool is enabled
  6. it ends with stopReason === "stop", emitted no visible output, the previous message was the extension's own automatic retry message, and autoContinueOnSilentStopAfterTool is enabled

The default retry message is:

"continue"

Setup command

If you want a reusable global config, run:

/pi-hodor:setup

What this command does:

  1. ensures the bundled default config exists inside the package
  2. creates the global config directory if needed
  3. copies the bundled default config to: ~/.pi/agent/extensions/pi-hodor/config.json
  4. does not overwrite the file if it already exists

So /pi-hodor:setup is a one-time bootstrap command for creating your editable global config file.

If the global config already exists, the command shows a warning and leaves your existing file unchanged.

Configuration

Configuration is resolved in this order:

  1. ./.pi-hodor.json
  2. ./.pi/pi-hodor.json
  3. ~/.pi/agent/extensions/pi-hodor/config.json
  4. the bundled config.json inside this package

That means:

  • project config overrides global config
  • global config overrides the packaged defaults
  • packaged defaults are only used when no override file exists

Use project config when you want repo-specific behavior. Use the global config when you want the same defaults across all projects.

Path details

1. Project config in repo root

./.pi-hodor.json

Best for a single repository.

2. Project config in .pi

./.pi/pi-hodor.json

Also project-scoped, useful if you prefer keeping pi-related files together.

3. Global config

~/.pi/agent/extensions/pi-hodor/config.json

Best for personal defaults shared across projects. You can generate this file with /pi-hodor:setup.

4. Bundled fallback config

The package ships with its own config.json, which acts as the final fallback when no project or global override exists.

Example flow

  • You install pi-hodor
  • You run /pi-hodor:setup
  • The extension creates ~/.pi/agent/extensions/pi-hodor/config.json
  • You edit that file to define your global defaults
  • In one specific repo, you add ./.pi-hodor.json
  • That repo now uses its local config instead of your global one

Example config

{
  "enabled": true,
  "retryMessage": "continue",
  "maxConsecutiveAutoRetries": 99,
  "notifyOnAutoContinue": true,
  "autoContinueOnLength": true,
  "autoContinueOnThinkingOnlyStop": true,
  "autoContinueOnSilentStopAfterTool": true,
  "errorPatterns": [
    "error decoding response body",
    "stream disconnected before completion",
    "ECONNRESET"
  ]
}

Config fields

Field Type Description
enabled boolean Enables or disables the extension logic.
retryMessage string The exact user message sent back to pi after a matched error.
maxConsecutiveAutoRetries number Maximum automatic retries before the extension stops retrying.
notifyOnAutoContinue boolean Shows a UI notification when an automatic retry happens or when the retry limit is reached.
autoContinueOnLength boolean Automatically retries when an assistant message ends with stopReason === "length".
autoContinueOnThinkingOnlyStop boolean Automatically retries when an assistant message ends with stopReason === "stop" after emitting only thinking content and no text or tool calls.
autoContinueOnSilentStopAfterTool boolean Automatically retries when an assistant message ends with stopReason === "stop" after a user message, after a toolResult, or immediately after the extension's own retry message, and emits no visible output.
errorPatterns string[] Case-insensitive substrings used to detect transient failures for stopReason === "error".

Development

Install dependencies:

npm install

Run the type check:

npm run check

Preview the npm package contents:

npm run pack:check

Package structure

.
├── auto-continue.ts
├── config.json
├── index.ts
├── LICENSE
├── package.json
├── README.md
└── tsconfig.json

Updating

Reinstall the package from npm:

pi install npm:pi-hodor

Or update from git:

pi install git:github.com/vurihuang/pi-hodor

Restart pi after updating.

Install as a pi package

This project is already structured as a pi package via the pi field in package.json:

{
  "pi": {
    "extensions": ["./index.ts"]
  }
}

That means pi can install it from a local path, npm, or git using the standard pi package flow.