2026-10-12

linetta 1.6 도구 호출 한도 조정과 iOS 27 실행 크래시 수정

linetta의 내장 에이전트는 한 턴에 도구를 쓸 수 있는 횟수가 정해져 있다. 그 한도가 24회였는데, 한도에 닿으면 패널에 도구 줄만 남기고 턴이 바로 끊겼다. 안내 문구는 “답변에 어디까지 했는지 적혀 있습니다”라고 했지만 모델에게는 그 답변을 쓸 기회가 없었고, 다음 턴은 이전 턴의 도구 기록을 다시 읽지 않아서 이어받을 근거도 없었다. 2026-10-11에 낸 v1.6.0은 이 문제부터 고쳤다.

한도에 걸린 턴에 마무리 답변 주기

이제 턴이 한도에 닿거나 같은 도구가 세 번 연달아 실패해서 멈출 때, 도구 호출을 막아 둔 채로 모델과 한 번 더 주고받는다. 모델은 이 마지막 답변에서 끝낸 것과 남은 것을 말하고, 그 답변은 패널과 대화 기록에 남는다. 결과 없는 도구 호출이 이력에 남아 있으면 모델 API 제공자(프로바이더)가 요청을 거부해서, 한도 때문에 실행하지 못한 도구 호출에도 결과를 채워 넣었다. 마무리 왕복이 실패하면 턴은 예전처럼 그대로 끝나고, 마무리 도중에 중지를 누르면 취소로 끝난다.

안내 문구도 “더 작게 나눠서 요청해 보세요”에서 “이어서 하려면 ‘계속’이라고 보내 보세요”로 바꿨다. 영어와 일본어 문구도 같이 바꿨다.

한도 자체는 24에서 48로 올렸다. “모든 씬 요약” 같은 요청은 씬마다 읽기와 쓰기가 한 번씩 들어서, 24회 한도로는 12씬에서 끊겼다.

설정에서 한도 바꾸기

씬이 많은 작품을 한 번에 맡길 때를 위해 한도를 설정에서 바꿀 수 있게 했다. 설정의 툴 예산 섹션에 “한 턴 도구 호출 한도” 칸이 생겼고, 8~200 사이로 정할 수 있으며 기본값은 48이다. 화면 설명에도 적어 두었듯이 한도를 높일수록 한 턴의 비용도 커진다. 이 값은 내장 에이전트에만 적용되고, 외부 MCP 클라이언트는 자기 루프를 돌리므로 상관이 없다.

에이전트는 턴을 시작할 때 이 값을 한 번만 읽어서, 턴 도중에 설정을 바꿔도 진행 중인 턴의 한도는 그대로다. 범위 밖 값은 엔진이 저장 단계에서 거부하고, 화면 입력란에서는 가장 가까운 경계값으로 당긴다. settings.json에 키가 없거나 범위를 벗어난 값이 들어 있으면 기본값으로 읽는다.

두 변경 모두 실제 앱에서 한도에 걸리는 턴을 돌려 보지는 않았고 테스트로 확인했다. 마무리 답변 테스트는 도구 호출을 한도보다 두 개 많이 쏟아내는 응답을 흉내 낸 뒤, 마무리 왕복에서 도구가 하나도 실행되지 않는지, 실행하지 못한 호출에도 결과가 채워졌는지, 마무리 답변이 대화 기록에 남는지를 본다. 저장소의 engine 디렉터리에서 두 테스트만 골라 돌린 결과다.

$ GOTOOLCHAIN=go1.26.9 CGO_ENABLED=0 go test ./internal/agent/ ./internal/settings/ \
    -run 'TestRun_theWallLetsTheModelSayWhereItStopped|TestAgentMaxToolCalls_defaultsPersistsAndStaysInRange' -v -count=1
=== RUN   TestRun_theWallLetsTheModelSayWhereItStopped
--- PASS: TestRun_theWallLetsTheModelSayWhereItStopped (0.19s)
PASS
ok  	github.com/devlikebear/linetta/engine/internal/agent	0.201s
=== RUN   TestAgentMaxToolCalls_defaultsPersistsAndStaysInRange
--- PASS: TestAgentMaxToolCalls_defaultsPersistsAndStaysInRange (0.00s)
PASS
ok  	github.com/devlikebear/linetta/engine/internal/settings	0.004s

