Skip to content

feat(web,hub): export session conversation as JSON or Markdown download #793

@swear01

Description

@swear01

What feature would you like to see?

Export the entire session conversation from the web UI as a single file download.

User flow

  • Session header overflow menu (⋯) → Export conversation
  • Small dialog: choose format JSON (default) or Markdown, then Download
  • Remember last format in localStorage (hapi.sessionExportFormat)
  • Show loading / error toasts; support AbortController if the user leaves mid-export
  • Trigger browser download via Blob + <a download> (desktop + mobile PWA)

Why JSON is the default

  • Lossless: preserves hub DecryptedMessage + session metadata (tools, codex, attachments meta, etc.)
  • Markdown is a human-readable derived view from the same payload, not a second source of truth

Hub: single export endpoint

GET /api/sessions/:id/export

Returns HapiSessionExport v1 (format-agnostic):

{
  "schemaVersion": 1,
  "exportedAt": 1730000000000,
  "session": { },
  "messages": []
}
  • Same auth as existing session routes (requireSessionFromParam)
  • Server-side getAllMessagesForExport(sessionId) — do not paginate via repeated public /messages calls from the browser
  • Apply visible-message filtering consistent with the chat UI where applicable
  • Hard cap (e.g. 20_000 messages) → 413 with a clear message; no silent truncation

Web serialization

  • JSON: JSON.stringify(payload, null, 2).json
  • Markdown: serializeSessionMarkdown(payload) using normalizeDecryptedMessage; skip nulls; ## User / ## Assistant sections; concise tool summaries; optional YAML front matter → .md
  • Filename example: {title-slug}-{sessionId-8chars}-{YYYY-MM-DD}.{json|md}

Suggested files

  • shared/src/sessionExport.ts — schema/types
  • hub/src/store/messages.ts — export query helper
  • hub/src/web/routes/sessions.ts — route
  • web/src/lib/sessionExport/* — fetch, download helper, markdown serializer + tests
  • web/src/components/SessionHeader.tsx — menu + dialog
  • web/src/lib/locales/en.ts, zh-CN.ts

Additional information

Motivation

Acceptance criteria

  • GET /api/sessions/:id/export returns HapiSessionExport v1 (session + chronological visible messages)
  • Over cap → 413, explicit error
  • Export menu in session header; JSON default; format preference persisted
  • JSON download matches API payload (pretty-print OK)
  • Markdown generated from the same payload (one fetch)
  • File download works on desktop and mobile browsers
  • Tests: hub route (empty, multi-message, over-limit); serializeMarkdown unit tests

Out of scope

Prior art
Open WebUI, LibreChat, LobeChat: JSON as canonical export + optional Markdown for reading.

Manual test plan

  1. Short session → JSON → verify count/order
  2. Same session → Markdown → readable structure
  3. Reload → format preference retained
  4. Very long session → 413 or success with clear UX
  5. iPhone PWA / Android Chrome → file downloads

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions