kimi-code/apps/web
liruifengv 1b97e95243
feat(web): settings-native provider management, blue-mark brand fork (#173)
- Move custom provider management into Settings as a Providers tab
  (ProvidersPanel + AddProviderFlow + ProviderForm + providerForm lib),
  replacing the standalone ProviderManager overlay; add/update/delete,
  models.dev directory import, custom registry import, API key
  show/hide, inline error banners
- Onboarding login step gains a custom-provider card landing on
  Settings → Providers
- Fork web branding back to the legacy little-blue mark (sidebar,
  onboarding BrandLogo, favicon); build-brand-icons.mjs now only
  writes desktop assets
- Drop the dev backend switcher pill from the sidebar (switch backends
  via KIMI_SERVER_URL instead)
- Rebind web new-chat shortcut to Ctrl+Shift+O (browsers reserve
  Cmd/Ctrl+N for new window)
- Source __KIMI_CLIENT_VERSION__ from the kimi-code submodule CLI
  version instead of apps/web/package.json
- Warning toasts honor notice severity (info/success/error variants)
- Remove the stale ToolRow.vue copy from the desktop renderer snapshot
- Minor internal tidy-ups in transcript/detail-panel helpers
2026-08-04 16:44:25 +08:00
..
public feat(web): settings-native provider management, blue-mark brand fork (#173) 2026-08-04 16:44:25 +08:00
scripts feat(desktop): add secondary model settings with a linked model-effort picker (#163) 2026-07-31 10:54:42 +08:00
src feat(web): settings-native provider management, blue-mark brand fork (#173) 2026-08-04 16:44:25 +08:00
test feat(chat): preview files outside the workspace via host fs:content (#172) 2026-08-03 19:47:36 +08:00
AGENTS.md feat(chat): transcript find bar + native editing context menu (#114) 2026-07-27 18:03:20 +08:00
CHANGELOG.md chore: import kimi-web as apps/web 2026-07-10 11:38:49 +08:00
index.html feat: stepped font scale, kimi skin palette, and macOS frosted sidebar (#91) 2026-07-24 10:48:20 +08:00
package.json fix(markdown): upgrade markstream-vue to 1.0.9-beta.1 to fix fallback line-number overlap (#160) 2026-07-30 19:28:08 +08:00
README.md docs: document web package split and consumer configuration 2026-07-10 18:14:49 +08:00
tsconfig.json feat(chat): add on-demand subagent transcripts (#137) 2026-07-28 23:06:53 +08:00
vite.config.ts feat(web): settings-native provider management, blue-mark brand fork (#173) 2026-08-04 16:44:25 +08:00
vitest.config.ts fix(markdown): restore streaming code highlight via markstream-vue 1.0.7 (#155) 2026-07-29 21:38:46 +08:00

Kimi Web

Browser client for Kimi Code — a peer to the TUI that talks to a local server over REST + WebSocket. Vue 3 + Vite + TypeScript.

Since phase 3 this app is no longer a monolith: it aggregates the three source-only shared packages (exports → ./src/*, transpiled by this app's bundler) and keeps only the web-specific glue:

  • @moonshot-ai/web-ui — presentational components + design tokens.
  • @moonshot-ai/web-markdown — chat Markdown renderer.
  • @moonshot-ai/web-core — daemon transport, session state machine, state container, appearance composables.

Quick start

# from the repo root
pnpm dev:web                 # vite dev server (proxies /api/v1 to KIMI_SERVER_URL)
pnpm -C apps/web run dev:stub  # offline stub faking the server API + event stream

# checks
pnpm -C apps/web run typecheck   # vue-tsc --noEmit
pnpm -C apps/web run test        # vitest (pure logic only)
pnpm -C apps/web run build       # vite build → apps/web/dist

How it connects to the server

The browser cannot reach the server cross-origin (no CORS), so Vite same-origin proxies /api/v1 (HTTP + WS) to the server (vite.config.ts):

env var default meaning
WEB_PORT 5175 port the dev server listens on
KIMI_SERVER_URL http://127.0.0.1:58627 where /api/v1 (and /api/v1/ws) is forwarded

Behind a corporate HTTP proxy, also set NO_PROXY=<server-host> (for example, NO_PROXY=127.0.0.1,localhost) so the proxy forward reaches the server directly.

vite.config.ts also carries the two consumer requirements the shared packages need: the unplugin-icons kimi collection (~icons/kimi/*) and worker: { format: 'es' } for web-markdown's off-thread KaTeX / Mermaid workers.


Architecture

src/api/bootstrap.ts is the only module that knows both sides: it composes web-core's DaemonKimiWebApi with this app's bridges — tracer (debug/trace), credentialStore (lib/serverAuth), and the required projectorFactory (src/api/daemon/agentEventProjector.ts) — and exposes the shared api singleton (plus a getKimiWebApi() back-compat accessor).

src/main.ts stays thin: createApp(App).use(i18n), an app.provide(IconResolverKey, …) that bridges web-ui's <Icon> to this app's icon registry (lib/icons.ts), and a desktop-only theme-IPC bridge that mirrors <html data-color-scheme> to the host's nativeTheme. There is no client factory / provide of an un-singletoned client here — that is deferred to a later phase.

src/api keeps only the web-specific glue (bootstrap, config, daemon/agentEventProjector, errors, index, types); the transport, reducer, and state container live in @moonshot-ai/web-core. i18n and tool metadata stay in this app.

server (REST + WS)
  └─ @moonshot-ai/web-core/api   DaemonKimiWebApi (transport + projector + reducer)
        └─ src/api/bootstrap.ts  injects tracer / credentialStore / projectorFactory → api
  └─ @moonshot-ai/web-core       createKimiWebClientCore({ api, t }) → reactive state
  └─ @moonshot-ai/web-ui         <Button> / <Dialog> / <Icon> / tokens
  └─ @moonshot-ai/web-markdown   <Markdown>
  └─ src/components/*.vue        render props, emit intents (no transport access)

Server contract — non-obvious notes

The server's wire protocol has a few things that will bite you if forgotten:

  • Envelope: every response is { code, msg, data, request_id } and the HTTP status is always 200 — check code (0 = ok), not the status.
  • Persisted sessions are directly promptable — selecting an old session and sending a message just works; there is no :activate step.
  • Creating a session needs a registered workspace. workspace_id must be a wd_<slug>_<hash> id that exists in the server's registry.

Release & deployment

build → dist produces apps/web/dist. It is consumed two ways, never published as a standalone package:

  1. Desktopapps/desktop/scripts/copy-web-dist.mjs copies apps/web/dist into apps/desktop/web-dist/ at desktop build time.
  2. SEA / CLI embedpnpm run sync:web builds the web and syncs dist into the kimi-code submodule's apps/kimi-code/dist-web/ for SEA embedding.