# pi-cap-context-images

> 스크린샷이 쌓여서 긴 [pi 코딩 에이전트](https://github.com/earendil-works/pi-mono) 세션이 **압축 무한 루프**에 빠지는 걸 막습니다. 모델로 나가는 페이로드에는 최근 이미지 몇 장만 남겨서, 누적된 base64 캡처가 컨텍스트 한도를 넘기지 못하게 합니다.

[English](README.md) | 한국어

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Platform](https://img.shields.io/badge/platform-WSL2%20%7C%20Linux%20%7C%20macOS-blue)]()
[![GitHub stars](https://img.shields.io/github/stars/Blue-B/pi-cap-context-images?style=flat&logo=github&color=yellow)](https://github.com/Blue-B/pi-cap-context-images/stargazers)
[![GitHub issues](https://img.shields.io/github/issues/Blue-B/pi-cap-context-images?logo=github)](https://github.com/Blue-B/pi-cap-context-images/issues)

## 왜 필요한가

브라우저 자동화(`pi-playwright`)나 화면 캡처(`pi-winshot`) 같은 도구는 모델에게 **base64 이미지**를 넘깁니다. 긴 세션에서 이게 계속 쌓이는데, 함정은 여기 있습니다:

> 압축(compaction)은 *텍스트는 요약*할 수 있지만 **이미지는 줄이지 못합니다.** 통째로 유지하거나 통째로 버리는 것만 가능합니다.

스크린샷 수십 장이 압축이 보존하는 "최근" 구간에 들어앉으면, 압축할 때마다 그걸 전부 그대로 끌고 갑니다. `tokensBefore`가 임계선 아래로 안 내려가니, 에이전트는 압축하고… 또 압축하고… 영원히 반복합니다.

가설이 아닙니다. 실제 한 세션이 **이미지 51장 ≈ 4.5MB**를 쌓아 ~90만~96.8만 토큰에서 **연속 6번 압축**이 일어났고 끝내 수렴하지 못해 세션이 사실상 멈췄습니다.

`pi-cap-context-images`는 근본 원인을 제거합니다. 프로바이더로 도달하는 이미지 수를 제한해서 토큰 사용량을 일정하게 묶고, 압축이 제 역할을 하도록 만듭니다.

## 동작 방식

pi는 `before_provider_request` 이벤트로 나가는 전체 페이로드를 넘겨주고, 확장이 수정본을 돌려줄 수 있게 합니다 — 내장 `sanitize-tool-call-ids` 확장이 쓰는 것과 동일한 공개 훅입니다. 이 확장은 매 요청마다:

1. 페이로드를 문서 순서대로 순회하며 모든 이미지 블록을 찾고,
2. **가장 최근 `N`장**(기본 `3`)만 남긴 뒤,
3. 나머지 오래된 이미지는 한 줄짜리 텍스트 placeholder로 치환합니다.

```
 대화 (오래됨 → 최근)
 ┌────────────────────────────────────────────────┐
 │ 🖼  🖼  🖼  🖼  🖼  🖼  🖼   🖼   🖼   🖼 │
 │  ↓   ↓   ↓   ↓   ↓   ↓   ↓                       │
 │ [placeholder × 7]            🖼  🖼  🖼          │  → 모델로 전송
 └────────────────────────────────────────────────┘
                                  └── KEEP_IMAGES (3) ──┘
```

모델은 최신 스크린샷은 그대로 보므로 진행 중인 시각 작업은 정상 동작합니다 — 오래된 것만 전송 페이로드에서 빠집니다.

> **건드리는 건 나가는 페이로드뿐입니다.** 저장되는 세션 `.jsonl` 원본은 그대로라, 트랜스크립트/스크롤백에는 그동안 찍은 스크린샷이 모두 남아 있습니다.

처리하는 이미지 블록 형태: pi 내부 `{type:"image", data, mimeType}`, Anthropic `{type:"image", source:{…}}`, OpenAI `{type:"image_url", image_url:{…}}`.

## 설치

```bash
pi install pi-cap-context-images
/reload
```

또는 클론해서:

```bash
git clone https://github.com/Blue-B/pi-cap-context-images
pi install ./pi-cap-context-images
/reload
```

또는 로컬 패키지로 쓴다면 pi `settings.json`의 `packages`에 폴더 경로를 추가합니다 (경로는 settings 파일 기준 상대경로):

```json
{
  "packages": [
    "../../projects/pi-cap-context-images"
  ]
}
```

### 요구사항
- pi 코딩 에이전트 ≥ 0.70
- 그 외 없음 — 런타임 의존성 없는 단일 훅입니다.

## 설정

| 환경변수 | 기본값 | 의미 |
| --- | --- | --- |
| `PI_CAP_CONTEXT_IMAGES` | `3` | 전송 페이로드에 남길 최근 이미지 수. `0`이면 모든 이미지 제거. |

```bash
PI_CAP_CONTEXT_IMAGES=5 pi   # 3장 대신 최근 5장 유지
```

## 프로젝트 구조

```
pi-cap-context-images/
├── package.json
├── extensions/cap-context-images/index.ts   # before_provider_request 훅
├── README.md
└── LICENSE
```

## 되돌리기

`packages` 항목을 제거(또는 `pi uninstall pi-cap-context-images`)하고 `/reload`.

## 후원

[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub-EA4AAA?style=for-the-badge&logo=github-sponsors&logoColor=white)](https://github.com/sponsors/Blue-B) [![Buy Me A Coffee](https://img.shields.io/badge/One%E2%80%91time_$3-Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=000)](https://buymeacoffee.com/beckycode7h) [![PayPal](https://img.shields.io/badge/Donate-PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://www.paypal.com/ncp/payment/ZEWFKDX595ESJ)

이 확장이 무한 압축으로 멈출 뻔한 세션을 살려줬다면, 직접 후원은 유지보수에 큰 힘이 됩니다:

- 후원이 도움이 되는 곳: pi·프로바이더 페이로드 포맷이 바뀌어도 이미지 블록 감지를 맞춰 유지, 여러 프로바이더(Anthropic / OpenAI / bridge) 테스트, 이슈 응답 시간 단축.
- 투명성: 기금은 전부 유지보수 시간과 테스트 인프라에 쓰입니다. 일회성 후원은 일회성으로 유지되며 의무는 없습니다.
- 월 후원자($3/월, GitHub Sponsors)는 "Sponsor Request" 이슈에 대해 최선을 다해 우선 처리해 드립니다.

## 라이선스

MIT
