PageSourceSearch

https://aimathproblemsolver.com/assets/CrLHLS9U.js

js aimathproblemsolver.com collected 2026-10-02 00:46:07 UTC 7,662 bytes, 224 lines download raw bytes

1import { ap as fetchEventSource, aq as DiffMatchPatch } from "./GKSP12iv.js";
2import { j as ABORTED, b as getUserId, k as safeErrorCause, l as uuidv7b64, m as fileToBase64 } from "./B8ejy0IY.js";
3import { a as atom, f as withAssign, g as reatomBoolean, h as reatomNumber, e as action, r as reatomAsync } from "./BmDlrdls.js";
4const DEFAULT_EXPERTISE_LEVEL = "highschool";
5const DEFAULT_SOLUTION_TYPE = "stepby";
6const urlSafeSlug = (s) => {
7  if (s) {
8    let slug;
9    if (typeof s === "string") {
10      slug = `${s}`;
11    } else {
12      const sol = s;
13      slug = sol.urlSlug || sol.guidanceTitle || sol.problem || sol.shortProblem || "";
14    }
15    if (slug) {
16      slug = slug.toLowerCase().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
17      return encodeURIComponent(slug);
18    }
19  }
20  return null;
21};
22const DIFF_PREFIX = "@@ ";
23var MathSolutionEventType;
24(function(MathSolutionEventType2) {
25  MathSolutionEventType2["Partial"] = "p";
26  MathSolutionEventType2["Final"] = "f";
27})(MathSolutionEventType || (MathSolutionEventType = {}));
28const chatAtom = atom(null, "chat").pipe(withAssign((chatAtom2, name) => {
29  const id = atom(null, name + ".id");
30  const loading = reatomBoolean(false, name + ".loading");
31  const error = atom(null, name + ".error");
32  const visibleSteps = reatomNumber(0, name + ".visibleSteps");
33  const abortController = atom(null, name + ".abortController");
34  return {
35    id,
36    loading,
37    error,
38    visibleSteps,
39    abortController,
40    // Action to reset the chat state and start anew.
41    reset: action((ctx, isLoading, newAc) => {
42      chatAtom2(ctx, null);
43      error(ctx, null);
44      visibleSteps(ctx, 0);
45      loading(ctx, !!isLoading);
46      if (isLoading && typeof isLoading === "string") id(ctx, isLoading);
47      const prevAc = ctx.get(abortController);
48      abortController(ctx, newAc || null);
49      if (prevAc) ctx.schedule(() => prevAc.abort(ABORTED)).catch(console.error);
50    }, name + ".reset"),
51    // Action to reveal the next solution step
52    revealNextStep: action((ctx) => {
53      const steps = ctx.get(chatAtom2)?.solution?.steps;
54      if (steps && ctx.get(visibleSteps) < steps.length) {
55        visibleSteps.increment(ctx);
56        return true;
57      }
58    }, "revealNextStep"),
59    hashString: atom(null, name + ".hashString")
60  };
61}));
62const chatUrlSlug = (chat) => {
63  return chat ? urlSafeSlug(chat.solution || chat.title || chat.content) : null;
64};
65async function throwResponseError(response) {
66  let suppressedError;
67  let responseError = null;
68  let responseText = null;
69  try {
70    responseText = (await response.text())?.trim();
71    if (responseText) responseError = JSON.parse(responseText);
72  } catch (e2) {
73    suppressedError = e2;
74  }
75  const e = new Error(responseError && responseError.error ? responseError.error : responseError || responseText || "Failed to load");
76  safeErrorCause(e, suppressedError);
77  console.error("Failed to load", `${response.status} ${response.statusText}`, e, {
78    response
79  });
80  throw e;
81}
82const fetchChatAsync = reatomAsync(async (ctx, chatId, userId) => {
83  if (!chatId) {
84    console.error("fetchChatAsync: chatId is required");
85    return;
86  }
87  if (ctx.get(chatAtom)?.id === chatId || ctx.get(chatAtom.id) === chatId) return;
88  const ac = new AbortController();
89  chatAtom.reset(ctx, chatId, ac);
90  try {
91    const chat = await fetchChatRequest(chatId, userId || getUserId(ctx), ac.signal);
92    chatAtom(ctx, chat);
93    return chat;
94  } catch (error) {
95    chatAtom.error(ctx, error);
96    throw error;
97  } finally {
98    chatAtom.loading.setFalse(ctx);
99  }
100}, "fetchChatAsync");
101const fetchChatRequest = async (chatId, userId = getUserId(), signal) => {
102  const response = await fetch(`${API_HOST}/problems/${chatId}?userId=${userId}`, {
103    method: "GET",
104    headers: {
105      "Content-Type": "application/json"
106    },
107    signal
108  });
109  return response.ok ? response.json() : await throwResponseError(response);
110};
111const API_HOST = window.location.origin + "/api";
112const dmp = new DiffMatchPatch();
113const submitProblem = reatomAsync(async (ctx, { content, image, lvl, type }) => {
114  if (!content && !image) {
115    console.error("submitProblem: content or image is required");
116    return;
117  }
118  const ac = new AbortController();
119  chatAtom.reset(ctx, true, ac);
120  try {
121    const tmpId = uuidv7b64();
122    content = content?.trim();
123    const base64Image = !image ? image : typeof image === "string" ? image : await fileToBase64(image);
124    const tmpChatData = {
125      id: tmpId,
126      title: content,
127      solutionType: type || DEFAULT_SOLUTION_TYPE,
128      expertiseLvl: lvl || DEFAULT_EXPERTISE_LEVEL,
129      content: content || "",
130      imageUrl: base64Image || null,
131      unfinished: true
132    };
133    chatAtom(ctx, structuredClone(tmpChatData));
134    chatAtom.id(ctx, tmpId);
135    const requestBody = {
136      id: tmpId,
137      userId: getUserId()
138    };
139    if (content) requestBody.content = content;
140    if (base64Image) requestBody.imageUrl = base64Image;
141    if (lvl && lvl !== DEFAULT_EXPERTISE_LEVEL) requestBody.lvl = lvl;
142    if (type && type !== DEFAULT_SOLUTION_TYPE) requestBody.type = type;
143    let solutionJson = "{}";
144    await fetchEventSource(`${API_HOST}/problems`, {
145      method: "POST",
146      headers: {
147        "Content-Type": "application/json"
148      },
149      body: JSON.stringify(requestBody),
150      // Disable retries by setting retry options
151      openWhenHidden: false,
152      onopen: async (response) => {
153        if (response.ok && response.headers.get("content-type")?.includes("text/event-stream")) {
154          return;
155        }
156        try {
157          await throwResponseError(response);
158        } catch (error) {
159          chatAtom.loading.setFalse(ctx);
160          chatAtom.error(ctx, error);
161          throw error;
162        }
163      },
164      onmessage: (event) => {
165        const me = event;
166        if (!me.event) return;
167        if (me.event === MathSolutionEventType.Final) {
168          if (me.data) {
169            const realId = me.data;
170            if (tmpChatData.id !== realId) {
171              tmpChatData.id = realId;
172            }
173          }
174          tmpChatData.unfinished = false;
175          chatAtom(ctx, structuredClone(tmpChatData));
176          chatAtom.loading.setFalse(ctx);
177        } else if (me.data) {
178          const diff = DIFF_PREFIX + JSON.parse(me.data);
179          const patch = dmp.patch_fromText(diff);
180          const updatedJson = dmp.patch_apply(patch, solutionJson)[0];
181          if (updatedJson === solutionJson) {
182            console.warn("Failed to apply patch:", {
183              patch,
184              solutionJson,
185              updatedJson
186            });
187            return;
188          }
189          solutionJson = updatedJson;
190          const solution = JSON.parse(solutionJson);
191          const realId = solution.id;
192          if (realId) {
193            tmpChatData.id = realId;
194            chatAtom.id(ctx, realId);
195          }
196          delete solution.id;
197          tmpChatData.solution = solution;
198          chatAtom(ctx, structuredClone(tmpChatData));
199          chatAtom.loading.setFalse(ctx);
200        }
201      },
202      onerror: (e) => {
203        const err = e instanceof Error ? e : new Error("Failed to submit problem " + e);
204        safeErrorCause(err, e);
205        chatAtom.error(ctx, err);
206        chatAtom.loading.setFalse(ctx);
207        throw err;
208      }
209    });
210  } catch (error) {
211    chatAtom.error(ctx, error);
212    throw error;
213  } finally {
214    chatAtom.loading.setFalse(ctx);
215  }
216}, "submitProblemAsync");
217export {
218  API_HOST as A,
219  chatUrlSlug as a,
220  chatAtom as c,
221  fetchChatAsync as f,
222  submitProblem as s,
223  throwResponseError as t
224};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.