zeekayandhanzo-dev d4e7f97947
Hanzo CI/CD / cicd (push) Successful in 7m22s
CI/CD / cicd (push) Successful in 7m24s
deploy / build (push) Successful in 13m36s
chat: PanelControls and a bottom bar — beside upstream's Dock, not over it
Adds the two affordances the app implied and never offered: a top-right control
cluster, and a dockable bottom bar.

NAMING FIRST, because this collided once already. Upstream owns Chat/Dock — a
HORIZONTAL column of iframe cards beside the conversation. An earlier pass built
a VERTICAL bottom dock and called it the same thing. Upstream keeps its name;
this is Chat/BottomBar (BottomBar, BottomBarGroup, BottomBarTab), with store
keys, translation keys and test ids renamed to match. Both now render together:
["messages-view","chat-column","dock-panel","controls-nav"].

PanelControls: full width (Maximize2/Minimize2 over the existing
store.maximizeChatSpace), the companions menu (Monitor, highlighted while the bar
is open) opening a right-aligned DropdownPopup with "Side chat ⌥⌘S" and
"Browser ⌘T", and the Controls panel. Shortcuts are one document keydown effect
testing e.code, because Option+S types ß on macOS.

Three things were adapted to today's main rather than force-applied:

- OpenSidebar is NOT mounted in the header. Upstream moved that toggle into the
  rail and Header.spec.tsx exists to keep the header's left edge empty; a second
  one would be the duplicate the rail was invented to remove. The component still
  becomes a real toggle (navVisible, aria-expanded, PanelLeft) for its three
  existing call sites.
- The right-panel control is SlidersHorizontal, not PanelRight: upstream's
  CanvasToggle already wears PanelRight in the same cluster for the artifacts
  canvas. Same rule as the Dock — whoever took the glyph keeps it. The panel
  calls itself Controls in its own aria-label, which is what sliders say.
- SidePanel/Preview/Panel was still mounted nowhere, so the bar gives it a home
  rather than adding a second frame.

Two shared-package fixes in DropdownPopup. `kbd` hardcoded a ⌘ prefix (cannot
express ⌥⌘S, wrong on non-Apple keyboards) and rendered only on hover. And
`placement` had to move to useMenuStore — Ariakit reads it off the store and
ignores it on <Menu>. That one had a LIVE call site: SidePanel/Agents/Images.tsx
passed placement="bottom", which type-errored and did nothing. tsc goes 819 -> 818
because of it.

The right panel's open state also moves out of React state inside
SidePanelGroup's subtree — which is exactly why the header could not reach it —
into store.sidePanelOpen, reconciled to the imperative handle by one effect.
Consequence to know: that state is now binary, so the default hides the ~50px
icon rail main shows today; the header button is the replacement affordance.

Measured in Chromium, not asserted: menu rows 44.0px, right edge 1381 vs button
1379, Escape unmounts and returns aria-expanded=false; right panel 0->352->0;
bottom bar tabs 1->2 (+) ->3 (⌘T) ->2 (×), drag 315.3->475.0px, floor holding at
135.7px under a 700px overdrag, composer clear at 415.7 vs 584.7 and still clear
at the floor; scrollWidth === clientWidth at 1440 and 390; open bar, 2 tabs and
height all restored across reload; a DOM stamp on <main> survives the toggle, so
the conversation never remounts. Upstream's Dock still resizes 427.4->592.1px.

Failing-suite list is byte-identical to clean origin/main (81 files, same names);
+1 suite and +8 tests are BottomBar.spec.tsx.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-08-06 16:04:43 -07:00

Hanzo Chat

Hanzo Chat

The chat surface of the Hanzo AI cloud: multi-model chat with agents, tools, and retrieval, running on Hanzo's backend. Live at hanzo.chat.

Hanzo Chat is a sibling to hanzo.app (the app builder) and the Hanzo console (admin). All inference, code execution, and web search route through the unified Hanzo API at api.hanzo.ai/v1, and sign-in is federated to Hanzo IAM (hanzo.id).

Features

  • Multi-model chat — the Zen model family and other frontier models, served through api.hanzo.ai.
  • Agents — build agents in the thread, or run your Hanzo Cloud agents (/v1/agents) with an /agent command or @mention.
  • MCP tools — connect Model Context Protocol servers for tool use.
  • RAG — chat over your own files and documents.
  • Web search — grounded answers via Hanzo web search.
  • Code interpreter — run code in a sandboxed runtime.
  • Image generation — generate images inline.
  • Guest chat — try a free Zen model with no account (optional, off by default).

Requirements

Quick start (Docker)

git clone https://github.com/hanzoai/chat.git
cd chat
cp .env.example .env        # set HANZO_API_KEY
make up

Open http://localhost:3080. make up starts the full stack (app, MongoDB, Meilisearch) from compose.yml; make down stops it.

Development

pnpm install               # install workspace dependencies
pnpm build:packages        # build the shared workspace packages
pnpm backend:dev           # API server on :3080 (nodemon)
pnpm frontend:dev          # Vite client dev server (second terminal)

Tests and checks:

pnpm test:all              # all workspace tests
pnpm e2e                   # Playwright end-to-end tests
pnpm lint                  # ESLint
pnpm format                # Prettier

Configuration

Secrets live in .env; the model catalog and endpoints live in chat.yaml (copy chat.example.yaml). Key variables:

HANZO_API_KEY=             # Hanzo API key — inference, tools, search
MONGO_URI=                 # MongoDB connection — chat history, users
JWT_SECRET=                # session token signing
CREDS_KEY=                 # credential encryption
CREDS_IV=

Sign-in is federated to Hanzo IAM over OpenID Connect (OPENID_ISSUER=https://hanzo.id, client hanzo-chat).

Workspace

api/           Express backend (:3080) — routes, controllers, Mongoose models
client/        React frontend (Vite)
packages/      data-provider · data-schemas · api · client · agents · mcp

Documentation

License

MIT — see LICENSE and NOTICE.

S
Description
No description provided
Readme MIT
610 MiB
Languages
TypeScript 68.3%
JavaScript 22%
Python 6.5%
HTML 2.1%
CSS 0.5%
Other 0.5%