UNPKG

@langchain/langgraph-sdk

Version:

Client library for interacting with the LangGraph API

118 lines (117 loc) • 4.24 kB
const require_message_coercion = require("./message-coercion.cjs"); const require_messages = require("../ui/messages.cjs"); //#region src/stream/optimistic-input.ts function isBaseMessageInstance(value) { return value != null && typeof value.getType === "function"; } /** * Serialize `BaseMessage` instances under a state update's message key * into plain message dicts so they survive JSON transport. * * `respond({ update })` / `respondAll({}, { update })` fold `update` into * `Command(update=...)` on the wire. A `BaseMessage`'s default JSON form * is the `lc` "constructor" envelope (`{ lc, type: "constructor", id, * kwargs }`), which the server's `add_messages` reducer does **not** * coerce — whereas the flat `{ type, content, ... }` dict that * {@link toMessageDict} emits (and that `submit()` already sends) does. * Mirroring the `submit()` path lets * `respond({ update: { messages: [new AIMessage(...)] } })` behave like * `submit({ messages: [new AIMessage(...)] })`. * * Only the configured `messagesKey` is touched — in both the object form * and the `[key, value][]` tuple form. Every other key, and any already * plain (non-`BaseMessage`) entry, passes through untouched. */ function serializeUpdateMessages(update, messagesKey) { if (Array.isArray(update)) return update.map((entry) => Array.isArray(entry) && entry[0] === messagesKey ? [entry[0], serializeMessageValue(entry[1])] : entry); if (!(messagesKey in update)) return update; return { ...update, [messagesKey]: serializeMessageValue(update[messagesKey]) }; } function serializeMessageValue(value) { if (isBaseMessageInstance(value)) return require_messages.toMessageDict(value); if (Array.isArray(value)) return value.map((item) => isBaseMessageInstance(item) ? require_messages.toMessageDict(item) : item); return value; } function extractId(value) { const id = value?.id; return typeof id === "string" && id.length > 0 ? id : void 0; } /** * Normalize a message-key value into an array of entries. Mirrors the * server's `add_messages` coercion: a bare string or single message * object is treated as a one-element list. */ function toEntryArray(value) { if (Array.isArray(value)) return value; return [value]; } /** * Build a message dict carrying `id` from an arbitrary input entry, * without mutating the original. */ function toDispatchDict(entry, id) { if (typeof entry === "string") return { type: "human", content: entry, id }; if (isBaseMessageInstance(entry)) return { ...require_messages.toMessageDict(entry), id }; return { ...entry, id }; } /** * Prepare a raw submit input for optimistic dispatch. * * @param raw - Raw input passed to `submit()`. Must be a * non-null, non-array object (caller guards this). * @param messagesKey - State key holding the message array. * @param mintId - Factory for stable client message ids. * @returns The dispatch payload, optimistic messages, echoed ids, and * the non-message portion of the input. */ function prepareOptimisticInput(raw, messagesKey, mintId) { const dispatchInput = { ...raw }; const extraValues = {}; for (const key of Object.keys(raw)) if (key !== messagesKey) extraValues[key] = raw[key]; const echoedIds = []; const messagesValue = raw[messagesKey]; if (messagesValue == null) return { dispatchInput, optimisticMessages: [], echoedIds, extraValues }; const entries = toEntryArray(messagesValue); const dispatchEntries = []; const optimisticDicts = []; for (const entry of entries) { if (!(typeof entry === "string" || isBaseMessageInstance(entry) || entry != null && typeof entry === "object" && !Array.isArray(entry))) { dispatchEntries.push(entry); continue; } const id = extractId(entry) ?? mintId(); const dict = toDispatchDict(entry, id); dispatchEntries.push(dict); optimisticDicts.push(dict); echoedIds.push(id); } dispatchInput[messagesKey] = dispatchEntries; return { dispatchInput, optimisticMessages: require_message_coercion.ensureMessageInstances(optimisticDicts), echoedIds, extraValues }; } //#endregion exports.prepareOptimisticInput = prepareOptimisticInput; exports.serializeUpdateMessages = serializeUpdateMessages; //# sourceMappingURL=optimistic-input.cjs.map