Skip to content

fix(web): persist input history so recall works after the first message#1015

Merged
wbxl2000 merged 3 commits into
mainfrom
fix/web-persist-input-history
Jun 23, 2026
Merged

fix(web): persist input history so recall works after the first message#1015
wbxl2000 merged 3 commits into
mainfrom
fix/web-persist-input-history

Conversation

@wbxl2000

@wbxl2000 wbxl2000 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #1011 — this PR is based on refactor/web-extract-input-history. Review/merge #1011 first; this PR's diff is only the last commit (fix(web): persist input history so recall works after the first message).

Related Issue

Bug found while reviewing #1011. No standalone issue.

Problem

Pressing ↑ in the composer often did nothing, most notably right after sending the first message of a new session — the very case where you want to recall and edit what you just sent.

Root cause: the composer has two mutually-exclusive instances:

  • the empty-session composer (turns.length === 0), and
  • the docked composer (inside ChatDock, once there are turns).

Each kept its own in-memory inputHistory (ref([])), never persisted. So:

  1. New session → empty composer.
  2. Send the first message → it gets pushed into the empty composer's history.
  3. The first turn appears → the empty composer unmounts (discarding that push) and the docked composer mounts fresh with an empty history.
  4. Press ↑ → empty history → nothing happens.

The history was also wiped on every page reload for the same reason (purely in-memory).

What changed

  • useInputHistory now persists the history to localStorage (key kimi-web.input-history) and re-reads it on mount.
    • Global, not per-session: a new session has no id until after the first submit (startSessionAndSendPrompt runs at submit time), so per-session keys would not line up across the empty → docked handoff (the empty composer would write history:__new__ while the docked composer reads history:<realId>). A single global list sidesteps that and also matches shell-style recall.
    • Capped at 200 entries so storage can't grow without bound.
  • Added the key to STORAGE_KEYS in lib/storage.ts.
  • Slash commands are now recorded in history too, covering both paths:
    • typed-and-submitted (/goal <task>, /model) — the history.push call moved ahead of the slash-command branch in handleSubmit;
    • picked from the slash menu (/model, /login, …) — selectSlashCommand now pushes before emitting, since those bypass handleSubmit entirely.
      Previously only plain messages were recallable.
  • Added persistence-focused unit tests: surviving a remount, the 200-entry cap, and a malformed stored value being ignored.

No change to the recall navigation logic itself — only where the list lives.

Verification

  • pnpm --filter @moonshot-ai/kimi-web typecheck — pass (vue-tsc --noEmit)
  • pnpm --filter @moonshot-ai/kimi-web test — 55 passed (15 in input-history.test.ts)
  • pnpm --filter @moonshot-ai/kimi-web build — pass
  • oxlint --type-aware on the changed files — 0 warnings, 0 errors

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works. (test/input-history.test.ts — persistence/remount/cap/corruption cases.)
  • Ran gen-changesets skill, or this PR needs no changeset. (Added .changeset/fix-web-persist-input-history.md, patch on @moonshot-ai/kimi-code.)
  • Ran gen-docs skill, or this PR needs no doc update. (No user-facing doc change.)

@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: aa83b9a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 23, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@aa83b9a
npx https://pkg.pr.new/@moonshot-ai/kimi-code@aa83b9a

commit: aa83b9a

Base automatically changed from refactor/web-extract-input-history to main June 23, 2026 09:01
wbxl2000 added 2 commits June 23, 2026 17:20
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).
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.
@wbxl2000 wbxl2000 force-pushed the fix/web-persist-input-history branch from fe128dd to 32669b8 Compare June 23, 2026 09:21
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32669b8e09

ℹ️ 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".

// Record for ↑/↓ recall before the slash branch so commands (with or without
// args) are recallable too, not just plain messages. `push` ignores empty /
// whitespace, so an image-only send adds nothing.
history.push(trimmed);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Record slash-menu command selections in history

When a user runs a bare slash command from the open slash menu, the keydown handler calls selectSlashCommand and returns before handleSubmit; for non-acceptsInput commands such as /model or /login, that path emits the command directly. Since history is only pushed here, those common menu-selected slash commands still are not recallable even though typed-and-submitted slash commands are; consider pushing the selected command in selectSlashCommand before emitting it.

Useful? React with 👍 / 👎.

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.
@wbxl2000 wbxl2000 merged commit 83384ee into main Jun 23, 2026
9 of 10 checks passed
@wbxl2000 wbxl2000 deleted the fix/web-persist-input-history branch June 23, 2026 10:07
@github-actions github-actions Bot mentioned this pull request Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant