콘텐츠로 이동

프로바이더란

호출자는 프로바이더(Claude)를 이름으로 부를 뿐, 어댑터를 직접 다루지 않습니다. 이 구분은 의도적입니다. 어댑터는 협력 객체와 상태를 가진 동작하는 객체인 반면, 프로바이더는 CLI의 정체성 — “claude와 대화한다”, “codex로 전환한다”라고 말할 때 가리키는 그것입니다.

command.provider = Codex; // 기계를 넘겨주는 것이 아니라 값 대입

프로바이더는 command가 실제로 어댑터를 필요로 하는 시점, 즉 send() 시점에 어댑터를 만듭니다. 그 전이 아닙니다.

두 단어는 실제로 서로 다른 것을 가리키며, 이 분리가 위의 대입문을 정직하게 만듭니다.

프로바이더 어댑터
무엇인가 CLI의 정체성 동작하는 객체
무엇을 가지는가 이름, 그리고 어댑터를 만드는 방법 협력 객체와 상태 — argv 빌더, PATH 보강, job spawner, 이벤트 파서
몇 개 존재하는가 CLI당 하나, 싱글턴으로 export 세션마다 새로 하나
호출자가 무엇을 하는가 이름으로 부른다 결코 손대지 않는다

Claude는 인스턴스화할 클래스가 아니라 싱글턴으로 export됩니다. claude CLI는 하나뿐이기 때문입니다. Command.open(Claude, …)는 무언가를 생성하는 문장이 아니라 그것을 지목하는 문장으로 읽혀야 합니다.

import { Claude, Command } from 'activecli';
const command = Command.open(Claude, { workingDir: '/proj' });

command.provider = Codex가 기계를 넘기는 일이었다면 대가가 있어야 합니다 — 시작할 프로세스, 찾아야 할 실행 파일, 조립할 환경. 그런 대가는 없습니다. 프로바이더는 그중 아무것도 지니고 있지 않기 때문입니다.

이것은 Command가 ActiveRecord의 Relation에서 빌려 온 바로 그 지연입니다. 세터는 의도를 쌓고, toArgv()는 무엇이 실행될지 보여주며, send()가 실행합니다. 커넥션을 바꾸는 일은 실행 전까지 아무 비용도 들지 않습니다.

ActiveRecord ActiveCLI
커넥션 전환은 실행 전까지 비용이 없다 command.provider = Codex는 다음 send() 전까지 비용이 없다

command를 다른 CLI로 향하게 하는 것은 대입하는 순간이 아니라 다음 send()에서 효력을 가집니다. CLI 프로세스는 다른 프로세스가 될 수 없으므로, 전환한다는 것은 프로세스를 교체한다는 뜻입니다 — 그리고 실행할 것이 생기기 전까지 그 비용을 치를 이유가 없습니다.

AbstractProvider는 하위 클래스가 채워야 할 멤버 두 개를 선언하며, 그 외에는 아무것도 요구하지 않습니다.

abstract get name(): string;
abstract createAdapter(): AbstractAdapter;

createAdapter() 어댑터를 반환합니다. 세션은 자신만의 파이프와 상태를 가진 실행 중인 프로세스이므로 자신만의 어댑터를 가집니다. 프로바이더는 두 세션 모두가 그 이름으로 불린 대상일 뿐입니다.

프로바이더를 공짜로 교체할 수 있는 이유도 여기에 있습니다. send()가 어댑터를 요구하기 전까지 Codex에 관한 그 무엇도 살아 있지 않으므로, 그것을 지목하는 일은 그저 지목하는 일입니다.

이 라이브러리를 쓰기 전에 조사한 경쟁 플러그인은 여섯 개의 CLI 채널을 붙여 두었지만 그 사이에 공통 계약이 없습니다. send는 Claude에 대해 sessionId·disableThinking·agentPrompt를, Codex에 대해 threadId·baseUrl·apiKey·serviceTier를 받습니다 — 같은 동사에 다른 파라미터이므로, 호출자는 페이로드를 만들기 위해 지금 상대가 어느 프로바이더인지 알아야 합니다. 그것은 통합이 아니라 한 지붕 아래의 분리 수납입니다.

정체성을 기계와 분리해 두는 것이 다른 방식을 가능하게 합니다. 호출자는 어느 CLI인지를 한 단어로 말하고, 그 단어가 함축하는 것은 호출자가 아니라 어댑터의 문제입니다.