@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.d.cts CHANGED
@@ -26,6 +26,10 @@ interface ActivationConfig {
26
26
  brand: {
27
27
  name: string;
28
28
  logoUrl: string | null;
29
+ /** The brand's public site, for the footer link. */
30
+ siteUrl?: string;
31
+ /** False on whitelabelled installs: the footer does not name the platform. */
32
+ poweredBy?: boolean;
29
33
  };
30
34
  theme: Record<string, string | undefined> | null;
31
35
  /** Widget modules the activation unlocks; empty means all. */
@@ -124,7 +128,8 @@ declare class AginiesError extends Error {
124
128
  declare class AginiesClient {
125
129
  readonly baseUrl: string;
126
130
  readonly token: string | null;
127
- private readonly hosted;
131
+ /** True when activated from the platform's own page. */
132
+ readonly hosted: boolean;
128
133
  readonly locale: 'tr' | 'en';
129
134
  private readonly fetchImpl;
130
135
  private state;
@@ -401,6 +406,7 @@ declare function useChat(identifier: string, enabled?: boolean): {
401
406
  }) => Promise<boolean>;
402
407
  requestCode: (email: string) => Promise<CodeRequestResult>;
403
408
  verifyCode: (email: string, otp: string) => Promise<boolean>;
409
+ signInWithSso: (email: string) => Promise<"redirected" | "unauthorized" | "error">;
404
410
  reload: () => Promise<void>;
405
411
  };
406
412
  interface ChatWidgetProps {
@@ -677,6 +683,10 @@ declare const STRINGS: {
677
683
  readonly tr: "Kurumsal giriş";
678
684
  readonly en: "Sign in";
679
685
  };
686
+ readonly ssoRetry: {
687
+ readonly tr: "Giriş yaptım, yenile";
688
+ readonly en: "I have signed in, refresh";
689
+ };
680
690
  };
681
691
  readonly voice: {
682
692
  readonly talk: {
package/dist/index.d.ts CHANGED
@@ -26,6 +26,10 @@ interface ActivationConfig {
26
26
  brand: {
27
27
  name: string;
28
28
  logoUrl: string | null;
29
+ /** The brand's public site, for the footer link. */
30
+ siteUrl?: string;
31
+ /** False on whitelabelled installs: the footer does not name the platform. */
32
+ poweredBy?: boolean;
29
33
  };
30
34
  theme: Record<string, string | undefined> | null;
31
35
  /** Widget modules the activation unlocks; empty means all. */
@@ -124,7 +128,8 @@ declare class AginiesError extends Error {
124
128
  declare class AginiesClient {
125
129
  readonly baseUrl: string;
126
130
  readonly token: string | null;
127
- private readonly hosted;
131
+ /** True when activated from the platform's own page. */
132
+ readonly hosted: boolean;
128
133
  readonly locale: 'tr' | 'en';
129
134
  private readonly fetchImpl;
130
135
  private state;
@@ -401,6 +406,7 @@ declare function useChat(identifier: string, enabled?: boolean): {
401
406
  }) => Promise<boolean>;
402
407
  requestCode: (email: string) => Promise<CodeRequestResult>;
403
408
  verifyCode: (email: string, otp: string) => Promise<boolean>;
409
+ signInWithSso: (email: string) => Promise<"redirected" | "unauthorized" | "error">;
404
410
  reload: () => Promise<void>;
405
411
  };
406
412
  interface ChatWidgetProps {
@@ -677,6 +683,10 @@ declare const STRINGS: {
677
683
  readonly tr: "Kurumsal giriş";
678
684
  readonly en: "Sign in";
679
685
  };
686
+ readonly ssoRetry: {
687
+ readonly tr: "Giriş yaptım, yenile";
688
+ readonly en: "I have signed in, refresh";
689
+ };
680
690
  };
681
691
  readonly voice: {
682
692
  readonly talk: {
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ var trimSlash = (s) => s.replace(/\/+$/, "");
15
15
  var AginiesClient = class {
16
16
  baseUrl;
17
17
  token;
18
+ /** True when activated from the platform's own page. */
18
19
  hosted;
19
20
  locale;
20
21
  fetchImpl;
@@ -549,7 +550,8 @@ var STRINGS = {
549
550
  tr: "Bu sohbet kurumsal kimlikle a\xE7\u0131l\u0131r.",
550
551
  en: "This chat opens with your organisation account."
551
552
  },
552
- ssoButton: { tr: "Kurumsal giri\u015F", en: "Sign in" }
553
+ ssoButton: { tr: "Kurumsal giri\u015F", en: "Sign in" },
554
+ ssoRetry: { tr: "Giri\u015F yapt\u0131m, yenile", en: "I have signed in, refresh" }
553
555
  },
554
556
  voice: {
555
557
  talk: { tr: "Konu\u015Fmak i\xE7in dokunun", en: "Tap to talk" },
@@ -1627,6 +1629,26 @@ function useChat(identifier, enabled = true) {
1627
1629
  },
1628
1630
  [client, chatPath, conversationId, load]
1629
1631
  );
1632
+ const signInWithSso = useCallback3(
1633
+ async (email) => {
1634
+ const res = await client.fetchRaw(chatPath, {
1635
+ method: "POST",
1636
+ headers: { "Content-Type": "application/json" },
1637
+ body: JSON.stringify({ email, checkSSOAccess: true })
1638
+ });
1639
+ if (!res.ok) return res.status === 401 || res.status === 403 ? "unauthorized" : "error";
1640
+ const hostedPage = `${client.baseUrl}/chat/${encodeURIComponent(identifier)}`;
1641
+ if (client.hosted) {
1642
+ window.location.assign(
1643
+ `${client.baseUrl}/sso?email=${encodeURIComponent(email)}&callbackUrl=${encodeURIComponent(window.location.pathname)}`
1644
+ );
1645
+ } else {
1646
+ window.open(hostedPage, "_blank", "noopener");
1647
+ }
1648
+ return "redirected";
1649
+ },
1650
+ [client, chatPath, identifier]
1651
+ );
1630
1652
  const requestCode = useCallback3(
1631
1653
  async (email) => {
1632
1654
  const res = await client.fetchRaw(`${chatPath}/otp`, {
@@ -1702,6 +1724,14 @@ function useChat(identifier, enabled = true) {
1702
1724
  if (text2 && !content) {
1703
1725
  content = text2;
1704
1726
  update({ content });
1727
+ } else if (!content) {
1728
+ const raw = extractFinalOutput(ev.data);
1729
+ if (raw) {
1730
+ content = `\`\`\`json
1731
+ ${raw}
1732
+ \`\`\``;
1733
+ update({ content });
1734
+ }
1705
1735
  }
1706
1736
  } else if (ev.type === "error") {
1707
1737
  update({ content: ev.message, error: true, streaming: false });
@@ -1732,6 +1762,7 @@ function useChat(identifier, enabled = true) {
1732
1762
  authenticate,
1733
1763
  requestCode,
1734
1764
  verifyCode,
1765
+ signInWithSso,
1735
1766
  reload: load
1736
1767
  };
1737
1768
  }
@@ -1748,6 +1779,14 @@ function extractFinalText(data) {
1748
1779
  }
1749
1780
  return null;
1750
1781
  }
1782
+ function extractFinalOutput(data) {
1783
+ if (!data || typeof data !== "object") return null;
1784
+ const d = data;
1785
+ const payload = d.output ?? d.error;
1786
+ if (payload === void 0 || payload === null) return null;
1787
+ const text = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
1788
+ return text.trim() ? text : null;
1789
+ }
1751
1790
  function randomId() {
1752
1791
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
1753
1792
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
@@ -1763,7 +1802,7 @@ function ChatWidget({
1763
1802
  className
1764
1803
  }) {
1765
1804
  const [open, setOpen] = useState4(defaultOpen || mode !== "bubble");
1766
- const { t } = useAginies();
1805
+ const { t, client } = useAginies();
1767
1806
  const enabled = useModule("chat");
1768
1807
  const chat = useChat(identifier, enabled);
1769
1808
  const [voiceMode, setVoiceMode] = useState4(false);
@@ -1781,6 +1820,8 @@ function ChatWidget({
1781
1820
  });
1782
1821
  const capabilities = chat.config?.voice;
1783
1822
  const voiceAvailable = voice && voiceControls.supported && capabilities?.stt === true;
1823
+ const state = client.getState();
1824
+ const brand = state.status === "active" ? state.config.brand : { name: "Aginies", logoUrl: null };
1784
1825
  const title = chat.config?.title ?? chat.authTitle ?? launcherLabel ?? "Aginies";
1785
1826
  const themeClass = theme === "auto" ? void 0 : theme === "dark" ? "dark" : "light";
1786
1827
  if (!enabled) return null;
@@ -1824,7 +1865,9 @@ function ChatWidget({
1824
1865
  need: chat.authNeed,
1825
1866
  onPassword: chat.authenticate,
1826
1867
  onRequestCode: chat.requestCode,
1827
- onVerifyCode: chat.verifyCode
1868
+ onVerifyCode: chat.verifyCode,
1869
+ onSso: chat.signInWithSso,
1870
+ onRetry: () => void chat.reload()
1828
1871
  }
1829
1872
  ) : !chat.config ? /* @__PURE__ */ jsx6("div", { className: "agi-chat__state", children: /* @__PURE__ */ jsx6(Spinner, { label: t("common", "loading") }) }) : voiceMode ? /* @__PURE__ */ jsx6(
1830
1873
  VoiceConversation,
@@ -1861,7 +1904,7 @@ function ChatWidget({
1861
1904
  }
1862
1905
  )
1863
1906
  ] }),
1864
- /* @__PURE__ */ jsx6("footer", { className: "agi-chat__foot", children: /* @__PURE__ */ jsx6("a", { href: "https://www.aginies.com", target: "_blank", rel: "noreferrer", children: t("chat", "poweredBy") }) })
1907
+ brand.poweredBy !== false && /* @__PURE__ */ jsx6("footer", { className: "agi-chat__foot", children: /* @__PURE__ */ jsx6("a", { href: brand.siteUrl ?? "https://www.aginies.com", target: "_blank", rel: "noreferrer", children: t("chat", "poweredBy") }) })
1865
1908
  ]
1866
1909
  }
1867
1910
  );
@@ -2241,28 +2284,55 @@ function ChatAuth({
2241
2284
  need,
2242
2285
  onPassword,
2243
2286
  onRequestCode,
2244
- onVerifyCode
2287
+ onVerifyCode,
2288
+ onSso,
2289
+ onRetry
2245
2290
  }) {
2246
- const { t, client } = useAginies();
2247
2291
  if (need === "sso") {
2248
- return /* @__PURE__ */ jsxs5("div", { className: "agi-chat__state", children: [
2249
- /* @__PURE__ */ jsx6("h3", { children: t("auth", "ssoTitle") }),
2250
- /* @__PURE__ */ jsx6("p", { children: t("auth", "ssoHint") }),
2251
- /* @__PURE__ */ jsx6(
2252
- Button,
2253
- {
2254
- variant: "signal",
2255
- onClick: () => window.open(`${client.baseUrl}/chat/`, "_blank", "noopener"),
2256
- children: t("auth", "ssoButton")
2257
- }
2258
- )
2259
- ] });
2292
+ return /* @__PURE__ */ jsx6(SsoAuth, { onSso, onRetry });
2260
2293
  }
2261
2294
  if (need === "email") {
2262
2295
  return /* @__PURE__ */ jsx6(EmailAuth, { onRequestCode, onVerifyCode });
2263
2296
  }
2264
2297
  return /* @__PURE__ */ jsx6(PasswordAuth, { onPassword });
2265
2298
  }
2299
+ function SsoAuth({
2300
+ onSso,
2301
+ onRetry
2302
+ }) {
2303
+ const { t } = useAginies();
2304
+ const [email, setEmail] = useState4("");
2305
+ const [error, setError] = useState4(null);
2306
+ const [pending, setPending] = useState4(false);
2307
+ const [redirected, setRedirected] = useState4(false);
2308
+ const submit = async (e) => {
2309
+ e.preventDefault();
2310
+ setPending(true);
2311
+ setError(null);
2312
+ const result = await onSso(email.trim());
2313
+ setPending(false);
2314
+ if (result === "redirected") setRedirected(true);
2315
+ else setError(t("auth", result === "unauthorized" ? "invalidEmail" : "codeError"));
2316
+ };
2317
+ return /* @__PURE__ */ jsxs5("form", { className: "agi-chat__state agi-chat__auth", onSubmit: submit, children: [
2318
+ /* @__PURE__ */ jsx6("h3", { children: t("auth", "ssoTitle") }),
2319
+ /* @__PURE__ */ jsx6("p", { children: t("auth", "ssoHint") }),
2320
+ /* @__PURE__ */ jsx6(Field, { label: t("auth", "email"), error: error ?? void 0, children: /* @__PURE__ */ jsx6(
2321
+ Input,
2322
+ {
2323
+ type: "email",
2324
+ value: email,
2325
+ onChange: (e) => setEmail(e.target.value),
2326
+ required: true,
2327
+ autoComplete: "email"
2328
+ }
2329
+ ) }),
2330
+ /* @__PURE__ */ jsxs5("div", { className: "agi-chat__auth-actions", children: [
2331
+ /* @__PURE__ */ jsx6(Button, { variant: "signal", type: "submit", disabled: pending || !email.trim(), children: t("auth", "ssoButton") }),
2332
+ redirected && /* @__PURE__ */ jsx6(Button, { variant: "ghost", type: "button", onClick: onRetry, children: t("auth", "ssoRetry") })
2333
+ ] })
2334
+ ] });
2335
+ }
2266
2336
  function PasswordAuth({
2267
2337
  onPassword
2268
2338
  }) {