feat(control-ui): session grouping with drag & drop and channel categorization#100262
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 12:10 PM ET / 16:10 UTC. Summary Reproducibility: not applicable. as a bug reproduction: this PR adds a new Control UI grouping feature, and source inspection confirms current main lacks the Review metrics: 2 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Default Do we have a high-confidence way to reproduce the issue? Not applicable as a bug reproduction: this PR adds a new Control UI grouping feature, and source inspection confirms current main lacks the Is this the best way to solve the issue? No, not as-is: the category-based implementation is plausible, but the generated Swift compatibility break, missing real UI proof, and unconfirmed persisted API contract make it short of the best mergeable solution. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 286d0b9fb340. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (6 earlier review cycles)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3ae7fe009
ℹ️ 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".
| const key = event.dataTransfer?.getData(SESSION_DRAG_MIME); | ||
| if (key) { | ||
| props.onAssignCategory(key, category); |
There was a problem hiding this comment.
Reject non-session drags before patching categories
When the sessions table is grouped by category, every group/row drop target calls preventDefault() and then accepts any text/plain payload as a session key. In browsers, dragging selected text, a URL, or other external content commonly provides text/plain; dropping that onto a group will call onAssignCategory with that arbitrary string, and sessions.patch creates a session entry when the key is missing. Please use a custom OpenClaw drag MIME (and/or verify the key exists in the current rows) before patching so external drags cannot pollute the session store.
Useful? React with 👍 / 👎.
f6f589e to
f390b53
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f390b53e96
ℹ️ 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".
| agentId: Type.Optional(NonEmptyString), | ||
| label: Type.Optional(Type.Union([SessionLabelString, Type.Null()])), | ||
| /** User-defined organization bucket ("category", not chat-group); null clears it. */ | ||
| category: Type.Optional(Type.Union([SessionLabelString, Type.Null()])), |
There was a problem hiding this comment.
Regenerate native protocol models for category
Adding category to the gateway protocol schema also needs the generated native protocol artifact refreshed: scripts/protocol-gen-swift.ts emits SessionsPatchParams into apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift, but that struct still lacks a category property/CodingKey. In CI the bundled protocol lane runs pnpm protocol:check, which regenerates and diffs these artifacts, so this schema-only change will leave the generated model stale and block the protocol check; please regenerate the Swift protocol model with this field.
Useful? React with 👍 / 👎.
69acb6d to
4a8e8ba
Compare
0e7ff31 to
171d049
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 60cb104b9b
ℹ️ 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".
| key: String, | ||
| agentid: String? = nil, | ||
| label: AnyCodable?, | ||
| category: AnyCodable?, |
There was a problem hiding this comment.
Default the Swift category initializer parameter
When native OpenClawKit callers construct SessionsPatchParams for existing patches (label/archive/model/etc.), this new optional category parameter is inserted into the public initializer without a = nil default, so every existing Swift call site must be edited even though the protocol field is additive. The generator already has a per-struct default list for additive optional params (scripts/protocol-gen-swift.ts:57, and this PR did it for ChatAbortedEvent.errorMessage); add category there and regenerate so existing clients can omit it.
Useful? React with 👍 / 👎.
…orization (openclaw#100262) * feat(control-ui): session grouping with drag & drop and channel categorization * fix(control-ui): restrict session drag&drop to private session-key payloads * chore(i18n): translate session grouping strings across control ui locales * chore(protocol): regenerate swift gateway models for session category * chore(protocol): regenerate swift gateway models for session category
What Problem This Solves
The Control UI sessions table is a flat list. Once an operator runs many sessions across agents and message channels (Discord, Telegram, WhatsApp, ...), there is no way to organize them: no grouping, no way to categorize channel-originated sessions, and no equivalent of the desktop app's custom session groups.
Why This Change Was Made
Adds a persistent per-session
categoryfield end-to-end (gateway protocolsessions.patch-> session store -> list rows -> live session-change events) and a "Group by" control on the web Sessions page with None / Custom groups / Channel / Kind / Agent / Date modes. The field is namedcategoryto stay clearly separate from the existing chat-group concepts (groupId,groupChannel, kindgroup). Custom group membership persists server-side on the session entry; empty just-created groups live in browser localStorage until a session is assigned. Cleared categories emit an explicitnullin session events so other connected clients drop the group during merge-reconcile instead of going stale.User Impact
sessions.patchacceptscategory: string | null; session rows and change events carrycategory.Evidence
sessions-patchsuite 239 passed (new category persist/trim/clear/duplicate/empty tests),server.sessions.list-changed46 passed after the event payload change, protocol + session-utils + store-rpc 690 passed.tsgocore and UI lanes clean; oxfmt/oxlint clean on touched files.agent:main:mainmisgrouped in Agent mode, stale category on other clients after clear) were fixed with regression tests; final run reported no actionable findings.docs/web/control-ui.mddescribes the new grouping behavior.