Chuyển tới nội dung chính

Chat from Share

Hướng dẫn tích hợp luồng chia sẻ phiên chat và tiếp tục chat từ link share cho app mobile/web.

Tổng quan

┌──────────────────┐     ┌──────────────────────────┐     ┌─────────────────────────┐
│ Bấm nút Share │────▶│ Share Link (read-only) │────▶│ Continue Chat (new) │
│ POST /share │ │ GET /share/{id} │ │ WS: chat + share_id │
└──────────────────┘ └──────────────────────────┘ └─────────────────────────┘

Luồng chính:

  1. Tạo share - User bấm share, backend lưu snapshot tại thời điểm hiện tại
  2. Xem share - Bất kỳ ai có link đều xem được (public, không cần auth)
  3. Continue chat - User đăng nhập, gửi tin nhắn qua WebSocket với share_id → nhận session_created → chuyển sang chat bình thường
POST /v2/sessions/{session_id}/share?title=Phân+tích+HPG

Response:

{
"share_id": "2uRJLYz57j-jxwmcHpjiZQ",
"share_url": "/share/2uRJLYz57j-jxwmcHpjiZQ",
"title": "Phân tích HPG",
"expires_at": null,
"is_existing": false
}
FieldMô tả
share_idID duy nhất của share link
share_urlPath tương đối, frontend ghép với domain
titleTên share, mặc định lấy từ session name
is_existingtrue nếu session đã share trước đó (tự update snapshot mới)
thông tin
  • Nếu session đã share, API không tạo mới mà update snapshot. Bấm share nhiều lần = cùng link, cập nhật nội dung.
  • Nếu không truyền title, tự lấy session_name.
  • Người xem share chỉ thấy messages đến thời điểm bấm share, chat thêm sau đó không ảnh hưởng.

Phase 2: Xem Share (Read-only)

GET /v2/share/{share_id}

Endpoint public - không cần auth token.

Response:

{
"share_info": {
"share_id": "2uRJLYz57j-jxwmcHpjiZQ",
"session_id": "f6281ea8-...",
"title": "Phân tích HPG",
"last_message_uuid": "4d09a45d-...",
"view_count": 5,
"created_at": "2026-04-01T01:36:40.787329+00:00",
"expires_at": null
},
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "phân tích hpg"
}
],
"uuid": "38ff5e7c-..."
},
{
"role": "assistant",
"message_type": "chat",
"content": [
{
"type": "text",
"text": "..."
}
],
"uuid": "a9336b5d-...",
"parent_uuid": "38ff5e7c-..."
}
],
"message_count": 12
}

Render: Messages format giống /v2/sessions/{id}/history. Dùng chung component render chat history.

Phase 3: Continue Chat từ Share

Khi user đăng nhập và gửi tin nhắn từ share view, gửi qua WebSocket với share_id.

3.1 Gửi message

{
"type": "chat",
"message": "Phân tích thêm về doanh thu Q4",
"share_id": "2uRJLYz57j-jxwmcHpjiZQ"
}
cảnh báo

Gửi share_id thay vì session_id. Không gửi đồng thời cả hai.

3.2 Nhận session_created

Backend clone session gốc → tạo session mới → gửi event:

{
"type": "session_created",
"session_id": "dfb5e5b0-d3ce-4546-...",
"from_share": true,
"title": "Phân tích HPG"
}

Frontend xử lý khi nhận event này:

  1. Thêm session mới vào danh sách sidebar
  2. Chuyển activeSessionId sang session mới
  3. Tắt share view mode
  4. Navigate sang /chat/{newSessionId}

3.3 Nhận stream response

Sau session_created, tiếp tục nhận stream events giống chat bình thường:

← session_created      (session mới đã tạo)
← subscribed (đã subscribe session mới)
← message_start (agent bắt đầu xử lý)
← content_block_delta (streaming nội dung)
← ...
← message_stop (hoàn thành)

Sequence Diagram

Client (WS)                    Server (WS)
│ │
│─── chat + share_id ─────────▶│
│ │── clone messages → new session
│◀── session_created ──────────│
│◀── subscribed ───────────────│
│ │── run agent
│◀── message_start ────────────│
│◀── content_block_delta ──────│
│◀── ... (stream events) ──────│
│◀── message_stop ─────────────│
│ │

Luồng Login từ Share

Khi user chưa đăng nhập xem share và muốn chat tiếp:

Share View → Gửi tin nhắn → Redirect /login?returnUrl=/share/xxx → Login → Redirect về /share/xxx → Gửi tin nhắn → Continue chat

Quan trọng: Khi redirect sang login, truyền returnUrl để sau login quay về đúng share page:

/login?returnUrl=%2Fshare%2F2uRJLYz57j-jxwmcHpjiZQ

Login xong, đọc returnUrl từ query params và redirect về.

Quản lý Share

Danh sách share của user

GET /v2/users/shares?page=1&page_size=12

Response:

{
"shares": [
{
"share_id": "2uRJLYz57j-...",
"session_id": "f6281ea8-...",
"title": "Phân tích HPG",
"share_type": "session",
"is_active": true,
"view_count": 5,
"created_at": "2026-04-01T01:36:40",
"expires_at": null,
"share_url": "/share/2uRJLYz57j-..."
}
],
"page": 1,
"total": 3,
"total_pages": 1
}

Xóa share

DELETE /v2/shares/{share_id}

WebSocket Reference

Chat payload

FieldTypeRequiredDescription
typestringYes"chat"
messagestringYesNội dung tin nhắn
share_idstringConditionalGửi khi chat từ share (thay session_id)
session_idstringConditionalGửi khi chat bình thường
modelstringNoModel override
content_urlsarrayNoURLs đính kèm

Event: session_created

FieldTypeDescription
typestring"session_created"
session_idstringID session mới được tạo
from_sharebooleanLuôn true
titlestringTên session (từ share title)

Lưu ý tích hợp

  1. Share là snapshot - Bấm share = chốt nội dung tại thời điểm đó. Chat thêm sau không ảnh hưởng link share. Bấm share lại = update snapshot.

  2. Session clone độc lập - Session mới từ share hoàn toàn tách biệt session gốc. Hai bên chat song song không ảnh hưởng nhau.

  3. WebSocket connect khi đã login - Dù đang ở share view, nếu user đã đăng nhập thì WS phải connect sẵn để gửi tin nhắn ngay.

  4. Render share giống history - API trả messages cùng format với session history. Dùng chung component render.

  5. Nút share disable ở share view - Không cho share lại khi đang xem share của người khác.