Skip to content

feat(server): add GUI store API mirroring localStorage - #1231

Merged
sailist merged 3 commits into
MoonshotAI:mainfrom
sailist:feat/gui-store
Jun 30, 2026
Merged

feat(server): add GUI store API mirroring localStorage#1231
sailist merged 3 commits into
MoonshotAI:mainfrom
sailist:feat/gui-store

Conversation

@sailist

@sailist sailist commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add a server-side key/value store API that mirrors the browser localStorage interface, so the web UI can persist its preferences to the user's data directory (~/.kimi-code/gui.toml) and sync them across browsers and devices. This PR only adds the server endpoint; web-side integration will follow separately.

Related Issue

No related issue. See "Problem" below.

Problem

The web UI currently keeps all of its preferences (theme, font size, locale, layout, notification toggles, etc.) only in the browser's localStorage. They are lost when the user switches browsers or devices, and there is no server-side source of truth. Because the browser cannot access the user filesystem directly, the server needs to proxy a small persistence API that writes under ~/.kimi-code.

What changed

  • New REST endpoints under /api/v1/gui/store/* that map 1:1 to localStorage: getItem, setItem, removeItem, clear, and length. Values are opaque strings, so the server does not interpret them; keys travel in the query/body so any string is allowed.
  • New IGuiStoreService that persists entries to ~/.kimi-code/gui.toml via smol-toml, with atomic writes and an in-process write lock so concurrent writes from multiple tabs cannot clobber each other. Missing or corrupt files are treated as empty.
  • Wired up the protocol schema, route registration, and DI registration, plus e2e tests and the API surface snapshot.

gui.toml is kept separate from config.toml (agent/runtime settings) and tui.toml (terminal preferences), following the existing per-client preferences convention.

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.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

sailist added 2 commits June 30, 2026 19:31
- add /api/v1/gui/store/* endpoints (getItem/setItem/removeItem/clear/length) mirroring the browser localStorage interface
- add IGuiStoreService persisting opaque string values to ~/.kimi-code/gui.toml via smol-toml with atomic writes and an in-process write lock
- wire protocol schema, service, routes, and DI registration; add e2e tests and update the API surface snapshot
@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: caa5725

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

This PR includes changesets to release 3 packages
Name Type
@moonshot-ai/protocol Patch
@moonshot-ai/server Patch
@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 30, 2026

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

commit: caa5725

@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: 124ecf9f1e

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


async getItem(key: string): Promise<string | null> {
const all = await this.readAll();
return all[key] ?? null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use own-key storage for GUI store keys

When a caller uses a legal localStorage key that exists on Object.prototype (toString, constructor, hasOwnProperty) on an empty store, this returns the inherited function instead of null; for __proto__, setItem also goes through the prototype setter and does not persist the entry. The route schema accepts any non-empty string key, so these valid keys produce malformed responses or cannot be stored; use a null-prototype object/Map and an own-property check for reads.

Useful? React with 👍 / 👎.

// Atomic replace via temp file + rename (POSIX-atomic), so readers never
// observe a half-written file.
const tmp = `${this.filePath}.tmp.${process.pid}.${randomBytes(4).toString('hex')}`;
await writeFile(tmp, text, 'utf-8');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Create gui.toml with private permissions

On POSIX systems where <homeDir> already exists, this writeFile creates the temp file with the process umask (commonly 0644), and the later rename preserves that mode for gui.toml. This store mirrors web localStorage, which includes composer drafts and input history (useComposerDraft, useInputHistory), so on multi-user hosts another local user can read unsent prompts/preferences from <homeDir>/gui.toml; write the temp file as 0600 or reuse the existing private-file helper.

Useful? React with 👍 / 👎.

- use a null-prototype record and an own-property check so keys that exist on Object.prototype (toString, constructor, __proto__) behave like ordinary keys
- write gui.toml with 0600 permissions so unsent drafts and input history stay private to the owning user
@sailist

sailist commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: caa5725648

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

@sailist
sailist merged commit ceb27f5 into MoonshotAI:main Jun 30, 2026
9 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 30, 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