Arvin Xu 837a3daa58 feat(chat): consume gateway uiMessages snapshot as SoT at step boundaries (#15153)
* ♻️ refactor(chat-store): useFetchMessages accepts options object

LOBE-9501

Replace the positional `skipFetch?: boolean` second argument with an
`options?: { skipFetch?, revalidateOnFocus? }` object on both
`useChatStore.useFetchMessages` and `useConversationStore.useFetchMessages`.
Plumb `revalidateOnFocus` through to the underlying SWR config so callers
can suppress focus revalidate per-call (default behaviour unchanged).

Mechanically migrate all 7 call sites to the new shape. No behaviour
change in this commit — the streaming-aware `revalidateOnFocus: false`
follow-up lives in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

*  feat(chat): consume gateway uiMessages snapshot as SoT at step boundaries

LOBE-9501

Server attaches the canonical UIChatMessage[] snapshot to step_start and
agent_runtime_end events (#15152). The client now uses that pushed payload
as the source of truth instead of refetching from DB:

- step_start handler calls replaceMessages(uiMessages, { context }) when
  the snapshot is present, so the assistant tab-switch / next-step path
  no longer issues a refetch that returns a stale assistant placeholder.
- agent_runtime_end handler does the same for the terminal step — the
  last step has no later step_start to carry a fresh snapshot, so this
  branch is the only one that reconciles the final commit.
- step_complete on phase=tool_execution stops calling refreshMessages.
  That refetch was the direct cause of the assistantGroup→assistant
  clobber regression captured by the agent-gateway probe scripts.
- ChatList disables SWR revalidateOnFocus while the current topic is
  streaming (via operationSelectors.isAgentRuntimeRunningByContext) and
  automatically restores it after the run ends. Tab-focus during a run
  no longer triggers the stale DB read.

Doesn't touch streamingExecutor.ts (homogeneous runtime — parallel path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(chat-store): wire gateway handler to consume server-pushed uiMessages SoT

LOBE-9501

#15152 (server) attaches the canonical UIChatMessage[] snapshot to both
the Redis SSE channel and the gateway /push-event channel. The earlier
client patch wired the consumer into `runAgent.ts`, but that file only
runs on the Group Chat SSE path. The actual gateway entry point
(`createGatewayEventHandler` in `gatewayEventHandler.ts`, used by single
agent, sub-agent, and hetero-CLI flows) ignored the field entirely and
kept refetching from DB.

Fix the gateway handler:

- step_start: consume `event.data.uiMessages` and replaceMessages with
  the pushed SoT. Skipped when absent — hetero adapters don't emit
  step_start at all (HeterogeneousEventType excludes it), so the new
  branch is invisible to hetero.

- agent_runtime_end: same SoT consumption; the existing
  `fetchAndReplaceMessages` becomes the fallback for events without the
  field. Claude Code adapter emits agent_runtime_end with empty data,
  so hetero terminal behavior is preserved by the fallback.

- stream_start: gate the DB fetch on `!newAssistantMessageId`. Native
  gateway streams carry `assistantMessage.id` (the preceding step_start
  also delivered the SoT), so the await is unnecessary — AND it was
  blocking the enqueue chain. Live chunks queued behind that await
  could not dispatch, which manifested as "streaming content never
  lands in messagesMap" during tab-switch and slow-network repros.
  Hetero CLI streams never set `assistantMessage.id`, so the fetch
  still runs for them on every stream_start.

Verified with the agent-gateway probe (separate commit): chunks now
land in real time (cLen grows 3 → 529 monotonically), and tab-switch
mid-stream no longer rolls the streamed assistantGroup back to the
LOADING placeholder (ROLLBACKS=none in the analyzer output).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🧪 chore(local-testing): rewrite agent-gateway probes in TS + add CLI

LOBE-9501

Convert the local-testing agent-gateway probes from .js/.mjs to TypeScript
and add a unified `run.ts` CLI that bundles via Bun.build (no extra
deps) and persists dumps to a gitignored `.agent-gateway/` directory for
use as streaming-replay test fixtures.

- types.ts: shared dump shape (ProbeStreamEvent / ProbeTimelineSample /
  ProbeDump) and `declare global` for the `window.__PROBE_*` surface
- probe-events.ts: WebSocket + fetch interception (gateway WS captures
  any socket with `operationId=`; fetch captures `/api/agent/stream` for
  direct SSE). Per-key timeline samples every 200ms so we can see
  which messagesMap key streaming chunks actually land in
- probe-dump.ts: stops the timeline timer and stashes JSON dump on
  `window.__PROBE_LAST_DUMP_JSON` (runner returns that global)
- analyze-events.ts: stream events (non-chunk) + chunks summary +
  action-call stacks + correlation + per-key assistant growth +
  rollback detection. Per-key growth was added specifically to
  diagnose "chunks arrive but assistant cLen never moves"
- run.ts: `install` | `dump [name]` | `analyze [path]` CLI. Bundles via
  Bun.build, wraps as IIFE with explicit return, pipes to
  `agent-browser eval --stdin`. Dumps land at
  `.agent-gateway/<name>-<YYYYMMDD-HHmmss>.json`

`.agent-gateway/` is gitignored so dumps accumulate across debugging
sessions without polluting git.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🐛 fix(local-testing): repair run.ts after autofix mangled path imports

LOBE-9501

The eslint --fix run during the previous commit applied the unicorn
`import-style` rule and renamed every `join(` / `dirname(` / `resolve(`
to `path.join(` / `path.dirname(` / `path.resolve(`, but the replacement
was a naive text substitution that:

1. rewrote `array.join('\n')` to `array.path.join('\n')` — broke bundle
   error reporting (would TypeError on the build-failure path)
2. produced `const path = path.join(DUMP_DIR, filename)` inside cmdDump
   — shadowed the `path` module with itself, ReferenceError on every
   dump invocation

Rename the local `path` to `dumpPath` and drop the spurious `.path`
prefix on the array `.join`. Verified round-trip: install + dump now
write a valid capture to `.agent-gateway/`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🧪 chore(local-testing): capture per-call message snapshot in probe

LOBE-9501

The probe's `replaceMessages` wrapper used to record only `count` and
`params` — enough to see "two messages were written" but not WHICH two.
For post-stream collapse debugging we need to see whether each call
restored streamed content (cLen=N) or wiped to LOADING_FLAT (cLen=3).

Two changes:

- Capture `snapshot` field on every replaceMessages call: last 2
  messages' id / role / cLen / rLen / updatedAt. The analyzer prints
  this inline next to each call so reviewers can see content drift /
  collapse without re-reading the dump.

- Make wrapping idempotent across re-installs. The old guard
  `chat.__probeWrapped = true` froze the first-installed wrapper across
  re-installs, so updates to the probe body had no effect without a
  page reload. Stash the originals on
  `window.__PROBE_ORIG_REFRESH_MESSAGES` /
  `window.__PROBE_ORIG_REPLACE_MESSAGES` and re-wrap from those on
  every install.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🧪 chore(local-testing): add mutation log + dispatchMessage wrap to probe

LOBE-9501

The replaceMessages-only wrap couldn't catch chunk-level writes (those go
through internal_dispatchMessage) or attribute post-stream collapses to a
specific writer. Add:

- `__PROBE_MUTATIONS` — unified ordered log of every dbMessagesMap[key]
  reference change, with `last`/`prevLast` summaries and a `delta` field
  that tags interesting transitions (`cLen↓N→M`, `rLen↓`, `id:A→B`,
  `n↓prev→cur`). Both writers — replaceMessages AND internal_dispatchMessage
  — push to the same buffer so a single timeline shows all stores writes.

- Idempotent action wrapping. Originals are stashed on
  `window.__PROBE_ORIG_*` and re-wrapped from there on every install, so
  probe edits take effect without a page reload (previous
  `chat.__probeWrapped` flag froze the first wrapper).

- Snapshot field on replaceMessages — last 2 messages'
  id/role/cLen/rLen/updatedAt — so reviewers can see WHICH content each
  call is writing instead of just the count.

- Dump file now carries the `mutations` array alongside streamEvents,
  actionCalls, timeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🐛 fix(chat-store): gate SWR onData by isStreaming for streaming topic

LOBE-9501

Backstop for the post-stream cLen collapse that survives even with the
gateway SoT consume in place. Reproduction (confirmed):

1. Send a stream that lands lots of WS chunks into ChatStore
2. Immediately reload the page

If the page reload races against server-side chunk fan-out into Postgres,
SWR's fresh fetch returns the assistant row in its LOADING_FLAT placeholder
state (cLen=3) and writes that to ChatStore via the conversation-store
mirror — even though the WS push at agent_runtime_end carried the
correct full content moments earlier.

`mergeFetchedMessagesWithLocalState`'s updatedAt tie-breaker handles
this for in-session repros (local message wins when its updatedAt is
newer), but it degenerates when:

- The SoT consume just wrote server's snapshot updatedAt onto the local
  message, equalising the timestamps so the next stale DB fetch wins
- The user reloads (no local state to merge against — fresh fetch wins
  outright)

Add a gate at the bottom of `ConversationStore.useFetchMessages.onData`:
while `isAgentRuntimeRunningByContext(context)` is true, drop the SWR
write entirely. SWR's own cache still updates, so once streaming ends a
normal revalidate writes through correctly.

This is layered defense — it does NOT fix the underlying server-side
fan-out lag (filed as separate Linear issue). It does prevent the
client-side flash users currently see during the lag window.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* 🧪 test(chat-store): align gateway handler tests with SoT contract

The previous assertions still expected `stream_start` to issue a DB refetch
on every native gateway stream — the very behaviour LOBE-9501 removes
(`acb9523a04`). Update the three failing cases to the new contract:

- `stream_start > should associate new message with operation`:
  assert `messageService.getMessages` is NOT called when
  `assistantMessage.id` is present (the SoT snapshot from the preceding
  `step_start` already pre-populated `dbMessagesMap`).
- `sequential processing`: rewrite around the surviving ordering guarantee
  — `associate` (stream_start) must precede `dispatch` (stream_chunk) so
  the chunk targets the new id. Add a sibling case for hetero CLI streams
  (no `assistantMessage.id` → DB fetch is still mandatory).
- `multi-step integration > full LLM → tools → LLM cycle`: keep the
  post-`tool_end` `replaceMessages` assertion (tool_end still refreshes
  from DB), invert the post-`stream_start` assertion for step 2.

42 tests passing (was 41 + 1 new hetero fallback test).

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:05:58 +08:00
2026-05-14 13:26:10 +07:00
2026-04-11 18:43:28 +08:00
2024-09-18 17:35:19 +08:00
2026-05-01 14:45:28 +08:00
2025-12-05 01:35:20 +08:00
2025-10-30 20:59:48 +08:00
2025-12-24 12:54:35 +08:00
2026-05-20 12:00:22 +08:00
2026-05-20 12:00:22 +08:00

LobeHub

LobeHub organizes your agents into 7×24 operation.

It hires, schedules, reports on your entire AI team.

You stay in charge — without staying online.

English · 简体中文 · Official Site · Changelog · Documents · Blog · Feedback




Share LobeHub Repository

Your Chief Agent Operator

LobeHub - Your Chief Agent Operator for multi-agent work | Product Hunt lobehub%2Flobehub | Trendshift

Table of contents

TOC



https://github.com/user-attachments/assets/0a33365f-b786-48b5-9ed6-f8af7927bccb

👋🏻 Getting Started & Join Our Community

We are a group of e/acc design-engineers, hoping to provide modern design components and tools for AIGC. By adopting the Bootstrapping approach, we aim to provide developers and users with a more open, transparent, and user-friendly product ecosystem.

Whether for users or professional developers, LobeHub will be your AI Agent playground. Please be aware that LobeHub is currently under active development, and feedback is welcome for any issues encountered.

We are live on Product Hunt! We are thrilled to bring LobeHub to the world. If you believe in a future where humans and agents co-evolve, please support our journey.
Join our Discord community! This is where you can connect with developers and other enthusiastic users of LobeHub.

[!IMPORTANT]

Star Us, You will receive all release notifications from GitHub without any delay ~

Star History

Features

Todays agents are one-off, task-driven tools. They lack context, live in isolation, and require manual hand-offs between different windows and models. While some maintain memory, it is often global, shallow, and impersonal. In this mode, users are forced to toggle between fragmented conversations, making it difficult to form structured productivity.

LobeHub changes everything.

LobeHub is a work-and-lifestyle space to find, build, and collaborate with agent teammates that grow with you. In LobeHub, we treat Agents as the unit of work, providing an infrastructure where humans and agents co-evolve.

Operator: Agents as the Unit of Work

Hires, schedules, and reports on your entire AI team.

  • More productivity. Fewer tools: Bring all your agents under one roof.
  • IM Gateway: Agents where you already chat.

Create: Agents as the Unit of Work

Building a personalized AI team starts with the Agent Builder. You can describe what you need once, and the agent setup starts right away, applying auto-configurations so you can use it instantly.

  • Unified Intelligence: Seamlessly access any model and any modality—all under your control.
  • 10,000+ Skills: Connect your agents to the skills you use every day with a library of over 10,000 tools and MCP-compatible plugins.

Collaborate: Scale New Forms of Collaboration Networks

LobeHub introduces Agent Groups, allowing you to work with agents like real teammates. The system assembles the right agents for the task, enabling parallel collaboration and iterative improvement.

  • Pages: Write and refine content with multiple agents in one place with a shared context.
  • Schedule: Schedule runs and let agents do the work at the right time, even while you are away.
  • Project: Organize work by project to keep everything structured and easy to track.
  • Workspace: A shared space for teams to collaborate with agents, ensuring clear ownership and visibility across the organization.

Evolve: Co-evolution of Humans and Agents

The best AI is one that understands you deeply. LobeHub features Personal Memory that builds a clear understanding of your needs.

  • Continual Learning: Your agents learn from how you work, adapting their behavior to act at the right moment.
  • White-Box Memory: We believe in transparency. Your agents use structured, editable memory, giving you full control over what they remember.

more features will be added when LobeHub evolve.

🛳 Self Hosting

LobeHub provides Self-Hosted Version with Vercel, Alibaba Cloud, and Docker Image. This allows you to deploy your own chatbot within a few minutes without any prior knowledge.

[!TIP]

Learn more about 📘 Build your own LobeHub by checking it out.

A Deploying with Vercel, Zeabur , Sealos or Alibaba Cloud

"If you want to deploy this service yourself on Vercel, Zeabur or Alibaba Cloud, you can follow these steps:

  • Prepare your OpenAI API Key.
  • Click the button below to start deployment: Log in directly with your GitHub account, and remember to fill in the OPENAI_API_KEY(required) on the environment variable section.
  • After deployment, you can start using it.
  • Bind a custom domain (optional): The DNS of the domain assigned by Vercel is polluted in some areas; binding a custom domain can connect directly.
Deploy with Vercel Deploy with Zeabur Deploy with Sealos Deploy with RepoCloud Deploy with Alibaba Cloud

After Fork

After fork, only retain the upstream sync action and disable other actions in your repository on GitHub.

Keep Updated

If you have deployed your own project following the one-click deployment steps in the README, you might encounter constant prompts indicating "updates available." This is because Vercel defaults to creating a new project instead of forking this one, resulting in an inability to detect updates accurately.

[!TIP]

We suggest you redeploy using the following steps, 📘 Auto Sync With Latest


B Deploying with Docker

We provide a Docker image for deploying the LobeHub service on your own private device. Use the following command to start the LobeHub service:

  1. create a folder to for storage files
$ mkdir lobehub-db && cd lobehub-db
  1. init the LobeHub infrastructure
bash <(curl -fsSL https://lobe.li/setup.sh)
  1. Start the LobeHub service
docker compose up -d

[!NOTE]

For detailed instructions on deploying with Docker, please refer to the 📘 Docker Deployment Guide


Environment Variable

This project provides some additional configuration items set with environment variables:

Environment Variable Required Description Example
OPENAI_API_KEY Yes This is the API key you apply on the OpenAI account page sk-xxxxxx...xxxxxx
OPENAI_PROXY_URL No If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL https://api.chatanywhere.cn or https://aihubmix.com/v1
The default value is
https://api.openai.com/v1
OPENAI_MODEL_LIST No Used to control the model list. Use + to add a model, - to hide a model, and model_name=display_name to customize the display name of a model, separated by commas. qwen-7b-chat,+glm-6b,-gpt-3.5-turbo

[!NOTE]

The complete list of environment variables can be found in the 📘 Environment Variables

📦 Ecosystem

NPM Repository Description Version
@lobehub/ui lobehub/lobe-ui Open-source UI component library dedicated to building AIGC web applications.
@lobehub/icons lobehub/lobe-icons Popular AI / LLM Model Brand SVG Logo and Icon Collection.
@lobehub/tts lobehub/lobe-tts High-quality & reliable TTS/STT React Hooks library
@lobehub/lint lobehub/lobe-lint Configurations for ESlint, Stylelint, Commitlint, Prettier, Remark, and Semantic Release for LobeHub.

🧩 Plugins

Plugins provide a means to extend the Function Calling capabilities of LobeHub. They can be used to introduce new function calls and even new ways to render message results. If you are interested in plugin development, please refer to our 📘 Plugin Development Guide in the Wiki.

  • lobe-chat-plugins: This is the plugin index for LobeHub. It accesses index.json from this repository to display a list of available plugins for LobeHub to the user.
  • chat-plugin-template: This is the plugin template for LobeHub plugin development.
  • @lobehub/chat-plugin-sdk: The LobeHub Plugin SDK assists you in creating exceptional chat plugins for LobeHub.
  • @lobehub/chat-plugins-gateway: The LobeHub Plugins Gateway is a backend service that provides a gateway for LobeHub plugins. We deploy this service using Vercel. The primary API POST /api/v1/runner is deployed as an Edge Function.

[!NOTE]

The plugin system is currently undergoing major development. You can learn more in the following issues:

  • Plugin Phase 1: Implement separation of the plugin from the main body, split the plugin into an independent repository for maintenance, and realize dynamic loading of the plugin.
  • Plugin Phase 2: The security and stability of the plugin's use, more accurately presenting abnormal states, the maintainability of the plugin architecture, and developer-friendly.
  • Plugin Phase 3: Higher-level and more comprehensive customization capabilities, support for plugin authentication, and examples.

⌨️ Local Development

You can use GitHub Codespaces for online development:

Or clone it for local development:

$ git clone https://github.com/lobehub/lobehub.git
$ cd lobehub
$ pnpm install
$ pnpm dev          # Full-stack (Next.js + Vite SPA)
$ bun run dev:spa   # SPA frontend only (port 9876)

Debug Proxy: After running dev:spa, the terminal prints a proxy URL like https://app.lobehub.com/_dangerous_local_dev_proxy?debug-host=http%3A%2F%2Flocalhost%3A9876. Open it to develop locally against the production backend with HMR.

If you would like to learn more details, please feel free to look at our 📘 Development Guide.

🤝 Contributing

Contributions of all types are more than welcome; if you are interested in contributing code, feel free to check out our GitHub Issues and Projects to get stuck in to show us what you're made of.

[!TIP]

We are creating a technology-driven forum, fostering knowledge interaction and the exchange of ideas that may culminate in mutual inspiration and collaborative innovation.

Help us make LobeHub better. Welcome to provide product design feedback, user experience discussions directly to us.

Principal Maintainers: @arvinxx @canisminor1990




❤️ Sponsor

Every bit counts and your one-time donation sparkles in our galaxy of support! You're a shooting star, making a swift and bright impact on our journey. Thank you for believing in us your generosity guides us toward our mission, one brilliant flash at a time.

🔗 More Products

  • 🅰️ Lobe SD Theme: Modern theme for Stable Diffusion WebUI, exquisite interface design, highly customizable UI, and efficiency-boosting features.
  • Lobe Midjourney WebUI: WebUI for Midjourney, leverages AI to quickly generate a wide array of rich and diverse images from text prompts, sparking creativity and enhancing conversations.
  • 🌏 Lobe i18n : Lobe i18n is an automation tool for the i18n (internationalization) translation process, powered by ChatGPT. It supports features such as automatic splitting of large files, incremental updates, and customization options for the OpenAI model, API proxy, and temperature.
  • 💌 Lobe Commit: Lobe Commit is a CLI tool that leverages Langchain/ChatGPT to generate Gitmoji-based commit messages.


📝 License

Copyright © 2026 LobeHub.
This project is LobeHub Community License licensed.

S
Description
AI chat UI framework. Reference for chat/agent UX. License: review before adapting code.
Readme 1,015 MiB
Languages
TypeScript 98.8%
HTML 0.5%
Shell 0.3%
JavaScript 0.2%