{"version":3,"file":"messages_reducer.cjs","names":["coerceMessageLikeToMessage","RemoveMessage"],"sources":["../../src/graph/messages_reducer.ts"],"sourcesContent":["import {\n  BaseMessage,\n  BaseMessageLike,\n  coerceMessageLikeToMessage,\n  RemoveMessage,\n} from \"@langchain/core/messages\";\nimport { v4 } from \"uuid\";\n\n/**\n * Special value that signifies the intent to remove all previous messages in the state reducer.\n * Used as the unique identifier for a `RemoveMessage` instance which, when encountered,\n * causes all prior messages to be discarded, leaving only those following this marker.\n */\nexport const REMOVE_ALL_MESSAGES = \"__remove_all__\";\n\n/**\n * Type that represents an acceptable input for the messages state reducer.\n *\n * - Can be a single `BaseMessage` or `BaseMessageLike`.\n * - Can be an array of `BaseMessage` or `BaseMessageLike`.\n */\nexport type Messages =\n  | Array<BaseMessage | BaseMessageLike>\n  | BaseMessage\n  | BaseMessageLike;\n\n/**\n * Reducer function for combining two sets of messages in LangGraph's state system.\n *\n * This reducer handles several tasks:\n * 1. Normalizes both `left` and `right` message inputs to arrays.\n * 2. Coerces any message-like objects into real `BaseMessage` instances.\n * 3. Ensures all messages have unique, stable IDs by generating missing ones.\n * 4. If a `RemoveMessage` instance is encountered in `right` with the ID `REMOVE_ALL_MESSAGES`,\n *    all previous messages are discarded and only the subsequent messages in `right` are returned.\n * 5. Otherwise, merges `left` and `right` messages together following these rules:\n *    - If a message in `right` shares an ID with a message in `left`:\n *      - If it is a `RemoveMessage`, that message (by ID) is marked for removal.\n *      - If it is a normal message, it replaces the message with the same ID from `left`.\n *    - If a message in `right` **does not exist** in `left`:\n *      - If it is a `RemoveMessage`, this is considered an error (cannot remove non-existent ID).\n *      - Otherwise, the message is appended.\n *    - Messages flagged for removal are omitted from the final output.\n *\n * @param left - The existing array (or single message) of messages from current state.\n * @param right - The new array (or single message) of messages to be applied.\n * @returns A new array of `BaseMessage` objects representing the updated state.\n *\n * @throws Error if a `RemoveMessage` is used to delete a message with an ID that does not exist in the merged list.\n *\n * @example\n * ```ts\n * const msg1 = new AIMessage(\"hello\");\n * const msg2 = new HumanMessage(\"hi\");\n * const removal = new RemoveMessage({ id: msg1.id });\n * const newState = messagesStateReducer([msg1], [msg2, removal]);\n * // newState will only contain msg2 (msg1 is removed)\n * ```\n */\nexport function messagesStateReducer(\n  left: Messages,\n  right: Messages\n): BaseMessage[] {\n  // Ensure both left and right are arrays\n  const leftArray = Array.isArray(left) ? left : [left];\n  const rightArray = Array.isArray(right) ? right : [right];\n\n  // Convert all input to BaseMessage instances\n  const leftMessages = (leftArray as BaseMessageLike[]).map(\n    coerceMessageLikeToMessage\n  );\n  const rightMessages = (rightArray as BaseMessageLike[]).map(\n    coerceMessageLikeToMessage\n  );\n\n  // Assign missing IDs to any message in the left array\n  for (const m of leftMessages) {\n    if (m.id === null || m.id === undefined) {\n      m.id = v4();\n      m.lc_kwargs.id = m.id;\n    }\n  }\n\n  // Assign missing IDs and check for \"remove all\" marker in right array\n  let removeAllIdx: number | undefined;\n  for (let i = 0; i < rightMessages.length; i += 1) {\n    const m = rightMessages[i];\n    if (m.id === null || m.id === undefined) {\n      m.id = v4();\n      m.lc_kwargs.id = m.id;\n    }\n\n    // If RemoveMessage with special REMOVE_ALL_MESSAGES id is found\n    if (RemoveMessage.isInstance(m) && m.id === REMOVE_ALL_MESSAGES) {\n      removeAllIdx = i;\n    }\n  }\n\n  // If remove-all is present, all previous messages are wiped; return only subsequent ones\n  if (removeAllIdx != null) return rightMessages.slice(removeAllIdx + 1);\n\n  // Begin normal merging logic\n  const merged = [...leftMessages];\n  const mergedById = new Map(merged.map((m, i) => [m.id, i]));\n  const idsToRemove = new Set();\n\n  for (const m of rightMessages) {\n    const existingIdx = mergedById.get(m.id);\n    if (existingIdx !== undefined) {\n      // Case: updating or removing an existing message by id\n      if (RemoveMessage.isInstance(m)) {\n        idsToRemove.add(m.id);\n      } else {\n        idsToRemove.delete(m.id);\n        merged[existingIdx] = m;\n      }\n    } else {\n      // Case: inserting a completely new message\n      if (RemoveMessage.isInstance(m)) {\n        throw new Error(\n          `Attempting to delete a message with an ID that doesn't exist ('${m.id}')`\n        );\n      }\n      mergedById.set(m.id, merged.length);\n      merged.push(m);\n    }\n  }\n\n  // Remove any messages whose IDs are marked for removal\n  return merged.filter((m) => !idsToRemove.has(m.id));\n}\n"],"mappings":";;;;;;;;AAaA,MAAa,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CnC,SAAgB,qBACd,MACA,OACe;CAEf,MAAM,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC,KAAK;CACrD,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CAGzD,MAAM,eAAgB,UAAgC,IACpDA,yBAAAA,2BACD;CACD,MAAM,gBAAiB,WAAiC,IACtDA,yBAAAA,2BACD;AAGD,MAAK,MAAM,KAAK,aACd,KAAI,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAA,GAAW;AACvC,IAAE,MAAA,GAAA,KAAA,KAAS;AACX,IAAE,UAAU,KAAK,EAAE;;CAKvB,IAAI;AACJ,MAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK,GAAG;EAChD,MAAM,IAAI,cAAc;AACxB,MAAI,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAA,GAAW;AACvC,KAAE,MAAA,GAAA,KAAA,KAAS;AACX,KAAE,UAAU,KAAK,EAAE;;AAIrB,MAAIC,yBAAAA,cAAc,WAAW,EAAE,IAAI,EAAE,OAAA,iBACnC,gBAAe;;AAKnB,KAAI,gBAAgB,KAAM,QAAO,cAAc,MAAM,eAAe,EAAE;CAGtE,MAAM,SAAS,CAAC,GAAG,aAAa;CAChC,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;CAC3D,MAAM,8BAAc,IAAI,KAAK;AAE7B,MAAK,MAAM,KAAK,eAAe;EAC7B,MAAM,cAAc,WAAW,IAAI,EAAE,GAAG;AACxC,MAAI,gBAAgB,KAAA,EAElB,KAAIA,yBAAAA,cAAc,WAAW,EAAE,CAC7B,aAAY,IAAI,EAAE,GAAG;OAChB;AACL,eAAY,OAAO,EAAE,GAAG;AACxB,UAAO,eAAe;;OAEnB;AAEL,OAAIA,yBAAAA,cAAc,WAAW,EAAE,CAC7B,OAAM,IAAI,MACR,kEAAkE,EAAE,GAAG,IACxE;AAEH,cAAW,IAAI,EAAE,IAAI,OAAO,OAAO;AACnC,UAAO,KAAK,EAAE;;;AAKlB,QAAO,OAAO,QAAQ,MAAM,CAAC,YAAY,IAAI,EAAE,GAAG,CAAC"}