diff --git a/agent-client/pi/extensions/iop-read-limit.ts b/agent-client/pi/extensions/iop-read-limit.ts new file mode 100644 index 00000000..b519d8a2 --- /dev/null +++ b/agent-client/pi/extensions/iop-read-limit.ts @@ -0,0 +1,13 @@ +import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; + +const IOP_MAX_READ_LINES = 240; + +export default function (pi: ExtensionAPI) { + pi.on("tool_call", (event, ctx) => { + if (ctx.model?.provider !== "iop" || event.toolName !== "read") return; + const limit = event.input.limit; + if (typeof limit !== "number" || limit > IOP_MAX_READ_LINES) { + event.input.limit = IOP_MAX_READ_LINES; + } + }); +} diff --git a/agent-client/pi/install.sh b/agent-client/pi/install.sh index dbb2f941..86981e5d 100755 --- a/agent-client/pi/install.sh +++ b/agent-client/pi/install.sh @@ -4,6 +4,7 @@ set -euo pipefail PI_DIR="$HOME/.pi/agent" SETTINGS="$PI_DIR/settings.json" MODELS="$PI_DIR/models.json" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PYTHON_BIN="/usr/bin/python3" if [[ ! -x "$PYTHON_BIN" ]]; then @@ -16,6 +17,8 @@ if [[ -z "$PYTHON_BIN" || ! -x "$PYTHON_BIN" ]]; then fi mkdir -p "$PI_DIR" +mkdir -p "$PI_DIR/extensions" +install -m 0644 "$SCRIPT_DIR/extensions/iop-read-limit.ts" "$PI_DIR/extensions/iop-read-limit.ts" "$PYTHON_BIN" - "$SETTINGS" "$MODELS" <<'PY' import json diff --git a/agent-client/pi/install_test.py b/agent-client/pi/install_test.py index ae34db6c..fc058239 100644 --- a/agent-client/pi/install_test.py +++ b/agent-client/pi/install_test.py @@ -55,6 +55,7 @@ class _TempHomeMixin: self.pi_dir.mkdir(parents=True) self.settings_path = self.pi_dir / "settings.json" self.models_path = self.pi_dir / "models.json" + self.read_limit_path = self.pi_dir / "extensions" / "iop-read-limit.ts" def tearDown(self): shutil.rmtree(self.tmp_home, ignore_errors=True) @@ -192,6 +193,7 @@ class TestPreservesOpenaiResponsesConsumptionAndUserSettings(_TempHomeMixin, uni # (already checked above but be explicit about the contract) legacy_in_enabled = [m for m in enabled if m.startswith("seulgivibe-openai/")] self.assertEqual(legacy_in_enabled, [], "Legacy openai entries must be removed from enabledModels") + self.assertIn("IOP_MAX_READ_LINES = 240", self.read_limit_path.read_text()) class TestIdempotentRerun(_TempHomeMixin, unittest.TestCase):