Skip to content

feat(web): hide ACP-created sessions and workspaces from the sidebar#1908

Open
zhiyuan1i wants to merge 4 commits into
MoonshotAI:mainfrom
zhiyuan1i:lizhiyuan/web-hide-acp-workspace
Open

feat(web): hide ACP-created sessions and workspaces from the sidebar#1908
zhiyuan1i wants to merge 4 commits into
MoonshotAI:mainfrom
zhiyuan1i:lizhiyuan/web-hide-acp-workspace

Conversation

@zhiyuan1i

Copy link
Copy Markdown

Motivation

When a bot/automation client drives kimi-code over ACP (e.g. a chat-ops bot spawning one session per workspace directory), the kimi-web sidebar fills up with machine-owned workspaces (s_xxxx-style directories) and sessions whose titles are raw injected prompt prefixes. There is currently no way to tell these apart from interactive sessions, let alone hide them.

Approach

Tag at the source. The ACP adapter now passes metadata: { source: 'acp', acp_client: <clientInfo.name> } when handling session/new. metadata is a first-class CreateSessionOptions field, so it lands in the session's persisted custom map (same extension channel as goal / parent_session_id) and kap-server's buildWireMetadata already forwards it onto the wire session — zero server-side changes.

Filter in the web view layer. With a new on-by-default setting (Settings → General → "Hide ACP sessions", persisted in localStorage):

  • sessionsForView, workspaceGroups, and both archived lists (desktop Settings dialog + mobile sheet) drop source === 'acp' sessions.
  • A workspace whose loaded sessions are all ACP-created (with at least one such session — empty workspaces are never hidden) is hidden via a computed root set applied only at the mergeWorkspaces call site. It is deliberately not written into the user-owned hiddenWorkspaceRoots (which persists to localStorage and gets auto-cleared by workspace WS broadcasts).
  • Passive "pick next session" paths (fresh-load auto-select, openWorkspace, popstate dead-link fallback, post-archive successor, handleSessionNotFound) skip hidden sessions so the user never lands on a session the sidebar does not render. Explicit deep links and notification clicks still open ACP sessions directly.

Semantics and trade-offs (intentional)

  • The tag means "created via ACP", not "currently driven by an ACP client": session/load and session/resume never tag, and forks inherit custom (minus goal), so a fork of an ACP session stays hidden.
  • Only new sessions created after this change carry the tag; pre-existing ACP sessions are not retroactively identifiable (they can still be removed individually via the existing "Remove workspace").
  • Workspace hiding is computed from the loaded (paginated) session pages, so a mixed workspace whose non-ACP sessions are all beyond the loaded pages may be hidden until those load — the toggle restores everything instantly.
  • Toggling the preference drops ACP-only workspaces from the persisted manual workspace order (same semantics as the existing "Remove workspace").

Testing

  • acp-adapter: session/new passes the metadata tag, with and without clientInfo (325 tests green).
  • kimi-web: new unit tests for acpOnlyWorkspaceRoots (mixed/empty/no-cwd edge cases) and for the hidden-aware pick-next paths (654 tests green, vue-tsc clean).
  • Manual E2E: kap-server + vite dev + Playwright against three fixture workspaces (human-only, ACP-only, mixed): 13/13 checks — default-on hides ACP workspaces/sessions, auto-select lands on the newest visible session, toggle off restores everything instantly, preference survives reload.

zhiyuan1i added 4 commits July 18, 2026 21:17
The ACP adapter now tags every session it creates with
`source: 'acp'` (plus the client's `clientInfo.name` when advertised)
in the persisted custom metadata, which kap-server already forwards
onto the wire session. kimi-web reads that tag and, behind a new
on-by-default setting, filters ACP sessions out of the sidebar lists
and archived views; workspaces whose loaded sessions are all
ACP-created are hidden as well, via a computed root set applied only
at the mergeWorkspaces call site (never persisted, so WS broadcasts
cannot resurrect them).

The tag marks "created via ACP": forked sessions inherit it through
the existing custom-metadata copy, and `session/resume` never tags.
With the ACP-hiding preference on, the most recent session is often a
bot-driven ACP session that the sidebar does not render; fresh load
still auto-selected it, leaving the user on an invisible session.
useWorkspaceState now takes an optional isSessionHiddenFromList dep
(the facade wires it to the hide-ACP preference) and both the
workspace pick and the session auto-select skip hidden sessions.
Explicit deep links and notification clicks are unaffected — only the
passive landing changes.
Follow-up to the fresh-load fix: openWorkspace (clicking a mixed
workspace), the popstate dead-link fallback, and the post-archive
successor pick all used rawState.sessions[0] and could land on a
session the sidebar hides. They now share the same
isSessionHiddenFromList predicate; openWorkspace with only hidden
sessions left falls back to the empty composer, matching the
empty-workspace behavior.
Last rawState.sessions[0] pick-next path: when the daemon reports the
active session as gone, the fallback could land on a sidebar-hidden
(ACP-created) session. Now shares the same hide-ACP predicate as the
other pick-next paths.
@changeset-bot

changeset-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d66cc0

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

This PR includes changesets to release 2 packages
Name Type
@moonshot-ai/acp-adapter Patch
@moonshot-ai/kimi-web 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

@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: 7d66cc0afd

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

(s) =>
!s.parentSessionId &&
visibleWorkspaceIds.has(workspaceIdForSession(s)) &&
!(hideAcpSessions.value && isAcpSession(s)),

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 Apply ACP filtering to recent workspace ordering

When hideAcpSessions is enabled and a mixed workspace has a newer ACP session plus an older human session, this filter removes the ACP row, but workspacesView still builds its recent-sort lastEditedAt from all rawState.sessions above. The hidden ACP activity can move that workspace to the top of the sidebar, so the setting still leaks/sorts by sessions it claims to hide; apply the same hideAcpSessions && isAcpSession predicate before computing workspace recency.

Useful? React with 👍 / 👎.

const filteredArchived = computed<AppSession[]>(() => {
const q = archiveQuery.value.trim().toLowerCase();
let rows = archivedItems.value.filter((s) => s.archived === true);
if (client.hideAcpSessions.value) rows = rows.filter((s) => s.source !== 'acp');

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 Expose the ACP-session toggle in mobile settings

On mobile, App.vue opens MobileSettingsSheet instead of the desktop SettingsDialog, and this newly added filter is controlled by client.hideAcpSessions, which defaults to true. Because the mobile sheet has no corresponding toggle/event, mobile users cannot turn the filter off to find or restore archived ACP sessions, or reveal hidden ACP workspaces, from the mobile UI; add the same setting row here or pass through the existing setter.

Useful? React with 👍 / 👎.

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