16. 파일 참조 규격 (File Reference)
사용자가 프롬프트 텍스트 내에서 로컬 파일을 인라인으로 참조하기 위한 실시간 퍼지 검색, 인라인 토큰 포맷, 이스케이프 규칙, 어댑터별 변환 규칙을 정의한다.
16.1. 파일 검색 이벤트
16.1.1. control.file.search (Master → Client)
마스터가 클라이언트에 파일 퍼지 검색을 요청한다. 사용자가 @ 이후 문자를 입력할 때마다 디바운싱을 거쳐 발송된다.
{
"type": "control.file.search",
"payload": {
"query_id": "String (필수, UUID v4, 이 검색 요청의 고유 식별자)",
"query": "String (필수, 퍼지 검색 문자열. 빈 문자열이면 최근 수정 파일 목록 반환)",
"scope": "String (선택, 'workspace' | 'project' | 'global', 기본값 'workspace')",
"max_results": "Number (선택, 기본값 20, 최대 50)",
"filters": {
"extensions": ["String (선택, 확장자 필터. 예: ['.ts', '.tsx'])"],
"exclude_patterns": [
"String (선택, 제외 glob 패턴. 예: ['node_modules/**', '.git/**'])"
]
}
}
}
query_id는 사용자가 빠르게 타이핑할 때 여러 검색 요청이 동시에 진행되는 상황에서, 늦게 도착한 이전 쿼리의 결과가 최신 결과를 덮어쓰는 문제를 방지하기 위해 필수이다.
16.1.2. session.file.candidates (Client → Master)
{
"type": "session.file.candidates",
"parent_id": "String (필수, 대응하는 control.file.search의 message_id)",
"payload": {
"query_id": "String (필수, 대응하는 query_id 에코백)",
"candidates": [
{
"path": "String (필수, workspace_path 기준 상대 경로)",
"name": "String (필수, 파일명)",
"directory": "String (필수, 소속 디렉토리 경로)",
"extension": "String (선택, 확장자. 예: '.ts')",
"mime_type": "String (선택, IANA MIME 타입)",
"size_bytes": "Number (선택)",
"modified_at": "String (선택, ISO 8601, 최종 수정 시각)",
"match_score": "Number (선택, 0.0–1.0, 퍼지 매칭 점수)",
"match_ranges": [
{
"start": "Number (필수, 매칭된 문자 시작 인덱스)",
"end": "Number (필수, 매칭된 문자 종료 인덱스)"
}
]
}
],
"total_count": "Number (선택, 필터 적용 후 전체 후보 수. max_results로 잘린 경우 참고용)",
"truncated": "Boolean (필수, max_results 초과로 잘렸는지 여부)"
}
}
match_ranges는 CRS에서 퍼지 매칭된 문자를 하이라이팅하기 위해 포함된다. 예: 쿼리 "aut", 결과 "auth.ts" → [{start:0, end:3}]으로 aut 부분을 강조.
16.1.3. control.file.search.cancel (Master → Client)
진행 중인 검색을 취소한다. 사용자가 @ 모드에서 Esc를 누르거나 @를 지웠을 때 발송한다.
{
"type": "control.file.search.cancel",
"payload": {
"query_id": "String (필수, 취소 대상 query_id)"
}
}
16.2. 파일 참조 인라인 토큰 포맷 (File Reference Token)
control.prompt.request의 prompt_text 내에서 파일 참조를 표현하는 인라인 토큰 포맷을 정의한다.
16.2.1. 토큰 형식
<@file:ref_id|display_path>
예시: "이 파일의 버그를 찾아줘 <@file:ref_0|src/auth.ts>"
구성요소:
| 부분 | 설명 |
|---|---|
<@file: |
파일 참조 토큰 시작 마커 |
ref_id |
file_references 배열 내 항목과 매핑되는 식별자 |
| |
구분자 |
display_path |
사용자에게 표시된 경로 (팝업에서 선택한 표시명) |
> |
토큰 종료 마커 |
생성 경로의 단일성: 파일 참조 토큰은 오직 UI의 파일 선택 팝업(CRS §3.4)을 통해서만 생성될 수 있다 (MUST). 사용자가 키보드로 직접 입력한 텍스트에서는 토큰이 생성되어서는 안 된다 (MUST NOT). 이를 보장하기 위한 이스케이프 규칙은 §16.2.2에서 정의한다.
파싱 정규식: 토큰은 이스케이프되지 않은 패턴만 매칭하는 다음 정규식으로 식별한다 (MUST):
(?<!\\)<@file:([a-zA-Z0-9_-]+)\|([^>]+)>
매핑 실패 처리: 토큰의 ref_id가 file_references 배열에 매핑되지 않으면, 수신 측은 해당 토큰을 리터럴 텍스트로 처리해야 한다 (MUST). 토큰을 무시하거나 삭제해서는 안 된다 (MUST NOT).
16.2.2. 토큰 이스케이프 규칙 (Token Escaping)
사용자가 직접 <@file:...> 패턴을 타이핑하여 토큰을 위조하는 것을 방지하고, 일반 텍스트에서 토큰 패턴과 우연히 일치하는 문자열이 파일 참조로 오파싱되는 것을 방지하기 위한 이스케이프 규칙이다.
이스케이프 테이블:
| 리터럴 입력 | 이스케이프 결과 | 근거 |
|---|---|---|
\ |
\\ |
백슬래시 리터럴 보존 |
<@ |
\<@ |
모든 토큰 시작 패턴 보호. 현재의 <@file: 뿐 아니라, 향후 확장 토큰(<@user:, <@symbol: 등)과의 충돌도 예방한다. |
적용 주체 및 시점:
- 이스케이프(인코딩): 엣지 노드(또는 마스터 서버)가
control.prompt.request의prompt_text를 구성할 때, 사용자가 직접 입력한 텍스트 구간에 대해 이스케이프를 적용한다 (MUST). UI 파일 선택 팝업을 통해 삽입된 토큰 구간은 이스케이프 대상에서 제외한다 (MUST). - 언이스케이프(디코딩): 수신 측(로컬 클라이언트)이
prompt_text를 파싱할 때, 아래의 파싱 순서에 따라 토큰 추출 후 나머지 텍스트에서 이스케이프 시퀀스를 해제한다 (MUST).
파싱 순서 (MUST):
- 이스케이프되지 않은 토큰 패턴 매칭: 정규식
(?<!\\)<@file:([a-zA-Z0-9_-]+)\|([^>]+)>으로 유효한 토큰을 추출한다. - 매칭된 토큰을
file_references배열과 대조하여 유효성을 검증한다. - 토큰이 아닌 나머지 텍스트 구간에서 이스케이프 시퀀스를 해제한다:
\\→\,\<@→<@순서로 치환한다.
구현 예시:
# 사용자 입력 (입력창에서의 원문)
"<@file:injection>은 위조이고, 이건 진짜야 {토큰: src/auth.ts}"
# 전송 시 prompt_text (이스케이프 적용)
"\<@file:injection>은 위조이고, 이건 진짜야 <@file:ref_0|src/auth.ts>"
# 수신 측 파싱 결과
- 토큰: ref_0 → src/auth.ts (유효한 파일 참조)
- 텍스트: "<@file:injection>은 위조이고, 이건 진짜야" (리터럴)
16.3. 어댑터별 변환 규칙 (Adapter Conversion)
로컬 클라이언트는 에이전트의 요구사항에 따라 인라인 토큰을 변환해야 한다 (MUST). 변환 전략은 에이전트별로 다르며, 클라이언트 구현에 위임한다. 본 규격은 대표적 변환 패턴을 다음과 같이 예시한다:
| 어댑터 | 변환 예시 | 설명 |
|---|---|---|
| Claude Code | 토큰을 prompt_text에서 제거하고, context_files 또는 도구 호출로 분리 |
에이전트가 파일 내용을 자체 로드하는 경우 |
| 범용 LLM | <@file:ref_0|src/auth.ts> → [File: src/auth.ts] 또는 파일 내용 인라인 삽입 |
에이전트가 파일 참조 개념이 없는 경우 |
| 스크립트 에이전트 | 토큰에서 경로를 추출하여 프로세스 인자로 전달 | CLI 기반 에이전트 |
변환 불가 시 동작: 클라이언트가 특정 토큰을 해석할 수 없는 경우, display_path를 리터럴 텍스트로 치환하여 에이전트에 전달해야 한다 (MUST). 토큰을 무시하거나 삭제해서는 안 된다 (MUST NOT).
16.4. control.prompt.request 확장
§6.1.1의 control.prompt.request에 file_references 필드가 추가되었다. 상세 스키마는 §6.1.1을 참조한다.
file_references와 기존 context_files의 관계: context_files는 프롬프트와 함께 첨부되는 참조 파일이고, file_references는 프롬프트 텍스트 내에서 인라인으로 언급된 파일의 메타데이터이다. 양자는 독립적이며, 동일 파일이 양쪽에 모두 존재할 수 있다.
16.5. 능력 협상 (Capability Negotiation)
§12.2.1의 session.capabilities에 파일 참조 관련 능력 필드가 추가되었다. 상세 스키마와 필터링 규칙은 §12.2.1을 참조한다.