Editing and regenerating
Introduction
Section titled “Introduction”Readers expect to fix a typo in an earlier message or ask for another answer. The kit does both by forking: run:start takes an optional forkFromMessageId, and the thread restarts from the checkpoint before that human message. The message and everything after it are replaced by the run’s own, and the old branch is discarded. There is no branch switching, and the client never sees a checkpoint id.
Adding edit and retry to a message
Section titled “Adding edit and retry to a message”useConversation gives edit and regenerate. useMessageEdit runs the edit in the main composer.
import { useConversation } from '@pilotoo/chat-core';import { EditingBanner, MessageActions, offeredMessageActions, useMessageEdit } from '@pilotoo/chat-ui';
const { edit, regenerate } = useConversation(id);const editing = useMessageEdit({ edit, attachments });const offered = offeredMessageActions(message, isRunning);
<MessageActions content={message.content} onEdit={offered.edit ? () => editing.begin(message) : undefined} onRetry={offered.regenerate ? () => regenerate(message.id) : undefined}/>;<EditingBanner onCancel={editing.cancel} />;| Call | Does |
|---|---|
edit(messageId, text, attachments?) |
Resends the message under a new id. Omitted attachments keep the original’s; [] removes them. |
regenerate(assistantMessageId) |
Forks at the human message that preceded the reply and resends it unchanged. |
Both return whether the session took them. Attachments travel as references and admission checks their ownership again, so nothing is uploaded twice. See Attachments.
In the UI
Section titled “In the UI”offeredMessageActionswithdraws both actions while a run is live.useMessageEditedits in the main composer, with its own attachment chips so cancelling leaves the draft alone. While the edit is open, swap theComposer’svalue,header(EditingBanner), attach action andsubmitLabelfor the edit’s.@pilotoo/ui/chatexports the same names (useMessageEdit,EditingBanner,MessageActions,offeredMessageActions).
Handling refusals
Section titled “Handling refusals”Refusals arrive as protocol:error and land in the session’s error, and the withdrawn messages come back. A refused edit drops the edited text.
| Code | When |
|---|---|
FORK_POINT_NOT_FOUND |
The message is unknown, is not a human message, or its checkpoint was pruned |
INVALID_COMMAND |
A run is live on the thread, or a decision is pending |
DUPLICATE_MESSAGE |
The new id is one the kept branch already holds |
CONVERSATION_NOT_FOUND |
The thread is not the caller’s |
The rules are forkPointFor in packages/agent-runtime/src/agent-runner.ts and the checks in packages/server/src/streaming/streaming.gateway.ts.
Next steps
Section titled “Next steps”- Attachments for keeping or removing files on an edit.
- Chat UI for the composer and message components.
- Protocol for the error codes.