mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-19 21:56:00 +00:00
38 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c0c9f155da | fix: restore prompt id in server-v2 snapshots | ||
|
|
b905dd4910
|
feat(web): redesign web UI and add design system (#1258)
* feat: redesign web ui & add design system * feat(web): add motion to redesigned UI and add changesets Animate toast enter/leave, dialog open, and workspace-list and tool-row expand/collapse instead of snapping, and add the changesets covering the web redesign. * fix(web): remove undo message exit animation * fix(web): route agent tools to AgentTool and focus dialog on open - toolRegistry matched the raw 'agent' name, but normalizeToolName folds agent/subagent into 'task', so agent calls fell through to GenericTool and lost the inline Open button for the subagent detail panel. - Dialog's focus watcher only fired on change; callers that mount with open already true (Login, Settings, ...) never moved focus into the modal. Run it immediately so initial focus and restore-on-close work. * feat(web): add logo long-press design-system easter egg Hold the sidebar logo for 3 seconds to open a dialog showing the design system page. Also trim and rebalance the redesign changesets. * fix(web): silence Sidebar v-show warning by making it single-root Nest the design-system Teleport inside the sidebar <aside> so the component has a single element root. App applies v-show to Sidebar, which needs an element root to attach to; the fragment root logged a "non-element root node" warning on every reactive update and the collapse did not take effect. * fix(web): thinking toggle, tool-group i18n, agent detail button - Show the default-thinking switch as on whenever thinking is effectively enabled (enabled !== false), matching the core resolver. - Route the grouped tool-call header and status through vue-i18n. - Hide the subagent "Open detail" button when no matching task exists (e.g. a completed foreground subagent after a refresh). * fix(web): use strict equality in agent detail button guard oxlint eqeqeq flagged the loose != null check; resolveAgentTaskId returns string | undefined, so compare with !== undefined. * chore(web): remove stray design mockups and screenshots Remove the design exploration mockups, screenshots, prompts, and notes that were accidentally committed under apps/kimi-web/design. Keep design-system.html, which the sidebar logo easter egg still references. * fix(web): keep sessions on continuation failure, treat absent thinking as on - Keep sessions already loaded from earlier pages when a continuation page fetch fails, instead of replacing the workspace with an empty page. - Treat an absent thinking config as enabled in the settings toggle, matching the core resolver (thinking is on unless explicitly disabled). * feat(web): open design-system easter egg on 10 logo clicks Replace the 3-second long-press trigger with 10 consecutive clicks on the Kimi mark; the count resets after a short idle. The long-press was unreliable because pointerleave cancelled the timer on any drift. * fix(web): treat cancelled swarm members as finished phaseForTask now lets a terminal status (completed/failed/cancelled) override a stale subagentPhase, so a cancelled swarm member no longer stays live and suppresses the finished AgentSwarm card. * feat(web): use 1s long-press for design-system easter egg Switch the logo easter egg back to a long-press, shortened to 1 second, and make it reliable this time: use pointer capture plus touch-action:none so a slight drift no longer cancels the hold. * fix(web): use plain Spinner for activity notices ActivityNotice renders for non-chat loading states (e.g. compaction), so it must use Spinner per the design-system rule that reserves MoonSpinner for the chat first-response state. * docs(web): add a11y guidance to design system * docs(web): drop stale design README link * fix(web): restore model search focus and define panel header weight - Bind the model picker's search Input to searchRef so useDialogFocus moves focus into it on open instead of the dialog's close button. - Use the defined --weight-semibold token for panel header titles (--weight-bold is not declared, so the shorthand was invalid). * fix(web): let any open dialog own Escape over the side panel Track open design-system Dialog instances in a shared count and include it in App.vue's anyOverlayOpen, so a dialog whose open state lives outside App.vue (such as the sidebar session search) captures Escape before the background side panel closes. * fix(web): base dock-work flag on filtered dock task lists Foreground subagents are excluded from the dock task lists, so a session whose only task is a foreground subagent no longer renders an empty workbar above the composer. * fix(web): create subagent task before forwarding text deltas A client that subscribes from a snapshot after subagent.spawned already fired never received the lifecycle taskCreated; the reducer only applies taskProgress to existing tasks, so assistant text deltas were dropped and the live subagent detail stayed blank. Emit taskCreated (via patchSubagent) before the text progress, mirroring the tool-progress path. * fix(web): keep plan, swarm, and goal mode toggles per session Plan, swarm, and goal modes were stored as global scalars on the web client and a single localStorage key each, so they leaked across sessions. Bind them to the active session via per-session maps, persist per session, and apply server status/events to the originating session so background sessions keep independent state. * fix(web): keep subagent detail reachable for synthesized tasks When the web client subscribes after a subagent already spawned, the synthesized subagent task has no parentToolCallId, so the Agent tool's Open-detail button was hidden and the panel would not open. Fall back to the single unmapped subagent task when resolving the detail target in both the button visibility and the panel open paths. * fix(web): keep session kebab menu from being clipped Teleport the SessionRow kebab menu to body and anchor it with fixed positioning so the collapsing group-sessions list's overflow:hidden no longer clips the dropdown. * fix(web): apply staged modes to the created session by id When starting the first prompt, apply the staged plan/swarm/goal modes to the just-created session's per-session maps by id instead of via the activeSessionId-based setters, so a session switch during the selectSession await can't drop the modes for this session or pollute another. * refactor(web): unify confirmation dialogs into a single modal Replace the inconsistent confirmation patterns (native confirm(), two-step menu arming, hand-rolled inline strips, bare buttons) with one modal ConfirmDialog driven by a global useConfirmDialog() composable, and consolidate the duplicated confirm/cancel i18n keys. * feat(web): inline message queue with separate stop button - Send button always sends/enqueues; interrupt moves to a separate red Stop button shown only while running, so the two can no longer be confused. - Queued prompts now render inline at the tail of the transcript (after the running turn) instead of behind the dock panel: click to edit, remove, drag the grip to reorder, with image thumbnails and a "next up" marker. - Remove the dock queue panel and the QueuePane component; Steer stays on Ctrl/Cmd+S. * chore: add changeset for web queue UX * feat(web): prompt reliability, sidebar menu, and composer/markdown polish - Fix spurious errors when question/approval/task actions were already complete - Add loading feedback to question and approval prompts; block double-clicks - Make the question "Other" option selectable by row click and let Enter advance/submit - Consolidate workspace section actions into an overflow menu - Tighten markdown prose line-height and block spacing - Recall input history only when the caret is at text start |
||
|
|
882cf355a9
|
fix(web): persist workspace rename and hide provider manager (#1234)
* fix(web): persist workspace rename via the daemon update API * fix(web): hide the unshipped provider manager * fix(web): fall back to a local override for derived workspace renames * fix(web): preserve workspace name override across registration |
||
|
|
bfe8e6ace3
|
fix(web): surface error when adding a workspace by path fails (#1236)
* fix(web): surface error when adding a workspace by path fails Previously, addWorkspaceByPath swallowed any error from the daemon and created a local-only workspace that could not host sessions and vanished on reload, so an invalid absolute path appeared to succeed but never took effect. Now the error is reported to the user and no fake workspace is added. * fix(web): preserve pending prompt when adding workspace fails addWorkspaceByPath now returns a boolean success signal. handleAddWorkspace only clears pendingWorkspaceSubmit and sends the prompt on success, so a daemon-rejected path no longer drops the user's pending submission; they can retry with a valid path. * fix(web): keep workspace picker open when add fails Move closing the add-workspace dialog until after a successful add. On a daemon-rejected path the picker now stays open with the user's input intact, so they can correct the path and retry; the pending submission is consumed by a successful retry or dropped only when the user explicitly closes the picker. * fix(web): show add-workspace errors inline in the picker When the daemon rejects a path, the global warning toast rendered behind the picker's backdrop (z-index 60 vs 200) and could auto-dismiss unseen. Surface the failure as an inline error inside the dialog instead, so it is visible and persists until the user retries or closes. addWorkspaceByPath now returns a boolean and leaves surfacing to the caller; the picker shows a localized inline message. |
||
|
|
a3f9cec8a9
|
fix(web): deduplicate workspaces shown in the sidebar (#1221)
Collapse registered workspaces that share a root in the daemon registry (preferring the canonical id) and in the web sidebar merge, so the same folder no longer renders as two identical, synchronously-selected entries. |
||
|
|
1dab2c2268
|
feat(web): preserve side panel and scope input history per session (#1181)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / build (push) Waiting to run
CI / test (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat(web): preserve open side panel across session switches * feat(web): scope composer input history to current session * fix(web): suppress side panel open animation on session switch * fix(web): preserve per-session scroll position on session switch * chore: add changeset for per-session scroll position * fix(web): preserve follow-bottom state per session * fix(web): scope composer attachments to their session * fix(web): restore saved scroll position on session switch |
||
|
|
fc3d69dbdc
|
feat(web): add completion sound and question notifications (#1179)
* feat(web): play a sound when a turn completes Synthesize a short chime when a session finishes a turn. Opt-in via Settings -> Notifications (off by default); the audio context is unlocked on the first user gesture so it also plays while the tab is backgrounded. * feat(web): notify and play a sound when a question needs an answer Reuse the existing notification/sound toggles so they also fire when the agent asks a question (the awaiting-answer state). Generalize the Settings labels to cover both cases. * fix(web): don't queue the chime on a suspended audio context A suspended AudioContext has a frozen clock, so tones scheduled on it would play stale when the context later resumes (e.g. on the next click). Only schedule the chime when the context is actually running; if it is still suspended, try to unlock it for next time and skip this one. * fix(web): gate question notifications behind explicit opt-in Question notifications surface question text, so they must not fire for users who only opted into turn-completion alerts (which default on). Split question notifications into their own persisted preference that defaults off, with a separate Settings toggle. Completion notifications keep their existing default-on behavior. * fix(web): show the question text in question notifications Lead with the actionable question text in the desktop notification body, keeping the short header as context (e.g. 'Storage: Which database?'). Previously the header alone was shown, so users had to open the tab to learn what was being asked. |
||
|
|
ff6e8bbd7c
|
fix(web): clear composer draft synchronously on send (#1163)
When the first message of an empty session is submitted, the optimistic user turn unmounts the empty-session composer before the post-flush text watcher can persist the cleared draft. The docked composer then mounts and reloads the stale text from localStorage. Clear the persisted draft synchronously in the submit / steer / slash command paths instead of relying on the text watcher, so the next mount always starts empty. |
||
|
|
81ba48f455
|
feat(web): auto-grow composer and add expandable editing mode (#1121)
* feat(web): auto-grow composer and add expandable editing mode - Grow the chat textarea with its content up to a 1/4-viewport cap. - Add an expand toggle above the send button for a taller editor; in that mode Enter inserts a newline and Cmd/Ctrl+Enter or the button sends, then the editor collapses back. * fix(web): reset expanded composer state on session change The composer instance is reused across sessions (not keyed by session id), so the expanded preference leaked into the next session's draft, leaving it stuck in the tall editor with Enter inserting newlines. Collapse back when the active session changes. * fix(web): match expand-toggle threshold to theme resting height The modern/kimi global theme overrides the composer min-height to 40px (the scoped default is 56px), so a hard-coded 56px threshold kept the expand toggle hidden until a third line under the default theme. Read the computed min-height from the element instead. * fix(web): recompute expand-toggle visibility after collapsing While expanded the computed min-height is 70vh, so a multi-line draft measured there sets isGrown=false. Collapsing did not recompute it, hiding the toggle even though the collapsed draft was still multi-line. Recompute growth after every toggle via a shared helper. The expanded state itself is unchanged and stays at 70vh until toggled or sent. * fix(web): collapse expanded editor on slash-command submit Known slash commands return early from handleSubmit, above the post-send collapse, so sending an expanded /goal, /btw, /compact, or skill command left an empty 70vh editor. Collapse in the slash-command path too. * fix(web): refocus textarea after toggling expand Clicking the expand toggle leaves focus on the button, so subsequent keystrokes do not reach the textarea and Enter would activate the button again instead of inserting a newline. Return focus to the textarea after toggling. * fix(web): refit textarea when collapsing after image-only sends When the expanded editor collapses on an image-only send, the text is already empty so the draft watcher never re-runs autosize; the textarea kept the inline height measured at 70vh and the collapsed cap left an oversized empty box. Route all send/steer collapses through a helper that re-runs autosize after the 70vh min-height is removed. --------- Co-authored-by: liruifengv <liruifeng1024@gmail.com> |
||
|
|
6194d3fad3
|
perf(web): reuse sessions reference to stop sidebar re-render on streaming deltas (#1113) | ||
|
|
d554f9ac87
|
feat(web): show full accumulated subagent progress (#1109)
* feat(web): show full accumulated subagent progress The subagent detail panel only showed the most recent 40 progress lines because the reducer truncated the accumulated output. Keep the full history so the panel reflects the entire process as it grows. * fix(web): preserve subagent progress across task updates The projector emits a taskCreated (without reducer-owned outputLines) right before every taskProgress, and the taskCreated branch replaced the task object outright, resetting outputLines to empty on each progress event. So the panel still only showed the latest chunk. Preserve the accumulated outputLines when replacing a task, and update the test to mirror the real taskCreated-before-taskProgress path. * feat(web): clean up subagent progress text Drop the noisy 'Started a step' line and summarize tool calls with a concise target (path / command / pattern) instead of the full JSON args, so the subagent progress panel shows what the subagent is actually doing. * fix(web): strip numeric index from subagent tool result names Some subagents name tool calls with a trailing index (e.g. Read_0, Bash_4), which surfaced in tool.result progress lines since the label did not resolve. Strip the index before resolving the label. * fix(web): bound non-subagent task output and subagent progress text Restore a tail cap for background bash/tool task output (which can grow without bound) while keeping subagent progress in full, and cap individual subagent tool.progress chunks so a single huge output cannot dominate the panel. * feat(web): group and fold subagent progress output Drop the noisy 'Finished' lines, group tool output under its call, and fold long output (first 5 + last 2 lines, expandable) so the subagent progress panel shows the call rhythm at a glance. |
||
|
|
18f7c34a07
|
feat(web): show edit diffs inline in tool call cards (#1103)
* feat(web): show edit diffs inline in tool call cards Render a line-by-line diff inside Edit/Write tool cards in the web chat, reusing the existing diff-line style from the changes panel. The diff is built client-side from the tool input, so no protocol or server changes are needed; the header chip now shows real +/- counts. * fix(web): extend diff line backgrounds through horizontal scroll Diff rows were only as wide as the viewport, so the add/del background stopped where long lines overflowed and the area revealed by horizontal scroll had no color. Size each row to its content so the background paints the full line. * fix(web): make all diff rows fill the longest line width Size the diff container to the longest line and have every row fill it, so add/del backgrounds form one continuous band across the whole horizontal scroll instead of stopping at each line's own length. * fix(web): resolve oxlint errors in diff line builder Use Array.at(-1) and Array.from instead of index access and new Array(length), which oxlint flags as errors. * fix(web): show tool output for failed edit/write calls When an Edit/Write call fails, render the tool output (the failure reason) instead of the requested diff, so error cards explain why no change was applied. * fix(web): fall back to tool output for replace_all and append edits A single-pair diff misrepresents replace_all edits (which change many occurrences) and from-empty diffs misrepresent append writes (which extend an existing file). Skip the synthetic diff in those cases and render the truthful tool output instead. * feat(web): open edit diffs in the right-side detail panel Move the Edit/Write diff out of the inline tool-card body into the shared right-side detail layer, opened by clicking the card (like the subagent detail panel). The panel shows the line diff when it faithfully represents the operation, otherwise the tool output (replace_all, append, errors), so failed calls explain why no change was applied. * feat(web): toggle detail panels closed when their trigger is clicked again Clicking the same Edit/Write card, file link, or git-status area a second time now collapses the right-side detail panel, matching the existing thinking / compaction / subagent toggle behavior. * fix(web): cap client-side edit diff to avoid freezing on large inputs The line-level LCS allocates an (oldLines+1) x (newLines+1) matrix and runs eagerly when an Edit/Write card renders. For large edits (e.g. a 5k x 5k block, ~25M cells) this can freeze or exhaust the chat. Cap the matrix at 1M cells and fall back to the raw tool output beyond that. * fix(web): keep the edit diff panel in sync with live tool state Store only the tool id and re-derive the diff panel payload from the live tool call in the session turns, so a panel opened while the tool is still running reflects later status/output changes (e.g. an eventual error shows the failure output instead of the stale attempted diff). * fix(web): do not render a synthetic diff for Write calls Write only reports the new content, so the client cannot tell a new file from an overwrite of an existing one. A from-empty diff showed overwrites as all additions and no deletions, which is misleading. Fall back to the tool output for every Write (append already did). * fix(web): also cap diff output rows, not just the LCS matrix The matrix-size cap alone let through asymmetric edits (e.g. one line replaced by hundreds of thousands) whose small matrix still produced a huge row array that the chip computed on render. Cap each side's line count too, so the diff output is bounded. * fix(web): keep edit/write cards expandable when the diff panel is unwired Clicking an Edit/Write card opens the right-side diff panel, but the nested ChatPane in the side chat does not wire that event, so the click became a no-op and the card could no longer expand to show its output. Gate the panel behavior behind a toolDiffPanel prop (enabled only in the main conversation); elsewhere the cards expand inline as before. * fix(web): close the tool diff panel when its target disappears When a session resync removes the tool call an open diff panel is showing, toolDiffTarget becomes null but detailTarget stayed 'toolDiff', leaving an empty aside that Escape would not close. Gate sidePanelVisible on toolDiffVisible so the panel collapses once its target is gone. |
||
|
|
f1fad7222c
|
fix: reduce streaming stutter in the web chat (#1085)
Some checks are pending
CI / test (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix(web): coalesce streaming token updates into one render per frame * fix(server): disable Nagle on WebSocket socket for lower streaming latency * fix(web): flush pending streaming deltas before re-subscribing * fix(web): flush pending streaming deltas before forgetting a session |
||
|
|
884b65a040
|
fix(web): coalesce snapshot reloads on resync (#1087)
Avoid concurrent session snapshot requests when resync_required fires repeatedly, while still allowing one queued rerun after the in-flight reload settles. |
||
|
|
98d3e5b71d
|
feat(web): stabilize and drag-reorder workspaces in the sidebar (#1047)
* feat(web): stabilize and drag-reorder workspaces in the sidebar * fix(web): preserve dragged workspace order after refresh * fix(web): float session to top of its group on new message * fix(web): align workspace drop order with insertion marker * fix(web): allow dropping a workspace after the last item * fix(web): use reordered workspaces for active fallback * fix(web): honor drag order for next-workspace fallback on removal |
||
|
|
ac1882fe28
|
feat(web): persist collapsed workspace groups to localStorage (#1045) | ||
|
|
9d197e0f67
|
fix(web): make clipboard copy work over plain HTTP (#1044)
* fix(web): make clipboard copy work over plain HTTP
The Clipboard API (navigator.clipboard) is only exposed in secure contexts. When the web UI is served over plain HTTP, every copy action threw synchronously and silently failed. Route all copy call sites through a helper that falls back to execCommand('copy') in insecure contexts, and surface success or failure feedback to the user.
* test: address review feedback and a flaky goal-badge test
- clipboard test: drop the jsdom environment and mock the small navigator/document surface in the default node environment, per the kimi-web "pure logic tests only" rule.
- footer-goal-badge test: assert the absence of the "[goal" badge instead of the bare "goal" substring, which could match a rotating working tip ("/goal ...") and fail depending on Date.now().
|
||
|
|
27df39c7ed
|
fix(web): fall back to session abort for stale prompts (#1043)
* fix(web): fall back to session abort for stale prompts * test(web): cover stale prompt abort fallback |
||
|
|
603a7679de
|
refactor(web): extract attachment upload into a composable (#1034)
Move the image/video attachment state, the file-picker / paste / drag-drop handlers, the upload machinery, the preview lightbox, and the paste-listener + object-URL cleanup lifecycle out of Composer into useAttachmentUpload. The composer keeps handleSubmit / handleSteer (which read the attachments to build the payload) and the hasUpload toolbar flag; it consumes the returned refs and handlers directly. The destructured names match the originals so the template bindings are unchanged. handleSubmit / handleSteer now call the composable's clearAfterSubmit() to revoke object URLs and drop the list. Composer.vue: 1937 -> 1787 lines. Adds unit tests for useAttachmentUpload. No behavior change. |
||
|
|
2bfd6860e4
|
refactor(web): extract composer text + draft persistence into a composable (#1031)
Move the composer's text ref, textarea ref, autosize helper, the per-session draft load/save watchers, and the loadForEdit handle into useComposerDraft. The returned text/textareaRef/autosize refs are passed straight through to the history / slash / mention composables as their deps, so the rest of the component is unchanged. Composer.vue: 1987 -> 1937 lines. Adds unit tests for useComposerDraft. No behavior change. |
||
|
|
661c1fbe5b
|
refactor(web): extract @-mention menu into a composable (#1030)
Move the @-mention menu's open/items/active/loading state, the @token detection, debounced search, and insertion logic out of Composer into useMentionMenu. The composer keeps the keydown orchestration (it also juggles the slash menu and history recall) and consumes the returned refs directly; the destructured refs are aliased back to the original names so the rest of the component is unchanged. Move the FileItem view type into types.ts (mirroring the FileData move) so the .ts composable can import it without hitting the type-aware lint rule against importing types from .vue files; MentionMenu re-exports it for the existing .vue consumers. Composer.vue: 2035 -> 1987 lines. Adds unit tests for useMentionMenu. No behavior change. |
||
|
|
318c964f07
|
refactor(web): extract slash-command menu into a composable (#1026)
Move the slash menu's open/items/active state, the filter logic, and item selection out of Composer into useSlashMenu. The composable takes the text ref, textarea ref, autosize, a skills getter, and the emit/history-push callbacks as deps. The composer keeps the keydown orchestration (arrow keys, Enter/Tab, Escape) because it also juggles the mention menu and history recall; it consumes the returned open/items/active refs directly and calls update/select. The destructured refs are aliased back to the original names so the rest of the component is unchanged. Composer.vue: 2058 -> 2035 lines. Adds unit tests for useSlashMenu. No behavior change. |
||
|
|
83384ee6d4
|
fix(web): persist input history so recall works after the first message (#1015)
* fix(web): persist input history so recall works after the first message The composer has two mutually-exclusive instances: the empty-session composer and the docked composer. The first message of a new session is sent by the empty composer, which unmounts as soon as the first turn appears; the docked composer then mounted with an empty in-memory history, so ArrowUp did nothing until a second message was sent. The history was also lost on every page reload. Persist the history to localStorage as a single global list and re-read it on mount. Global (not per-session) because a new session has no id until after the first submit, so per-session keys would not line up across the empty -> docked handoff. Caps the list at 200 entries. Adds persistence-focused unit tests (surviving a remount, the 200-entry cap, and a malformed stored value). * fix(web): record slash commands in input history too Move the history.push call ahead of the slash-command branch so that known commands (with or without args, e.g. /goal <task> or /model) are recorded and can be recalled with ArrowUp, instead of only plain messages. Steer already pushed; only the submit slash path was missing it. * fix(web): record menu-selected slash commands in history Bare slash commands picked from the slash menu (e.g. /model, /login) go through selectSlashCommand and emit directly, never reaching handleSubmit, so they were not recorded even after the typed-slash fix. Push the command name before emitting. acceptsInput commands are still recorded later by handleSubmit together with their argument. |
||
|
|
fb780fce96
|
refactor(web): extract input-history recall into a composable (#1011)
* refactor(web): extract input-history recall into a composable Move the shell-style up/down recall of previously sent messages out of Composer into useInputHistory. The composable owns the history list, the browsing cursor, and the textarea caret/selection work needed to apply a recalled entry, taking the text ref, textarea ref, and autosize as deps. The composer keeps the keydown orchestration (which also juggles the slash and mention menus) and calls into the composable for push / recall / caret / browsing state. Composer.vue: 2104 -> 2050 lines. No behavior change. * test(web): cover useInputHistory recall behavior Add unit tests for the extracted input-history composable: push dedup and empty-skip, walking backward/forward through entries, restoring the live draft (empty and non-empty), empty-history no-op, resetBrowsing, and the caretAtFirstLine gate. |
||
|
|
ea1b33b674
|
refactor(web): extract pure turn-rendering helpers from ChatPane (#1001)
* refactor(web): extract pure turn-rendering helpers from ChatPane * chore: add changeset for chat pane helper extraction * test(kimi-web): cover chat turn-rendering helpers Pure-logic tests for the helpers extracted from ChatPane, focused on assistantRenderBlocks (tool-stack grouping, interrupt/media break, single tool) plus the formatting/boundary helpers. Doubles as a safety net confirming the extraction preserved behavior. |
||
|
|
d4ae02d82e
|
fix(web): keep sidebar unread dots in sync across browser tabs (#978) | ||
|
|
3b9938b4c3
|
refactor(web): consolidate localStorage access and split appearance/notification modules (#973) | ||
|
|
845de6bd51
|
test(kimi-web): keep only pure logic unit tests (#959)
* test(kimi-web): keep only pure logic unit tests Remove jsdom/component Vitest coverage from apps/kimi-web, keep server-e2e as the e2e path, and add focused pure-logic Vitest coverage for diff parsing, file path links, tool summaries, turn grouping, and todo derivation. * build(nix): update pnpm deps hash |
||
|
|
98905eb409
|
fix(web): show longer branch names in chat header (#958) | ||
|
|
d7ec05686a
|
feat(web): add scroll-up lazy loading for older session messages and fix new-messages pill (#893)
* feat(web): add scroll-up lazy loading for older session messages * fix(web): keep new-messages pill above the composer dock * fix(web): observe top sentinel after DOM flush in ChatPane * fix(web): avoid eager lazy-load on open and suppress pill during history prepend * fix(web): gate scroll-key watcher and skip scroll restore on session switch * fix(web): restore scroll position from stable top anchor when prepending history * fix(web): preserve new-message pill during history lazy load * fix(web): resolve lint regressions in lazy load tests * fix(web): harden session lazy-load retry and scroll restore * fix(web): treat same-turn history prepends as non-bottom updates |
||
|
|
495fe8c674
|
feat(web): add session search (#895)
* feat(web): add session search Add a search box to the web sidebar that instantly filters all loaded sessions by title and the last user prompt (case-insensitive). Surface the last user prompt from the server: the daemon already persisted it in session metadata, and it now flows through the session schema into the REST response so the web client can match against it. * fix(web): keep lastPrompt fresh on session.meta.updated Address Codex review: the daemon emits session.meta.updated with patch.lastPrompt whenever a new prompt is submitted, but the web projector only forwarded the title. That left the cached session's lastPrompt stale, so sidebar search by the latest prompt text failed until a full reload. Forward lastPrompt through the projector and reducer, and cover it with a pipeline test. * refactor(web): avoid conditional spreads in meta patch Address Codex review: per the root AGENTS.md, optional object properties should be passed directly rather than via conditional spreads. Use nullish coalescing so a field the event does not carry keeps its prior value. * fix(web): stop Escape from aborting a run while search is focused Address Codex review: ConversationPane registers a document-level keydown that aborts the active prompt on Escape. Without handling it on the search input, pressing Escape to dismiss the search would unexpectedly stop the agent. Stop propagation and clear the query, matching the inline rename inputs. * fix(web): exclude hidden-workspace sessions from search Address Codex review: removing a workspace only records its root in hiddenWorkspaceRoots and leaves the sessions intact; the grouped sidebar skips the hidden root, but sessionsForView (the search source) did not, so a matching title or prompt could resurrect sessions from a removed workspace. Filter sessionsForView by the visible workspace set so the flat list matches what the grouped sidebar renders. |
||
|
|
de610deb5f
|
fix(web): drop workspace session count after archiving the last session (#896)
The daemon's workspace session_count counted archived session directories, so a workspace still reported a non-zero count after its last session was archived. The web sidebar then showed the workspace as non-empty, making it look like the archive had failed (and a retry would error out). Count only non-archived sessions in the workspace registry, and trust the live local count in the web app once sessions have loaded. |
||
|
|
8ab9e96963
|
fix(web): paginate session list on load (#882)
* fix(web): list sessions per workspace with pagination * fix(web): use global paginated session list instead of per-workspace |
||
|
|
23277a574c
|
feat(web): show server version in settings (#889)
* feat(web): show server version in settings Display the server version reported by GET /api/v1/meta in the web settings General tab, under a new Build section. * feat(web): show server version in mobile settings too Address Codex review: the mobile settings sheet renders instead of SettingsDialog on mobile, so surface the server version there as well. |
||
|
|
a74a6b7f6b
|
fix(web): improve slash menu and skill editing experience (#878)
* fix(web): keep slash skills editable * fix(web): wrap long slash menu entries * fix(web): rank exact slash matches before substrings |
||
|
|
bd0979578b
|
feat(web): group default model dropdown by provider in settings (#861)
* feat(web): group default model dropdown by provider in settings * fix(web): prevent login dialog closing on backdrop click |
||
|
|
05fe7595ab
|
fix: improve web login and workspace startup (#853) | ||
|
|
9a8fea5c85
|
feat(web): introduce Kimi web app and daemon gateway (#625)
* docs(reports): collapse P3 plan into a single final-solution doc 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). * fix(kimi-web): normalize chat block spacing Group consecutive tool cards structurally so chat block spacing is applied consistently without leaking card borders or shadows. * feat(web): land P3 — goal / swarm / subagent + terminal + view split 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. * docs(reports): P3 landing acceptance review Comprehensive acceptance of the P3 landing ( |