You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add an action seat to human messages (conversation.chat.user-actions)
#12148
Replies already expose conversation.chat.assistant-actions, so a plugin can add an entry to the icon row under an assistant message. The icon row under a human message exposes no slot at all, so a plugin cannot add anything there. This proposes one new client slot with the same shape as the existing one: conversation.chat.user-actions.
Current state
conversation.chat.assistant-actions — list, session scope, owner { messageId }; rendered inline in the icon row under the Turn-closing reply, beside copy, like/dislike, branch, usage and the clock.
The icon row under a user bubble (MessageIconActions) renders only the built-in copy control. There is no seat, so quote, export, send-to-MCP or translate style actions cannot live in that row.
MessageActionOwnerProps { messageId: MessageId; text: string }, shared by both strips (AssistantActionOwnerProps / UserActionOwnerProps are aliases)
Rendering
Inline in the same row, right after the built-in copy control
Steering rows
A separate SteeringMessageNodeView; a steering row has no durable message identity, so it must not receive the seat
text is the body the built-in copy control writes. It is new on the assistant owner as well: today a plugin that wants the reply body has to reconstruct it.
Rows without durable identity — pending submissions, echo rows, steering rows, interruption-frozen partials — render no contributions.
Left: the built-in copy control. Right: an entry contributed by a zero-build plugin into both strips. The plugin (4 files, no build step) is on the same branch: demo/user-actions.
Blast radius
Additive only: no Session format change, no model-visible change, no new package.
Regenerated client slot catalog, so cordis_inspect lists the new seat.
Docs updated in the same change: docs/subsystems/slots.md (slot tree plus strip description) and the @deepseek-ai/dsh-client-ui-chat README, each with its Chinese pair.
Tests: the ui-chat suite passes locally (974 tests); a case asserts that a contributed entry renders in the same row after copy, and that steering rows render none.
Alternative considered
Mounting a child slot on conversation.chat.node keyed by node kind would not be inline in the row, and it would force the row to hand down the messageId and text that the seat already carries.
Ask
Is this scope acceptable upstream? If it is, the change is a 16-file diff and I can provide a patch or a PR — I understand external PRs are not accepted at the moment, so posting here first.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
TL;DR
Replies already expose
conversation.chat.assistant-actions, so a plugin can add an entry to the icon row under an assistant message. The icon row under a human message exposes no slot at all, so a plugin cannot add anything there. This proposes one new client slot with the same shape as the existing one:conversation.chat.user-actions.Current state
conversation.chat.assistant-actions—list, session scope, owner{ messageId }; rendered inline in the icon row under the Turn-closing reply, beside copy, like/dislike, branch, usage and the clock.MessageIconActions) renders only the built-in copy control. There is no seat, so quote, export, send-to-MCP or translate style actions cannot live in that row.Proposal
'conversation.chat.user-actions'—kind: 'list',scope: 'session'MessageActionOwnerProps { messageId: MessageId; text: string }, shared by both strips (AssistantActionOwnerProps/UserActionOwnerPropsare aliases)SteeringMessageNodeView; a steering row has no durable message identity, so it must not receive the seattextis the body the built-in copy control writes. It is new on the assistant owner as well: today a plugin that wants the reply body has to reconstruct it.Rows without durable identity — pending submissions, echo rows, steering rows, interruption-frozen partials — render no contributions.
Left: the built-in copy control. Right: an entry contributed by a zero-build plugin into both strips. The plugin (4 files, no build step) is on the same branch: demo/user-actions.
Blast radius
cordis_inspectlists the new seat.docs/subsystems/slots.md(slot tree plus strip description) and the@deepseek-ai/dsh-client-ui-chatREADME, each with its Chinese pair.ui-chatsuite passes locally (974 tests); a case asserts that a contributed entry renders in the same row after copy, and that steering rows render none.Alternative considered
Mounting a child slot on
conversation.chat.nodekeyed by node kind would not be inline in the row, and it would force the row to hand down themessageIdandtextthat the seat already carries.Ask
Is this scope acceptable upstream? If it is, the change is a 16-file diff and I can provide a patch or a PR — I understand external PRs are not accepted at the moment, so posting here first.
Diff: master...feat/user-message-actions
All reactions