Skip to content
Pilotoo
v0.1

Editing and regenerating

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.

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.

  • offeredMessageActions withdraws both actions while a run is live.
  • useMessageEdit edits in the main composer, with its own attachment chips so cancelling leaves the draft alone. While the edit is open, swap the Composer’s value, header (EditingBanner), attach action and submitLabel for the edit’s.
  • @pilotoo/ui/chat exports the same names (useMessageEdit, EditingBanner, MessageActions, offeredMessageActions).

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.

  • Attachments for keeping or removing files on an edit.
  • Chat UI for the composer and message components.
  • Protocol for the error codes.