Conversation
🦋 Changeset detectedLatest commit: 7f8c558 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
❌ Nix build failed Hash mismatch in
Please update |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59d44f9b2b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| port: options.port, | ||
| logLevel: options.logLevel, | ||
| debugEndpoints: options.debugEndpoints, | ||
| webAssetsDir: daemonWebAssetsDir(), |
There was a problem hiding this comment.
Include web assets for native daemon startup
In native builds, the workflow runs build:native:* and package:native, and scripts/native/package.mjs zips only the executable, so there is no dist-web directory beside a package root for the SEA binary. Passing daemonWebAssetsDir() here makes startDaemon assert filesystem web assets before listening, so native users running kimi daemon or kimi web hit the “Kimi web assets were not found” startup failure even though the command is now exposed.
Useful? React with 👍 / 👎.
| if (input.apiKey !== undefined) body['api_key'] = input.apiKey; | ||
| if (input.baseUrl !== undefined) body['base_url'] = input.baseUrl; | ||
| if (input.defaultModel !== undefined) body['default_model'] = input.defaultModel; | ||
| const data = await this.http.post<WireProvider>('/providers', body); |
There was a problem hiding this comment.
Implement provider mutation endpoints before calling them
When the ProviderManager tries to add a provider, this client posts to /api/v1/providers, but the real daemon route file only registers GET /providers and GET /providers/{provider_id}; I also searched the repo for provider routes and found no POST/DELETE/refresh handlers. As a result the UI's add provider flow always receives a missing-route error instead of saving the provider.
Useful? React with 👍 / 👎.
20d3161 to
f9417af
Compare
High-fidelity 'this is what it looks like' mockup built from the user's choices: goal as an expandable dock strip, swarm/subagent as inline TUI-style chat cards (referencing agent-swarm-progress / AgentGroup), plan/goal/swarm activation badges in the status line, and a VSCode-style flexible terminal split (single tab first). Records the locked decisions in the design doc; subagent placement flagged as pending final confirmation.
- Status checkmarks now render as SVG icons (swarm counts, member summaries, agent sub-tools) instead of text glyphs. - Swarm card lays members in a multi-column grid (multiple per row, TUI-style) instead of one per row. - Clarify the flexible terminal split: it is a tab/view-dimension split (VSCode editor groups holding chat/tasks/todo/files/terminal), NOT a split inside the terminal tab. Updated the mockup and the locked-decision record accordingly.
File/event/component/test-level plan for the locked P3 design: subagent lifecycle projection + inline agent cards, inline swarm card, goal dock strip, plan/goal/swarm activation badges, terminal tab, and tab/view-dimension split. TDD with real test code for the projector/reducer/pure-logic layers; phased, each phase independently shippable.
Drop the per-step TDD/commit scaffolding; keep the substance as one final approach per area (what it does, files to touch, key types/events/projection, component responsibilities, verification, risks, sequencing).
Group consecutive tool cards structurally so chat block spacing is applied consistently without leaking card borders or shadows.
Implements the locked P3 design end-to-end: - subagent lifecycle projection (spawned→started→suspended→completed/failed) + inline Agent / AgentGroup cards; swarm progress card (multi-column) derived from swarmIndex; goal dock strip (expandable) from goal.updated; plan/goal/ swarm activation badges in the composer status line. - terminal as a view (xterm + WS terminal_* frames with since_seq replay) and a tab/view-dimension split (usePaneLayout tree + ViewGroup + SplitLayout, VSCode editor-group style), persisted to localStorage. Adds swarm-groups / subagent-goal / agent-group-turns unit tests and stub-daemon seeds. 98 tests pass; vue-tsc + oxlint clean; production build OK. Accepted by review (see reports/web-p3-acceptance.md); no blocking issues.
Comprehensive acceptance of the P3 landing (f5a7f21): per-area verdicts, the terminal 'map' crash explained as a stale-stub test artifact, non-blocking recommendations, and verification record (98 tests, vue-tsc/oxlint clean, prod build, in-browser smoke). No serious issues found; no code changed per the 'only fix serious issues' instruction.
…ilds Two distinct PTY failures: - 'Failed to load native module: pty.node' (npx/published daemon): node-pty was transitively bundled via @moonshot-ai/services (alwaysBundle), inlining its JS while its native binary can't be bundled and wasn't shipped. Mark node-pty external in tsdown (neverBundle) and declare it as a runtime dependency of @moonshot-ai/kimi-code so npm/npx installs it with its prebuilt pty.node. - 'posix_spawnp failed' (local pnpm dev): node-pty's prebuilds/*/spawn-helper loses its +x bit through pnpm's store extraction. Add a root postinstall (scripts/fix-node-pty-perms.mjs) that restores the executable bit; verified it fixes a reproducible spawn failure. Also harden defaultShell() to fall back on an empty (not just unset) $SHELL. Note: the SEA standalone binary still needs node-pty's pty.node + spawn-helper wired into scripts/native/native-deps.mjs (not addressed here; npx path covers the reported case).
…inal xterm's fontFamily takes a literal font string, so 'var(--mono)' never resolved and the terminal fell back to courier with loose metrics — the wrong-looking font and spacing. Pass the actual JetBrains Mono stack, await document.fonts before xterm measures the cell (so the variable font isn't mismeasured), tighten lineHeight 1.25 → 1.1, and pin letterSpacing 0.
…l output Remove the per-line kimi-line-in stagger on `.box.open .bb > div` (modern/kimi themes) and its keyframes — expanding a tool card no longer animates each output line in.
Previously the command/summary always sat on the header. Now it shows on the header only while collapsed; expanding hides it from the header and renders it at the top of the card body (above the output) — so it appears exactly once and the expanded header stays clean. Re-adds the .bb-summary style and a mount test.
The expanded body has room to wrap, so it shouldn't keep the header's '…' clip. Add a `full` flag to toolSummary that skips the length clip and use it for the .bb-summary; the collapsed header keeps the clipped form (CSS ellipsis still guards overflow). Extends the mount test to cover full-vs-clipped.
Reverts 980ff9d: dropping the moon the instant the first token streamed wasn't wanted. Remove the assistantDelta/messageUpdated clear so sendingBySession is again cleared only on turn end (onSessionIdle), restoring the prior behavior, and delete the now-moot sending-moon test.
The composer input (.ph) under the modern/kimi themes was 13px while the terminal-theme baseline is 14px. Unify on 14px so the textarea text matches the rest of the composer.
…bble)
Steering an image while a turn was running rendered TWO user bubbles and the
steer text looked like it never landed. Two causes:
1. The reducer matched the daemon's user-message echo to our optimistic copy by
exact content equality. Image content serializes differently on each side
(our {source:{kind:'file',fileId}} vs the daemon's resolved URL/base64), so
the echo never matched and appended a duplicate. Match by prompt_id first
(stamped on the optimistic message at submit), falling back to content.
2. Optimistic message ids were msg_opt_<Date.now()>. A queued send + a steer in
the same millisecond collided on one id, so the prompt_id stamp landed on the
wrong message. Use a monotonic counter for a unique id per optimistic message.
steerPrompt now also stamps the real prompt_id onto its optimistic echo, like
submitPromptInternal already did.
Selecting a never-opened session set sessionLoading=true until its snapshot arrived, so the chat pane (loading spinner) rendered for a beat before the empty-composer. A session the daemon reports as empty (messageCount 0) has nothing to load — keep sessionLoading false for it so the empty-composer shows immediately. Non-empty sessions still show the loading state.
Refreshing while a turn was streaming left two things parked above the live output: - The thinking block's inner 5-line window stayed at its TOP. Its scroll watcher only re-pins when already at the bottom, but a refresh delivers the whole thinking text at once with scrollTop 0. Pin a streaming block to its latest line on mount. - The transcript could stop short of the bottom: the first scroll runs before markdown highlighting/images lay out and grow the content. Re-pin on the next couple of frames (only while still following) so a refresh ends at the latest content.
A subagent runs under the parent session id and streams its own turn / step / delta / tool frames over the SAME session channel, each tagged with the subagent's agentId. The web projector folded them into the parent transcript, which produced the reported bug: empty 'skeleton' assistant bubbles (a subagent turn.step.started opened a parent assistant message the main agent never filled) and fragmented snippets (subagent deltas appended to the parent). Skip transcript-building frames whose agentId is a non-main subagent, mirroring the server's InFlightTurnTracker (which already tracks only main-agent activity). Subagent progress is unaffected — it flows through the subagent.* -> task -> AgentCard path, which is intentionally not gated.
The wide-screen float-stack pinned a todo card + running-tasks card to the top-right of the chat. Drop the overlay entirely (and the now-unused TasksCard.vue) — todos and background tasks live in their own ~/todo and ~/tasks tabs, so the overlay was a redundant, transcript-covering duplicate.
…flow The tasks tab capped the list at 5 rows and showed '… +N more', hiding the rest even with plenty of room. Render every task and let the list scroll internally once it overflows the pane, so nothing is silently dropped.
The gutter slot left of each session title (which kept the title aligned under the workspace name) now carries a status indicator instead of being an empty spacer: - a small SVG spinner (Kimi-blue arc) while the session is running, replacing the old absolutely-positioned pulse dot; - an unread blue dot when a BACKGROUND session finished a turn the user hasn't opened yet. Tracked via unreadBySession (set on idle for a non-active session, cleared when the session is selected).
On Windows, spawning a console-subsystem executable (gh.exe / git.exe) from the background Kimi server creates a visible console window that flashes on screen. Set windowsHide: true (a no-op on POSIX) to suppress it.
- bootstrap telemetry in `kimi web`/`kimi server run` via initializeServerTelemetry (ui_mode=web, honors telemetry=false) - wire the real client into KimiCore so agent-core events carry the enriched context - emit server_started after the server listens; flush telemetry on shutdown - emit ws_connected/ws_disconnected from WSGateway via WSGatewayOptions.telemetry - re-export loadRuntimeConfigSafe/resolveConfigPath from the SDK for host config reads
- add `kimi server kill` to stop the running daemon (graceful API + forced PID kill) - add `POST /api/v1/shutdown` so the server can terminate itself - make `kimi server run` start in the background and print the ready banner - route `kimi web` through the same path as `server run` so it prints the banner too
Resolves eslint no-dupe-keys and TS1117 errors that broke the lint and typecheck CI jobs.
The local Inter font dependency changed pnpm-lock.yaml, so refresh the fixed-output derivation hash to match what the nix builder computes. Resolves the nix build .#kimi-code CI failure.
Restore forwarding of x-kimi-client-* headers into session creation telemetry, which was dropped during the services-to-agent-core merge and left the new-session telemetry test with empty records.\n\nRetry the skills e2e sandbox cleanup to ride out ENOTEMPTY races when the core process flushes files into the sandboxed home after close().
These 20 changeset files were applied during the version bump and are no longer needed.
Remove files that were not intended for submission: - docs HTML research/design archives - docs/superpowers specs added during design phase - apps/kimi-web icon preview pages and one-off test script
The real server package is now available; the throwaway stub daemon is no longer needed for development.
Related Issue
No linked issue. This PR introduces the web client, daemon gateway, and supporting service foundation for browser-based Kimi Code sessions.
Summary
Adds a Vite/Vue Kimi web application backed by a local daemon REST/WebSocket gateway, wires the CLI
kimi weband daemon entry points, and moves daemon-facing capabilities into reusable services with focused e2e and unit coverage.1. Web Client Experience
Problem: Kimi Code currently has no browser UI for managing workspaces, sessions, prompts, tools, approvals, file diffs, and provider settings against a local daemon.
What was done:
apps/kimi-webwith Vue components, i18n, API clients, state projection/reduction, markdown/image rendering, composer controls, responsive desktop/mobile layouts, onboarding, login, session, and workspace flows.2. Daemon Gateway And CLI Entry Points
Problem: A web UI needs stable daemon endpoints and a simple way for CLI users to launch the daemon-backed browser workflow.
What was done:
daemonandwebsubcommands plus scripts for web asset copying and daemon development restart flows.3. Shared Services, Protocol Boundaries, And DI
Problem: Daemon-facing capabilities were spread across layers, making reuse and lifecycle management harder as web and daemon features expanded.
What was done:
4. Verification, Docs, And Release Metadata
Problem: The new daemon/web flow needs coverage for REST/WS behavior and release metadata for affected packages.
What was done:
Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.