1 USD ≈ 27,000 credits · display only
Reference rate may change over time.
1 USD ≈ 27,000 credits · display only
Reference rate may change over time.
/app/chat Manual end-to-end QA for portal product mode (79ai-style): intent → assistant reply → inline job form → submit → job result (or clear error).
Automated unit coverage: npm run theme:test. This doc does not replace live job runs against Gommo.
Maintainer source mirror: repo doc/CHAT-PRODUCT-E2E.md.
| Step | Pass when |
|---|---|
| Stack | npm run docs:stack — docs :5173, gateway :3001 (or GATEWAY_PROXY_TARGET remote) |
| Login | Signed in at /app/chat/ (Bearer in browser) |
| Mode | Chat settings: product assistant (default gw_portal_chat_settings_v1 → assistantMode: "product") |
| Credits | Balance enough for at least one cheap job per type you test (note starting balance: _____ cr) |
| Network | DevTools → filter gateway/chat, gateway/jobs — no CORS / 401 surprises |
Also linked from Portal smoke test.
Optional regression before manual E2E:
npm run theme:test
npm run portal:browser:test -- tests/browser/site-agent-widget.spec.ts tests/browser/site-agent-widget-guide.spec.ts
npm run portal:browser:test -- tests/browser/chat-product-inline.spec.ts tests/browser/chat-product-intents.spec.ts
npm run portal:smoke # routes only; needs docs:stack
npm run catalog:audit-remove-bg # dealer mis-tag check (exit 2 = filtered empty)Playwright starts its own VitePress on :5200 (see playwright.config.ts) — not the same port as docs:stack (:5173).
Do once per session or after large chat changes.
| # | Check | Pass when |
|---|---|---|
| C1 | SSE stream | Assistant text streams; no raw thinking in main bubble (reasoning collapsed if shown) |
| C2 | Lead vs API details | Long spec in Chi tiết API / API details accordion; lead ≤ few lines or type-specific fallback (e.g. “Dùng form bên dưới để tạo video…”) |
| C3 | Inline card UI | Form is stacked card (.or-chat-inline-job-form), not horizontal playground bar |
| C4 | mediaModelContext | DevTools: POST /gateway/chat body includes mediaModelContext on product media turns (JSON object, not empty for active job type) |
| C5 | Session sync | After turn, ai-chat-sessions sync no hard error in network (if remoteSessionSync: true) |
| C6 | Submit disabled | Create disabled until prompt non-empty or (tool jobs: remove-bg, upscale, …) at least one job ref when notes are optional |
| C7 | Model picker | If catalog has 2+ models for type, dropdown works; fields refresh without invalid ratio/mode |
| C8 | Dev JSON | Developer JSON <details> opens; sample matches POST /gateway/jobs/{type} |
| C9 | Credits hint | Footer shows ~N cr when model has pricing (approximate OK) |
| C10 | Error path | Sign out mid-test → friendly auth message, not blank bubble |
| C11 | Account context | POST /gateway/chat → mediaModelContext.account.credits when signed in |
| C12 | Quick actions | Under inline form: Top up, Playground, Copy API path |
| C13 | Job refs | Video/avatar form: optional image/video ref upload → included in job submit |
| C14 | Result actions | After success: Files, Copy job id, Open/copy result URL |
| C15 | Support intents | Ask còn bao nhiêu credit → no inline job form; chips (Nạp credits). Ask lấy access_token → Login + Auth docs. affiliate → Affiliate link |
| C16 | Product context | Any product turn (not only media): POST /gateway/chat includes mediaModelContext.account when signed in |
Automated (mock chat, no job spend): npm run portal:browser:test -- tests/browser/chat-product-inline.spec.ts
For each row: send sample message → verify UI → fill prompt (short test string) → Submit → record job outcome.
Job outcome legend
| Type | Sample user message (copy-paste) | UI pass | Submit route | Job outcome | Notes |
|---|---|---|---|---|---|
image | đưa tôi api tạo ảnh | Badge Image, quantity, ratio/mode if catalog has them | Create image → image job wait | ☐ OK ☐ UP ☐ FAIL | |
video | đưa tôi api để tạo video 5s | Badge Video, duration hint if user said 5s | Create video → video job wait | ☐ OK ☐ UP ☐ FAIL | Poll may take minutes |
music | api tạo nhạc / music | Badge Music | Create music → generic createMediaJobWait | ☐ OK ☐ UP ☐ FAIL | |
tts | api TTS giọng đọc | Badge TTS | Create speech → generic job | ☐ OK ☐ UP ☐ FAIL | |
avatar-lipsync | api avatar lipsync nhép môi | Badge Avatar/lipsync | Create avatar job → generic job | ☐ OK ☐ UP ☐ FAIL | May need ref URLs in payload |
image-upscale | api upscale ảnh | Badge + upscale copy | Upscale image | ☐ OK ☐ UP ☐ FAIL | |
remove-bg | api xóa nền ảnh | Badge remove-bg | Remove background | ☐ OK ☐ UP ☐ FAIL | UP = catalog message “chưa có model xóa nền” (strict filter) — not HTTP 404 on wrong video slug |
video-upscale | api upscale video | Badge video upscale | Upscale video | ☐ OK ☐ UP ☐ FAIL | |
video-vfx | api video vfx hiệu ứng | Badge VFX | Apply VFX | ☐ OK ☐ UP ☐ FAIL | |
video-subtitle | api phụ đề video subtitle | Badge subtitles | Create subtitles | ☐ OK ☐ UP ☐ FAIL | |
video-cut | api cắt video trim | Badge cut | Cut video | ☐ OK ☐ UP ☐ FAIL |
After submit for any type:
POST /gateway/jobs/{type} (or image/video helpers) returns; poll completes or times out with messageSend once to ensure wrong form is not shown.
| Message | Expected inlineJobType | Pass |
|---|---|---|
api avatar lipsync | avatar-lipsync (not video) | ☐ |
api upscale video | video-upscale (not image-upscale) | ☐ |
api xóa nền | remove-bg | ☐ |
api tạo video 5s | video (not music) | ☐ |
Switch chat to integration coach (settings → assistantMode: "integration").
| Check | Pass when |
|---|---|
| I1 | Same message “api tạo ảnh” → no product inline job card (or no inlineJobType meta) |
| I2 | Reply skews Tier A / public API coach, not “form below” product lead |
Switch back to product before closing QA.
Repeat §1 + 3 rows (video, music, image) on production URL (e.g. https://79router.com/app/chat/).
| Env | Date | Tester | C1–C10 | 3 job types | Blockers |
|---|---|---|---|---|---|
| Local | ☐ | ☐ | |||
| Live | ☐ | ☐ |
Maintainer copy with latest automated run: repo doc/CHAT-PRODUCT-SIGNOFF-2026-10-21.md.
Product chat E2E — YYYY-MM-DD
Environment: local | staging | live (URL)
Commit / deploy: ___
Tester: ___
Cross-cutting C1–C16: PASS | FAIL (ids: ___)
Site Agent widget W1–W10: PASS | FAIL (ids: ___)
Automated browser (mock): `site-agent-widget` + `site-agent-widget-guide` (W14) + `chat-product-inline` + `chat-product-intents` PASS | FAIL
Job types tested (live submit): ___ / 11 (full chat) | widget image only ☐
Failures: (type, symptom, network status, screenshot path)
Follow-ups:
-| # | Check | Pass when |
|---|---|---|
| T3-1 | Low-credit inline | Balance < threshold → yellow notice on inline form + link Nạp credits; submit asks confirm |
| T3-2 | Unaffordable model | Create disabled when balance < model ~N cr estimate |
| T3-3 | Remote sessions | With remoteSessionSync: true, sign in → sidebar lists Gommo sessions (remote: true); opening empty local copy pulls get_messages |
| T3-4 | Hydrated UI | Old assistant messages show support chips / result actions from metadata.productChat (no duplicate inline form after completed job) |
| T3-5 | Support chips | Credits → Usage activity; Auth → BYOK link |
| T3-6 | Site widget | Floating agent in product mode sends mediaModelContext.account on chat (DevTools) — full checklist §8 |
Same product chat capabilities as /app/chat/ in a side panel. Widget is hidden on full chat (/app/chat/) and docs zones; quick entry: /app/playground/ (FAB Ask Agent / Hỏi Agent).
Automated (no login, mock Bearer):
npm run theme:test # includes site-agent-widget-storage + handoff unit tests
npm run portal:browser:test -- tests/browser/site-agent-widget.spec.tsManual setup: npm run docs:stack → open http://localhost:5173/app/playground/, sign in, ensure gw_portal_chat_settings_v1 → assistantMode: "product".
| # | Check | Pass when |
|---|---|---|
| W1 | FAB + panel | FAB opens panel; backdrop/close collapses panel |
| W2 | Multi-tab | + adds tab (max 8); switch tabs; close tab; + works while another tab is streaming |
| W3 | Stream stop | Stop / Dừng aborts in-flight reply; can send again |
| W4 | Reload persistence | F5 with panel open → tabs/messages restore; no stuck streaming dots (streaming cleared on read/write) |
| W5 | Attach image | + attach → pending chip → send; POST /gateway/chat includes attachments when signed in |
| W6 | Full chat handoff | Open full chat / Mở chat đầy đủ → /app/chat/?session=… with same thread |
| W7 | Inline job UI | One stacked inline form per anchor; no duplicate horizontal quick bar |
| W8 | Confirm prompt | After assistant Prompt chi tiết (or nearest media turn), user says tạo đi / oke → job uses that prompt (not an older thread subject) |
| W9 | Agent copy | Assistant does not claim image/video is already rendering or that billing already started — only form submit or confirm starts jobs |
| W10 | mediaModelContext | DevTools: product turns include mediaModelContext and account.credits when signed in (same as T3-6) |
| W11 | Playground guide | Ask hướng dẫn tôi tạo ảnh con mèo → guide card; Tạo ngay trong chat opens inline form with seed prompt; on /app/playground/ Áp dụng lên Playground updates iframe + URL worker=create-image&prompt=… without full reload |
| W12 | Playground tour | On /app/playground/, card Bắt đầu tour → Tiếp cycles steps 1–4; iframe shows yellow highlight + tooltip on model / options / prompt / Send; Tắt highlight clears overlay |
| W13 | Guide + video (tour) | Ask hướng dẫn tạo video quảng cáo → guide card jobType=video; Áp dụng / tour switches iframe to create-video |
| W14 | Guide + tool (chat-only) | Ask hướng dẫn xóa nền ảnh → card shows chat-only hint; no tour / no Apply Playground; Tạo ngay trong chat opens inline form |
Optional live job (spends credits): repeat §2 row image inside the widget only — intent → inline form → Create image → poll result. Record OK / UP / FAIL in sign-off.
Storage key (debug): gw_site_agent_widget_state_v1 in localStorage (JSON version: 2 for multi-tab).
| Area | Path |
|---|---|
| Intent rules | docs/.vitepress/theme/models/chat-product-job-intent.ts |
| Inline form | docs/.vitepress/theme/components/ChatInlineJobForm.vue |
| Panel orchestration | docs/.vitepress/theme/components/AppChatPanel.vue |
| Site Agent widget | docs/.vitepress/theme/components/SiteAgentWidget.vue, models/site-agent-widget-storage.ts, models/site-agent-widget-handoff.ts |
| Widget inline jobs | docs/.vitepress/theme/composables/use-product-inline-jobs.ts, models/chat-product-confirm-intent.ts |
| Gateway chat + context | src/routes/chat.ts, src/services/gommoChat.ts |
Remote sync productChat block | docs/.vitepress/theme/models/chat-product-sync-meta.ts, chat-session-sync.ts |
| Remote pull / hydrate | docs/.vitepress/theme/models/chat-remote-sync.ts |
| Low-credit inline guards | docs/.vitepress/theme/models/chat-product-credits.ts |
| Browser smoke (mock) | tests/browser/site-agent-widget.spec.ts, site-agent-widget-guide.spec.ts, chat-product-inline.spec.ts, chat-product-intents.spec.ts |
| Unit tests | npm run theme:test |