@aginies/webuikit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -87,6 +87,7 @@ var trimSlash = (s) => s.replace(/\/+$/, "");
87
87
  var AginiesClient = class {
88
88
  baseUrl;
89
89
  token;
90
+ /** True when activated from the platform's own page. */
90
91
  hosted;
91
92
  locale;
92
93
  fetchImpl;
@@ -621,7 +622,8 @@ var STRINGS = {
621
622
  tr: "Bu sohbet kurumsal kimlikle a\xE7\u0131l\u0131r.",
622
623
  en: "This chat opens with your organisation account."
623
624
  },
624
- ssoButton: { tr: "Kurumsal giri\u015F", en: "Sign in" }
625
+ ssoButton: { tr: "Kurumsal giri\u015F", en: "Sign in" },
626
+ ssoRetry: { tr: "Giri\u015F yapt\u0131m, yenile", en: "I have signed in, refresh" }
625
627
  },
626
628
  voice: {
627
629
  talk: { tr: "Konu\u015Fmak i\xE7in dokunun", en: "Tap to talk" },
@@ -1699,6 +1701,26 @@ function useChat(identifier, enabled = true) {
1699
1701
  },
1700
1702
  [client, chatPath, conversationId, load]
1701
1703
  );
1704
+ const signInWithSso = (0, import_react6.useCallback)(
1705
+ async (email) => {
1706
+ const res = await client.fetchRaw(chatPath, {
1707
+ method: "POST",
1708
+ headers: { "Content-Type": "application/json" },
1709
+ body: JSON.stringify({ email, checkSSOAccess: true })
1710
+ });
1711
+ if (!res.ok) return res.status === 401 || res.status === 403 ? "unauthorized" : "error";
1712
+ const hostedPage = `${client.baseUrl}/chat/${encodeURIComponent(identifier)}`;
1713
+ if (client.hosted) {
1714
+ window.location.assign(
1715
+ `${client.baseUrl}/sso?email=${encodeURIComponent(email)}&callbackUrl=${encodeURIComponent(window.location.pathname)}`
1716
+ );
1717
+ } else {
1718
+ window.open(hostedPage, "_blank", "noopener");
1719
+ }
1720
+ return "redirected";
1721
+ },
1722
+ [client, chatPath, identifier]
1723
+ );
1702
1724
  const requestCode = (0, import_react6.useCallback)(
1703
1725
  async (email) => {
1704
1726
  const res = await client.fetchRaw(`${chatPath}/otp`, {
@@ -1774,6 +1796,14 @@ function useChat(identifier, enabled = true) {
1774
1796
  if (text2 && !content) {
1775
1797
  content = text2;
1776
1798
  update({ content });
1799
+ } else if (!content) {
1800
+ const raw = extractFinalOutput(ev.data);
1801
+ if (raw) {
1802
+ content = `\`\`\`json
1803
+ ${raw}
1804
+ \`\`\``;
1805
+ update({ content });
1806
+ }
1777
1807
  }
1778
1808
  } else if (ev.type === "error") {
1779
1809
  update({ content: ev.message, error: true, streaming: false });
@@ -1804,6 +1834,7 @@ function useChat(identifier, enabled = true) {
1804
1834
  authenticate,
1805
1835
  requestCode,
1806
1836
  verifyCode,
1837
+ signInWithSso,
1807
1838
  reload: load
1808
1839
  };
1809
1840
  }
@@ -1820,6 +1851,14 @@ function extractFinalText(data) {
1820
1851
  }
1821
1852
  return null;
1822
1853
  }
1854
+ function extractFinalOutput(data) {
1855
+ if (!data || typeof data !== "object") return null;
1856
+ const d = data;
1857
+ const payload = d.output ?? d.error;
1858
+ if (payload === void 0 || payload === null) return null;
1859
+ const text = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
1860
+ return text.trim() ? text : null;
1861
+ }
1823
1862
  function randomId() {
1824
1863
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
1825
1864
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
@@ -1835,7 +1874,7 @@ function ChatWidget({
1835
1874
  className
1836
1875
  }) {
1837
1876
  const [open, setOpen] = (0, import_react6.useState)(defaultOpen || mode !== "bubble");
1838
- const { t } = useAginies();
1877
+ const { t, client } = useAginies();
1839
1878
  const enabled = useModule("chat");
1840
1879
  const chat = useChat(identifier, enabled);
1841
1880
  const [voiceMode, setVoiceMode] = (0, import_react6.useState)(false);
@@ -1853,6 +1892,8 @@ function ChatWidget({
1853
1892
  });
1854
1893
  const capabilities = chat.config?.voice;
1855
1894
  const voiceAvailable = voice && voiceControls.supported && capabilities?.stt === true;
1895
+ const state = client.getState();
1896
+ const brand = state.status === "active" ? state.config.brand : { name: "Aginies", logoUrl: null };
1856
1897
  const title = chat.config?.title ?? chat.authTitle ?? launcherLabel ?? "Aginies";
1857
1898
  const themeClass = theme === "auto" ? void 0 : theme === "dark" ? "dark" : "light";
1858
1899
  if (!enabled) return null;
@@ -1896,7 +1937,9 @@ function ChatWidget({
1896
1937
  need: chat.authNeed,
1897
1938
  onPassword: chat.authenticate,
1898
1939
  onRequestCode: chat.requestCode,
1899
- onVerifyCode: chat.verifyCode
1940
+ onVerifyCode: chat.verifyCode,
1941
+ onSso: chat.signInWithSso,
1942
+ onRetry: () => void chat.reload()
1900
1943
  }
1901
1944
  ) : !chat.config ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "agi-chat__state", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Spinner, { label: t("common", "loading") }) }) : voiceMode ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1902
1945
  VoiceConversation,
@@ -1933,7 +1976,7 @@ function ChatWidget({
1933
1976
  }
1934
1977
  )
1935
1978
  ] }),
