Skip to content

fix(tui): extension 컴포넌트의 render/invalidate 예외가 TUI를 죽이지 않게 격리 - #355

Merged
dmae97 merged 1 commit into
mainfrom
extension-render-guard-20261106
Nov 6, 2026
Merged

dmae97 merged 1 commit into
mainfrom
extension-render-guard-20261106

Conversation

@dmae97

@dmae97 dmae97 commented Nov 6, 2026

Copy link
Copy Markdown
Owner

요약

extension이 돌려준 컴포넌트의 render()나 invalidate()가 나중에 예외를 던져도, 그 예외가 TUI를 죽이지 않게 격리합니다. 지금 main에서는 setFooter로 등록한 footer가 render에서 예외를 던지면 OMK 프로세스가 종료 코드 1로 끝나고, 예외 메시지가 stderr에 그대로 찍힙니다.

  • guardExtensionRender(component, fallback?)
    • 원래 객체를 그대로 감싸므로 focus, dispose, lastComponent 같은 객체 식별이 유지됩니다.
    • 예외가 나면 그 인스턴스를 실패로 표시하고, 이후 Extension render failed 안내와 fallback만 그립니다. 같은 인스턴스는 다시 호출하지 않습니다.
  • 적용 지점과 실패 시 동작
    • tool 행(renderCall, renderResult): raw 결과 텍스트와 실행 상태를 유지합니다.
    • custom message: 원래 메시지 내용을 보여 줍니다.
    • widget, footer, header: 안내 문구를 표시합니다.
    • custom editor: 입력하던 텍스트를 지키며 기본 에디터로 돌아갑니다.
    • custom UI(showExtensionCustom): 창을 닫고 고정 오류로 reject합니다. 그래서 그 UI를 기다리던 tool이 pending으로 남지 않습니다.
  • 잡지 않는 것: handleInput() 예외, extension 코드 sandbox, verification 결과 변경
  • 문서: docs/extensions.md(Fallback), CHANGELOG.md(Fixed)

원래 체크아웃의 미커밋 작업에서 이 부분만 골라 main 기준으로 옮겼습니다.

검증 (로컬, 커밋 88fa372)

  • extension-render-errors.test.ts(원래 작업의 테스트, 21개)
    • guard 모듈만 넣고 적용 지점을 붙이기 전에는 16개가 실패했습니다.
    • 적용 지점을 붙인 뒤 custom UI 2개가 더 실패했습니다. close(result, error)로 reject 경로를 추가하고 21개 모두 통과했습니다.
    • 예외 메시지(private-secret)가 화면 출력에 나오지 않는지도 검사합니다.
  • npx vitest --run: ToolExecutionComponent, CustomMessageComponent, InteractiveMode, guardExtensionRender를 쓰는 파일과 extension*, tool-execution*, custom-message*, interactive* 33개 파일. 346개 통과, 1개 skip
  • 종료 0: npx tsgo --noEmit, npx biome check --error-on-warnings ., check:module-size, check:import-cycles, check:doc-links, check:feature-claims, check:release-surface
  • 실제 tmux(170x40, render에서 예외를 던지는 footer를 등록하는 임시 extension -e)
    • 이 브랜치: Extension render failed가 표시되고 입력 대기 상태가 유지됩니다. 예외 메시지는 화면에 나오지 않습니다.
    • main 기준: OMK가 EXITED=1로 종료되고, 예외 메시지가 stderr에 남습니다.

- guardExtensionRender: 같은 객체를 유지한 채 render/invalidate 예외를 잡고, 실패한 인스턴스는
  다시 부르지 않고 `Extension render failed`와 fallback을 그린다.
- 적용: tool renderCall/renderResult, custom message, widget, footer, header, custom editor
  (기본 에디터로 복구), custom UI(고정 오류로 reject해 tool이 pending으로 남지 않음).
- extensions 문서(Fallback), CHANGELOG 갱신.
@dmae97

dmae97 commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

OMK Community

Thanks for opening this pull request. Mention @omk-community with reproduction steps, a question, or the review help you need.

Automated response. No code changes or merges are performed.

@dmae97
dmae97 merged commit 25d0ede into main Nov 6, 2026
2 checks passed
@dmae97
dmae97 deleted the extension-render-guard-20261106 branch November 6, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant