Four fixes folded together:
- The ~/todo TAB was still collapsible, so opening it could hide everything.
Collapse now applies only to the floating card; the tab is always expanded.
- The floating background-task card had no collapse. Add a chevron toggle while
keeping the header click as 'open the tasks tab'.
- The card truncated to 4 rows and showed '+N' even with room. Raise the cap to
12 and let the list scroll (max-height) so it shows more before truncating.
- Bump the floating stack width 260→300 and card font so the panels aren't so
cramped.
P2-15 verification: confirm steering a running turn with an image works
end-to-end — the image rides the steered prompt's content alongside the text and
the optimistic transcript echo shows it. No bug found; locks it as a regression.
The KAP debug panel already exported REST + WS traffic as JSONL, but a broken
page is usually explained by a JS error the network log doesn't show. Fold
window error/unhandledrejection and console.error/warn into the trace buffer
(opt-in, install-once, behavior-preserving) as a 'client' source, surface them
in the panel with an 'app errors' filter + APP badge, so 'export jsonl' yields a
complete troubleshooting log.
Browsing into a folder with many subdirectories meant scrolling a long flat
list. Add a live case-insensitive filter input above the folder list (shown
once a folder has entries), filtering the current folder's subfolders by name,
with a no-match hint and a reset on each navigation. Adds zh/en strings.
Typing / only offered the 17 built-in app commands; the daemon's session skills
(GET /sessions/{id}/skills) were unreachable from the web composer. Wire the
skills endpoints into the API client, load them per session, and append them to
the / menu as /<skill-name> with their description. Selecting one (or typing
/<skill> args) activates it via POST .../skills/{name}:activate — the web
analogue of /<skill> in the TUI. Built-in commands are unchanged.
Questions replaced the composer in the pinned bottom dock; approvals rendered at
the end of the scrolling transcript — two different positions for the same
'agent is blocked on you' moment. Render the pending approval in the same dock
slot (question takes priority, then approval, then composer), cap its height so
a tall diff scrolls internally instead of pushing the dock off-screen, and match
the question card's margin. Remove the now-dead inline approval rendering and
its emit wiring from ChatPane.
- The command/summary was printed twice when a tool card was expanded (header
line + a repeated summary atop the body). Drop the body copy; the header
already shows it.
- Consecutive tool calls rendered as N separate cards with gaps. Collapse a run
of adjacent ToolCall .box cards into one continuous panel (shared borders,
squared inner corners) via :has/+ sibling CSS; text/thinking between tools
still breaks the group, and media cards (.media-tool) are untouched.
- Downward expansion already correct (body renders below the header).
The existing override targeted a 'table-node' element, but markstream-vue uses
a .table-node CLASS, so the scoped '.table-node[data-v-…] tbody tr:hover'
background still showed on read-only conversation tables. Match the class and
use !important so the override wins regardless of style-injection order.
sendingBySession only cleared on turn end / error, so the in-flight moon
lingered beside the streaming reply for the whole turn. Clear it on the first
assistantDelta (thinking/text token) or messageUpdated (a turn that opens with a
tool use), matching the moon's intended 'before the reply starts' semantics.
Manual interrupt already worked (Esc key + the composer's stop button, both
wired to abortCurrentPrompt), but only the Esc path showed the 'aborted' toast —
clicking stop aborted silently. Route both paths through a single handleInterrupt
so the stop button gives the same toast feedback as Esc.
messagesToTurns kept the final group's running tools spinning so live in-flight
tools show a spinner. But when a tool's result frame is dropped on a reconnect /
ordering race, the tool stayed 'running' forever after the turn finished —
the intermittent 'read file then spins forever' report. Thread whether the
session is still active into messagesToTurns and settle the final group's
dangling tools to ok when it is idle, keeping live spinners during a real turn.
onPanesScroll swallowed any scroll event within 100ms of a programmatic scroll
to dodge the smooth-scroll echo. But the streaming follow re-pins every ~120ms
during the thinking phase, so a user's upward scroll almost always landed inside
a fresh window and was ignored — following never flipped off and the view
snapped back to the bottom. The window is only needed for the async smooth path
(the pill); the synchronous streaming scroll updates lastScrollTop inline and
its echo event is a no-op. Scope the suppression window to smooth scrolls only.
setModel optimistically shows the chosen model, but on failure it only pushed a
warning and left the picker on the new value — so a switch that never reached
the daemon (socket dropped / daemon unreachable) looked like it succeeded.
Capture the previous model and restore it when updateSession throws, keeping the
best-effort status refresh from rolling back a switch that did land.
A volatile assistant/thinking delta whose pre-append offset is 0 while the
projector still believes it is mid-stream means the daemon began a fresh
assistant stream (new turn / retry) whose durable turn.started raced past the
client's cursor on reconnect and was never re-delivered. Every such delta then
had offset < turnTextLen and hit the silent skip path (which, unlike gap, never
triggers a resync), so streaming stayed dead until a full page reload.
Reset the per-turn stream counter when a delta arrives at offset 0 mid-stream,
and clear both counters on turn.ended, so a missed turn boundary can no longer
wedge delta alignment. Adds reconnect-streaming regression tests.
- unconditionally expose /openapi.json and /asyncapi.json\n- add --swagger flag to kimi server run\n- mount Swagger UI at /documentation only when --swagger is passed\n- generate AsyncAPI document from ws-control schemas\n- update tests and docs
The onboarding composer (workspace draft) has no backend session yet, so
setModel() hit the early return and the pick was silently dropped. The
pick is now remembered as draftModel: the status line reflects it
immediately, and the first prompt passes it to createSession so the new
session starts on the chosen model.
Also keep the user's model when the daemon echoes model as '' — both in
/status refreshes and in snapshot syncs racing an optimistic setModel —
and guard the createSession echo the same way.
A user turn whose origin metadata marks it as a skill_activation
(trigger user-slash) no longer dumps the raw XML block into the chat:
the turn shows only the user-provided args plus an "activated skill"
label with the skill name.
Enable with ?debug=1 or localStorage kimi-web.debug=1. A ring buffer
(1000 entries, redacted secrets, truncated payloads) records every REST
call (method/path/requestId/status/envelope code/duration) and WS frame
(lifecycle, outbound control frames, inbound events with session/seq/
offset) as a side channel — request ordering and error handling are
unchanged. The panel offers a filterable timeline, per-entry JSON with
copy, JSONL export, and per-session/event-type aggregation.
* feat(skill): qualify sub-skill names with parent prefix
- qualify sub-skill names with parent prefix and set isSubSkill metadata\n- hide sub-skills from the model skill listing
- expose sub-skills as dotted slash commands in TUI
- update slash command docs for English and Chinese
- align built-in sub-skill local names with their directories
Map the /models three-state supports_thinking_type field ('only' /
'no' / 'both', taking precedence over the legacy supports_reasoning
boolean) onto the existing always_thinking capability:
- oauth: parse the field in both /models parsers; 'only' emits
always_thinking alongside thinking, 'no' suppresses thinking even
when supports_reasoning is set, absent falls back to the legacy
boolean. Default thinking selection is forced on for 'only' (and
off for 'no') models during login and provider refresh
- TUI: render the thinking control with a fixed On/Off layout — locked
models show a greyed-out "Off (Unsupported)" segment, and
non-thinking models mirror the style with "On (Unsupported)"
- agent-core: clamp thinkingLevel at the getter so a stale
thinking-off config can never reach the request builder, status
events, or subagent inheritance
- acp-adapter: derive alwaysThinking from capabilities, collapse the
thinking select to a single locked "on" entry, and ignore off
requests for locked models while re-emitting the snapshot
* chore: ignore .worktrees directory
* feat: add tips banner below welcome panel on startup
- Fetch active/fallback tips from the configured CDN with a 3s timeout.
- Filter tips by semver, client version, and date range.
- Render the banner directly below the welcome panel on startup/resume.
- Support tag, multi-line text, subtext, automatic wrapping, and narrow-terminal safety.
* refactor(tui): use theme color methods in banner component
Replace raw chalk calls with currentTheme helpers: tag uses
boldFg('primary'), main text uses boldFg('textStrong'), and subtext
uses fg('textDim') without stacking the dim modifier on the already
dim shade. Strengthen tests to assert the exact themed ANSI output.
- Open the active server URL when `kimi server run` finds an existing local server\n- Distinguish background vs foreground server mode in conflict message\n- Show mode-appropriate stop command (`kimi server stop` or `pkill`)\n- Always include host in lock file contents\n- Add tests for already-running server handling
- collect and embed server web assets into the native SEA binary\n- add web-assets manifest and collection scripts for native builds\n- make swagger/swagger-ui registration conditional in server start\n- enrich lifecycle commands with service URL, running state, log path, and notes\n- add --no-open flag to control auto-opening web UI after install\n- introduce ServiceUnavailableError and ProgramServiceManager\n- update service managers (launchd, systemd, schtasks) with new status fields
- switch createServerLogger from pino transport target to in-process pretty stream\n- update changeset to cover @moonshot-ai/server\n- add test asserting pretty logger does not use ThreadStream\n- rename cli server test description
add pino-pretty to apps/kimi-code dependencies to fix server startup when pretty logging is enabled\nadd regression test verifying the dependency is declared\ninclude changeset for patch release
Add a third UI theme "kimi" implementing the official Kimi design
language (Quiet Utility) with token-exact values from kimi-design-skill
tokens.json v0.2.0:
- Interaction accent = kimiDark (black in light / white in dark);
kimiBlue stays reserved for brand/data-viz (::selection only)
- Gray user bubbles (bubbleGrayPc), flat tool cards and dialogs; shadows
only on the composer (shadow.inputDefault) and floating menus
(shadow.small); dark elevated surfaces use background.tertiary
- PingFang SC for UI, Geist Mono for code (bundled JetBrains fallback)
- Modern's de-terminalization rules are shared via
:is(html[data-theme="modern"], html[data-theme="kimi"]) — identical
specificity, so Modern renders exactly as before; kimi token blocks
sit after the data-accent rules and pin the accent (the accent picker
is hidden while kimi is active)
Theme pickers (sidebar popover, mobile sheet) and onboarding now offer
Modern/Kimi only. Terminal remains the CSS baseline and a persisted
'terminal' choice still loads; it's just no longer offered in the UI.
Also: file-preview pane default width now follows half the window.
- rename workspace package `@moonshot-ai/daemon` to `@moonshot-ai/server`\n- rename `@moonshot-ai/daemon-e2e` to `@moonshot-ai/server-e2e`\n- replace `kimi daemon` and `kimi web` with `kimi server run`\n- keep `kimi web` as alias for `kimi server run --open`\n- add `kimi server install/uninstall/start/stop/restart/status`\n for launchd (darwin), systemd (linux), and schtasks (win32)\n- update dev scripts, kimi-web stub, documentation, and service naming checks\n\nBREAKING CHANGE: the `kimi daemon` command and `@moonshot-ai/daemon`\npackage are removed; use `kimi server` and `@moonshot-ai/server`.