72 lines · 2.8 KB · TypeScript
RawDownload
import { PROVIDER_SEND_TURN_MAX_ATTACHMENTS } from "@t3tools/contracts";import { scopedThreadKey } from "../lib/scopedEntities";import { appAtomRegistry } from "./atom-registry";import {  confirmThreadOutboxMessageQueued,  threadOutboxRevision,  type QueuedThreadMessage,} from "./thread-outbox";import { removeThreadOutboxMessage } from "./thread-outbox-removal";import {  flushComposerDrafts,  getComposerDraftSnapshot,  mergeComposerDraftContent,  undoComposerDraftMerge,  updateComposerDraftSettings,  waitForComposerDraftsLoaded,} from "./use-composer-drafts";import {  dispatchingQueuedMessageIdAtom,  editingQueuedMessageIdsAtom,  holdEditingQueuedMessage,  releaseEditingQueuedMessage,} from "./use-thread-outbox"; /** Take delivery ownership before any await; the durable draft then takes ownership of the files. */export async function editPendingThreadMessage(message: QueuedThreadMessage): Promise<boolean> {  if (    message.creation ||    appAtomRegistry.get(dispatchingQueuedMessageIdAtom) === message.messageId ||    appAtomRegistry.get(editingQueuedMessageIdsAtom)[message.messageId]  ) {    return false;  }  holdEditingQueuedMessage(message.messageId);  const draftKey = scopedThreadKey(message.environmentId, message.threadId);  let rollback: {    snapshot: ReturnType<typeof getComposerDraftSnapshot>;    merged: ReturnType<typeof getComposerDraftSnapshot>;  } | null = null;  try {    if (!(await confirmThreadOutboxMessageQueued(message))) return false;    const revision = threadOutboxRevision(message.messageId);    await waitForComposerDraftsLoaded();    const snapshot = getComposerDraftSnapshot(draftKey);    const attachmentIds = new Set(snapshot.attachments.map((attachment) => attachment.id));    for (const attachment of message.attachments) attachmentIds.add(attachment.id);    if (attachmentIds.size > PROVIDER_SEND_TURN_MAX_ATTACHMENTS) {      throw new Error("Remove attachments from the composer before editing this message.");    }    try {      await mergeComposerDraftContent(draftKey, message);    } finally {      rollback = { snapshot, merged: getComposerDraftSnapshot(draftKey) };    }    updateComposerDraftSettings(draftKey, {      ...(message.modelSelection ? { modelSelection: message.modelSelection } : {}),      ...(message.runtimeMode ? { runtimeMode: message.runtimeMode } : {}),      ...(message.interactionMode ? { interactionMode: message.interactionMode } : {}),    });    rollback = { snapshot, merged: getComposerDraftSnapshot(draftKey) };    await flushComposerDrafts();    if (!(await removeThreadOutboxMessage(message, revision))) return false;    rollback = null;    return true;  } finally {    try {      if (rollback) await undoComposerDraftMerge(draftKey, rollback.snapshot, rollback.merged);    } finally {      releaseEditingQueuedMessage(message.messageId);    }  }}