# next-prompts

[← README로 돌아가기](../README.md)

> Claude가 답을 마치면 다음에 보낼 만한 요청을 입력창 위에 제안합니다.

<p><picture>
<source media="(prefers-color-scheme: dark)" srcset="./images/showcase/suggest-dark.gif">
<img alt="턴이 끝나면 다음에 보낼 만한 요청이 하나씩 나타난다" src="./images/showcase/suggest-light.gif" width="560">
</picture></p>

| 항목 | 값 |
| --- | --- |
| 버전 | `0.8.1` |
| 표시 위치 | 입력창 위 |
| 요구 사항 | Claude Code 2.1.296 이상. 터미널(`terminal`)과 데스크톱(`desktop`) 화면에서만 표시됩니다 |
| 외부 호출 | 턴마다 최대 한 번 `haiku` 모델 호출. 하위 프로세스와 네트워크 요청은 없습니다 |
| 저장 데이터 | 없음. 제안은 세션 상태에만 유지하고 파일이나 `$.store`에는 저장하지 않습니다 |

## 목차

- [개요](#개요)
- [빠른 시작](#빠른-시작)
- [사용법](#사용법)
- [키와 명령](#키와-명령)
- [화면 구성](#화면-구성)
- [동작 방식](#동작-방식)
- [설정과 저장 데이터](#설정과-저장-데이터)
- [외부 호출과 사용량](#외부-호출과-사용량)
- [제한 사항](#제한-사항)
- [문제 해결](#문제-해결)
- [소스 구성](#소스-구성)
- [변경 이력](#변경-이력)

## 개요

메인 대화에서 Claude가 답변을 마치면 작은 모델(`haiku`)을 한 번 호출해 사용자가 다음에 보낼 만한 요청을 최대 3개 받아옵니다. 제안은 입력창 위에 한 줄씩 표시됩니다. 입력창에 `$1`을 입력하고 스페이스를 누르거나 번호를 클릭하면 문구가 입력되고, 문구를 클릭하면 바로 전송됩니다.

매번 다음 요청을 직접 입력하지 않고 작업을 이어갈 수 있게 돕는 모드입니다. 어디까지나 보조 기능이므로 모델 호출에 실패하거나 쓸 만한 제안이 없으면 아무것도 표시하지 않습니다.

다음과 같은 제한이 있습니다.

- 서브에이전트의 턴, 사용자가 중단한 턴, 거절이나 API 오류로 끝난 턴에는 제안을 만들지 않습니다.
- 제안을 따로 저장할 수 없으며, 닫은 제안은 다시 불러올 수 없습니다.
- 모델 호출만 끄는 설정은 없습니다.

이 모드는 [hamzafer/claude-code-mods](https://hamzafer.github.io/claude-code-mods/mods/next-steps/)의 next-steps에서 아이디어를 얻었습니다. 원본 코드는 보지 않고 동작 설명만 참고해 새로 구현했습니다.

## 빠른 시작

마켓플레이스를 등록한 적이 없다면 먼저 `/plugin marketplace add oobg/claude-code-mods`를 실행합니다. 그다음 모드를 설치합니다.

```
/plugin install next-prompts@oobg
```

설치한 모드는 Claude Code를 다시 시작하거나 `/reload-plugins`를 실행하면 적용됩니다. 설치 직후에는 아무것도 보이지 않고, 첫 턴이 끝난 뒤에 제안이 나타납니다.

1. 평소처럼 요청을 보내고 Claude의 답을 기다립니다.
2. 답이 끝나면 입력창 위에 `다음 제안` 제목과 함께 `$1:`, `$2:`처럼 번호가 붙은 문구가 나타납니다.
3. 문구를 클릭하면 해당 요청을 바로 보냅니다. 입력창에 `$1`을 입력하고 스페이스를 누르면 그 자리가 1번 문구로 바뀝니다.

## 사용법

### 제안이 나타나는 조건

턴이 끝날 때 아래 조건을 모두 채우면 제안을 만듭니다.

- 메인 대화의 턴만 처리합니다. 서브에이전트의 턴(`agentId`가 있음)은 건너뜁니다.
- 턴이 답변으로 끝나야 합니다(`reason`이 `answer`). 사용자가 중단한 턴(`isAborted`), 거절(`refusal`), API 오류(`error`)로 끝난 턴은 제외합니다.
- 답 본문이 120자 이상이어야 합니다(`MIN_ANSWER_CHARS`). 답 본문은 해당 턴에서 Claude가 마지막으로 표시한 텍스트입니다. 텍스트 답변을 남기지 않은 턴은 본문이 비어 있으므로 제외합니다.

모델에 제안 2~3개를 요청하지만, 60자를 넘거나 중복된 제안은 제외하므로 1개만 남을 수도 있습니다.

### 제안 고르기

- 입력창에 `$1`을 치고 스페이스를 누르면 `$1`이 1번 문구로 바뀌고, 이어서 쓸 수 있게 문구 뒤에 스페이스가 하나 붙습니다. 글 중간에서도 쓸 수 있습니다. 스페이스 없이 바로 Enter를 눌러도 보낼 때 `$1`을 1번 문구로 바꿔 보냅니다. 이때 입력창에는 바뀐 글이 보이지 않고, 보내는 내용만 바뀝니다.
- 번호(`$1:`)를 클릭하면 입력창의 내용을 1번 문구로 바꾸고 제안을 닫습니다. 이때는 전송하지 않습니다.
- 문구를 클릭하면 해당 문구를 사용자 메시지로 바로 보냅니다. 입력창에 작성 중이던 내용은 함께 보내지 않습니다.

```
다음 제안  닫기
  $1: 바뀐 내용을 README 문서에 반영해줘
  $2: 커밋해줘
```

### 제안 닫기와 숨김

- `닫기`를 클릭하면 제안을 닫습니다. 닫은 제안은 다시 열 수 없고, 다음 턴이 위 조건을 채우고 끝나면 새 제안이 나타납니다.
- Claude가 작업하는 동안에는 제안을 숨깁니다.
- 새 프롬프트를 보내면(슬래시 명령 포함) 제안을 지웁니다.

### 나타나는 모양

제안은 한 줄씩 차례로 나타납니다(0.7.0부터).

- 각 줄의 애니메이션은 120ms 간격으로 시작합니다. 한 줄의 글자는 약 320ms 동안 앞에서부터 채워지며, 화면은 40ms마다 갱신합니다.
- 글자가 채워지는 동안에는 흐리게 표시되고, 한 줄이 완성되면 일반 색으로 바뀝니다.
- `다음 제안` 제목과 `닫기`는 첫 줄과 함께 나타납니다. 아직 표시되지 않은 줄도 빈 줄로 공간을 확보해 입력창 위 영역의 높이가 바뀌지 않도록 합니다.
- 애니메이션 도중 `$1`과 스페이스를 입력하거나 번호 또는 문구를 클릭해도, 화면에 표시된 부분만이 아니라 전체 문구가 입력되거나 전송됩니다.
- 애니메이션 도중 `닫기`를 클릭하거나 새 프롬프트를 보내면 애니메이션이 즉시 멈춥니다. 모드 코드를 다시 불러와도(핫 리로드) 제안은 남지만, 애니메이션을 이어서 실행하지 않고 전체 문구를 바로 표시합니다.

### quick-replies와 함께 쓰기

quick-replies를 함께 설치하면 두 모드가 입력창 위 영역을 나눠 씁니다. 다음 제안은 위에, 프리셋은 아래에 표시되며 번호는 두 목록에 걸쳐 이어집니다. 다음 제안은 늘 `$1`부터 시작하고, 프리셋은 현재 표시된 제안 수 다음 번호부터 시작합니다. 제안이 2개면 프리셋은 `$3`부터입니다.

quick-replies의 접기(`$0`)는 프리셋에만 적용됩니다. 다음 제안은 접히지 않고 늘 전체 문구로 보입니다.

## 키와 명령

| 입력 | 동작 | 조건 |
| --- | --- | --- |
| `$1 `~`$3 ` 입력(번호 뒤 스페이스) | `$`, 숫자, 친 스페이스를 그 번호의 제안 문구와 스페이스 하나로 바꿉니다 | `$`가 입력창 맨 앞에 있거나 바로 앞이 공백이고, 해당 번호의 제안이 표시되어 있으며, 선택 영역 없이 번호 뒤에 스페이스 한 글자를 입력했을 때만 |
| 번호(`$n:`) 클릭 | 입력창의 글을 그 문구로 바꾸고 제안을 닫습니다 | 제안이 보일 때 |
| 문구 클릭 | 제안을 닫고 해당 문구를 사용자 메시지로 바로 보냅니다 | 제안이 보일 때 |
| `닫기` 클릭 | 제안을 지우고 애니메이션을 멈춥니다 | 제안이 보일 때 |
| 슬래시 명령 | 해당 없음 | 이 모드는 명령을 등록하지 않습니다 |

`$1 `로 바꾼 내용은 Claude Code의 되돌리기 키 `ctrl+_`로 되돌립니다.

## 화면 구성

| 요소 | 내용 | 표시 조건 |
| --- | --- | --- |
| 제목 줄 | 흐린 색 `다음 제안` | 첫 제안의 글자가 하나라도 보일 때. 그 전에는 빈 줄 |
| `닫기` | 흐린 색 버튼. 제목 줄 오른쪽 | 제목 줄과 함께 |
| 번호 | `$1:` 형식. 테마 색 `suggestion`(Claude Code가 입력창의 `/명령`에 쓰는 색) | 제안 줄마다 |
| 제안 문구 | 두 칸 들여 쓴 한 줄. 채워지는 동안은 흐린 색, 다 나오면 보통 색 | 그 줄의 차례가 오면. 그 전에는 빈 줄 |
| 영역 전체 | 위에 한 칸을 띄운 다음 제안 블록 | 제안이 있고 Claude가 작업 중이 아닐 때 |

설문이 표시될 때(`hasSurvey`)나 터미널, 데스크톱이 아닌 화면에서는 이 모드가 입력창 위 영역을 변경하지 않습니다.

## 동작 방식

### 이벤트

| 이벤트 | 하는 일 | 소스 |
| --- | --- | --- |
| `session.start` | `reveal`을 비워 핫 리로드로 중단된 애니메이션을 재개하는 대신 제안 전체를 표시합니다 | `hooks/register.tsx`: `register` |
| `prompt.submit` | `generation`을 1 올리고, 입력창에서 보낸 글에 남은 `$번호`(스페이스 없이 Enter)를 제안 문구로 바꿔 넘깁니다. 보낸 뒤 `suggestions`와 `reveal`을 비우고 보낸 글을 `lastPrompt`에 남깁니다. 제안을 보낸 뒤에 비우는 것은 안쪽에서 도는 quick-replies가 프리셋 번호를 셀 때 제안 개수가 남아 있어야 하기 때문입니다. 슬래시 명령도 포함합니다 | `hooks/register.tsx`: `register`, `hooks/band.ts`: `expandNumbers` |
| `prompt.edit` | `$1`처럼 번호를 친 뒤 스페이스를 입력하면(`typedNumber`) `$`부터 친 스페이스까지 해당 제안 문구와 스페이스 하나로 바꿉니다. 해당 번호의 제안이 없으면 그대로 둡니다 | `hooks/register.tsx`: `register`, `hooks/band.ts`: `typedNumber` |
| `turn.complete` | 엔진의 처리(`next(e)`)를 먼저 끝내고, 조건을 만족하면 `suggest`를 시작하되 완료를 기다리지 않습니다. 턴 종료 처리가 지연되지 않도록 하기 위해서입니다 | `hooks/register.tsx`: `register`, `suggest` |
| `ui.render` (`AbovePrompt`) | 다른 모드가 그린 틀(`next(e)`)에 제안 줄을 추가합니다. 작업 중이거나 제안이 없으면 제안 줄을 제거합니다 | `hooks/register.tsx`: `register`, `hooks/band.ts`: `withBandSection` |

`turn.complete`의 조건은 `e.agentId === undefined && e.reason === 'answer' && !e.isAborted && e.answer.length >= MIN_ANSWER_CHARS`입니다.

### 제안 만들기

1. `buildPrompt`는 `lastPrompt`의 마지막 1000자와 답 본문의 마지막 4000자(`MAX_CONTEXT_CHARS`)로 요청을 만듭니다. 앞부분이 잘렸다면 해당 텍스트 앞에 `…`를 붙입니다.
2. `$.model.complete`로 `haiku`를 호출합니다(`SYSTEM` 시스템 프롬프트, `maxTokens: 200`, `effort: 'low'`, `timeoutMs: 20_000`).
3. 답이 없거나(`isAnswered`가 false) 그사이 `generation`이 바뀌었으면 버립니다.
4. `parseSuggestions`는 답을 줄 단위로 나누고, 각 줄 앞의 번호(`1.`, `1)`) 또는 글머리표(`-`, `*`, `•`)와 양끝 따옴표를 제거합니다. 빈 줄, 60자(`MAX_SUGGESTION_CHARS`)를 넘는 줄, 중복된 줄은 제외하고 3개(`MAX_SUGGESTIONS`)까지 고릅니다.
5. 하나도 남지 않으면 아무것도 띄우지 않습니다. 남으면 `animate`로 넘깁니다.
6. 호출 중 예외가 발생하면 오류를 표시하지 않고 해당 호출을 무시합니다.

`SYSTEM`은 사용자의 언어와 말투에 맞춰 제안 2개 또는 3개를 만들되, 번호나 기호 없이 한 줄에 하나씩 60자 이내로 작성하도록 지시합니다. 이미 끝낸 일이나 사용자가 거절한 일은 제외하고, 적절한 제안이 없으면 아무것도 출력하지 않도록 합니다.

### 애니메이션

`animate`는 먼저 `reveal`에 첫 프레임 값을 넣고, 이어서 `suggestions`에 전체 문구를 저장합니다. 이후 `$.clock.sleep(FRAME_MS)`마다 `reveal` 값을 늘리며, 모든 줄이 나타나면 `reveal`을 빈 배열로 되돌립니다.

| 상수 | 값 | 뜻 |
| --- | --- | --- |
| `FRAME_MS` | `40` | 상태 갱신 간격(ms). 코드 주석에 따르면 엔진은 입력창 위 영역을 초당 30번까지 다시 그리므로 33ms 이상으로 설정합니다 |
| `LINE_GAP_MS` | `120` | 다음 줄이 시작하는 간격(ms). 프레임으로는 `LINE_GAP_FRAMES` = 3 |
| `LINE_MS` | `320` | 한 줄을 채우는 시간(ms). 프레임으로는 `LINE_FRAMES` = 8 |

`f`번째 프레임에서 `i`번째 줄이 보여 주는 글자 수는 `min(길이, (f - 3i + 1) × ceil(길이 / 8))`입니다(`revealAt`). 글자 수는 `Array.from`으로 세므로 한글과 이모지도 한 글자로 셉니다.

### 취소(`generation`)

`generation`은 현재 유효한 제안 요청을 구분하는 모듈 내부의 숫자 카운터입니다. `prompt.submit`, `닫기`, 문구 클릭 때마다 1씩 증가합니다.

- `turn.complete`는 그 시점의 `generation`을 `suggest`에 넘깁니다. 모델 답이 돌아왔을 때 값이 달라졌으면 결과를 버립니다.
- `animate`는 프레임마다 `generation`을 비교하고, 값이 달라졌으면 즉시 멈춥니다. 제안 삭제는 generation을 증가시킨 쪽에서 처리합니다.
- 모델 호출 자체를 끊지는 않습니다(`AbortSignal`을 쓰지 않습니다). 호출은 끝까지 가고 결과만 버립니다.

### 상태

아래 키는 모두 `$.state`의 `next-prompts`에 속합니다. 세션 동안 유지되며 핫 리로드 후에도 남지만, 디스크에는 저장하지 않습니다.

| 키 | 타입 | 내용 | 비우는 때 |
| --- | --- | --- | --- |
| `suggestions` | `readonly string[]` | 지금 띄운 제안. 늘 전체 문구입니다 | `prompt.submit`, `닫기`, 번호나 문구 클릭 |
| `reveal` | `readonly number[]` | 줄마다 지금 보이는 글자 수. 빈 배열이면 전부 보입니다 | `session.start`, `prompt.submit`, `닫기`, 애니메이션 끝 |
| `lastPrompt` | `string` | 마지막으로 보낸 요청. 다음 제안을 만들 때 사용합니다 | 비우지 않고 덮어씁니다(`prompt.submit`, 문구 클릭) |

`ui.render`는 `reveal`과 `suggestions`의 배열 길이가 다르면 애니메이션 중이 아닌 것으로 판단해 전체 문구를 표시합니다. `ui.render` 안에서 읽은 상태가 바뀌면 엔진이 해당 영역을 다시 렌더링합니다.

### 다른 모드와 주고받는 것

- 입력창 위 영역에는 UI 트리가 하나만 렌더링되므로 quick-replies와 같은 컨테이너를 사용합니다. 키가 `oobg-band`인 세로 `Box`가 공통 컨테이너이며, 각 모드는 `oobg-band:<순서>:<이름>` 키를 가진 줄을 추가합니다. next-prompts는 `oobg-band:10:next-prompts`(`ORDER` = 10)를 사용하고, 순서가 20인 quick-replies는 그 아래에 표시됩니다.
- quick-replies가 편집 화면처럼 입력창 위 영역을 단독으로 사용할 때는 키가 `oobg-band-exclusive`인 컨테이너를 반환합니다. next-prompts는 이 컨테이너가 있으면 제안 줄을 추가하지 않고 그대로 넘깁니다.
- quick-replies는 `{ plugin: 'next-prompts', key: 'suggestions' }`를 읽어 문자열 항목 개수를 세고, 프리셋 번호를 그다음부터 매깁니다. next-prompts가 없으면 0으로 봅니다. next-prompts는 quick-replies의 상태를 읽지 않습니다.
- 각 모드가 번호를 직접 매기므로 컨테이너를 합치는 순서와 관계없이 번호가 이어집니다.

## 설정과 저장 데이터

사용자가 변경할 수 있는 설정은 없습니다. 제안 수, 길이 한도, 모델, 애니메이션 속도는 모두 코드에 상수로 지정되어 있습니다.

| 종류 | 키 | 비고 |
| --- | --- | --- |
| `$.state` | `suggestions`, `reveal`, `lastPrompt` | 세션 동안만 유지. [상태](#상태) 참고 |
| `$.store` | 없음 | |
| 파일 | 없음 | |

모델 호출을 멈추려면 모드를 끄거나 지웁니다(`/plugin uninstall next-prompts@oobg`).

## 외부 호출과 사용량

| 항목 | 값 |
| --- | --- |
| 호출 | `$.model.complete`. 조건을 채운 턴마다 한 번 |
| 모델 | `haiku` |
| 보내는 내용 | `SYSTEM` 지시문, 사용자가 마지막으로 보낸 요청의 끝 1000자, 답 본문의 끝 4000자 |
| 보내지 않는 것 | 대화 기록, 도구 실행 결과, 답 본문에 들어 있지 않은 글 |
| 응답 한도 | `maxTokens: 200`, `effort: 'low'` |
| 제한 시간 | 20초(`timeoutMs: 20_000`). 넘으면 호출이 `aborted`로 끝납니다 |
| 실패 시 | `api-error`, `empty-reply`, `aborted` 상태이거나 예외가 발생해도 제안이나 오류 메시지를 표시하지 않습니다 |
| 하위 프로세스, 네트워크 | 없음 |

`$.model.complete`는 현재 Claude Code 세션의 API 클라이언트와 자격 증명을 사용합니다. 따라서 호출은 같은 계정으로 처리되며, 호출할 때마다 해당 계정의 사용량에 포함됩니다. 도구와 대화 기록은 보내지 않고, 시스템 프롬프트는 Claude Code의 기본 식별 블록 뒤에 `SYSTEM`을 붙여 구성합니다.

## 제한 사항

- 제안 품질은 `haiku`에 전달한 마지막 요청의 끝 1000자와 답 본문의 끝 4000자에 달려 있습니다. 이전 대화나 도구 결과는 모델에 전달하지 않습니다.
- 답 본문이 120자보다 짧으면 제안하지 않습니다.
- 60자를 넘는 제안은 버립니다. 모델이 긴 줄만 내면 아무것도 뜨지 않습니다.
- 제안을 기다리는 동안 새 프롬프트를 보내면 늦게 도착한 제안은 버립니다. 이미 시작한 호출은 사용량에 포함됩니다.
- 문구를 클릭해 보낸 요청에서는 `@파일` 멘션이 확장되지 않습니다. Claude Code 엔진이 모드에서 보낸 프롬프트를 처리하는 방식 때문입니다.
- 터미널과 데스크톱 화면에서만 표시됩니다. 다른 화면에서는 보이지 않습니다.

## 문제 해결

| 증상 | 원인 | 해결 |
| --- | --- | --- |
| 턴이 끝났는데 제안이 없습니다 | 답 본문이 120자 미만이거나 턴이 중단, 거절, 오류로 끝남. 모델 호출 실패, 20초 초과, 모든 제안이 60자 초과 | 다음 턴을 기다립니다. 실패해도 오류는 표시하지 않습니다 |
| 서브에이전트가 끝났을 때는 제안이 없습니다 | 서브에이전트의 턴(`agentId`가 있음)은 건너뜁니다 | 메인 대화의 턴이 끝나면 나타납니다 |
| 제안이 1개만 뜹니다 | 겹치거나 60자를 넘는 줄을 버렸습니다 | 정상 동작입니다 |
| 작업 중에 제안이 사라졌습니다 | Claude가 작업하는 동안에는 숨깁니다(`isWorking`) | 작업이 끝나면 다시 보입니다. 새 프롬프트를 보냈다면 지워진 것입니다 |
| `$1`을 쳤는데 바뀌지 않습니다 | 번호 뒤에 스페이스를 치지 않았거나, `$` 바로 앞에 글자가 있거나, 그 번호의 제안이 없거나, 선택 영역이 있었습니다 | `$`를 글 맨 앞이나 공백 뒤에 치고, 번호 뒤에 스페이스를 누릅니다 |
| 닫은 제안을 다시 보고 싶습니다 | 닫으면 `suggestions`를 비웁니다 | 되살릴 수 없습니다. 다음 턴을 기다립니다 |
| 업데이트 뒤 이전 형식의 제목이 붙은 제안이 남아 있습니다 | 0.3.0~0.4.0은 제안을 `{ title, text }`로 저장했습니다 | 렌더링과 `$번호` 치환에서 문자열이 아닌 항목은 걸러 내므로 보이지 않습니다 |

## 소스 구성

| 파일 | 역할 |
| --- | --- |
| `mods/next-prompts/.claude-plugin/plugin.json` | 모드 이름, 버전(`0.8.1`), 설명, 타입 선언 경로 |
| `mods/next-prompts/hooks/hooks.json` | 불러올 모듈 목록(`./register.tsx`) |
| `mods/next-prompts/hooks/register.tsx` | 이벤트 훅, 상태 atom, 모델 호출(`suggest`), 애니메이션(`animate`, `revealAt`), 입력창 위 줄 그리기 |
| `mods/next-prompts/hooks/suggest.ts` | `$`를 쓰지 않는 순수 함수. `SYSTEM`, `buildPrompt`, `parseSuggestions`와 길이 상수 |
| `mods/next-prompts/hooks/band.ts` | 입력창 위 영역을 함께 사용하는 공통 규칙(`withBandSection`, `exclusiveBand`, `typedNumber`, `numberLabel`). `mods/quick-replies/hooks/band.ts`와 내용이 같으므로 수정할 때는 두 파일을 모두 고쳐야 합니다 |
| `mods/next-prompts/types/index.d.ts` | `Suggestions`, `Reveal` 타입과 `PluginState`의 `next-prompts` 키 선언 |
| `mods/next-prompts/tests/next-prompts.test.tsx` | `claude plugin test ./mods/next-prompts`로 돌리는 테스트. 답 파싱, 요청 구성, 번호와 문구 클릭, 애니메이션과 취소, `$번호` 치환, 서브에이전트 제외 |
| `mods/next-prompts/tsconfig.json` | Claude Code가 모드를 불러올 때 만드는 `.claude-plugin/types/tsconfig.json`을 확장합니다. 그 폴더는 커밋하지 않습니다 |

## 변경 이력

- `0.8.1`: `$번호` 뒤에 스페이스를 쳐서 바꾸면 문구 뒤에 스페이스를 하나 붙여, 바로 이어서 쓸 수 있습니다.
- `0.8.0`: 입력창에 `$번호` 뒤 스페이스를 쳐야 제안으로 바뀝니다. 스페이스 없이 바로 Enter를 눌러도 보낼 때 제안으로 바꿉니다. 번호는 9개 제한 없이 모든 제안에 붙습니다. 제안은 보낸 뒤에 비워 quick-replies가 번호를 맞게 셉니다.
- `0.7.2`: 두 줄로 넘친 제안에 마우스를 올리면 모든 줄이 함께 반전되도록 했습니다.
- `0.7.1`: 서브에이전트의 턴에서는 제안을 만들지 않습니다. `turn.complete`가 서브에이전트의 턴에서도 발생하므로 `agentId`가 있으면 건너뜁니다.
- `0.7.0`: 제안을 120ms 간격으로 한 줄씩 표시합니다. 글자가 채워지는 동안에는 흐린 색으로 보이고, 한 줄이 완성되면 일반 색으로 바뀝니다. 애니메이션 진행 상태는 `reveal`에 별도로 저장해 `$번호` 치환과 quick-replies 번호가 그대로 동작하도록 합니다.
- 버전 변화 없음: 모드 폴더를 저장소 최상위에서 `mods/` 아래로 옮겼습니다.
- `0.6.0`: 빈 입력창의 숫자 키 단축키 대신 `$번호`로 문구를 넣습니다. 번호 표시도 `$1:`로 바뀌고, 각 모드가 번호를 직접 매깁니다.
- `0.5.0`: quick-replies의 접기 상태를 읽지 않습니다. 다음 제안은 늘 전체 문구로 보이고, `제목 :: 요청` 형식 대신 요청만 받습니다.
- `0.4.0`: 제안을 번호 버튼과 문구 버튼으로 나눴습니다. 번호는 입력창에 넣기만 하고, 문구 클릭은 바로 보냅니다.
- `0.3.0`: quick-replies의 접기(`0`)에 맞춰 제안을 `제목 :: 요청` 형식으로 받고, 접으면 제목만 보였습니다. `닫기`는 클릭으로만 합니다.
- `0.2.0`: 제안을 한 줄에 하나씩 보여 줍니다.
- `0.1.0`: 처음 추가. 턴이 끝나면 `haiku`로 다음 요청 2~3개를 제안하고, 숫자 1~3으로 입력창에 초안을 넣었습니다.
