DAY 02작업 2일째

위젯에서 답하고 메시지를 보내게 했다

질문 답장은 앱 질문 창과 경주를 붙이고, 메시지는 위젯이 들고 있다가 작업이 끝나면 넘겨 취소도 되게 했다.

보기만 하는 위젯으로는 반쪽이었다

세션이 질문을 하고 기다리면 코어가 보라색으로 바뀌는데, 정작 답하려면 앱을 열어 그 세션을 찾아야 했다. 짧은 지시 하나를 보낼 때도 마찬가지였다. 위젯 안에서 질문에 답하고, 세션에 메시지를 보낼 수 있어야 했다.

질문은 앱 질문 창과 경주를 붙였다

Claude가 선택지 질문을 하면 엔진은 AskUserQuestion 도구를 부르고 앱에 질문 창을 띄운다. 플러그인은 이 도구 호출에 훅을 걸어 질문 내용을 세션 파일로 내보내고, 두 가지를 동시에 기다린다. 앱 질문 창의 답(next(e))과 위젯이 쓴 답 파일이다. 먼저 온 쪽이 이긴다.

const first = await Promise.race([fromApp, fromWidget])
if (first.via === 'widget' && first.answers) {
  return { result: { questions: raw, answers: first.answers } } as never
}
return (await fromApp).r

위젯이 이기면 훅이 그 답으로 도구 호출을 끝낸다. 앱 쪽이 먼저 답하면 위젯의 대기는 그 신호를 보고 멈춘다. 그래서 어느 쪽에서 답해도 된다.

메시지는 위젯이 들고 있다

최근 대화와 입력창이 있는 채팅 카드
작업 중에 보낸 메시지에는 대기 표시와 취소가 붙는다

세션을 누르면 패널 옆에 채팅 카드가 열린다. 보낸 메시지는 플러그인이 $.prompt.submit({ text, asUser: true })로 세션에 넣는다. 최근 대화는 $.session.messages()로 읽어 파일로 내보내는데, 대화가 길면 매번 읽기 부담스러워서 채팅 카드가 열려 있을 때만 읽는다. 위젯이 카드를 연 동안 2초마다 감시 파일을 고쳐 쓰고, 플러그인은 그 파일이 최근에 바뀐 세션만 대화를 내보낸다.

여러 개를 미리 보내도 하나씩 넘어간다. 앞의 메시지로 세션이 다시 일을 시작하면 나머지는 그 작업이 끝날 때까지 다시 기다린다. 넘긴 직후 세션 상태가 아직 작업 중으로 바뀌기 전이라 다음 메시지가 연달아 넘어가는 일이 있어서, 넘긴 뒤 4초는 다음 메시지를 붙잡아 둔다.

감수한 것

위젯에서 보낸 메시지는 사람이 입력한 것처럼 들어가지만, 대화 기록에는 플러그인이 보낸 것으로 남는다. 대기 중인 메시지는 위젯 메모리에만 있어서 위젯을 다시 띄우면 사라진다.

기록 #04 · 2026.10.04