1936
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("footer", { className: "agi-chat__foot", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://www.aginies.com", target: "_blank", rel: "noreferrer", children: t("chat", "poweredBy") }) })
1979
+ brand.poweredBy !== false && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("footer", { className: "agi-chat__foot", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: brand.siteUrl ?? "https://www.aginies.com", target: "_blank", rel: "noreferrer", children: t("chat", "poweredBy") }) })
1937
1980
  ]
1938
1981
  }
1939
1982
  );
@@ -2313,28 +2356,55 @@ function ChatAuth({
2313
2356
  need,
2314
2357
  onPassword,
2315
2358
  onRequestCode,
2316
- onVerifyCode
2359
+ onVerifyCode,
2360
+ onSso,
2361
+ onRetry
2317
2362
  }) {
2318
- const { t, client } = useAginies();
2319
2363
  if (need === "sso") {
2320
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "agi-chat__state", children: [
2321
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: t("auth", "ssoTitle") }),
2322
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t("auth", "ssoHint") }),
2323
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2324
- Button,
2325
- {
2326
- variant: "signal",
2327
- onClick: () => window.open(`${client.baseUrl}/chat/`, "_blank", "noopener"),
2328
- children: t("auth", "ssoButton")
2329
- }
2330
- )
2331
- ] });
2364
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SsoAuth, { onSso, onRetry });
2332
2365
  }
2333
2366
  if (need === "email") {
2334
2367
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EmailAuth, { onRequestCode, onVerifyCode });
2335
2368
  }
2336
2369
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PasswordAuth, { onPassword });
2337
2370
  }
2371
+ function SsoAuth({
2372
+ onSso,
2373
+ onRetry
2374
+ }) {
2375
+ const { t } = useAginies();
2376
+ const [email, setEmail] = (0, import_react6.useState)("");
2377
+ const [error, setError] = (0, import_react6.useState)(null);
2378
+ const [pending, setPending] = (0, import_react6.useState)(false);
2379
+ const [redirected, setRedirected] = (0, import_react6.useState)(false);
2380
+ const submit = async (e) => {
2381
+ e.preventDefault();
2382
+ setPending(true);
2383
+ setError(null);
2384
+ const result = await onSso(email.trim());
2385
+ setPending(false);
2386
+ if (result === "redirected") setRedirected(true);
2387
+ else setError(t("auth", result === "unauthorized" ? "invalidEmail" : "codeError"));
2388
+ };
2389
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { className: "agi-chat__state agi-chat__auth", onSubmit: submit, children: [
2390
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: t("auth", "ssoTitle") }),
2391
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t("auth", "ssoHint") }),
2392
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { label: t("auth", "email"), error: error ?? void 0, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2393
+ Input,
2394
+ {
2395
+ type: "email",
2396
+ value: email,
2397
+ onChange: (e) => setEmail(e.target.value),
2398
+ required: true,
2399
+ autoComplete: "email"
2400
+ }
2401
+ ) }),
2402
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "agi-chat__auth-actions", children: [
2403
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { variant: "signal", type: "submit", disabled: pending || !email.trim(), children: t("auth", "ssoButton") }),
2404
+ redirected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { variant: "ghost", type: "button", onClick: onRetry, children: t("auth", "ssoRetry") })
2405
+ ] })
2406
+ ] });
2407
+ }
2338
2408
  function PasswordAuth({
2339
2409
  onPassword
2340
2410
  }) {