pi-hodor

内容来源:README.md(说明文档) · 原始地址 · 查看安装指南

原始内容

pi-hodor

pi-hodor showcase

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 and enough context remains, 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" when enough context remains
  • 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
  • Defers configured errors that should be left to pi's built-in auto-retry, such as WebSocket error
  • Automatically sends a configurable retry message when an error matches errorPatterns but not deferredErrorPatterns
  • 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", its text matches errorPatterns, and it does not match deferredErrorPatterns
  2. it ends with stopReason === "length", autoContinueOnLength is enabled, and the remaining context is above the configured length-continue safety threshold
  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,
  "minRemainingTokensForLengthAutoContinue": 16384,
  "autoContinueOnThinkingOnlyStop": true,
  "autoContinueOnSilentStopAfterTool": true,
  "deferredErrorPatterns": [
    "WebSocket error",
    "fetch failed",
    "socket hang up"
  ],
  "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".
minRemainingTokensForLengthAutoContinue number Defers length auto-continue when known remaining context tokens are at or below this value, so pi can compact first. Set to 0 to disable this guard.
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.
deferredErrorPatterns string[] Case-insensitive substrings for errors hodor should skip because pi or another layer handles them. Set to [] to disable error deferral.
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.