@inkeep/agents-ui 0.16.5 → 0.17.1

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.
@@ -1,3 +1,3 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("../../hooks/use-inkeep-api-client.cjs");function r(t){const e=Number(t.code)||Number(t.statusCode);if(e&&!Number.isNaN(e))return e;try{const s=Number(JSON.parse(t.message??"").status);return s&&!Number.isNaN(s)?s:null}catch{return null}}function o(t){const e=r(t),s=n.parseAuthError(e??0,{detail:t.message??""});return s!==null?s:e===401?"session":null}function a(t){const e=r(t);return e===400||e===429}const u=`Hmm..
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("../../hooks/use-inkeep-api-client.cjs");function s(t){const e=Number(t.code)||Number(t.statusCode);if(e&&!Number.isNaN(e))return e;try{const r=Number(JSON.parse(t.message??"").status);return r&&!Number.isNaN(r)?r:null}catch{return null}}function o(t){const e=s(t),r=n.parseAuthError(e??0,{detail:t.message??""});return r!==null?r:e===401?"session":e===403?"captcha":null}function a(t){const e=s(t);return e===400||e===429}const u=`Hmm..
2
2
 
3
- It seems I might be having some issues right now. Please clear the chat and try again.`,E="Please try again.",i="You're sending requests too quickly. Please wait a moment and try again.",c=8e3;exports.DEFAULT_ERROR_MESSAGE=u;exports.RATE_LIMIT_MESSAGE=i;exports.RECOVERABLE_FALLBACK_MESSAGE=E;exports.RECOVERABLE_NOTIFICATION_DURATION_MS=c;exports.isRecoverableError=a;exports.resolveHttpStatusCode=r;exports.resolveStreamingAuthError=o;
3
+ It seems I might be having some issues right now. Please clear the chat and try again.`,i="Please try again.",E="You're sending requests too quickly. Please wait a moment and try again.",c=8e3;exports.DEFAULT_ERROR_MESSAGE=u;exports.RATE_LIMIT_MESSAGE=E;exports.RECOVERABLE_FALLBACK_MESSAGE=i;exports.RECOVERABLE_NOTIFICATION_DURATION_MS=c;exports.isRecoverableError=a;exports.resolveHttpStatusCode=s;exports.resolveStreamingAuthError=o;
@@ -10,9 +10,10 @@ export interface ErrorWithCode extends Error {
10
10
  */
11
11
  export declare function resolveHttpStatusCode(error: Error): number | null;
12
12
  /**
13
- * Classifies a streaming-transport error as a PoW or session auth failure, or null.
13
+ * Classifies a streaming-transport error as a captcha (Sentinel) or session auth failure,
14
+ * or null.
14
15
  */
15
- export declare function resolveStreamingAuthError(error: Error): 'pow' | 'session' | null;
16
+ export declare function resolveStreamingAuthError(error: Error): 'captcha' | 'session' | null;
16
17
  /**
17
18
  * Recoverable errors are input-validation failures where the user can fix
18
19
  * their input and retry without clearing the conversation.
@@ -10,9 +10,9 @@ function n(t) {
10
10
  return null;
11
11
  }
12
12
  }
13
- function a(t) {
13
+ function o(t) {
14
14
  const e = n(t), s = r(e ?? 0, { detail: t.message ?? "" });
15
- return s !== null ? s : e === 401 ? "session" : null;
15
+ return s !== null ? s : e === 401 ? "session" : e === 403 ? "captcha" : null;
16
16
  }
17
17
  function u(t) {
18
18
  const e = n(t);
@@ -28,5 +28,5 @@ export {
28
28
  m as RECOVERABLE_NOTIFICATION_DURATION_MS,
29
29
  u as isRecoverableError,
30
30
  n as resolveHttpStatusCode,
31
- a as resolveStreamingAuthError
31
+ o as resolveStreamingAuthError
32
32
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("altcha-lib"),c=require("react"),x=30*1e3;function b(l){const e=/[?&]expires=(\d+)/.exec(l);return e?Number.parseInt(e[1],10)*1e3:null}const p=async l=>{try{const e=await fetch(l,{method:"GET"});if(!e.ok)throw new Error(`Failed to fetch challenge: ${e.statusText}`);const i=await e.json(),{challenge:u,algorithm:n,salt:r,maxnumber:t}=i,{promise:g}=await w.solveChallenge(u,r,n,t),f=await g||void 0;if(!f)throw new Error("Challenge not solved");return{payload:{number:f.number,...i},expiresAt:b(r)}}catch(e){console.warn("[captcha] Error fetching/solving challenge:",e);return}},m=({baseUrl:l,shouldBypassCaptcha:e=!1,shouldMakeInitialRequest:i=!0})=>{const u=`${l}/run/auth/pow/challenge`,n=c.useRef(null),r=c.useRef(null),t=c.useCallback(()=>{const o=p(u);n.current=o,o.then(a=>{a&&(r.current=a.expiresAt)})},[u]),g=c.useCallback(async()=>{if(e)return{};n.current||t();const o=n.current;n.current=null,t();const a=n.current,h=await o;if(!h){const s=await a;return s?{"x-inkeep-challenge-solution":btoa(JSON.stringify(s.payload))}:{}}if(h.expiresAt!==null&&Date.now()>=h.expiresAt){const s=await a;return s?{"x-inkeep-challenge-solution":btoa(JSON.stringify(s.payload))}:{}}return{"x-inkeep-challenge-solution":btoa(JSON.stringify(h.payload))}},[e,t]),f=c.useCallback(()=>{e||t()},[e,t]);return c.useEffect(()=>{if(!i||e)return;const o=r.current!==null&&Date.now()>=r.current-x;(!n.current||o)&&t()},[i,e,t]),{getCaptchaHeader:g,invalidate:f}};exports.fetchAndSolveChallenge=p;exports.useCaptcha=m;
1
+ "use client";"use strict";var A=Object.create;var w=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var L=(r,n,e,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of P(n))!O.call(r,t)&&t!==e&&w(r,t,{get:()=>n[t],enumerable:!(o=S(n,t))||o.enumerable});return r};var C=(r,n,e)=>(e=r!=null?A(b(r)):{},L(n||!r||!r.__esModule?w(e,"default",{value:r,enumerable:!0}):e,r));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react"),h="[sentinel]",x=45e3,M=3e4,N=3,D=5,F=250,I=4e3;let v=null;function Y(){return typeof customElements>"u"||customElements.get("altcha-widget")?Promise.resolve():v||(v=import("altcha").then(()=>customElements.whenDefined("altcha-widget")).then(()=>{}).catch(r=>{throw v=null,console.error(h,"failed to load altcha widget module",r),r instanceof Error?r:new Error("Failed to load altcha widget module")}),v)}function k(r){const n=document.createElement("div");n.style.cssText="position:fixed;left:-9999px;top:-9999px;width:0;height:0;overflow:hidden;pointer-events:none",document.body.appendChild(n);const e=document.createElement("altcha-widget");e.setAttribute("challenge",r),e.setAttribute("auto","onload"),e.setAttribute("hidefooter","true"),e.setAttribute("hidelogo","true"),e.setAttribute("configuration",JSON.stringify({disableAutoFocus:!0})),n.appendChild(e);let o=[],t,c="mounted",s=!1,E=!1,u=null,i=null,a=0,m=!1;const R=d=>{const l=o;o=[];for(const p of l)p(d)},g=()=>{s||m||(t=void 0,c="resetting",e.reset?.(),e.verify?.())},_=()=>{u&&clearTimeout(u),u=setTimeout(()=>{u=null,!(!s||m)&&(s=!1,a=0,t=void 0,c="resetting",e.reset?.(),e.verify?.())},M)},y=d=>{const l=d.detail;if(l&&(c=l.state??c,l.state==="verified"&&l.payload&&(E=!0,a=0,t=l.payload,R(l.payload)),l.state==="error"))if(t=void 0,a++,a>=(E?D:N))R(void 0),s=!0,console.warn(h,`Sentinel unavailable after ${a} consecutive errors, requests will proceed without bot protection`),_();else{const T=Math.min(F*2**(a-1),I);i&&clearTimeout(i),i=setTimeout(()=>{i=null,!(m||s)&&(c="resetting",e.reset?.(),e.verify?.())},T)}};return e.addEventListener("statechange",y),{getPayload:()=>{if(m||s)return Promise.resolve(void 0);if(t){const d=t;return t=void 0,g(),Promise.resolve(d)}return c==="verified"&&g(),new Promise(d=>{o.push(d),setTimeout(()=>{const l=o.indexOf(d);l!==-1&&(o.splice(l,1),d(void 0))},x)})},startNextSolve:g,destroy:()=>{m=!0,e.removeEventListener("statechange",y),u&&(clearTimeout(u),u=null),i&&(clearTimeout(i),i=null),R(void 0),n.remove()}}}const V=({baseUrl:r,appId:n,shouldBypassCaptcha:e=!1})=>{const o=f.useRef(null),t=f.useRef(null),c=f.useRef(!1),s=f.useCallback(()=>o.current?Promise.resolve():t.current?t.current:n?(t.current=Y().then(()=>{if(!c.current&&!o.current){const i=`${r}/run/auth/sentinel/challenge?appId=${encodeURIComponent(n)}`;o.current=k(i)}}).catch(i=>{console.error(h,"failed to mount widget",i),t.current=null}),t.current):Promise.resolve(),[r,n]);f.useEffect(()=>{if(c.current=!1,!e)return s(),()=>{c.current=!0,o.current?.destroy(),o.current=null,t.current=null}},[e,s]);const E=f.useCallback(async()=>{if(e)return{};await s();const i=o.current;if(!i)return{};const a=await i.getPayload();return a?{"x-inkeep-challenge-solution":btoa(JSON.stringify({payload:a}))}:{}},[e,s]),u=f.useCallback(()=>{o.current?.startNextSolve()},[]);return{getCaptchaHeader:E,invalidate:u}};exports.useCaptcha=V;
@@ -1,29 +1,9 @@
1
- import { Payload } from 'altcha-lib/types';
2
1
  interface UseCaptchaOptions {
3
2
  baseUrl: string;
3
+ appId: string | undefined;
4
4
  shouldBypassCaptcha?: boolean;
5
- shouldMakeInitialRequest?: boolean;
6
5
  }
7
- interface SolvedEntry {
8
- payload: Payload;
9
- expiresAt: number | null;
10
- }
11
- export declare const fetchAndSolveChallenge: (fetchUrl: string) => Promise<SolvedEntry | undefined>;
12
- /**
13
- * Manages the PoW captcha lifecycle for /run/* API requests.
14
- *
15
- * - getCaptchaHeader(): atomically consumes the current pre-fetched challenge,
16
- * immediately kicks off the next fetch so a fresh solution is always warm, and
17
- * returns the ready-to-use `{ 'x-inkeep-challenge-solution': '...' }` header
18
- * (or {} when bypassing or on failure). Checks token expiry and falls back to
19
- * the already-started pre-fetch if the resolved token is stale.
20
- *
21
- * - invalidate(): discards any in-flight solution and starts a fresh fetch.
22
- * Call this on request errors to recover from a rejected/stale challenge.
23
- *
24
- * All hooks are called unconditionally — bypass logic lives inside callbacks.
25
- */
26
- export declare const useCaptcha: ({ baseUrl, shouldBypassCaptcha, shouldMakeInitialRequest, }: UseCaptchaOptions) => {
6
+ export declare const useCaptcha: ({ baseUrl, appId, shouldBypassCaptcha }: UseCaptchaOptions) => {
27
7
  getCaptchaHeader: () => Promise<Record<string, string>>;
28
8
  invalidate: () => void;
29
9
  };
@@ -1,67 +1,92 @@
1
1
  "use client";
2
- import { solveChallenge as m } from "altcha-lib";
3
- import { useRef as p, useCallback as h, useEffect as x } from "react";
4
- const w = 30 * 1e3;
5
- function E(i) {
6
- const e = /[?&]expires=(\d+)/.exec(i);
7
- return e ? Number.parseInt(e[1], 10) * 1e3 : null;
2
+ import { useRef as R, useCallback as h, useEffect as A } from "react";
3
+ const y = "[sentinel]", P = 45e3, S = 3e4, O = 3, b = 5, L = 250, x = 4e3;
4
+ let m = null;
5
+ function N() {
6
+ return typeof customElements > "u" || customElements.get("altcha-widget") ? Promise.resolve() : m || (m = import("altcha").then(() => customElements.whenDefined("altcha-widget")).then(() => {
7
+ }).catch((a) => {
8
+ throw m = null, console.error(y, "failed to load altcha widget module", a), a instanceof Error ? a : new Error("Failed to load altcha widget module");
9
+ }), m);
8
10
  }
9
- const y = async (i) => {
10
- try {
11
- const e = await fetch(i, { method: "GET" });
12
- if (!e.ok)
13
- throw new Error(`Failed to fetch challenge: ${e.statusText}`);
14
- const c = await e.json(), { challenge: s, algorithm: t, salt: r, maxnumber: n } = c, { promise: g } = await m(
15
- s,
16
- r,
17
- t,
18
- n
19
- ), u = await g || void 0;
20
- if (!u)
21
- throw new Error("Challenge not solved");
22
- return {
23
- payload: { number: u.number, ...c },
24
- expiresAt: E(r)
25
- };
26
- } catch (e) {
27
- console.warn("[captcha] Error fetching/solving challenge:", e);
28
- return;
29
- }
30
- }, k = ({
31
- baseUrl: i,
32
- shouldBypassCaptcha: e = !1,
33
- shouldMakeInitialRequest: c = !0
34
- }) => {
35
- const s = `${i}/run/auth/pow/challenge`, t = p(null), r = p(null), n = h(() => {
36
- const o = y(s);
37
- t.current = o, o.then((l) => {
38
- l && (r.current = l.expiresAt);
39
- });
40
- }, [s]), g = h(async () => {
41
- if (e) return {};
42
- t.current || n();
43
- const o = t.current;
44
- t.current = null, n();
45
- const l = t.current, f = await o;
46
- if (!f) {
47
- const a = await l;
48
- return a ? { "x-inkeep-challenge-solution": btoa(JSON.stringify(a.payload)) } : {};
11
+ function C(a) {
12
+ const d = document.createElement("div");
13
+ d.style.cssText = "position:fixed;left:-9999px;top:-9999px;width:0;height:0;overflow:hidden;pointer-events:none", document.body.appendChild(d);
14
+ const e = document.createElement("altcha-widget");
15
+ e.setAttribute("challenge", a), e.setAttribute("auto", "onload"), e.setAttribute("hidefooter", "true"), e.setAttribute("hidelogo", "true"), e.setAttribute("configuration", JSON.stringify({ disableAutoFocus: !0 })), d.appendChild(e);
16
+ let n = [], t, l = "mounted", i = !1, E = !1, s = null, r = null, c = 0, f = !1;
17
+ const v = (u) => {
18
+ const o = n;
19
+ n = [];
20
+ for (const w of o) w(u);
21
+ }, g = () => {
22
+ i || f || (t = void 0, l = "resetting", e.reset?.(), e.verify?.());
23
+ }, _ = () => {
24
+ s && clearTimeout(s), s = setTimeout(() => {
25
+ s = null, !(!i || f) && (i = !1, c = 0, t = void 0, l = "resetting", e.reset?.(), e.verify?.());
26
+ }, S);
27
+ }, p = (u) => {
28
+ const o = u.detail;
29
+ if (o && (l = o.state ?? l, o.state === "verified" && o.payload && (E = !0, c = 0, t = o.payload, v(o.payload)), o.state === "error"))
30
+ if (t = void 0, c++, c >= (E ? b : O))
31
+ v(void 0), i = !0, console.warn(
32
+ y,
33
+ `Sentinel unavailable after ${c} consecutive errors, requests will proceed without bot protection`
34
+ ), _();
35
+ else {
36
+ const T = Math.min(
37
+ L * 2 ** (c - 1),
38
+ x
39
+ );
40
+ r && clearTimeout(r), r = setTimeout(() => {
41
+ r = null, !(f || i) && (l = "resetting", e.reset?.(), e.verify?.());
42
+ }, T);
43
+ }
44
+ };
45
+ return e.addEventListener("statechange", p), { getPayload: () => {
46
+ if (f || i) return Promise.resolve(void 0);
47
+ if (t) {
48
+ const u = t;
49
+ return t = void 0, g(), Promise.resolve(u);
49
50
  }
50
- if (f.expiresAt !== null && Date.now() >= f.expiresAt) {
51
- const a = await l;
52
- return a ? { "x-inkeep-challenge-solution": btoa(JSON.stringify(a.payload)) } : {};
51
+ return l === "verified" && g(), new Promise((u) => {
52
+ n.push(u), setTimeout(() => {
53
+ const o = n.indexOf(u);
54
+ o !== -1 && (n.splice(o, 1), u(void 0));
55
+ }, P);
56
+ });
57
+ }, startNextSolve: g, destroy: () => {
58
+ f = !0, e.removeEventListener("statechange", p), s && (clearTimeout(s), s = null), r && (clearTimeout(r), r = null), v(void 0), d.remove();
59
+ } };
60
+ }
61
+ const M = ({ baseUrl: a, appId: d, shouldBypassCaptcha: e = !1 }) => {
62
+ const n = R(null), t = R(null), l = R(!1), i = h(() => n.current ? Promise.resolve() : t.current ? t.current : d ? (t.current = N().then(() => {
63
+ if (!l.current && !n.current) {
64
+ const r = `${a}/run/auth/sentinel/challenge?appId=${encodeURIComponent(d)}`;
65
+ n.current = C(r);
53
66
  }
54
- return { "x-inkeep-challenge-solution": btoa(JSON.stringify(f.payload)) };
55
- }, [e, n]), u = h(() => {
56
- e || n();
57
- }, [e, n]);
58
- return x(() => {
59
- if (!c || e) return;
60
- const o = r.current !== null && Date.now() >= r.current - w;
61
- (!t.current || o) && n();
62
- }, [c, e, n]), { getCaptchaHeader: g, invalidate: u };
67
+ }).catch((r) => {
68
+ console.error(y, "failed to mount widget", r), t.current = null;
69
+ }), t.current) : Promise.resolve(), [a, d]);
70
+ A(() => {
71
+ if (l.current = !1, !e)
72
+ return i(), () => {
73
+ l.current = !0, n.current?.destroy(), n.current = null, t.current = null;
74
+ };
75
+ }, [e, i]);
76
+ const E = h(async () => {
77
+ if (e) return {};
78
+ await i();
79
+ const r = n.current;
80
+ if (!r) return {};
81
+ const c = await r.getPayload();
82
+ return c ? {
83
+ "x-inkeep-challenge-solution": btoa(JSON.stringify({ payload: c }))
84
+ } : {};
85
+ }, [e, i]), s = h(() => {
86
+ n.current?.startNextSolve();
87
+ }, []);
88
+ return { getCaptchaHeader: E, invalidate: s };
63
89
  };
64
90
  export {
65
- y as fetchAndSolveChallenge,
66
- k as useCaptcha
91
+ M as useCaptcha
67
92
  };
@@ -294,7 +294,7 @@ export declare const EmbeddedChatPrimitiveFormFieldSelectTrigger: React.ForwardR
294
294
  declare const PrimitiveFormFieldSelectValue: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectValueProps & React.RefAttributes<HTMLSpanElement>, "_id"> & Partial<Pick<SelectPrimitive.SelectValueProps & React.RefAttributes<HTMLSpanElement>, "_id">>>;
295
295
  export declare const EmbeddedChatPrimitiveFormFieldSelectValue: (props: ComponentPropsWithRef<typeof PrimitiveFormFieldSelectValue>) => import("react/jsx-runtime").JSX.Element;
296
296
  export declare const EmbeddedChatPrimitiveFormFieldSelectIcon: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectIconProps & React.RefAttributes<HTMLSpanElement>, "children" | "asChild" | "_id"> & Partial<Pick<SelectPrimitive.SelectIconProps & React.RefAttributes<HTMLSpanElement>, "children" | "asChild" | "_id">>>;
297
- export declare const EmbeddedChatPrimitiveFormFieldSelectContent: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "position" | "_id"> & Partial<Pick<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "position" | "_id">>>;
297
+ export declare const EmbeddedChatPrimitiveFormFieldSelectContent: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "_id" | "position"> & Partial<Pick<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "_id" | "position">>>;
298
298
  export declare const EmbeddedChatPrimitiveFormFieldSelectViewport: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectViewportProps & React.RefAttributes<HTMLDivElement>, "_id"> & Partial<Pick<SelectPrimitive.SelectViewportProps & React.RefAttributes<HTMLDivElement>, "_id">>>;
299
299
  export declare const EmbeddedChatPrimitiveFormFieldSelectItem: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectItemProps & React.RefAttributes<HTMLDivElement>, "_id"> & Partial<Pick<SelectPrimitive.SelectItemProps & React.RefAttributes<HTMLDivElement>, "_id">>>;
300
300
  export declare const EmbeddedChatPrimitiveFormFieldSelectItemText: React.ForwardRefExoticComponent< PolymorphicProps & Omit<SelectPrimitive.SelectItemTextProps & React.RefAttributes<HTMLSpanElement>, "_id"> & Partial<Pick<SelectPrimitive.SelectItemTextProps & React.RefAttributes<HTMLSpanElement>, "_id">>>;
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),j=require("./use-local-storage.cjs"),p=require("./use-inkeep-api-client.cjs"),_=30*1e3,q=2147483647,P=()=>{},B=async()=>({});function x(s){return new Date(s.expiresAt).getTime()-_<=Date.now()}const W=({baseUrl:s,appId:t,getCaptchaHeader:$,invalidateCaptcha:D,optOutAllAnalytics:m,enabled:n=!0})=>{const F=n&&t&&!m?`inkeep_session_${t}`:null,[c,h]=j.useLocalStorage(F),E=e.useRef(n);e.useEffect(()=>{const r=E.current;if(E.current=n,r&&!n&&t&&!m){try{localStorage.removeItem(`inkeep_session_${t}`)}catch{}h(null)}},[n,t,m,h]);const{fetchWithAuth:v}=p.useInkeepApiClient({appId:t,authToken:void 0,getCaptchaHeader:$??B,invalidateCaptcha:D??P}),R=e.useRef(s);R.current=s;const y=e.useRef(t);y.current=t;const f=e.useRef(c);f.current=c;const T=e.useRef(h);T.current=h;const g=e.useRef(v);g.current=v;const a=e.useRef(null),w=e.useRef(n);w.current=n;const o=e.useCallback(async r=>{if(!w.current||!R.current||!y.current)return null;if(!r&&a.current)return a.current;const u=`${R.current}/run/auth/apps/${y.current}/anonymous-session`,l=(async()=>{try{const i={"Content-Type":"application/json"},M=f.current?.token;M&&(i.Authorization=`Bearer ${M}`);const A=await g.current(u,{method:"POST",headers:i,signal:r});if(!A.ok)throw new Error(`Failed to fetch anonymous session: ${A.status}`);const S=await A.json();return T.current({token:S.token,expiresAt:S.expiresAt}),S.token}catch(i){return i instanceof Error&&i.name==="AbortError"||console.error("[anonymous-session] fetch failed",i),null}finally{r||(a.current=null)}})();return r||(a.current=l),l},[]),C=e.useRef(!1);e.useEffect(()=>{if(!n||!s||!t)return;const r=!C.current;if(C.current=!0,!r&&f.current&&!x(f.current)||a.current)return;const u=new AbortController;return o(u.signal),()=>u.abort()},[s,t,n,o]),e.useEffect(()=>{if(!n||!s||!t||!c?.expiresAt)return;const k=new Date(c.expiresAt).getTime()-_-Date.now();if(k<=0)return;const l=setTimeout(()=>o(),Math.min(k,q));return()=>clearTimeout(l)},[s,t,n,c?.expiresAt,o]),e.useEffect(()=>{if(!n||!s||!t)return;const r=()=>{if(document.visibilityState!=="visible")return;const u=f.current;(!u||x(u))&&o()};return document.addEventListener("visibilitychange",r),()=>document.removeEventListener("visibilitychange",r)},[s,t,n,o]);const L=e.useCallback(()=>o(),[o]);return{sessionToken:c?.token??null,refreshSession:L}};exports.useAnonymousSession=W;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),P=require("./use-local-storage.cjs"),B=require("./use-inkeep-api-client.cjs"),D=30*1e3,W=2147483647,X=()=>{},v=async()=>({});function j(s){return new Date(s.expiresAt).getTime()-D<=Date.now()}const z=({baseUrl:s,appId:t,getCaptchaHeader:R,invalidateCaptcha:F,optOutAllAnalytics:m,enabled:n=!0})=>{const L=n&&t&&!m?`inkeep_session_${t}`:null,[i,h]=P.useLocalStorage(L),T=e.useRef(n);e.useEffect(()=>{const r=T.current;if(T.current=n,r&&!n&&t&&!m){try{localStorage.removeItem(`inkeep_session_${t}`)}catch{}h(null)}},[n,t,m,h]);const{fetchWithAuth:w}=B.useInkeepApiClient({appId:t,authToken:void 0,getCaptchaHeader:R??v,invalidateCaptcha:F??X}),k=e.useRef(s);k.current=s;const y=e.useRef(t);y.current=t;const f=e.useRef(i);f.current=i;const g=e.useRef(h);g.current=h;const M=e.useRef(w);M.current=w;const x=e.useRef(R??v);x.current=R??v;const a=e.useRef(null),C=e.useRef(n);C.current=n;const o=e.useCallback(async r=>{if(!C.current||!k.current||!y.current)return null;if(!r&&a.current)return a.current;const u=`${k.current}/run/auth/apps/${y.current}/anonymous-session`,l=(async()=>{try{const c={"Content-Type":"application/json"},$=f.current?.token;$&&(c.Authorization=`Bearer ${$}`);const q=await x.current();Object.assign(c,q);const S=await M.current(u,{method:"POST",headers:c,signal:r});if(!S.ok)throw new Error(`Failed to fetch anonymous session: ${S.status}`);const E=await S.json();return g.current({token:E.token,expiresAt:E.expiresAt}),E.token}catch(c){return c instanceof Error&&c.name==="AbortError"||console.error("[anon-session] fetch failed",c),null}finally{r||(a.current=null)}})();return r||(a.current=l),l},[]),_=e.useRef(!1);e.useEffect(()=>{if(!n||!s||!t)return;const r=!_.current;if(_.current=!0,!r&&f.current&&!j(f.current)||a.current)return;const u=new AbortController;return o(u.signal),()=>u.abort()},[s,t,n,o]),e.useEffect(()=>{if(!n||!s||!t||!i?.expiresAt)return;const A=new Date(i.expiresAt).getTime()-D-Date.now();if(A<=0)return;const l=setTimeout(()=>o(),Math.min(A,W));return()=>clearTimeout(l)},[s,t,n,i?.expiresAt,o]),e.useEffect(()=>{if(!n||!s||!t)return;const r=()=>{if(document.visibilityState!=="visible")return;const u=f.current;(!u||j(u))&&o()};return document.addEventListener("visibilitychange",r),()=>document.removeEventListener("visibilitychange",r)},[s,t,n,o]);const p=e.useCallback(()=>o(),[o]);return{sessionToken:i?.token??null,refreshSession:p}};exports.useAnonymousSession=z;
@@ -1,96 +1,101 @@
1
1
  "use client";
2
- import { useRef as o, useEffect as l, useCallback as g } from "react";
3
- import { useLocalStorage as B } from "./use-local-storage.js";
4
- import { useInkeepApiClient as P } from "./use-inkeep-api-client.js";
5
- const p = 30 * 1e3, W = 2147483647, X = () => {
6
- }, z = async () => ({});
7
- function $(n) {
8
- return new Date(n.expiresAt).getTime() - p <= Date.now();
2
+ import { useRef as o, useEffect as l, useCallback as D } from "react";
3
+ import { useLocalStorage as X } from "./use-local-storage.js";
4
+ import { useInkeepApiClient as z } from "./use-inkeep-api-client.js";
5
+ const j = 30 * 1e3, H = 2147483647, K = () => {
6
+ }, T = async () => ({});
7
+ function F(n) {
8
+ return new Date(n.expiresAt).getTime() - j <= Date.now();
9
9
  }
10
- const Y = ({
10
+ const G = ({
11
11
  baseUrl: n,
12
- appId: e,
13
- getCaptchaHeader: D,
14
- invalidateCaptcha: F,
15
- optOutAllAnalytics: k,
16
- enabled: t = !0
12
+ appId: t,
13
+ getCaptchaHeader: k,
14
+ invalidateCaptcha: L,
15
+ optOutAllAnalytics: y,
16
+ enabled: e = !0
17
17
  }) => {
18
- const L = t && e && !k ? `inkeep_session_${e}` : null, [c, h] = B(L), S = o(t);
18
+ const B = e && t && !y ? `inkeep_session_${t}` : null, [u, h] = X(B), w = o(e);
19
19
  l(() => {
20
- const r = S.current;
21
- if (S.current = t, r && !t && e && !k) {
20
+ const r = w.current;
21
+ if (w.current = e, r && !e && t && !y) {
22
22
  try {
23
- localStorage.removeItem(`inkeep_session_${e}`);
23
+ localStorage.removeItem(`inkeep_session_${t}`);
24
24
  } catch {
25
25
  }
26
26
  h(null);
27
27
  }
28
- }, [t, e, k, h]);
29
- const { fetchWithAuth: T } = P({
30
- appId: e,
28
+ }, [e, t, y, h]);
29
+ const { fetchWithAuth: x } = z({
30
+ appId: t,
31
31
  authToken: void 0,
32
- getCaptchaHeader: D ?? z,
33
- invalidateCaptcha: F ?? X
34
- }), y = o(n);
35
- y.current = n;
36
- const A = o(e);
37
- A.current = e;
38
- const f = o(c);
39
- f.current = c;
40
- const w = o(h);
41
- w.current = h;
42
- const x = o(T);
43
- x.current = T;
44
- const a = o(null), M = o(t);
45
- M.current = t;
46
- const s = g(async (r) => {
47
- if (!M.current || !y.current || !A.current) return null;
32
+ getCaptchaHeader: k ?? T,
33
+ invalidateCaptcha: L ?? K
34
+ }), A = o(n);
35
+ A.current = n;
36
+ const R = o(t);
37
+ R.current = t;
38
+ const f = o(u);
39
+ f.current = u;
40
+ const M = o(h);
41
+ M.current = h;
42
+ const _ = o(x);
43
+ _.current = x;
44
+ const g = o(k ?? T);
45
+ g.current = k ?? T;
46
+ const a = o(null), C = o(e);
47
+ C.current = e;
48
+ const s = D(async (r) => {
49
+ if (!C.current || !A.current || !R.current) return null;
48
50
  if (!r && a.current)
49
51
  return a.current;
50
- const i = `${y.current}/run/auth/apps/${A.current}/anonymous-session`, m = (async () => {
52
+ const c = `${A.current}/run/auth/apps/${R.current}/anonymous-session`, m = (async () => {
51
53
  try {
52
- const u = { "Content-Type": "application/json" }, _ = f.current?.token;
53
- _ && (u.Authorization = `Bearer ${_}`);
54
- const v = await x.current(i, {
54
+ const i = { "Content-Type": "application/json" }, p = f.current?.token;
55
+ p && (i.Authorization = `Bearer ${p}`);
56
+ const W = await g.current();
57
+ Object.assign(i, W);
58
+ const E = await _.current(c, {
55
59
  method: "POST",
56
- headers: u,
60
+ headers: i,
57
61
  signal: r
58
62
  });
59
- if (!v.ok) throw new Error(`Failed to fetch anonymous session: ${v.status}`);
60
- const E = await v.json();
61
- return w.current({ token: E.token, expiresAt: E.expiresAt }), E.token;
62
- } catch (u) {
63
- return u instanceof Error && u.name === "AbortError" || console.error("[anonymous-session] fetch failed", u), null;
63
+ if (!E.ok)
64
+ throw new Error(`Failed to fetch anonymous session: ${E.status}`);
65
+ const S = await E.json();
66
+ return M.current({ token: S.token, expiresAt: S.expiresAt }), S.token;
67
+ } catch (i) {
68
+ return i instanceof Error && i.name === "AbortError" || console.error("[anon-session] fetch failed", i), null;
64
69
  } finally {
65
70
  r || (a.current = null);
66
71
  }
67
72
  })();
68
73
  return r || (a.current = m), m;
69
- }, []), C = o(!1);
74
+ }, []), $ = o(!1);
70
75
  l(() => {
71
- if (!t || !n || !e) return;
72
- const r = !C.current;
73
- if (C.current = !0, !r && f.current && !$(f.current) || a.current) return;
74
- const i = new AbortController();
75
- return s(i.signal), () => i.abort();
76
- }, [n, e, t, s]), l(() => {
77
- if (!t || !n || !e || !c?.expiresAt) return;
78
- const R = new Date(c.expiresAt).getTime() - p - Date.now();
79
- if (R <= 0) return;
80
- const m = setTimeout(() => s(), Math.min(R, W));
76
+ if (!e || !n || !t) return;
77
+ const r = !$.current;
78
+ if ($.current = !0, !r && f.current && !F(f.current) || a.current) return;
79
+ const c = new AbortController();
80
+ return s(c.signal), () => c.abort();
81
+ }, [n, t, e, s]), l(() => {
82
+ if (!e || !n || !t || !u?.expiresAt) return;
83
+ const v = new Date(u.expiresAt).getTime() - j - Date.now();
84
+ if (v <= 0) return;
85
+ const m = setTimeout(() => s(), Math.min(v, H));
81
86
  return () => clearTimeout(m);
82
- }, [n, e, t, c?.expiresAt, s]), l(() => {
83
- if (!t || !n || !e) return;
87
+ }, [n, t, e, u?.expiresAt, s]), l(() => {
88
+ if (!e || !n || !t) return;
84
89
  const r = () => {
85
90
  if (document.visibilityState !== "visible") return;
86
- const i = f.current;
87
- (!i || $(i)) && s();
91
+ const c = f.current;
92
+ (!c || F(c)) && s();
88
93
  };
89
94
  return document.addEventListener("visibilitychange", r), () => document.removeEventListener("visibilitychange", r);
90
- }, [n, e, t, s]);
91
- const j = g(() => s(), [s]);
92
- return { sessionToken: c?.token ?? null, refreshSession: j };
95
+ }, [n, t, e, s]);
96
+ const P = D(() => s(), [s]);
97
+ return { sessionToken: u?.token ?? null, refreshSession: P };
93
98
  };
94
99
  export {
95
- Y as useAnonymousSession
100
+ G as useAnonymousSession
96
101
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react");function y(e,r){if(e===400&&typeof r=="object"&&r!==null){const t=(r.detail??"").toLowerCase();if(t.includes("challenge")||t.includes("proof-of-work"))return"pow"}if(e===401&&typeof r=="object"&&r!==null){const t=r.detail??"";if(t.includes("Invalid end-user JWT")||t.includes("Bearer token required"))return"session"}return null}function H(e){if(!e)return{};if(e instanceof Headers){const r={};return e.forEach((t,c)=>{r[c]=t}),r}return Array.isArray(e)?Object.fromEntries(e):e}function p(e,r,t,c){return{...e?{"x-inkeep-app-id":e}:{},...r?{Authorization:`Bearer ${r}`}:{},...H(c),...t}}function g({appId:e,authToken:r,getCaptchaHeader:t,invalidateCaptcha:c,refreshSession:R}){const a=u.useRef(e);a.current=e;const i=u.useRef(r);i.current=r;const o=u.useRef(t);o.current=t;const w=u.useRef(c);w.current=c;const h=u.useRef(R);return h.current=R,{fetchWithAuth:u.useCallback(async(l,s)=>{const C=await o.current(),j=p(a.current,i.current,C,s?.headers),n=await fetch(l,{...s,headers:j});if(n.status!==400&&n.status!==401)return n;let A;try{A=await n.clone().json()}catch{return n}const k=y(n.status,A);if(k==="pow"){w.current();const f=await o.current(),d=p(a.current,i.current,f,s?.headers);return fetch(l,{...s,headers:d})}if(k==="session"&&h.current){const f=await h.current();if(!f)return n;const d=await o.current(),E=p(a.current,f,d,s?.headers);return fetch(l,{...s,headers:E})}return n},[])}}exports.parseAuthError=y;exports.useInkeepApiClient=g;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react");function w(r,e){if(r===400&&typeof e=="object"&&e!==null){const t=(e.detail??"").toLowerCase();if(t.includes("challenge")||t.includes("bot protection")||t.includes("proof-of-work"))return"captcha"}if(r===401&&typeof e=="object"&&e!==null){const t=e.detail??"";if(t.includes("Invalid end-user JWT")||t.includes("Bearer token required"))return"session"}return r===403&&typeof e=="object"&&e!==null&&(e.detail??"").toLowerCase().includes("bot protection")?"captcha":null}function E(r){if(!r)return{};if(r instanceof Headers){const e={};return r.forEach((t,c)=>{e[c]=t}),e}return Array.isArray(r)?Object.fromEntries(r):r}function A(r,e,t,c){return{...r?{"x-inkeep-app-id":r}:{},...e?{Authorization:`Bearer ${e}`}:{},...E(c),...t}}function g({appId:r,authToken:e,getCaptchaHeader:t,invalidateCaptcha:c,refreshSession:i}){const o=u.useRef(r);o.current=r;const f=u.useRef(e);f.current=e;const j=u.useRef(t);j.current=t;const l=u.useRef(c);l.current=c;const a=u.useRef(i);return a.current=i,{fetchWithAuth:u.useCallback(async(d,s)=>{const k=A(o.current,f.current,{},s?.headers),n=await fetch(d,{...s,headers:k});if(n.status!==400&&n.status!==401&&n.status!==403)return n;let h;try{h=await n.clone().json()}catch{return n}const p=w(n.status,h);if(p==="captcha")return l.current(),n;if(p==="session"&&a.current){const R=await a.current();if(!R)return n;const C=A(o.current,R,{},s?.headers);return fetch(d,{...s,headers:C})}return n},[])}}exports.parseAuthError=w;exports.useInkeepApiClient=g;
@@ -15,10 +15,15 @@ interface UseInkeepApiClientOptions {
15
15
  * Parses an API error response body to determine the failure type.
16
16
  *
17
17
  * The Run API returns:
18
- * - 400 + detail containing "challenge" or "proof-of-work" PoW failure
19
- * - 401 + detail matching JWT/bearer messages → session token failure
18
+ * - 400 + detail containing "challenge" or "bot protection" captcha format failure
19
+ * - 401 + detail matching JWT/bearer messages → session token failure
20
+ * - 403 + detail containing "bot protection verification failed" → captcha rejected
21
+ * (Sentinel classified as bot OR payload was replayed)
22
+ *
23
+ * Legacy "proof-of-work" wording is still matched so older server versions are handled
24
+ * gracefully during the rolling deploy window.
20
25
  */
21
- export declare function parseAuthError(status: number, body: unknown): 'pow' | 'session' | null;
26
+ export declare function parseAuthError(status: number, body: unknown): 'captcha' | 'session' | null;
22
27
  /**
23
28
  * Returns a stable `fetchWithAuth` function that automatically:
24
29
  * - Injects auth headers (x-inkeep-app-id, Authorization, x-inkeep-challenge-solution)
@@ -1,87 +1,75 @@
1
1
  "use client";
2
- import { useRef as u, useCallback as y } from "react";
3
- function E(e, r) {
4
- if (e === 400 && typeof r == "object" && r !== null) {
5
- const t = (r.detail ?? "").toLowerCase();
6
- if (t.includes("challenge") || t.includes("proof-of-work")) return "pow";
2
+ import { useRef as s, useCallback as C } from "react";
3
+ function E(r, e) {
4
+ if (r === 400 && typeof e == "object" && e !== null) {
5
+ const t = (e.detail ?? "").toLowerCase();
6
+ if (t.includes("challenge") || t.includes("bot protection") || t.includes("proof-of-work"))
7
+ return "captcha";
7
8
  }
8
- if (e === 401 && typeof r == "object" && r !== null) {
9
- const t = r.detail ?? "";
9
+ if (r === 401 && typeof e == "object" && e !== null) {
10
+ const t = e.detail ?? "";
10
11
  if (t.includes("Invalid end-user JWT") || t.includes("Bearer token required"))
11
12
  return "session";
12
13
  }
13
- return null;
14
+ return r === 403 && typeof e == "object" && e !== null && (e.detail ?? "").toLowerCase().includes("bot protection") ? "captcha" : null;
14
15
  }
15
- function m(e) {
16
- if (!e) return {};
17
- if (e instanceof Headers) {
18
- const r = {};
19
- return e.forEach((t, c) => {
20
- r[c] = t;
21
- }), r;
16
+ function m(r) {
17
+ if (!r) return {};
18
+ if (r instanceof Headers) {
19
+ const e = {};
20
+ return r.forEach((t, c) => {
21
+ e[c] = t;
22
+ }), e;
22
23
  }
23
- return Array.isArray(e) ? Object.fromEntries(e) : e;
24
+ return Array.isArray(r) ? Object.fromEntries(r) : r;
24
25
  }
25
- function p(e, r, t, c) {
26
+ function A(r, e, t, c) {
26
27
  return {
27
- ...e ? { "x-inkeep-app-id": e } : {},
28
- ...r ? { Authorization: `Bearer ${r}` } : {},
28
+ ...r ? { "x-inkeep-app-id": r } : {},
29
+ ...e ? { Authorization: `Bearer ${e}` } : {},
29
30
  ...m(c),
30
31
  // captcha last — must not be overridden by caller headers
31
32
  ...t
32
33
  };
33
34
  }
34
- function x({
35
- appId: e,
36
- authToken: r,
35
+ function W({
36
+ appId: r,
37
+ authToken: e,
37
38
  getCaptchaHeader: t,
38
39
  invalidateCaptcha: c,
39
- refreshSession: w
40
+ refreshSession: i
40
41
  }) {
41
- const a = u(e);
42
- a.current = e;
43
- const i = u(r);
44
- i.current = r;
45
- const o = u(t);
46
- o.current = t;
47
- const A = u(c);
48
- A.current = c;
49
- const h = u(w);
50
- return h.current = w, { fetchWithAuth: y(async (d, s) => {
51
- const C = await o.current(), H = p(
52
- a.current,
53
- i.current,
54
- C,
55
- s?.headers
56
- ), n = await fetch(d, { ...s, headers: H });
57
- if (n.status !== 400 && n.status !== 401) return n;
58
- let R;
42
+ const o = s(r);
43
+ o.current = r;
44
+ const f = s(e);
45
+ f.current = e;
46
+ const R = s(t);
47
+ R.current = t;
48
+ const l = s(c);
49
+ l.current = c;
50
+ const a = s(i);
51
+ return a.current = i, { fetchWithAuth: C(async (h, u) => {
52
+ const j = A(o.current, f.current, {}, u?.headers), n = await fetch(h, { ...u, headers: j });
53
+ if (n.status !== 400 && n.status !== 401 && n.status !== 403) return n;
54
+ let d;
59
55
  try {
60
- R = await n.clone().json();
56
+ d = await n.clone().json();
61
57
  } catch {
62
58
  return n;
63
59
  }
64
- const k = E(n.status, R);
65
- if (k === "pow") {
66
- A.current();
67
- const f = await o.current(), l = p(
68
- a.current,
69
- i.current,
70
- f,
71
- s?.headers
72
- );
73
- return fetch(d, { ...s, headers: l });
74
- }
75
- if (k === "session" && h.current) {
76
- const f = await h.current();
77
- if (!f) return n;
78
- const l = await o.current(), j = p(a.current, f, l, s?.headers);
79
- return fetch(d, { ...s, headers: j });
60
+ const p = E(n.status, d);
61
+ if (p === "captcha")
62
+ return l.current(), n;
63
+ if (p === "session" && a.current) {
64
+ const w = await a.current();
65
+ if (!w) return n;
66
+ const k = A(o.current, w, {}, u?.headers);
67
+ return fetch(h, { ...u, headers: k });
80
68
  }
81
69
  return n;
82
70
  }, []) };
83
71
  }
84
72
  export {
85
73
  E as parseAuthError,
86
- x as useInkeepApiClient
74
+ W as useInkeepApiClient
87
75
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),t=require("react"),p=require("./config-provider.cjs"),n=t.createContext(void 0),g=({children:e})=>{const{baseSettings:s,componentType:o}=p.useInkeepConfig(),{tags:r,analyticsProperties:i}=s,c="0.16.5",a=t.useMemo(()=>({widgetLibraryVersion:c,componentType:o,tags:r}),[o,r,c]),v={logEvent:t.useCallback(async u=>{const E={...a,...u.properties,...i},d={eventName:u.eventName,properties:E};return s.onEvent?.(d)},[s,a,i])};return l.jsx(n.Provider,{value:v,children:e})},m=()=>{const e=t.useContext(n);if(!e)throw new Error("useBaseEvents must be used within a BaseEventsProvider");return e};exports.BaseEventsContext=n;exports.BaseEventsProvider=g;exports.useBaseEvents=m;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),t=require("react"),p=require("./config-provider.cjs"),n=t.createContext(void 0),g=({children:e})=>{const{baseSettings:s,componentType:o}=p.useInkeepConfig(),{tags:r,analyticsProperties:i}=s,c="0.17.1",a=t.useMemo(()=>({widgetLibraryVersion:c,componentType:o,tags:r}),[o,r,c]),v={logEvent:t.useCallback(async u=>{const E={...a,...u.properties,...i},d={eventName:u.eventName,properties:E};return s.onEvent?.(d)},[s,a,i])};return l.jsx(n.Provider,{value:v,children:e})},m=()=>{const e=t.useContext(n);if(!e)throw new Error("useBaseEvents must be used within a BaseEventsProvider");return e};exports.BaseEventsContext=n;exports.BaseEventsProvider=g;exports.useBaseEvents=m;
@@ -3,7 +3,7 @@ import { jsx as u } from "react/jsx-runtime";
3
3
  import { createContext as E, useMemo as d, useCallback as l, useContext as g } from "react";
4
4
  import { useInkeepConfig as x } from "./config-provider.js";
5
5
  const c = E(void 0), b = ({ children: e }) => {
6
- const { baseSettings: t, componentType: o } = x(), { tags: s, analyticsProperties: n } = t, r = "0.16.5", i = d(
6
+ const { baseSettings: t, componentType: o } = x(), { tags: s, analyticsProperties: n } = t, r = "0.17.1", i = d(
7
7
  () => ({
8
8
  widgetLibraryVersion: r,
9
9
  componentType: o,
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("react/jsx-runtime"),d=require("react"),T=require("./config-provider.cjs"),O=require("../components/modal/modal-provider.cjs"),m=require("./chat-bubble-provider.cjs"),x=require("./sidebar-chat-provider.cjs"),B=require("../hooks/use-auth-token.cjs"),R=require("../components/embedded-chat/use-captcha.cjs"),w=require("../hooks/use-anonymous-session.cjs"),l=d.createContext(void 0),I=({children:e})=>{const{baseSettings:n,aiChatSettings:p}=T.useInkeepConfig(),{shouldBypassCaptcha:C,privacyPreferences:A}=n,{baseUrl:i,appId:b,apiKey:s}=p,v=O.useModal(),f=m.useOptionalChatBubble(),g=x.useOptionalSidebarChat(),k=v?.isOpen??f?.isOpen??g?.isOpen??!0,{authToken:o,isLoading:a,refreshToken:q}=B.useAuthToken(),y=!!n.getAuthToken,t=!!o,{getCaptchaHeader:r,invalidate:u}=R.useCaptcha({baseUrl:i,shouldBypassCaptcha:C||!!s,shouldMakeInitialRequest:k}),{sessionToken:c,refreshSession:h}=w.useAnonymousSession({baseUrl:i,appId:b,getCaptchaHeader:r,invalidateCaptcha:u,optOutAllAnalytics:A?.optOutAllAnalytics,enabled:!t&&!a}),P={authToken:o,isAuthenticated:t,isAuthLoading:a,isAuthConfigured:y,refreshAuthToken:q,sessionToken:c,refreshSession:h,getCaptchaHeader:r,invalidateCaptcha:u,effectiveAuthToken:s??(t?o:c),applicableRefreshSession:s||t?void 0:h};return S.jsx(l.Provider,{value:P,children:e})},j=()=>{const e=d.useContext(l);if(!e)throw new Error("useChatAuth must be used within a ChatAuthProvider");return e};exports.ChatAuthProvider=I;exports.useChatAuth=j;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react/jsx-runtime"),d=require("react"),T=require("./config-provider.cjs"),S=require("../hooks/use-auth-token.cjs"),b=require("../components/embedded-chat/use-captcha.cjs"),P=require("../hooks/use-anonymous-session.cjs"),l=d.createContext(void 0),q=({children:e})=>{const{baseSettings:o,aiChatSettings:p}=T.useInkeepConfig(),{shouldBypassCaptcha:C,privacyPreferences:f}=o,{baseUrl:i,appId:u,apiKey:s}=p,{authToken:n,isLoading:a,refreshToken:v}=S.useAuthToken(),g=!!o.getAuthToken,t=!!n,{getCaptchaHeader:r,invalidate:c}=b.useCaptcha({baseUrl:i,appId:u,shouldBypassCaptcha:C||!!s}),{sessionToken:h,refreshSession:A}=P.useAnonymousSession({baseUrl:i,appId:u,getCaptchaHeader:r,invalidateCaptcha:c,optOutAllAnalytics:f?.optOutAllAnalytics,enabled:!t&&!a}),k={authToken:n,isAuthenticated:t,isAuthLoading:a,isAuthConfigured:g,refreshAuthToken:v,sessionToken:h,refreshSession:A,getCaptchaHeader:r,invalidateCaptcha:c,effectiveAuthToken:s??(t?n:h),applicableRefreshSession:s||t?void 0:A};return y.jsx(l.Provider,{value:k,children:e})},x=()=>{const e=d.useContext(l);if(!e)throw new Error("useChatAuth must be used within a ChatAuthProvider");return e};exports.ChatAuthProvider=q;exports.useChatAuth=x;
@@ -1,46 +1,43 @@
1
1
  "use client";
2
- import { jsx as T } from "react/jsx-runtime";
3
- import { useContext as y, createContext as S } from "react";
4
- import { useInkeepConfig as x } from "./config-provider.js";
5
- import { useModal as w } from "../components/modal/modal-provider.js";
6
- import { useOptionalChatBubble as B } from "./chat-bubble-provider.js";
7
- import { useOptionalSidebarChat as I } from "./sidebar-chat-provider.js";
8
- import { useAuthToken as P } from "../hooks/use-auth-token.js";
9
- import { useCaptcha as R } from "../components/embedded-chat/use-captcha.js";
10
- import { useAnonymousSession as L } from "../hooks/use-anonymous-session.js";
11
- const p = S(void 0), J = ({ children: t }) => {
12
- const { baseSettings: n, aiChatSettings: l } = x(), { shouldBypassCaptcha: d, privacyPreferences: f } = n, { baseUrl: i, appId: m, apiKey: o } = l, C = w(), A = B(), b = I(), v = C?.isOpen ?? A?.isOpen ?? b?.isOpen ?? !0, { authToken: s, isLoading: a, refreshToken: k } = P(), g = !!n.getAuthToken, e = !!s, { getCaptchaHeader: r, invalidate: u } = R({
2
+ import { jsx as k } from "react/jsx-runtime";
3
+ import { useContext as g, createContext as T } from "react";
4
+ import { useInkeepConfig as y } from "./config-provider.js";
5
+ import { useAuthToken as b } from "../hooks/use-auth-token.js";
6
+ import { useCaptcha as x } from "../components/embedded-chat/use-captcha.js";
7
+ import { useAnonymousSession as S } from "../hooks/use-anonymous-session.js";
8
+ const f = T(void 0), E = ({ children: t }) => {
9
+ const { baseSettings: n, aiChatSettings: l } = y(), { shouldBypassCaptcha: A, privacyPreferences: d } = n, { baseUrl: i, appId: a, apiKey: o } = l, { authToken: s, isLoading: r, refreshToken: C } = b(), m = !!n.getAuthToken, e = !!s, { getCaptchaHeader: h, invalidate: u } = x({
13
10
  baseUrl: i,
14
- shouldBypassCaptcha: d || !!o,
15
- shouldMakeInitialRequest: v
16
- }), { sessionToken: h, refreshSession: c } = L({
11
+ appId: a,
12
+ shouldBypassCaptcha: A || !!o
13
+ }), { sessionToken: c, refreshSession: p } = S({
17
14
  baseUrl: i,
18
- appId: m,
19
- getCaptchaHeader: r,
15
+ appId: a,
16
+ getCaptchaHeader: h,
20
17
  invalidateCaptcha: u,
21
- optOutAllAnalytics: f?.optOutAllAnalytics,
22
- enabled: !e && !a
23
- }), O = {
18
+ optOutAllAnalytics: d?.optOutAllAnalytics,
19
+ enabled: !e && !r
20
+ }), v = {
24
21
  authToken: s,
25
22
  isAuthenticated: e,
26
- isAuthLoading: a,
27
- isAuthConfigured: g,
28
- refreshAuthToken: k,
29
- sessionToken: h,
30
- refreshSession: c,
31
- getCaptchaHeader: r,
23
+ isAuthLoading: r,
24
+ isAuthConfigured: m,
25
+ refreshAuthToken: C,
26
+ sessionToken: c,
27
+ refreshSession: p,
28
+ getCaptchaHeader: h,
32
29
  invalidateCaptcha: u,
33
- effectiveAuthToken: o ?? (e ? s : h),
34
- applicableRefreshSession: o || e ? void 0 : c
30
+ effectiveAuthToken: o ?? (e ? s : c),
31
+ applicableRefreshSession: o || e ? void 0 : p
35
32
  };
36
- return /* @__PURE__ */ T(p.Provider, { value: O, children: t });
37
- }, N = () => {
38
- const t = y(p);
33
+ return /* @__PURE__ */ k(f.Provider, { value: v, children: t });
34
+ }, H = () => {
35
+ const t = g(f);
39
36
  if (!t)
40
37
  throw new Error("useChatAuth must be used within a ChatAuthProvider");
41
38
  return t;
42
39
  };
43
40
  export {
44
- J as ChatAuthProvider,
45
- N as useChatAuth
41
+ E as ChatAuthProvider,
42
+ H as useChatAuth
46
43
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("react/jsx-runtime"),u=require("react"),B=require("./config-provider.cjs"),O=require("./chat-auth-provider.cjs"),U=require("../hooks/use-events-api.cjs"),x=require("./base-events-provider.cjs"),M=({children:g})=>{const{baseSettings:n,aiChatSettings:h,componentType:i}=B.useInkeepConfig(),{tags:t,analyticsProperties:r,privacyPreferences:y,userProperties:o}=n,c="0.16.5",a=u.useMemo(()=>({widgetLibraryVersion:c,componentType:i}),[i,c]),{effectiveAuthToken:b,applicableRefreshSession:f,getCaptchaHeader:E,invalidateCaptcha:P}=O.useChatAuth(),{baseUrl:m,appId:A,analyticsApiBaseUrl:C,headers:I}=h,p=y?.optOutAllAnalytics??!1,{logEvent:l}=U.useEventsApi({baseUrl:C??m,appId:A,authToken:b,getCaptchaHeader:E,invalidateCaptcha:P,refreshSession:f,headers:I}),k={logEvent:u.useCallback(async s=>{const q={eventName:s.eventName,properties:{...a,...t?{tags:t}:{},...s.properties,...r}};if(!p){const e=s.properties??{},v=typeof e.conversationId=="string"?e.conversationId:void 0,d=typeof e.messageId=="string"?e.messageId:void 0,S=!!o&&Object.keys(o).length>0,w={...t?{tags:t}:{},...r??{}},T={...a,...s.properties};l({body:{type:s.eventName,...v?{conversationId:v}:{},...d?{messageId:d}:{},...S?{userProperties:o}:{},properties:w,metadata:T}})}try{return await n.onEvent?.(q)}catch(e){console.warn("[events] onEvent callback threw",e)}},[n,a,t,r,l,p,o])};return j.jsx(x.BaseEventsContext.Provider,{value:k,children:g})};exports.ChatBaseEventsProvider=M;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("react/jsx-runtime"),u=require("react"),B=require("./config-provider.cjs"),O=require("./chat-auth-provider.cjs"),U=require("../hooks/use-events-api.cjs"),x=require("./base-events-provider.cjs"),M=({children:g})=>{const{baseSettings:n,aiChatSettings:h,componentType:i}=B.useInkeepConfig(),{tags:t,analyticsProperties:r,privacyPreferences:y,userProperties:o}=n,c="0.17.1",a=u.useMemo(()=>({widgetLibraryVersion:c,componentType:i}),[i,c]),{effectiveAuthToken:b,applicableRefreshSession:f,getCaptchaHeader:E,invalidateCaptcha:P}=O.useChatAuth(),{baseUrl:m,appId:A,analyticsApiBaseUrl:C,headers:I}=h,p=y?.optOutAllAnalytics??!1,{logEvent:l}=U.useEventsApi({baseUrl:C??m,appId:A,authToken:b,getCaptchaHeader:E,invalidateCaptcha:P,refreshSession:f,headers:I}),k={logEvent:u.useCallback(async s=>{const q={eventName:s.eventName,properties:{...a,...t?{tags:t}:{},...s.properties,...r}};if(!p){const e=s.properties??{},v=typeof e.conversationId=="string"?e.conversationId:void 0,d=typeof e.messageId=="string"?e.messageId:void 0,S=!!o&&Object.keys(o).length>0,w={...t?{tags:t}:{},...r??{}},T={...a,...s.properties};l({body:{type:s.eventName,...v?{conversationId:v}:{},...d?{messageId:d}:{},...S?{userProperties:o}:{},properties:w,metadata:T}})}try{return await n.onEvent?.(q)}catch(e){console.warn("[events] onEvent callback threw",e)}},[n,a,t,r,l,p,o])};return j.jsx(x.BaseEventsContext.Provider,{value:k,children:g})};exports.ChatBaseEventsProvider=M;
@@ -6,7 +6,7 @@ import { useChatAuth as O } from "./chat-auth-provider.js";
6
6
  import { useEventsApi as j } from "../hooks/use-events-api.js";
7
7
  import { BaseEventsContext as M } from "./base-events-provider.js";
8
8
  const F = ({ children: m }) => {
9
- const { baseSettings: r, aiChatSettings: g, componentType: i } = N(), { tags: t, analyticsProperties: n, privacyPreferences: f, userProperties: o } = r, c = "0.16.5", a = x(
9
+ const { baseSettings: r, aiChatSettings: g, componentType: i } = N(), { tags: t, analyticsProperties: n, privacyPreferences: f, userProperties: o } = r, c = "0.17.1", a = x(
10
10
  () => ({
11
11
  widgetLibraryVersion: c,
12
12
  componentType: i
@@ -5,6 +5,31 @@ export interface InkeepEmbeddedSearchAndChatFunctions {
5
5
  setView: (view: ModalViewTypes) => void;
6
6
  }
7
7
  export interface InkeepEmbeddedSearchAndChatProps extends Partial<Omit<InkeepConfig, 'componentType'>>, WidgetView {
8
+ /**
9
+ * Callback fired when the user selects "Ask AI" — via the Ask AI card or the
10
+ * Search/Ask AI toggle.
11
+ *
12
+ * When provided, this replaces the default behavior of switching to the
13
+ * component's internal chat view. The internal chat pane is not shown and no
14
+ * message is submitted to it; instead the parent handles the Ask AI intent
15
+ * (for example, closing the modal and opening a separate sidebar chat).
16
+ *
17
+ * `query` is the current search input, so the parent can autofill or submit it
18
+ * in the destination chat.
19
+ *
20
+ * `autoSubmit` reflects the user's intent based on how they selected Ask AI:
21
+ * `true` when they clicked the Ask AI card (a query-specific action), and
22
+ * `false`/`undefined` when they used the Search/Ask AI toggle (a mode switch).
23
+ * Honor it to decide between auto-submitting and only filling in the query.
24
+ *
25
+ * Precedence: this takes full ownership of the Ask AI intent. When it is
26
+ * provided, `onToggleView` is NOT called for `view: 'chat'` selections and the
27
+ * internal view does not change. `onToggleView` still fires for `view: 'search'`.
28
+ */
29
+ onSelectAskAI?: (opts: {
30
+ query?: string;
31
+ autoSubmit?: boolean;
32
+ }) => void;
8
33
  /**
9
34
  * The default view to show when the widget is loaded.
10
35
  * @default 'search'
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),a=require("./utils.cjs");function p(f){const{defaultView:u="search",aiChatSettings:i,baseSettings:g,searchSettings:o,shouldAutoFocusInput:l=!0,onToggleView:h,ref:R,...S}=f,s=t.useRef(null),m=a.composeRefs(s,i?.chatFunctionsRef),r=t.useRef(null),d=a.composeRefs(r,o?.searchFunctionsRef),w={...i,chatFunctionsRef:m},I={...o,searchFunctionsRef:d},[n,c]=t.useState(u),b=e=>{e.autoSubmit&&e.query&&s.current?.submitMessage(e.query),h?.(e),c(e.view)};return t.useImperativeHandle(R,()=>({setView:c})),t.useEffect(()=>{n==="chat"?s.current?.focusInput():r.current?.focusInput()},[n]),{config:{baseSettings:g,aiChatSettings:w,searchSettings:I},defaultView:u,view:n,setView:c,onToggleView:b,shouldAutoFocusInput:l,...S}}exports.useWidgetImpl=p;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),f=require("./utils.cjs");function y(g){const{defaultView:c="search",aiChatSettings:i,baseSettings:l,searchSettings:o,shouldAutoFocusInput:h=!0,onToggleView:S,onSelectAskAI:r,ref:R,...m}=g,s=t.useRef(null),w=f.composeRefs(s,i?.chatFunctionsRef),a=t.useRef(null),b=f.composeRefs(a,o?.searchFunctionsRef),d={...i,chatFunctionsRef:w},I={...o,searchFunctionsRef:b},[n,u]=t.useState(c),q=e=>{if(e.view==="chat"&&r){r({query:e.query,autoSubmit:e.autoSubmit});return}e.autoSubmit&&e.query&&s.current?.submitMessage(e.query),S?.(e),u(e.view)};return t.useImperativeHandle(R,()=>({setView:u})),t.useEffect(()=>{n==="chat"?s.current?.focusInput():a.current?.focusInput()},[n]),{config:{baseSettings:l,aiChatSettings:d,searchSettings:I},defaultView:c,view:n,setView:u,onToggleView:q,shouldAutoFocusInput:h,...m}}exports.useWidgetImpl=y;
@@ -1,43 +1,48 @@
1
1
  "use client";
2
- import { useRef as r, useState as V, useImperativeHandle as d, useEffect as b } from "react";
3
- import { composeRefs as a } from "./utils.js";
4
- function _(f) {
2
+ import { useRef as a, useState as d, useImperativeHandle as q, useEffect as v } from "react";
3
+ import { composeRefs as f } from "./utils.js";
4
+ function T(g) {
5
5
  const {
6
6
  defaultView: c = "search",
7
- aiChatSettings: i,
8
- baseSettings: g,
9
- searchSettings: o,
10
- shouldAutoFocusInput: h = !0,
11
- onToggleView: l,
7
+ aiChatSettings: u,
8
+ baseSettings: h,
9
+ searchSettings: i,
10
+ shouldAutoFocusInput: l = !0,
11
+ onToggleView: S,
12
+ onSelectAskAI: o,
12
13
  ref: m,
13
- ...S
14
- } = f, t = r(null), R = a(t, i?.chatFunctionsRef), u = r(null), w = a(u, o?.searchFunctionsRef), p = {
15
- ...i,
14
+ ...w
15
+ } = g, t = a(null), R = f(t, u?.chatFunctionsRef), r = a(null), I = f(r, i?.searchFunctionsRef), b = {
16
+ ...u,
16
17
  chatFunctionsRef: R
17
18
  }, F = {
18
- ...o,
19
- searchFunctionsRef: w
20
- }, [n, s] = V(c), I = (e) => {
21
- e.autoSubmit && e.query && t.current?.submitMessage(e.query), l?.(e), s(e.view);
19
+ ...i,
20
+ searchFunctionsRef: I
21
+ }, [n, s] = d(c), V = (e) => {
22
+ if (e.view === "chat" && o) {
23
+ o({ query: e.query, autoSubmit: e.autoSubmit });
24
+ return;
25
+ }
26
+ e.autoSubmit && e.query && t.current?.submitMessage(e.query), S?.(e), s(e.view);
22
27
  };
23
- return d(m, () => ({
28
+ return q(m, () => ({
24
29
  setView: s
25
- })), b(() => {
26
- n === "chat" ? t.current?.focusInput() : u.current?.focusInput();
30
+ })), v(() => {
31
+ n === "chat" ? t.current?.focusInput() : r.current?.focusInput();
27
32
  }, [n]), {
28
33
  config: {
29
- baseSettings: g,
30
- aiChatSettings: p,
34
+ baseSettings: h,
35
+ aiChatSettings: b,
31
36
  searchSettings: F
32
37
  },
33
38
  defaultView: c,
34
39
  view: n,
35
40
  setView: s,
36
- onToggleView: I,
37
- shouldAutoFocusInput: h,
38
- ...S
41
+ onToggleView: V,
42
+ shouldAutoFocusInput: l,
43
+ ...w
39
44
  };
40
45
  }
41
46
  export {
42
- _ as useWidgetImpl
47
+ T as useWidgetImpl
43
48
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-ui",
3
- "version": "0.16.5",
3
+ "version": "0.17.1",
4
4
  "description": "",
5
5
  "homepage": "",
6
6
  "repository": {
@@ -72,7 +72,7 @@
72
72
  "@zag-js/react": "^1.38.1",
73
73
  "@zag-js/remove-scroll": "^1.38.1",
74
74
  "ai": "6.0.44",
75
- "altcha-lib": "^1.2.0",
75
+ "altcha": "^3.0.9",
76
76
  "aria-hidden": "^1.2.4",
77
77
  "class-variance-authority": "0.7.1",
78
78
  "clsx": "2.1.1",