import { jsx as L } from "react/jsx-runtime";
import { useChatRuntime as q } from "./ChatRuntime.es.js";
import { logger as f } from "../utils/logger.es.js";
import "@langchain/langgraph-sdk";
import { useStream as D } from "@langchain/langgraph-sdk/react";
import { isUIMessage as J, isRemoveUIMessage as Q, uiMessageReducer as X } from "@langchain/langgraph-sdk/react-ui";
import { useContext as Y, createContext as Z, useState as b, useCallback as k, useMemo as A, useEffect as ee } from "react";
import { toast as te } from "sonner";
import { useThread as se } from "./Thread.es.js";
import ae from "../node_modules/.pnpm/uuid@13.0.0/node_modules/uuid/dist/v4.es.js";
const re = D, P = Z(void 0);
async function ne(c, l) {
  try {
    return (await fetch(`${c}/info`, {
      headers: l ? { Authorization: `Bearer ${l}` } : void 0
    })).ok;
  } catch {
    f.error("Failed to initialize LangGraph Agent");
  }
}
async function oe(c, l) {
  try {
    const v = await fetch(`${c}/agents/catalog`, {
      headers: l ? { Authorization: `Bearer ${l}` } : void 0
    });
    return v.ok ? await v.json() : null;
  } catch {
    return f.error("Failed to fetch LangGraph Catalog"), null;
  }
}
async function ie(c = 6e3) {
  return new Promise((l) => setTimeout(l, c));
}
const le = ({ children: c }) => {
  const { apiUrl: l, assistantId: v, identity: d } = q(), { mode: T, threadId: U, setThreadId: $, getThreads: G, setThreads: H, configuration: x } = se(), [R, w] = b([]), [S, M] = b([]), [C, O] = b(!1), [I, V] = b(null), i = re({
    apiUrl: l,
    assistantId: v,
    threadId: T === "multi" ? U : null,
    defaultHeaders: d?.authToken ? { Authorization: `Bearer ${d?.authToken}` } : void 0,
    fetchStateHistory: !0,
    onUpdateEvent: (t, e) => {
      const a = [], n = (o) => {
        if (!o || typeof o != "object") return;
        const s = o;
        if (Array.isArray(s.messages))
          for (const r of s.messages) {
            const g = r.additional_kwargs;
            if (r?.type === "ai" && r.id && g) {
              const h = typeof g.reasoning_content == "string" && g.reasoning_content.length > 0, p = Array.isArray(g.tool_status) && g.tool_status.length > 0;
              (h || p) && a.push(r);
            }
          }
        for (const r of Object.values(s))
          r && typeof r == "object" && !Array.isArray(r) && n(r);
      };
      n(t);
      let u;
      const _ = (o) => {
        if (!o || typeof o != "object") return;
        const s = o;
        "todos" in s && Array.isArray(s.todos) && (s.todos.length > 0 || u === void 0) && (u = s.todos);
        for (const r of Object.values(s))
          r && typeof r == "object" && !Array.isArray(r) && _(r);
      };
      _(t), (a.length > 0 || u !== void 0) && e.mutate((o) => {
        let s = o;
        if (a.length > 0) {
          const r = s.messages ?? [], g = /* @__PURE__ */ new Map();
          for (const m of a)
            m.id && g.set(m.id, m);
          let h = !1;
          const p = r.map((m) => {
            if (!m.id || !g.has(m.id)) return m;
            const N = g.get(m.id);
            g.delete(m.id), h = !0;
            const W = N.additional_kwargs;
            return {
              ...m,
              additional_kwargs: {
                ...m.additional_kwargs ?? {},
                ...W ?? {}
              }
            };
          });
          h && (s = { ...s, messages: p });
        }
        return u !== void 0 && u.length > 0 && (s = { ...s, todos: u }), s === o ? o : s;
      });
    },
    onCustomEvent: (t, e) => {
      (J(t) || Q(t)) && e.mutate((a) => {
        f.debug("UI Event received in StreamProvider:", t);
        const n = X(a.ui ?? [], t);
        return { ...a, ui: n };
      });
    },
    onThreadId: (t) => {
      t && (T === "single" ? U || $(t) : ($(t), ie().then(() => G().then(H).catch((e) => f.error("Failed to refresh threads:", e)))));
    }
  }), F = k(
    async (t, e) => {
      const a = e?.id || ae(), n = typeof t == "string" ? {
        id: a,
        // Use the determined ID
        type: e?.type ?? "human",
        content: t,
        ...e?.name && { name: e.name },
        ...e?.tool_calls && { tool_calls: e.tool_calls },
        ...e?.invalid_tool_calls && { invalid_tool_calls: e.invalid_tool_calls },
        ...e?.tool_call_id && { tool_call_id: e.tool_call_id },
        ...(e?.additional_kwargs || e?.hidden) && {
          additional_kwargs: {
            ...e?.hidden && { hidden: !0 },
            ...e?.additional_kwargs ?? {}
          }
        }
      } : {
        ...t,
        id: a,
        // Override with determined ID
        // Allow overriding message fields with options
        ...e?.tool_calls && { tool_calls: e.tool_calls },
        ...e?.additional_kwargs && {
          additional_kwargs: {
            ...t.additional_kwargs,
            ...e.additional_kwargs
          }
        }
      };
      if (f.debug("Sending message via sendMessage:", n), e?.type === "ai") {
        if (w((o) => [...o, n]), f.debug("Appended AI message to localMessages:", e?.ui), e.ui && e.ui.length > 0) {
          const o = e.ui.map((s, r) => ({
            ...s,
            id: a,
            // Link to the message ID so CustomComponentRender can find it
            // Ensure each UI component has a unique identifier for React keys
            _key: s._key || `${a}-ui-${r}`
          }));
          M((s) => [...s, ...o]);
        }
        return;
      }
      const u = i.messages || [], _ = e?.context ? { ...d, ...e.context, ...x } : d || {};
      await i.submit(
        { messages: [...u, n] },
        {
          context: _,
          streamMode: ["values", "messages-tuple", "updates", "custom"]
        }
      );
    },
    [i, d, x, w, M]
  ), y = A(() => {
    const t = [...R, ...i.messages || []], e = /* @__PURE__ */ new Set();
    return t.filter((a) => a.id ? e.has(a.id) ? !1 : (e.add(a.id), !0) : !0);
  }, [R, i.messages]), j = A(() => {
    f.debug("Combining local UI with stream UI:", S, i.values?.ui);
    const t = [...S, ...i.values?.ui || []], e = /* @__PURE__ */ new Set();
    return t.filter((a) => {
      const n = a._key || `${a.id}-${a.name}`;
      return e.has(n) ? !1 : (e.add(n), !0);
    });
  }, [S, i.values?.ui]), z = k(
    async (t, e) => {
      const a = y || [];
      await i.submit(
        { messages: [...a, t] },
        {
          context: { ...d, ...e?.contextValues },
          streamMode: e?.streamMode || ["values", "messages-tuple", "updates", "custom"],
          streamSubgraphs: e?.streamSubgraphs ?? !0,
          streamResumable: e?.streamResumable ?? !0,
          optimisticValues: (n) => ({
            ...n,
            messages: [...a, t]
          })
        }
      );
    },
    [i, d, y]
  ), B = k(
    async (t) => {
      const e = y || [], a = e.findIndex((s) => s.id === t);
      if (a === -1) {
        f.error("Message not found for regeneration:", t);
        return;
      }
      let n = a - 1;
      for (; n >= 0 && e[n].type !== "human"; )
        n--;
      if (n === -1) {
        f.error("No human message found before AI message:", t);
        return;
      }
      const u = e.slice(0, n + 1), _ = u.slice(0, -1), o = u[u.length - 1];
      w(
        (s) => s.filter((r) => e.findIndex((h) => h.id === r.id) < n)
      ), M(
        (s) => s.filter((r) => e.findIndex((h) => h.id === r.id) < n)
      ), await i.submit(
        { messages: [..._, o] },
        {
          streamMode: ["values"],
          streamSubgraphs: !0,
          streamResumable: !0
        }
      );
    },
    [y, i, d, x, w, M]
  );
  ee(() => {
    ne(l, d?.authToken).then((t) => {
      t || te.error("Failed to connect to LangGraph server", {
        description: `Unable to reach ${l}`,
        duration: 1e4
      });
    });
  }, [l, d?.authToken]);
  const E = k(async () => {
    if (C && I !== null)
      return I;
    if (!C) {
      O(!0);
      const t = await oe(l, d?.authToken);
      return V(t), t;
    }
    return I;
  }, [l, d?.authToken, C, I]), K = A(
    () => ({
      ...i,
      messages: y,
      // Override with combined messages
      values: {
        ...i.values,
        ui: j
        // Override with combined UI
      },
      sendMessage: F,
      submitMessage: z,
      regenerateMessage: B,
      fetchCatalog: E
    }),
    [i, y, j, F, z, B, E]
  );
  return /* @__PURE__ */ L(P.Provider, { value: K, children: c });
};
function we({ children: c }) {
  return /* @__PURE__ */ L(le, { children: c });
}
function Me() {
  const c = Y(P);
  if (!c)
    throw new Error("useStreamContext must be used within StreamProvider");
  return c;
}
export {
  we as StreamProvider,
  Me as useStreamContext
};
//# sourceMappingURL=Stream.es.js.map
