feat(my-deepagent): v0.4 chat UX boost + A/B live verification
Claude-Code 동급 chat 경험으로 끌어올림 + 7개 핵심 흐름 실제 OpenRouter verify.
A — Live verification (scripts/live_verify.py, 7 PASS, 약 $0.02):
- A1 1-turn chat (CLI-eq) → Haiku 4.5 한국어 응답
- A2 sessions resume → 같은 session_id 재투입 시 LangGraph state 복원
- A3 /skill <name> system inject → SKILL.md ("한국어 haiku 3 lines") 가 정확히
3행 한국어 시 생성 (LLM 행동 제어 강력한 증거)
- A4 /plan → /approve → LLM plan markdown only, 차단 도구 시도 없음
- A5 /agents spawn → 실제 sub-agent ainvoke + parent stream push
- A6 auto-compaction → 14 메시지 → 4 archive + 77 토큰 summary
- A7 /workflow wiring → role↔persona 매칭 사전 검증
B1 — Markdown rendering:
- app.js pure-JS 미니 파서: 코드 펜스 / ATX 헤더 / ul/ol / `code`/**bold**/
*italic*/[link](url)
- XSS 정책 유지: createElement + textContent only. 링크 href 는 http(s):
스킴 강제.
B2 — System event card (collapsible):
- _classifySystemMessage 가 [sub-agent .../workflow .../Earlier conversation
history/당신은 plan mode/The user APPROVED/skill] 접두사 분류 후 <details>
카드로 렌더.
B3 — Token streaming via AsyncCallbackHandler:
- ChatOpenAI(streaming=True)
- _StreamingChunkPusher (AsyncCallbackHandler) → asyncio.Queue per session.
- SSE _session_event_stream 이 queue drain → event: chunk SSE. 100ms poll.
- 순서 보장: chunk drain → message rows yield (placeholder 가 메시지로
교체되기 전에 토큰 visible).
- 라이브: 5 chunk events + 1 final message, "안녕하세요, / 무 / 엇을 도와드 /
릴까요?" 토큰 단위 push.
B4 — Cancel mid-turn:
- POST /api/sessions/{id}/abort + app.state.pending_per_session 인덱스.
- 새 user 메시지 도착 시 이전 in-flight task 자동 cancel.
- "■ 중단" 버튼 — 대기 중 visible, 완료/취소 시 hide.
B5 — IME composition-safe Enter:
- compositionstart/compositionend 플래그 — 한글 IME 후보 commit Enter 무시.
- Cmd/Ctrl+Enter 는 항상 전송.
DB hot-fix:
- Database.__init__ pool_pre_ping=True — Postgres asyncpg stale connection
→ SSE 부하에서 500 발생 해결.
기타:
- createNewSession 의 repo_path: "" → "." (min_length=1 검증 통과).
- test_conversation_gui.py fake_invoke 가 chunk_queue kwarg 받도록 업데이트.
게이트:
- ruff / format / mypy: PASS (143 source files)
- pytest -q --ignore=tests/integration/test_e2e_workflow.py
--ignore=tests/integration/test_openrouter_smoke.py: 709 passed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,70 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **v0.4 chat UX boost + A/B live verification** — Claude-Code 동급의 chat
|
||||
경험으로 끌어올림 + 7개 핵심 흐름을 실제 OpenRouter 로 verify.
|
||||
|
||||
**A — Live verification (`scripts/live_verify.py`, 7 PASS)**:
|
||||
- A1 1-turn chat (CLI-eq) → Anthropic Haiku 4.5 한국어 응답
|
||||
- A2 sessions resume → 같은 session_id 재투입 시 LangGraph thread state 복원
|
||||
- A3 `/skill <name>` system inject → SKILL.md ("한국어 haiku 3 lines") 가
|
||||
실제로 LLM 행동을 제어 (정확히 3행 한국어 시 출력)
|
||||
- A4 `/plan → /approve` → LLM 이 plan markdown 만 생성, 차단 도구 시도 없음
|
||||
- A5 `/agents spawn` → 실제 sub-agent ainvoke + 결과 parent stream push
|
||||
- A6 auto-compaction → 14 메시지 → 4 archive + 77 토큰 summary
|
||||
- A7 `/workflow` wiring → role↔persona 매칭 사전 검증
|
||||
- 총 비용 약 \$0.02.
|
||||
|
||||
**B1 — Markdown rendering** in conversation.html:
|
||||
- `app.js` 의 pure-JS 미니 마크다운 파서 — 코드 펜스, ATX 헤더, ul/ol,
|
||||
inline `code`/**bold**/*italic*/[link](url) 지원.
|
||||
- XSS 정책 유지: `createElement + textContent` 만 사용, `innerHTML`
|
||||
금지. 링크 href 는 `http(s):` 스킴으로 강제 제한.
|
||||
- `style.css` 에 `.md-p`, `.md-h`, `.md-ul`, `.md-ol`, `.md-code` 등
|
||||
스타일 추가. user bubble (brown 배경) 안에서도 코드/링크 가독성 유지.
|
||||
|
||||
**B2 — System event card** (collapsible):
|
||||
- `_classifySystemMessage` 가 system content 의 접두사를 보고
|
||||
"Sub-agent result / Workflow started / Compaction summary / Plan mode
|
||||
activated / Approved plan / Skill activated" 등으로 분류 → `<details>`
|
||||
카드로 렌더. 채팅 thread 가 이벤트 메시지로 도배되지 않음.
|
||||
|
||||
**B3 — Token streaming via AsyncCallbackHandler**:
|
||||
- `session.py:resolve_model_instance` 의 `ChatOpenAI(streaming=True)`.
|
||||
- `api/agent_runner._StreamingChunkPusher` (AsyncCallbackHandler) 가
|
||||
`on_llm_new_token` 마다 `asyncio.Queue` 에 `{"type":"delta","text":...}`
|
||||
push.
|
||||
- `api/routes/sessions._session_event_stream` 이 queue 를 drain 해 SSE
|
||||
`event: chunk` 로 전송. Poll interval 100ms. 순서 보장: chunk 먼저
|
||||
drain → message rows 후 yield (placeholder 가 메시지로 교체되기 전에
|
||||
토큰이 시각적으로 흐르도록).
|
||||
- 프론트엔드 `app.js` 의 `appendStreamDelta` 가 chunk 를 placeholder 에
|
||||
누적; 최종 `message` SSE 가 도착하면 markdown-rendered bubble 로 교체.
|
||||
- 라이브 verify: 5 chunk events + 1 final message, OpenRouter Haiku 응답
|
||||
"안녕하세요, / 무 / 엇을 도와드 / 릴까요?" 토큰 단위 push 확인.
|
||||
|
||||
**B4 — Cancel mid-turn** (`POST /api/sessions/{id}/abort`):
|
||||
- `app.state.pending_per_session: dict[session_id, Task]` 인덱스 +
|
||||
`_remove_from_session_map` done-callback.
|
||||
- 새 user 메시지 도착 시 이전 in-flight task 자동 cancel (Claude Code parity).
|
||||
- 프론트엔드 우하단 "**■ 중단**" 버튼 — 대기 중 visible, 완료/취소 시 hide.
|
||||
|
||||
**B5 — IME composition-safe Enter**:
|
||||
- 한글/일본어/중국어 IME 입력 중 Enter 가 후보 commit 용으로 쓰일 때
|
||||
전송되지 않도록 `compositionstart` / `compositionend` 플래그. 순수
|
||||
Enter 만 무시, Cmd/Ctrl+Enter 는 우선 적용.
|
||||
|
||||
**DB hot-fix** (v0.4 chat UX 라운드 도중 발견):
|
||||
- `Database.__init__` 에 `pool_pre_ping=True` — Postgres asyncpg pool 이
|
||||
idle/network blip 후 stale connection 을 넘기던 문제 (SSE 0.5s poll
|
||||
부하에서 500 발생) 해결.
|
||||
|
||||
**새 테스트** (정확한 인보크 시그니처 sync + 기존 통합 보존):
|
||||
- `tests/integration/test_conversation_gui.py` 의 `fake_invoke` 스텁이
|
||||
`chunk_queue` kwarg 도 받도록 업데이트.
|
||||
- 전체 회귀: 709 passed (no new failures).
|
||||
|
||||
### Added
|
||||
- **v0.4 — Workflow generator UI + hot-reload + UX polish**. 사용자가 직접
|
||||
YAML 을 작성하지 않고도 브라우저에서 새 워크플로우 템플릿을 만들고 즉시
|
||||
|
||||
Reference in New Issue
Block a user