Xcode 27로 빌드한 iOS 앱의 실행 크래시

Xcode 27(iOS 27 SDK)로 빌드한 1.5.0 iOS 앱은 실행 직후 SIGTRAP으로 종료됐다. 알고 보니 iOS 27 SDK는 UIScene 생명주기를 채택하지 않은 앱을 실행할 때 강제로 종료하는데, Tauri가 창을 띄울 때 쓰는 tao 0.35는 멀티 씬 플래그가 켜져 있을 때만 scene 방식으로 동작했다. Tauri를 2.11.2에서 2.12.1(tao 0.37.1)로 올리고 Info.ios.plist에 scene 매니페스트를 선언해서 해결했다. 두 창이 같은 library.db를 동시에 편집하지 않도록 멀티 씬은 꺼 두었다. Tauri 2.12.2와 2.12.3은 10월 9~10일에 나와서 배포 후 하루를 기다리는 pnpm 공급망 정책에 걸려서 9월 30일에 나온 2.12.1로 고정했다.

시뮬레이터에서 앱을 띄워 보면서 iOS 화면 문제도 같이 고쳤다. 상태바와 홈 인디케이터 영역에 생기던 흰 띠를 없앴고, 입력창에 포커스하면 페이지가 확대된 채 남던 문제와 작품 카드를 두 번 탭해야 열리던 문제도 고쳤다. 모바일에서는 쓰기 안전 체크리스트가 컨테이너 경로 대신 “이 기기의 앱 저장소”로 안내하고 Git 항목을 숨기며, 터치 기기에서 씬을 열 때 에디터에 자동으로 포커스하지 않는다. 에디터 본문은 한글을 어절 단위로 줄바꿈하도록 word-break: keep-all을 넣었고, 데스크톱에도 같이 적용된다.

iPhone 18 Pro와 iPad Pro 11-inch(M5) 시뮬레이터에서 make smoke-mobile-ios-sim이 통과했다. iPhone에서는 작품을 만들고 한글·영문 문장을 붙여 넣은 뒤 library.db에 자동 저장되는지, 앱을 종료했다 다시 열어도 같은 텍스트가 보이는지 확인했다. iPad에서는 화면 키보드로 “비가 온다.”를 자모 단위로 입력해 저장되는 것을 보고, 한 글자 더 입력한 직후 홈 버튼을 눌러도 저장되는지 확인했다.

마지막으로 10월 6일 이후 공개된 Go 표준 라이브러리 취약점 9건(net/http, net/textproto, crypto/tls)을 govulncheck가 잡아서, Linux CI의 의존성 감사 단계가 코드 변경과 상관없이 모든 PR에서 실패하고 있었다. engine/go.mod의 Go 버전을 1.26.6에서 1.26.9로 올려 해결했다.

확인한 것과 남은 것

Go 테스트와 프런트 테스트 601개는 통과했지만, 설정의 한도 칸과 한도에 걸리는 턴은 실제 앱 화면에서 눌러 보지 않았다. iOS는 회전, 멀티태스킹 창, 빠른 씬 전환, 외장 키보드, 좁은 화면에서 keep-all 줄바꿈이 어떻게 보이는지가 아직 확인 전이다.

App Store에서 받거나 brew install --cask devlikebear/tap/linetta로 설치한다. 직접 받은 1.5.0 데스크톱 앱은 메뉴의 업데이트 확인으로 올릴 수 있다.

이번 글에서 다룬 PR

  • #173 도구 호출 한도에 걸린 턴의 마무리 답변, 한도 24에서 48로
  • #175 한 턴 도구 호출 한도 설정
  • #172 Xcode 27 iOS 실행 크래시와 모바일 화면 수정
  • #174 Go 1.26.9

같은 작업대에서 나온 이웃 도구입니다.