Skip to content

fix(frontend): todo list empty bug in agent chat#21

Merged
tendtoyj merged 5 commits into
mainfrom
tendtoyj/plu-317-todo-list-empty-bug-in-agent-chat
Feb 9, 2026
Merged

fix(frontend): todo list empty bug in agent chat#21
tendtoyj merged 5 commits into
mainfrom
tendtoyj/plu-317-todo-list-empty-bug-in-agent-chat

Conversation

@tendtoyj
Copy link
Copy Markdown
Collaborator

@tendtoyj tendtoyj commented Feb 9, 2026

Summary

에이전트 채팅에서 write_todos 도구 호출 시 할 일 목록이 빈 상태로 렌더링되는 버그를 수정합니다. 기존에는 output만 파싱하여 할 일 항목을 추출했으나, 실제 데이터가 input에 포함되는 경우가 많아 목록이 비어 보이는 문제가 있었습니다. 또한 in_progress 상태가 누락되어 진행 중인 항목이 올바르게 표시되지 않았습니다.

Changes

  • write_todos 페이로드 파싱 로직을 전용 모듈(toolTodoParser.ts)로 분리하고, inputoutput 순서로 폴백 파싱하도록 개선
  • Python 리터럴 형식(', None, True/False)의 페이로드도 정규화하여 파싱 가능하도록 처리
  • 이스케이프된 아포스트로피(\') 포함 페이로드 파싱 지원
  • in_progress 상태를 QueueTodo 타입 및 큐 UI 컴포넌트에 추가하여 진행 중 항목을 시각적으로 구분(앰버 색상 인디케이터)
  • 순환 참조 및 과도한 중첩 깊이에 대한 방어 로직 추가
  • 파서에 대한 회귀 테스트 케이스 8건 추가

Test plan

  • toolTodoParser.test.ts 테스트 8건 전체 통과 확인
  • 에이전트 채팅에서 write_todos 호출 시 할 일 목록이 정상적으로 표시되는지 확인
  • in_progress 상태 항목이 앰버 색상 인디케이터와 함께 렌더링되는지 확인
  • completed 상태 항목이 취소선과 함께 표시되는지 확인

🤖 Generated with Claude Code

@tendtoyj tendtoyj self-assigned this Feb 9, 2026
Copy link
Copy Markdown
Collaborator Author

@tendtoyj tendtoyj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: fix(frontend): todo list empty bug in agent chat

Overview

에이전트 채팅에서 write_todos 도구 호출 시 할 일 목록이 빈 상태로 렌더링되는 버그를 수정하는 PR입니다. 핵심 원인은 output만 파싱하던 로직이었는데, 실제 데이터가 input에 있는 경우가 많았던 것. 추가로 in_progress 상태 지원도 포함됩니다.

변경 범위: +353 / -33, 파일 4개 (신규 2, 수정 2)


좋은 점

  • 관심사 분리가 깔끔합니다. 인라인 parseTodosFromOutput을 별도 모듈 toolTodoParser.ts로 분리하여 테스트 가능성과 재사용성이 크게 향상됐습니다.
  • 방어적 코딩이 잘 되어 있습니다. 순환 참조 감지(visited Set), 최대 깊이 제한(MAX_TODO_UNWRAP_DEPTH = 24), 비정상 항목 처리(normalizeTodoItem)가 모두 적절합니다.
  • 다중 폴백 전략이 합리적입니다. input → output, JSON → Python literal → bracket extraction 순서로 점점 관대한 파싱을 시도합니다.
  • 테스트 커버리지가 양호합니다. 8개 테스트 케이스로 핵심 시나리오를 잘 다루고 있습니다 (9건 전체 통과 확인).
  • UI 변경이 최소한으로 제한되어 있습니다. in_progress 상태 추가가 기존 컴포넌트 API를 자연스럽게 확장합니다.

개선 제안

1. isRecordArray.isArray 체크 누락 (Low risk)

toolTodoParser.ts:7-9

function isRecord(value: unknown): value is TodoRecord {
  return typeof value === 'object' && value !== null;
}

Array.isArray(value)typeof === 'object'를 반환합니다. resolveTodoArray에서 Array.isArray 체크가 isRecord 앞에 있어 현재 코드에서는 문제 되지 않지만, isRecord가 단독으로 사용될 경우를 대비해 && !Array.isArray(value) 추가를 권장합니다.

2. normalizePythonLiteral에서 문자열 내부 None/True/False 오치환 가능성 (Low risk)

toolTodoParser.ts:103-114

이 치환이 싱글쿼트로 감싸진 문자열 값 내부의 None, True 같은 단어까지 변환할 수 있습니다. 예: 'status': 'None of the above''status': 'null of the above'. 할 일 목록 데이터에서 이런 경우가 발생할 확률은 낮지만, 엣지 케이스로 인지해둘 필요가 있습니다.

3. content 키 unwrap과 todo 항목의 content 필드 충돌 가능성 (Medium risk)

toolTodoParser.ts:160-162

if (current.content !== undefined) {
  current = current.content;
  continue;
}

resolveTodoArray에서 content 키를 unwrap하는데, 만약 { content: "Task A", status: "pending" }처럼 단일 todo 객체가 직접 전달되면, content 문자열 "Task A"로 unwrap한 뒤 parseStringPayload를 시도하게 됩니다. 이때 "Task A"는 파싱에 실패하여 null을 반환하므로 데이터 손실이 됩니다. todos/items 키 체크 후 content를 추종하기 전에 해당 객체 자체가 todo 항목인지 확인하는 로직이 있으면 더 안전합니다.

4. 테스트 커버리지 보강 필요

누락된 시나리오:

  • items 키 경로: resolveTodoArray에서 current.items를 체크하지만 관련 테스트가 없음
  • update 키를 통한 정상 unwrap: 테스트는 64단계 초과와 순환만 다루고, 정상적인 { update: { todos: [...] } } 패턴이 없음
  • output이 문자열인 경우: output이 직접 JSON 문자열인 경우의 테스트가 없음
  • normalizePythonLiteralNone/True/False 변환: 이 경로를 명시적으로 검증하는 테스트가 없음

잠재적 위험

  • 보안: 외부 입력을 JSON.parse로 처리하지만, 파싱 결과를 DOM에 직접 삽입하지 않고 toOptionalStringString()으로 문자열 변환 후 React 컴포넌트로 렌더링하므로 XSS 위험은 낮습니다.
  • 성능: 문자 단위 bracket balancing이 있지만, 실제 todo 페이로드 크기를 감안하면 문제 없습니다.
  • 하위 호환: QueueTodo.status 타입에 in_progress가 추가되었으나, 기존 pending | completed 값은 영향 없음. 깔끔한 확장입니다.

결론

전반적으로 잘 작성된 PR입니다. 버그의 근본 원인을 정확히 파악하고, 파서를 견고하게 재설계했으며, 테스트도 충분히 작성되어 있습니다. 위 제안사항 중 #3 (content 키 충돌)이 가장 주의할 점이고, 나머지는 minor입니다. 테스트 보강(#4)을 추가하면 더 좋겠지만 머지를 블록할 정도는 아닙니다.

Verdict: Approve with minor suggestions

🤖 Reviewed with Claude Code

@tendtoyj tendtoyj merged commit cf9f88c into main Feb 9, 2026
1 check passed
@tendtoyj tendtoyj deleted the tendtoyj/plu-317-todo-list-empty-bug-in-agent-chat branch February 9, 2026 08:15
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