@useago/sdk 0.3.4 → 0.4.2
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/AgoClient-D4EL6nva.cjs +6 -0
- package/dist/{AgoClient-DF7M2WAz.js → AgoClient-rvTz2thR.js} +239 -218
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +27 -0
- package/dist/angular.d.ts +27 -0
- package/dist/angular.js +1 -1
- package/dist/createConversationSession-D9FesBQS.js +58 -0
- package/dist/createConversationSession-DtaeA418.cjs +1 -0
- package/dist/createFormCollector-BwvkKi48.js +211 -0
- package/dist/createFormCollector-Wb8Rr-U2.cjs +1 -0
- package/dist/{createMockClient-C50gjV0b.js → createMockClient-DwdxNwEn.js} +5 -2
- package/dist/createMockClient-zHQ0cjUH.cjs +1 -0
- package/dist/devtools.cjs +5 -4
- package/dist/devtools.d.cts +31 -26
- package/dist/devtools.d.ts +31 -26
- package/dist/devtools.js +39 -35
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +44 -42
- package/dist/react.cjs +1 -1
- package/dist/react.d.cts +35 -0
- package/dist/react.d.ts +35 -0
- package/dist/react.js +4 -4
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +27 -0
- package/dist/vue.d.ts +27 -0
- package/dist/vue.js +1 -1
- package/dist/widget.cjs +1 -1
- package/dist/widget.d.cts +114 -0
- package/dist/widget.d.ts +114 -0
- package/dist/widget.js +170 -150
- package/package.json +58 -15
- package/dist/AgoClient-bjN-z2ZQ.cjs +0 -6
- package/dist/createFormCollector-ClzHfaBd.js +0 -185
- package/dist/createFormCollector-H4Me_2uj.cjs +0 -1
- package/dist/createMockClient-DQvFFWnc.cjs +0 -1
- /package/dist/{functions-CWSRi3xv.js → functions-C1-5vadY.js} +0 -0
- /package/dist/{functions-BH1X5kas.cjs → functions-DsmzgHjC.cjs} +0 -0
package/dist/vue.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-CaekUdDJ.cjs"),p=require("./AgoClient-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-CaekUdDJ.cjs"),p=require("./AgoClient-D4EL6nva.cjs");let t=require("vue");var I=Symbol("ago-client"),y={install(o,n){const e=new p.AgoClient(n);o.provide(I,e)}};function g(o){if(o)return new p.AgoClient(o);const n=(0,t.inject)(I);if(!n)throw new Error("useAgo(): no AgoClient found. Either pass config or install AgoPlugin.");return n}function E(o={}){const n=o.client??g(),e=(0,t.ref)([]),s=(0,t.ref)(o.conversationId),i=(0,t.ref)(!1),r=(0,t.ref)(null),c=a=>{s.value||(s.value=a.conversationId)},f=a=>{const u=e.value.findIndex(v=>v.id===a.messageId);u>=0&&(e.value[u]={...e.value[u],content:e.value[u].content+a.content})},m=a=>{const u=e.value.findIndex(v=>v.id===a.id);u>=0?e.value[u]=a:e.value.push(a),i.value=!1},C=a=>{r.value=new Error(a.error),i.value=!1};(0,t.onMounted)(()=>{n.on("message:start",c),n.on("message:chunk",f),n.on("message:complete",m),n.on("message:error",C)}),(0,t.onUnmounted)(()=>{n.off("message:start",c),n.off("message:chunk",f),n.off("message:complete",m),n.off("message:error",C)});async function d(a,u){i.value=!0,r.value=null;const v={id:`temp-${Date.now()}`,conversationId:s.value||"",content:a,role:"user",status:"DONE",createdAt:new Date},L={id:`temp-assistant-${Date.now()}`,conversationId:s.value||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date};e.value.push(v,L);try{const l=await n.sendMessage(a,{conversationId:s.value,files:u});l.conversationId&&!s.value&&(s.value=l.conversationId),e.value=e.value.filter(w=>!w.id.startsWith("temp-"));const A={...v,id:v.id.replace("temp-","user-"),conversationId:l.conversationId};return e.value.some(w=>w.id===l.id)?e.value.push(A):e.value.push(A,l),l}catch(l){return r.value=l instanceof Error?l:new Error("Failed to send"),i.value=!1,e.value=e.value.filter(A=>!A.id.startsWith("temp-")),null}}function h(){e.value=[],s.value=void 0,r.value=null}return{messages:e,isLoading:i,error:r,conversationId:s,sendMessage:d,clearMessages:h}}function M(o={}){const n=o.client??g(),e=o.autoLoad??!0,s=(0,t.ref)([]),i=(0,t.ref)(null),r=(0,t.ref)(!1),c=(0,t.ref)(null);async function f(){r.value=!0,c.value=null;try{s.value=await n.getConversations()}catch(d){c.value=d instanceof Error?d:new Error("Failed to load conversations")}finally{r.value=!1}}async function m(d){r.value=!0,c.value=null;try{i.value=await n.getConversation(d)}catch(h){c.value=h instanceof Error?h:new Error("Failed to load conversation")}finally{r.value=!1}}function C(){i.value=null}return(0,t.onMounted)(()=>{e&&f()}),{conversations:s,currentConversation:i,isLoading:r,error:c,selectConversation:m,startNewConversation:C,refreshConversations:f}}function N(o={}){const n=E({client:o.client,conversationId:o.conversationId}),e=M({client:o.client,autoLoad:o.autoLoad}),s=(0,t.computed)(()=>n.error.value||e.error.value);return{messages:n.messages,isLoading:n.isLoading,error:s,sendMessage:n.sendMessage,clearMessages:n.clearMessages,conversationId:n.conversationId,conversations:e.conversations,currentConversation:e.currentConversation,isConversationsLoading:e.isLoading,selectConversation:e.selectConversation,startNewConversation:e.startNewConversation,refreshConversations:e.refreshConversations}}function F(o,n){const e=g();(0,t.onMounted)(()=>{e.registerFunction(o,n.handler,{description:n.description,parameters:n.parameters})}),(0,t.onUnmounted)(()=>{e.unregisterFunction(o)})}function S(o,n){const e=g();(0,t.onMounted)(()=>{e.registerNavigationFunction(o,n)}),(0,t.onUnmounted)(()=>{e.unregisterFunction("navigateToPage")})}function _(o,n){const e=g();(0,t.onMounted)(()=>{e.on(o,n)}),(0,t.onUnmounted)(()=>{e.off(o,n)})}function D(o){const n=(0,t.shallowRef)(o.get());return(0,t.onScopeDispose)(o.subscribe(e=>{n.value=e})),n}exports.AGO_CLIENT_KEY=I;exports.AgoPlugin=y;exports.useAgo=g;exports.useAgoEvents=_;exports.useAgoFunction=F;exports.useAgoNavigation=S;exports.useAgoStore=D;exports.useChat=N;exports.useConversation=M;exports.useMessages=E;
|
package/dist/vue.d.cts
CHANGED
|
@@ -39,6 +39,12 @@ declare class AgoClient {
|
|
|
39
39
|
* Get a specific conversation with messages
|
|
40
40
|
*/
|
|
41
41
|
getConversation(conversationId: string): Promise<Conversation>;
|
|
42
|
+
/**
|
|
43
|
+
* Map the backend's snake_case `tool_call_data` entries onto the camelCase
|
|
44
|
+
* {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
|
|
45
|
+
* `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
|
|
46
|
+
*/
|
|
47
|
+
private static mapPersistedToolCalls;
|
|
42
48
|
/**
|
|
43
49
|
* Get messages for a conversation
|
|
44
50
|
*/
|
|
@@ -149,6 +155,13 @@ declare class AgoClient {
|
|
|
149
155
|
* Remove a dynamic context provider.
|
|
150
156
|
*/
|
|
151
157
|
removeDynamicContext(key: string): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Broadcast that the client-side context changed by emitting `context:changed`
|
|
160
|
+
* with the fresh snapshot. The context-mutating methods call this automatically;
|
|
161
|
+
* stateful helpers whose context lives in a store (e.g. `createFormCollector`)
|
|
162
|
+
* call it when their store updates so observers like the dev panel stay live.
|
|
163
|
+
*/
|
|
164
|
+
notifyContextChanged(): void;
|
|
152
165
|
/**
|
|
153
166
|
* Enable automatic capture of the current browser page (URL + title).
|
|
154
167
|
* Injected as a dynamic context entry named `browser-page`.
|
|
@@ -194,6 +207,14 @@ declare class AgoClient {
|
|
|
194
207
|
* SDK Events
|
|
195
208
|
*/
|
|
196
209
|
declare interface AgoClientEvents {
|
|
210
|
+
/**
|
|
211
|
+
* The client-side context changed: a context entry or dynamic provider was
|
|
212
|
+
* added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
|
|
213
|
+
* store. Carries the fresh snapshot so observers — notably the dev panel — can
|
|
214
|
+
* repaint without waiting for the next message. Fires for the form collector's
|
|
215
|
+
* initial install too, so its missing fields show from the start of a conversation.
|
|
216
|
+
*/
|
|
217
|
+
"context:changed": ContextSnapshot | null;
|
|
197
218
|
"message:start": {
|
|
198
219
|
conversationId: string;
|
|
199
220
|
messageId: string;
|
|
@@ -209,6 +230,12 @@ declare interface AgoClientEvents {
|
|
|
209
230
|
conversationId?: string;
|
|
210
231
|
messageId?: string;
|
|
211
232
|
};
|
|
233
|
+
/**
|
|
234
|
+
* A full conversation was loaded from the server (e.g. after a page reload).
|
|
235
|
+
* Carries the messages and their persisted tool calls so stateful helpers —
|
|
236
|
+
* notably `createFormCollector` — can replay them to restore their state.
|
|
237
|
+
*/
|
|
238
|
+
"conversation:loaded": Conversation;
|
|
212
239
|
"toolCall:received": ToolCallData;
|
|
213
240
|
"toolCall:form": ToolCallData;
|
|
214
241
|
"function:invoke": ClientFunctionInvocation;
|
package/dist/vue.d.ts
CHANGED
|
@@ -39,6 +39,12 @@ declare class AgoClient {
|
|
|
39
39
|
* Get a specific conversation with messages
|
|
40
40
|
*/
|
|
41
41
|
getConversation(conversationId: string): Promise<Conversation>;
|
|
42
|
+
/**
|
|
43
|
+
* Map the backend's snake_case `tool_call_data` entries onto the camelCase
|
|
44
|
+
* {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
|
|
45
|
+
* `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
|
|
46
|
+
*/
|
|
47
|
+
private static mapPersistedToolCalls;
|
|
42
48
|
/**
|
|
43
49
|
* Get messages for a conversation
|
|
44
50
|
*/
|
|
@@ -149,6 +155,13 @@ declare class AgoClient {
|
|
|
149
155
|
* Remove a dynamic context provider.
|
|
150
156
|
*/
|
|
151
157
|
removeDynamicContext(key: string): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Broadcast that the client-side context changed by emitting `context:changed`
|
|
160
|
+
* with the fresh snapshot. The context-mutating methods call this automatically;
|
|
161
|
+
* stateful helpers whose context lives in a store (e.g. `createFormCollector`)
|
|
162
|
+
* call it when their store updates so observers like the dev panel stay live.
|
|
163
|
+
*/
|
|
164
|
+
notifyContextChanged(): void;
|
|
152
165
|
/**
|
|
153
166
|
* Enable automatic capture of the current browser page (URL + title).
|
|
154
167
|
* Injected as a dynamic context entry named `browser-page`.
|
|
@@ -194,6 +207,14 @@ declare class AgoClient {
|
|
|
194
207
|
* SDK Events
|
|
195
208
|
*/
|
|
196
209
|
declare interface AgoClientEvents {
|
|
210
|
+
/**
|
|
211
|
+
* The client-side context changed: a context entry or dynamic provider was
|
|
212
|
+
* added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
|
|
213
|
+
* store. Carries the fresh snapshot so observers — notably the dev panel — can
|
|
214
|
+
* repaint without waiting for the next message. Fires for the form collector's
|
|
215
|
+
* initial install too, so its missing fields show from the start of a conversation.
|
|
216
|
+
*/
|
|
217
|
+
"context:changed": ContextSnapshot | null;
|
|
197
218
|
"message:start": {
|
|
198
219
|
conversationId: string;
|
|
199
220
|
messageId: string;
|
|
@@ -209,6 +230,12 @@ declare interface AgoClientEvents {
|
|
|
209
230
|
conversationId?: string;
|
|
210
231
|
messageId?: string;
|
|
211
232
|
};
|
|
233
|
+
/**
|
|
234
|
+
* A full conversation was loaded from the server (e.g. after a page reload).
|
|
235
|
+
* Carries the messages and their persisted tool calls so stateful helpers —
|
|
236
|
+
* notably `createFormCollector` — can replay them to restore their state.
|
|
237
|
+
*/
|
|
238
|
+
"conversation:loaded": Conversation;
|
|
212
239
|
"toolCall:received": ToolCallData;
|
|
213
240
|
"toolCall:form": ToolCallData;
|
|
214
241
|
"function:invoke": ClientFunctionInvocation;
|
package/dist/vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as A } from "./AgoClient-
|
|
1
|
+
import { t as A } from "./AgoClient-rvTz2thR.js";
|
|
2
2
|
import { computed as y, inject as F, onMounted as g, onScopeDispose as N, onUnmounted as I, ref as c, shallowRef as D } from "vue";
|
|
3
3
|
var L = /* @__PURE__ */ Symbol("ago-client"), b = { install(t, n) {
|
|
4
4
|
const e = new A(n);
|
package/dist/widget.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const X=require("./AgoClient-bjN-z2ZQ.cjs"),Z=require("./createFormCollector-H4Me_2uj.cjs");var q='"IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function x(s,o){Object.assign(s.style,o)}function c(s={}){const o=document.createElement("div");return x(o,s),o}var P="ago-chat-widget-keyframes";function ee(){if(typeof document>"u"||document.getElementById(P))return;const s=document.createElement("style");s.id=P,s.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(s)}function te(s){const o=typeof s=="string"?document.querySelector(s):s;if(!o)throw new Error(`mountChatWidget: target "${String(s)}" not found.`);return o}function ne(s,o){const{title:y="Chat",welcomeMessage:I="Hello! How can I help you today?",placeholder:R="Type a message...",allowFiles:u=!1,height:g=500,logoUrl:f,showAgentName:b=!1,forms:_,onFollowUpClick:k,onMessageSent:D,onMessageReceived:l}=o;if(!o.client&&!o.config?.baseUrl)throw new Error("mountChatWidget requires either `client` or `config` (with a baseUrl).");const i=o.client??new X.AgoClient(o.config),W=te(s);let m=o.conversationId,n=[],w=!1,v=null;const N=c({display:"flex",flexDirection:"column",height:typeof g=="number"?`${g}px`:g,border:"1px solid #dee3e8",borderRadius:"16px",overflow:"hidden",backgroundColor:"#fff",fontFamily:q,boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});N.className="ago-chat-widget";const z=c({padding:"14px 16px",borderBottom:"1px solid #dee3e8",backgroundColor:"#03182f",color:"#e8f0fe",display:"flex",alignItems:"center",gap:"10px"});if(z.className="ago-chat-widget__header",f){const e=document.createElement("img");e.src=f,e.alt="Logo",x(e,{height:"24px",width:"auto"}),z.appendChild(e)}const F=document.createElement("h3");F.textContent=y,x(F,{margin:"0",fontSize:"15px",fontWeight:"600"}),z.appendChild(F);const E=c({flex:"1",overflow:"auto",padding:"16px",backgroundColor:"#fbfbfb"});E.className="ago-chat-widget__messages";const{inputRow:G,setDisabled:j,focus:K}=oe({placeholder:R,allowFiles:u,onSend:(e,t)=>{M(e,t)}});ee(),N.append(z,E,G),W.appendChild(N);const A=k!==!1,U=k===!1?void 0:k??(e=>{M(e)});function V(e){const t=e.role==="user",d=c({display:"flex",flexDirection:"column",alignItems:t?"flex-end":"flex-start",marginBottom:"16px"});if(d.className=`ago-message ago-message--${e.role}`,!t&&b&&e.agent){const a=c({fontSize:"13px",fontWeight:"500",color:"#30373e",marginBottom:"6px",padding:"0 4px"});a.className="ago-message__agent",a.textContent=e.agent.displayName||e.agent.name,d.appendChild(a)}if(!t&&e.sources&&e.sources.length>0){const a=c({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});a.className="ago-message__sources",e.sources.forEach((p,r)=>{const C=p.url?document.createElement("a"):document.createElement("div");p.url&&C instanceof HTMLAnchorElement&&(C.href=p.url,C.target="_blank",C.rel="noopener noreferrer"),x(C,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:"1px solid #dee3e8",borderRadius:"8px",backgroundColor:"#fff",textDecoration:"none",color:"#30373e",fontSize:"12px",overflow:"hidden"});const $=c({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:"1px solid #1b5fc4",color:"#1b5fc4",fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});$.textContent=String(r+1);const L=c({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});L.textContent=p.title,L.title=p.title,C.append($,L),a.appendChild(C)}),d.appendChild(a)}const h=c({maxWidth:t?"75%":"100%",padding:t?"10px 14px":"2px 8px",borderRadius:t?"16px":"0",backgroundColor:t?"#03182f":"transparent",color:t?"#fff":"#30373e",wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6",whiteSpace:"pre-wrap"});if(h.className="ago-message__content",e.content?h.textContent=e.content:e.status==="IN_PROGRESS"&&h.appendChild(Q()),d.appendChild(h),e.followUpReplies&&e.followUpReplies.length>0){const a=c({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});a.className="ago-message__followups";for(const p of e.followUpReplies){const r=document.createElement("button");r.type="button",r.className="ago-message__followup-btn",r.textContent=p,r.disabled=!A,x(r,{padding:"6px 14px",fontSize:"13px",borderRadius:"16px",border:"1px solid #dee3e8",backgroundColor:"#fff",color:"#30373e",cursor:A?"pointer":"default",transition:"border-color 0.15s"}),U&&r.addEventListener("click",()=>U(p)),r.addEventListener("mouseenter",()=>{r.style.borderColor="#1b5fc4"}),r.addEventListener("mouseleave",()=>{r.style.borderColor="#dee3e8"}),a.appendChild(r)}d.appendChild(a)}return d}function S(){if(E.replaceChildren(),n.length===0){const e=c({textAlign:"center",color:"#6b6d6f",padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});e.textContent=I,E.appendChild(e)}else for(const e of n)E.appendChild(V(e));if(v){const e=c({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});e.textContent=v,E.appendChild(e)}E.scrollTop=E.scrollHeight,j(w)}function Y(){for(let e=n.length-1;e>=0;e--){const t=n[e];if(t.role==="assistant"&&t.status==="IN_PROGRESS")return t}}const B=e=>{m||(m=e.conversationId)},H=e=>{const t=Y();t&&(t.content+=e.content,S())},O=e=>{const t=n.findIndex(d=>d.id===e.id||d.role==="assistant"&&d.status==="IN_PROGRESS");t>=0?n[t]=e:n.push(e),w=!1,S(),e.status==="DONE"&&l?.({id:e.id,content:e.content})},T=e=>{v=e.error,w=!1,n=n.filter(t=>!t.id.startsWith("temp-")),S()};i.on("message:start",B),i.on("message:chunk",H),i.on("message:complete",O),i.on("message:error",T);const J=(_??[]).map(e=>Z.createFormCollector(e).install(i));async function M(e,t){const d=e.trim();if(!d&&!t?.length||w)return;D?.(d),w=!0,v=null;const h=Date.now();n.push({id:`temp-user-${h}`,conversationId:m||"",content:d,role:"user",status:"DONE",createdAt:new Date}),n.push({id:`temp-assistant-${h}`,conversationId:m||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),S();try{const a=await i.sendMessage(d,{conversationId:m,files:t});a.conversationId&&!m&&(m=a.conversationId);const p=n.find(r=>r.id===`temp-user-${h}`);if(p&&(p.id=`user-${h}`,p.conversationId=a.conversationId),!n.some(r=>r.id===a.id)){const r=n.findIndex(C=>C.id===`temp-assistant-${h}`);r>=0?n[r]=a:n.push(a)}n=n.filter(r=>!r.id.startsWith("temp-")),w=!1,S()}catch(a){v=a instanceof Error?a.message:"Failed to send message",w=!1,n=n.filter(p=>!p.id.startsWith("temp-")),S()}}return S(),K(),{client:i,element:N,sendMessage:M,destroy(){i.off("message:start",B),i.off("message:chunk",H),i.off("message:complete",O),i.off("message:error",T),J.forEach(e=>e()),N.remove(),o.client||i.destroy()}};function Q(){const e=c({display:"flex",gap:"4px",padding:"4px 0"});for(let t=0;t<3;t++){const d=c({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${t*.2}s`});e.appendChild(d)}return e}}function oe(s){let o=[];const y=document.createElement("form");x(y,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:"1px solid #dee3e8",backgroundColor:"#fff"}),y.className="ago-chat-input";const I=c({display:"flex",flexWrap:"wrap",gap:"6px"}),R=c({display:"flex",gap:"8px",alignItems:"flex-end"}),u=document.createElement("textarea");u.placeholder=s.placeholder,u.rows=1,x(u,{flex:"1",resize:"none",padding:"10px 12px",border:"1px solid #dee3e8",borderRadius:"12px",fontSize:"14px",fontFamily:q,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const g=document.createElement("button");g.type="submit",g.textContent="Send",x(g,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:"#03182f",color:"#fff",fontSize:"14px",fontWeight:"500",cursor:"pointer"});let f=null,b=null;s.allowFiles&&(f=document.createElement("input"),f.type="file",f.multiple=!0,x(f,{display:"none"}),b=document.createElement("button"),b.type="button",b.textContent="📎",x(b,{padding:"10px 12px",border:"1px solid #dee3e8",borderRadius:"12px",backgroundColor:"#fff",cursor:"pointer",fontSize:"14px"}),b.addEventListener("click",()=>f?.click()),f.addEventListener("change",()=>{o=[...o,...Array.from(f?.files??[])],_()}));function _(){I.replaceChildren(),o.forEach((l,i)=>{const W=c({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:"1px solid #dee3e8",borderRadius:"8px",fontSize:"12px"}),m=document.createElement("span");m.textContent=l.name;const n=document.createElement("button");n.type="button",n.textContent="×",x(n,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),n.addEventListener("click",()=>{o=o.filter((w,v)=>v!==i),_()}),W.append(m,n),I.appendChild(W)})}const k=()=>{const l=u.value,i=o;return u.value="",o=[],_(),{content:l,files:i}},D=()=>{const{content:l,files:i}=k();(l.trim()||i.length>0)&&s.onSend(l.trim(),i.length>0?i:void 0)};return y.addEventListener("submit",l=>{l.preventDefault(),D()}),u.addEventListener("keydown",l=>{l.key==="Enter"&&!l.shiftKey&&(l.preventDefault(),D())}),b&&R.appendChild(b),R.append(u,g),f&&y.appendChild(f),y.append(I,R),{inputRow:y,getValueAndClear:k,setDisabled:l=>{u.disabled=l,g.disabled=l,g.style.opacity=l?"0.6":"1",g.style.cursor=l?"not-allowed":"pointer"},focus:()=>u.focus()}}exports.mountChatWidget=ne;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const re=require("./AgoClient-D4EL6nva.cjs"),ae=require("./createFormCollector-Wb8Rr-U2.cjs"),ie=require("./createConversationSession-DtaeA418.cjs");var Y='"IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function m(s,n){Object.assign(s.style,n)}function c(s={}){const n=document.createElement("div");return m(n,s),n}var V="ago-chat-widget-keyframes";function se(){if(typeof document>"u"||document.getElementById(V))return;const s=document.createElement("style");s.id=V,s.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(s)}function le(s){const n=typeof s=="string"?document.querySelector(s):s;if(!n)throw new Error(`mountChatWidget: target "${String(s)}" not found.`);return n}function de(s,n){const{title:v="Chat",welcomeMessage:_="Hello! How can I help you today?",placeholder:N="Type a message...",allowFiles:g=!1,height:x=500,logoUrl:f,showAgentName:b=!1,loadThreads:I=!1,forms:A,onFollowUpClick:R,onMessageSent:i,onMessageReceived:C}=n;if(!n.client&&!n.config?.baseUrl)throw new Error("mountChatWidget requires either `client` or `config` (with a baseUrl).");const l=n.client??new re.AgoClient(n.config),T=le(s),y=n.persistConversation,D=y?ie.createConversationSession(y===!0?{}:y):void 0;let u=n.conversationId??D?.getLastActiveThread()??void 0,o=[],k=!1,W=null;const F=[],z=c({display:"flex",flexDirection:"column",height:typeof x=="number"?`${x}px`:x,border:"1px solid #dee3e8",borderRadius:"16px",overflow:"hidden",backgroundColor:"#fff",fontFamily:Y,boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});z.className="ago-chat-widget";const L=c({padding:"14px 16px",borderBottom:"1px solid #dee3e8",backgroundColor:"#03182f",color:"#e8f0fe",display:"flex",alignItems:"center",gap:"10px"});if(L.className="ago-chat-widget__header",f){const e=document.createElement("img");e.src=f,e.alt="Logo",m(e,{height:"24px",width:"auto"}),L.appendChild(e)}const M=document.createElement("h3");M.textContent=v,m(M,{margin:"0",fontSize:"15px",fontWeight:"600"}),L.appendChild(M);const E=c({flex:"1",overflow:"auto",padding:"16px",backgroundColor:"#fbfbfb"});E.className="ago-chat-widget__messages";const{inputRow:J,setDisabled:Q,focus:X}=ce({placeholder:N,allowFiles:g,onSend:(e,t)=>{H(e,t)}});se(),z.append(L,E,J),T.appendChild(z);const O=R!==!1,$=R===!1?void 0:R??(e=>{H(e)});function Z(e){const t=e.role==="user",d=c({display:"flex",flexDirection:"column",alignItems:t?"flex-end":"flex-start",marginBottom:"16px"});if(d.className=`ago-message ago-message--${e.role}`,!t&&b&&e.agent){const r=c({fontSize:"13px",fontWeight:"500",color:"#30373e",marginBottom:"6px",padding:"0 4px"});r.className="ago-message__agent",r.textContent=e.agent.displayName||e.agent.name,d.appendChild(r)}if(!t&&e.sources&&e.sources.length>0){const r=c({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});r.className="ago-message__sources",e.sources.forEach((p,a)=>{const w=p.url?document.createElement("a"):document.createElement("div");p.url&&w instanceof HTMLAnchorElement&&(w.href=p.url,w.target="_blank",w.rel="noopener noreferrer"),m(w,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:"1px solid #dee3e8",borderRadius:"8px",backgroundColor:"#fff",textDecoration:"none",color:"#30373e",fontSize:"12px",overflow:"hidden"});const K=c({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:"1px solid #1b5fc4",color:"#1b5fc4",fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});K.textContent=String(a+1);const B=c({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});B.textContent=p.title,B.title=p.title,w.append(K,B),r.appendChild(w)}),d.appendChild(r)}const h=c({maxWidth:t?"75%":"100%",padding:t?"10px 14px":"2px 8px",borderRadius:t?"16px":"0",backgroundColor:t?"#03182f":"transparent",color:t?"#fff":"#30373e",wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6",whiteSpace:"pre-wrap"});if(h.className="ago-message__content",e.content?h.textContent=e.content:e.status==="IN_PROGRESS"&&h.appendChild(oe()),d.appendChild(h),e.followUpReplies&&e.followUpReplies.length>0){const r=c({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});r.className="ago-message__followups";for(const p of e.followUpReplies){const a=document.createElement("button");a.type="button",a.className="ago-message__followup-btn",a.textContent=p,a.disabled=!O,m(a,{padding:"6px 14px",fontSize:"13px",borderRadius:"16px",border:"1px solid #dee3e8",backgroundColor:"#fff",color:"#30373e",cursor:O?"pointer":"default",transition:"border-color 0.15s"}),$&&a.addEventListener("click",()=>$(p)),a.addEventListener("mouseenter",()=>{a.style.borderColor="#1b5fc4"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="#dee3e8"}),r.appendChild(a)}d.appendChild(r)}return d}function S(){if(E.replaceChildren(),o.length===0){const e=c({textAlign:"center",color:"#6b6d6f",padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});e.textContent=_,E.appendChild(e)}else for(const e of o)E.appendChild(Z(e));if(W){const e=c({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});e.textContent=W,E.appendChild(e)}E.scrollTop=E.scrollHeight,Q(k)}function ee(){for(let e=o.length-1;e>=0;e--){const t=o[e];if(t.role==="assistant"&&t.status==="IN_PROGRESS")return t}}const q=e=>{u||(u=e.conversationId)},P=e=>{const t=ee();t&&(t.content+=e.content,S())},G=e=>{const t=o.findIndex(d=>d.id===e.id||d.role==="assistant"&&d.status==="IN_PROGRESS");t>=0?o[t]=e:o.push(e),k=!1,S(),e.status==="DONE"&&C?.({id:e.id,content:e.content})},j=e=>{W=e.error,k=!1,o=o.filter(t=>!t.id.startsWith("temp-")),S()};l.on("message:start",q),l.on("message:chunk",P),l.on("message:complete",G),l.on("message:error",j);const te=(A??[]).map(e=>ae.createFormCollector(e).install(l));async function H(e,t){const d=e.trim();if(!d&&!t?.length||k)return;i?.(d),k=!0,W=null;const h=Date.now();o.push({id:`temp-user-${h}`,conversationId:u||"",content:d,role:"user",status:"DONE",createdAt:new Date}),o.push({id:`temp-assistant-${h}`,conversationId:u||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),S();try{const r=await l.sendMessage(d,{conversationId:u,files:t});r.conversationId&&(u||(u=r.conversationId),D?.setActiveThread(r.conversationId,r.createdAt));const p=o.find(a=>a.id===`temp-user-${h}`);if(p&&(p.id=`user-${h}`,p.conversationId=r.conversationId),!o.some(a=>a.id===r.id)){const a=o.findIndex(w=>w.id===`temp-assistant-${h}`);a>=0?o[a]=r:o.push(r)}o=o.filter(a=>!a.id.startsWith("temp-")),k=!1,S(),I&&U()}catch(r){W=r instanceof Error?r.message:"Failed to send message",k=!1,o=o.filter(p=>!p.id.startsWith("temp-")),S()}}async function U(){try{const e=await l.getConversations();F.splice(0,F.length,...e)}catch{}return F}async function ne(e){try{const t=(await l.getConversation(e))?.messages??[];t.length>0&&o.length===0&&(o=t,S())}catch{o.length===0&&(D?.clear(),u=void 0)}}return S(),X(),u&&ne(u),I&&U(),{client:l,element:z,sendMessage:H,session:D,threads:F,refreshThreads:U,destroy(){l.off("message:start",q),l.off("message:chunk",P),l.off("message:complete",G),l.off("message:error",j),te.forEach(e=>e()),z.remove(),n.client||l.destroy()}};function oe(){const e=c({display:"flex",gap:"4px",padding:"4px 0"});for(let t=0;t<3;t++){const d=c({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${t*.2}s`});e.appendChild(d)}return e}}function ce(s){let n=[];const v=document.createElement("form");m(v,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:"1px solid #dee3e8",backgroundColor:"#fff"}),v.className="ago-chat-input";const _=c({display:"flex",flexWrap:"wrap",gap:"6px"}),N=c({display:"flex",gap:"8px",alignItems:"flex-end"}),g=document.createElement("textarea");g.placeholder=s.placeholder,g.rows=1,m(g,{flex:"1",resize:"none",padding:"10px 12px",border:"1px solid #dee3e8",borderRadius:"12px",fontSize:"14px",fontFamily:Y,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const x=document.createElement("button");x.type="submit",x.textContent="Send",m(x,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:"#03182f",color:"#fff",fontSize:"14px",fontWeight:"500",cursor:"pointer"});let f=null,b=null;s.allowFiles&&(f=document.createElement("input"),f.type="file",f.multiple=!0,m(f,{display:"none"}),b=document.createElement("button"),b.type="button",b.textContent="📎",m(b,{padding:"10px 12px",border:"1px solid #dee3e8",borderRadius:"12px",backgroundColor:"#fff",cursor:"pointer",fontSize:"14px"}),b.addEventListener("click",()=>f?.click()),f.addEventListener("change",()=>{n=[...n,...Array.from(f?.files??[])],I()}));function I(){_.replaceChildren(),n.forEach((i,C)=>{const l=c({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:"1px solid #dee3e8",borderRadius:"8px",fontSize:"12px"}),T=document.createElement("span");T.textContent=i.name;const y=document.createElement("button");y.type="button",y.textContent="×",m(y,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),y.addEventListener("click",()=>{n=n.filter((D,u)=>u!==C),I()}),l.append(T,y),_.appendChild(l)})}const A=()=>{const i=g.value,C=n;return g.value="",n=[],I(),{content:i,files:C}},R=()=>{const{content:i,files:C}=A();(i.trim()||C.length>0)&&s.onSend(i.trim(),C.length>0?C:void 0)};return v.addEventListener("submit",i=>{i.preventDefault(),R()}),g.addEventListener("keydown",i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),R())}),b&&N.appendChild(b),N.append(g,x),f&&v.appendChild(f),v.append(_,N),{inputRow:v,getValueAndClear:A,setDisabled:i=>{g.disabled=i,x.disabled=i,x.style.opacity=i?"0.6":"1",x.style.cursor=i?"not-allowed":"pointer"},focus:()=>g.focus()}}exports.mountChatWidget=de;
|
package/dist/widget.d.cts
CHANGED
|
@@ -31,6 +31,12 @@ declare class AgoClient {
|
|
|
31
31
|
* Get a specific conversation with messages
|
|
32
32
|
*/
|
|
33
33
|
getConversation(conversationId: string): Promise<Conversation>;
|
|
34
|
+
/**
|
|
35
|
+
* Map the backend's snake_case `tool_call_data` entries onto the camelCase
|
|
36
|
+
* {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
|
|
37
|
+
* `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
|
|
38
|
+
*/
|
|
39
|
+
private static mapPersistedToolCalls;
|
|
34
40
|
/**
|
|
35
41
|
* Get messages for a conversation
|
|
36
42
|
*/
|
|
@@ -141,6 +147,13 @@ declare class AgoClient {
|
|
|
141
147
|
* Remove a dynamic context provider.
|
|
142
148
|
*/
|
|
143
149
|
removeDynamicContext(key: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Broadcast that the client-side context changed by emitting `context:changed`
|
|
152
|
+
* with the fresh snapshot. The context-mutating methods call this automatically;
|
|
153
|
+
* stateful helpers whose context lives in a store (e.g. `createFormCollector`)
|
|
154
|
+
* call it when their store updates so observers like the dev panel stay live.
|
|
155
|
+
*/
|
|
156
|
+
notifyContextChanged(): void;
|
|
144
157
|
/**
|
|
145
158
|
* Enable automatic capture of the current browser page (URL + title).
|
|
146
159
|
* Injected as a dynamic context entry named `browser-page`.
|
|
@@ -186,6 +199,14 @@ declare class AgoClient {
|
|
|
186
199
|
* SDK Events
|
|
187
200
|
*/
|
|
188
201
|
declare interface AgoClientEvents {
|
|
202
|
+
/**
|
|
203
|
+
* The client-side context changed: a context entry or dynamic provider was
|
|
204
|
+
* added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
|
|
205
|
+
* store. Carries the fresh snapshot so observers — notably the dev panel — can
|
|
206
|
+
* repaint without waiting for the next message. Fires for the form collector's
|
|
207
|
+
* initial install too, so its missing fields show from the start of a conversation.
|
|
208
|
+
*/
|
|
209
|
+
"context:changed": ContextSnapshot | null;
|
|
189
210
|
"message:start": {
|
|
190
211
|
conversationId: string;
|
|
191
212
|
messageId: string;
|
|
@@ -201,6 +222,12 @@ declare interface AgoClientEvents {
|
|
|
201
222
|
conversationId?: string;
|
|
202
223
|
messageId?: string;
|
|
203
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* A full conversation was loaded from the server (e.g. after a page reload).
|
|
227
|
+
* Carries the messages and their persisted tool calls so stateful helpers —
|
|
228
|
+
* notably `createFormCollector` — can replay them to restore their state.
|
|
229
|
+
*/
|
|
230
|
+
"conversation:loaded": Conversation;
|
|
204
231
|
"toolCall:received": ToolCallData;
|
|
205
232
|
"toolCall:form": ToolCallData;
|
|
206
233
|
"function:invoke": ClientFunctionInvocation;
|
|
@@ -313,6 +340,20 @@ export declare interface ChatWidgetHandle {
|
|
|
313
340
|
element: HTMLElement;
|
|
314
341
|
/** Programmatically send a message (same path as the input). */
|
|
315
342
|
sendMessage: (content: string, files?: File[]) => Promise<void>;
|
|
343
|
+
/**
|
|
344
|
+
* The conversation-persistence session, present only when `persistConversation`
|
|
345
|
+
* is set — exposes the stable `widgetId` and `session.clear()` to start a new thread.
|
|
346
|
+
*/
|
|
347
|
+
session?: ConversationSession;
|
|
348
|
+
/**
|
|
349
|
+
* The visitor's conversations (threads) — the vanilla equivalent of the React/Vue
|
|
350
|
+
* `useConversation().conversations`. Auto-loaded on mount and refreshed after each
|
|
351
|
+
* turn only when `loadThreads` is set; otherwise it stays empty until you call
|
|
352
|
+
* {@link ChatWidgetHandle.refreshThreads}.
|
|
353
|
+
*/
|
|
354
|
+
readonly threads: Conversation[];
|
|
355
|
+
/** Re-fetch the conversations list and update {@link ChatWidgetHandle.threads}. */
|
|
356
|
+
refreshThreads: () => Promise<Conversation[]>;
|
|
316
357
|
/** Remove listeners, uninstall forms, and clear the DOM. */
|
|
317
358
|
destroy: () => void;
|
|
318
359
|
}
|
|
@@ -400,6 +441,60 @@ declare interface Conversation {
|
|
|
400
441
|
messages?: AgoMessage[];
|
|
401
442
|
}
|
|
402
443
|
|
|
444
|
+
export declare interface ConversationSession {
|
|
445
|
+
/**
|
|
446
|
+
* The stable widget id identifying this visitor. Generated once and persisted
|
|
447
|
+
* forever, so a returning visitor keeps the same id (and therefore the same
|
|
448
|
+
* server-side conversation history) across reloads.
|
|
449
|
+
*/
|
|
450
|
+
readonly widgetId: string;
|
|
451
|
+
/**
|
|
452
|
+
* The last active thread id, decided **entirely on the front** so a reload costs
|
|
453
|
+
* no backend round-trip. Returns `null` when there is no cached thread, when its
|
|
454
|
+
* last message time is unknown, or when it has been idle longer than `ttlMs`.
|
|
455
|
+
*/
|
|
456
|
+
getLastActiveThread(): string | null;
|
|
457
|
+
/**
|
|
458
|
+
* Record (and refresh) the active thread together with the time of its last
|
|
459
|
+
* message — call it once per turn. The `lastMessageAt` drives the sliding TTL;
|
|
460
|
+
* omit it and the thread won't be resumed (no time → not displayed).
|
|
461
|
+
*/
|
|
462
|
+
setActiveThread(conversationId: string, lastMessageAt?: Date | number): void;
|
|
463
|
+
/** Forget the cached thread — e.g. on "new chat". */
|
|
464
|
+
clear(): void;
|
|
465
|
+
/** The resolved storage key holding the widget id — handy for debugging. */
|
|
466
|
+
readonly key: string;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export declare interface ConversationSessionOptions {
|
|
470
|
+
/**
|
|
471
|
+
* Storage backend. Defaults to `localStorage`, degrading to an in-memory store
|
|
472
|
+
* when storage is unavailable (SSR / disabled). Pass `sessionStorage` for a
|
|
473
|
+
* tab-scoped session, or any `{ getItem, setItem }` for a custom backend.
|
|
474
|
+
*/
|
|
475
|
+
storage?: StorageLike;
|
|
476
|
+
/**
|
|
477
|
+
* Storage key for the widget id. Default `"ago_widget_id"` — the same key the
|
|
478
|
+
* HTTP client reads, so the visitor's id is shared across the SDK.
|
|
479
|
+
*/
|
|
480
|
+
key?: string;
|
|
481
|
+
/**
|
|
482
|
+
* Explicit widget id to adopt (and persist) instead of reading or generating
|
|
483
|
+
* one — e.g. when the host app already has a stable visitor identifier.
|
|
484
|
+
*/
|
|
485
|
+
widgetId?: string;
|
|
486
|
+
/** Storage key for the cached last active thread. Default `"ago_last_thread"`. */
|
|
487
|
+
threadKey?: string;
|
|
488
|
+
/**
|
|
489
|
+
* Maximum idle age of a thread to still resume it, in milliseconds, compared
|
|
490
|
+
* against the recorded time of its last message. Checked entirely on the front
|
|
491
|
+
* (no backend call): a thread idle longer than this — or one with no recorded
|
|
492
|
+
* last-message time — is not resumed (`getLastActiveThread` returns `null`).
|
|
493
|
+
* Default 2h. Pass `Infinity` to never expire.
|
|
494
|
+
*/
|
|
495
|
+
ttlMs?: number;
|
|
496
|
+
}
|
|
497
|
+
|
|
403
498
|
export declare interface CreateFormCollectorOptions<V = Record<string, unknown>> {
|
|
404
499
|
/** Short identifier; becomes the `update_<name>` / `submit_<name>` function names. */
|
|
405
500
|
name: string;
|
|
@@ -488,6 +583,15 @@ export declare interface MountChatWidgetOptions {
|
|
|
488
583
|
config?: AgoConfig;
|
|
489
584
|
/** Initial conversation ID to continue. */
|
|
490
585
|
conversationId?: string;
|
|
586
|
+
/**
|
|
587
|
+
* Resume the visitor's last active thread across reloads. `true` enables defaults
|
|
588
|
+
* (localStorage, widget id under `ago_widget_id`); pass an object to set `storage`
|
|
589
|
+
* (e.g. `sessionStorage`), `key`, or an explicit `widgetId`. Built on
|
|
590
|
+
* {@link createConversationSession}: the visitor is identified by a single stable
|
|
591
|
+
* widget id and the backend hands back their most recently updated conversation.
|
|
592
|
+
* An explicit `conversationId` still wins as the initial thread. Off by default.
|
|
593
|
+
*/
|
|
594
|
+
persistConversation?: boolean | Partial<ConversationSessionOptions>;
|
|
491
595
|
/** Widget title shown in the header. */
|
|
492
596
|
title?: string;
|
|
493
597
|
/** Message shown before any conversation has started. */
|
|
@@ -502,6 +606,13 @@ export declare interface MountChatWidgetOptions {
|
|
|
502
606
|
logoUrl?: string;
|
|
503
607
|
/** Show the agent name above assistant messages. Defaults to `false`. */
|
|
504
608
|
showAgentName?: boolean;
|
|
609
|
+
/**
|
|
610
|
+
* Load the visitor's conversation list into `widget.threads` on mount and refresh
|
|
611
|
+
* it after each turn (one `GET /conversations` per load). Off by default to avoid
|
|
612
|
+
* the request when the integrator doesn't need it; `widget.refreshThreads()` stays
|
|
613
|
+
* callable on demand regardless.
|
|
614
|
+
*/
|
|
615
|
+
loadThreads?: boolean;
|
|
505
616
|
/**
|
|
506
617
|
* Conversational forms the agent can fill and submit during the chat. Each
|
|
507
618
|
* config is installed as a {@link createFormCollector} for the lifetime of the
|
|
@@ -535,6 +646,9 @@ declare interface SendMessageOptions {
|
|
|
535
646
|
files?: File[];
|
|
536
647
|
}
|
|
537
648
|
|
|
649
|
+
/** The slice of the Web Storage API that {@link createStore} relies on. */
|
|
650
|
+
declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
|
|
651
|
+
|
|
538
652
|
/**
|
|
539
653
|
* Where a completed form is sent.
|
|
540
654
|
* - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
|
package/dist/widget.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ declare class AgoClient {
|
|
|
31
31
|
* Get a specific conversation with messages
|
|
32
32
|
*/
|
|
33
33
|
getConversation(conversationId: string): Promise<Conversation>;
|
|
34
|
+
/**
|
|
35
|
+
* Map the backend's snake_case `tool_call_data` entries onto the camelCase
|
|
36
|
+
* {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
|
|
37
|
+
* `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
|
|
38
|
+
*/
|
|
39
|
+
private static mapPersistedToolCalls;
|
|
34
40
|
/**
|
|
35
41
|
* Get messages for a conversation
|
|
36
42
|
*/
|
|
@@ -141,6 +147,13 @@ declare class AgoClient {
|
|
|
141
147
|
* Remove a dynamic context provider.
|
|
142
148
|
*/
|
|
143
149
|
removeDynamicContext(key: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Broadcast that the client-side context changed by emitting `context:changed`
|
|
152
|
+
* with the fresh snapshot. The context-mutating methods call this automatically;
|
|
153
|
+
* stateful helpers whose context lives in a store (e.g. `createFormCollector`)
|
|
154
|
+
* call it when their store updates so observers like the dev panel stay live.
|
|
155
|
+
*/
|
|
156
|
+
notifyContextChanged(): void;
|
|
144
157
|
/**
|
|
145
158
|
* Enable automatic capture of the current browser page (URL + title).
|
|
146
159
|
* Injected as a dynamic context entry named `browser-page`.
|
|
@@ -186,6 +199,14 @@ declare class AgoClient {
|
|
|
186
199
|
* SDK Events
|
|
187
200
|
*/
|
|
188
201
|
declare interface AgoClientEvents {
|
|
202
|
+
/**
|
|
203
|
+
* The client-side context changed: a context entry or dynamic provider was
|
|
204
|
+
* added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
|
|
205
|
+
* store. Carries the fresh snapshot so observers — notably the dev panel — can
|
|
206
|
+
* repaint without waiting for the next message. Fires for the form collector's
|
|
207
|
+
* initial install too, so its missing fields show from the start of a conversation.
|
|
208
|
+
*/
|
|
209
|
+
"context:changed": ContextSnapshot | null;
|
|
189
210
|
"message:start": {
|
|
190
211
|
conversationId: string;
|
|
191
212
|
messageId: string;
|
|
@@ -201,6 +222,12 @@ declare interface AgoClientEvents {
|
|
|
201
222
|
conversationId?: string;
|
|
202
223
|
messageId?: string;
|
|
203
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* A full conversation was loaded from the server (e.g. after a page reload).
|
|
227
|
+
* Carries the messages and their persisted tool calls so stateful helpers —
|
|
228
|
+
* notably `createFormCollector` — can replay them to restore their state.
|
|
229
|
+
*/
|
|
230
|
+
"conversation:loaded": Conversation;
|
|
204
231
|
"toolCall:received": ToolCallData;
|
|
205
232
|
"toolCall:form": ToolCallData;
|
|
206
233
|
"function:invoke": ClientFunctionInvocation;
|
|
@@ -313,6 +340,20 @@ export declare interface ChatWidgetHandle {
|
|
|
313
340
|
element: HTMLElement;
|
|
314
341
|
/** Programmatically send a message (same path as the input). */
|
|
315
342
|
sendMessage: (content: string, files?: File[]) => Promise<void>;
|
|
343
|
+
/**
|
|
344
|
+
* The conversation-persistence session, present only when `persistConversation`
|
|
345
|
+
* is set — exposes the stable `widgetId` and `session.clear()` to start a new thread.
|
|
346
|
+
*/
|
|
347
|
+
session?: ConversationSession;
|
|
348
|
+
/**
|
|
349
|
+
* The visitor's conversations (threads) — the vanilla equivalent of the React/Vue
|
|
350
|
+
* `useConversation().conversations`. Auto-loaded on mount and refreshed after each
|
|
351
|
+
* turn only when `loadThreads` is set; otherwise it stays empty until you call
|
|
352
|
+
* {@link ChatWidgetHandle.refreshThreads}.
|
|
353
|
+
*/
|
|
354
|
+
readonly threads: Conversation[];
|
|
355
|
+
/** Re-fetch the conversations list and update {@link ChatWidgetHandle.threads}. */
|
|
356
|
+
refreshThreads: () => Promise<Conversation[]>;
|
|
316
357
|
/** Remove listeners, uninstall forms, and clear the DOM. */
|
|
317
358
|
destroy: () => void;
|
|
318
359
|
}
|
|
@@ -400,6 +441,60 @@ declare interface Conversation {
|
|
|
400
441
|
messages?: AgoMessage[];
|
|
401
442
|
}
|
|
402
443
|
|
|
444
|
+
export declare interface ConversationSession {
|
|
445
|
+
/**
|
|
446
|
+
* The stable widget id identifying this visitor. Generated once and persisted
|
|
447
|
+
* forever, so a returning visitor keeps the same id (and therefore the same
|
|
448
|
+
* server-side conversation history) across reloads.
|
|
449
|
+
*/
|
|
450
|
+
readonly widgetId: string;
|
|
451
|
+
/**
|
|
452
|
+
* The last active thread id, decided **entirely on the front** so a reload costs
|
|
453
|
+
* no backend round-trip. Returns `null` when there is no cached thread, when its
|
|
454
|
+
* last message time is unknown, or when it has been idle longer than `ttlMs`.
|
|
455
|
+
*/
|
|
456
|
+
getLastActiveThread(): string | null;
|
|
457
|
+
/**
|
|
458
|
+
* Record (and refresh) the active thread together with the time of its last
|
|
459
|
+
* message — call it once per turn. The `lastMessageAt` drives the sliding TTL;
|
|
460
|
+
* omit it and the thread won't be resumed (no time → not displayed).
|
|
461
|
+
*/
|
|
462
|
+
setActiveThread(conversationId: string, lastMessageAt?: Date | number): void;
|
|
463
|
+
/** Forget the cached thread — e.g. on "new chat". */
|
|
464
|
+
clear(): void;
|
|
465
|
+
/** The resolved storage key holding the widget id — handy for debugging. */
|
|
466
|
+
readonly key: string;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export declare interface ConversationSessionOptions {
|
|
470
|
+
/**
|
|
471
|
+
* Storage backend. Defaults to `localStorage`, degrading to an in-memory store
|
|
472
|
+
* when storage is unavailable (SSR / disabled). Pass `sessionStorage` for a
|
|
473
|
+
* tab-scoped session, or any `{ getItem, setItem }` for a custom backend.
|
|
474
|
+
*/
|
|
475
|
+
storage?: StorageLike;
|
|
476
|
+
/**
|
|
477
|
+
* Storage key for the widget id. Default `"ago_widget_id"` — the same key the
|
|
478
|
+
* HTTP client reads, so the visitor's id is shared across the SDK.
|
|
479
|
+
*/
|
|
480
|
+
key?: string;
|
|
481
|
+
/**
|
|
482
|
+
* Explicit widget id to adopt (and persist) instead of reading or generating
|
|
483
|
+
* one — e.g. when the host app already has a stable visitor identifier.
|
|
484
|
+
*/
|
|
485
|
+
widgetId?: string;
|
|
486
|
+
/** Storage key for the cached last active thread. Default `"ago_last_thread"`. */
|
|
487
|
+
threadKey?: string;
|
|
488
|
+
/**
|
|
489
|
+
* Maximum idle age of a thread to still resume it, in milliseconds, compared
|
|
490
|
+
* against the recorded time of its last message. Checked entirely on the front
|
|
491
|
+
* (no backend call): a thread idle longer than this — or one with no recorded
|
|
492
|
+
* last-message time — is not resumed (`getLastActiveThread` returns `null`).
|
|
493
|
+
* Default 2h. Pass `Infinity` to never expire.
|
|
494
|
+
*/
|
|
495
|
+
ttlMs?: number;
|
|
496
|
+
}
|
|
497
|
+
|
|
403
498
|
export declare interface CreateFormCollectorOptions<V = Record<string, unknown>> {
|
|
404
499
|
/** Short identifier; becomes the `update_<name>` / `submit_<name>` function names. */
|
|
405
500
|
name: string;
|
|
@@ -488,6 +583,15 @@ export declare interface MountChatWidgetOptions {
|
|
|
488
583
|
config?: AgoConfig;
|
|
489
584
|
/** Initial conversation ID to continue. */
|
|
490
585
|
conversationId?: string;
|
|
586
|
+
/**
|
|
587
|
+
* Resume the visitor's last active thread across reloads. `true` enables defaults
|
|
588
|
+
* (localStorage, widget id under `ago_widget_id`); pass an object to set `storage`
|
|
589
|
+
* (e.g. `sessionStorage`), `key`, or an explicit `widgetId`. Built on
|
|
590
|
+
* {@link createConversationSession}: the visitor is identified by a single stable
|
|
591
|
+
* widget id and the backend hands back their most recently updated conversation.
|
|
592
|
+
* An explicit `conversationId` still wins as the initial thread. Off by default.
|
|
593
|
+
*/
|
|
594
|
+
persistConversation?: boolean | Partial<ConversationSessionOptions>;
|
|
491
595
|
/** Widget title shown in the header. */
|
|
492
596
|
title?: string;
|
|
493
597
|
/** Message shown before any conversation has started. */
|
|
@@ -502,6 +606,13 @@ export declare interface MountChatWidgetOptions {
|
|
|
502
606
|
logoUrl?: string;
|
|
503
607
|
/** Show the agent name above assistant messages. Defaults to `false`. */
|
|
504
608
|
showAgentName?: boolean;
|
|
609
|
+
/**
|
|
610
|
+
* Load the visitor's conversation list into `widget.threads` on mount and refresh
|
|
611
|
+
* it after each turn (one `GET /conversations` per load). Off by default to avoid
|
|
612
|
+
* the request when the integrator doesn't need it; `widget.refreshThreads()` stays
|
|
613
|
+
* callable on demand regardless.
|
|
614
|
+
*/
|
|
615
|
+
loadThreads?: boolean;
|
|
505
616
|
/**
|
|
506
617
|
* Conversational forms the agent can fill and submit during the chat. Each
|
|
507
618
|
* config is installed as a {@link createFormCollector} for the lifetime of the
|
|
@@ -535,6 +646,9 @@ declare interface SendMessageOptions {
|
|
|
535
646
|
files?: File[];
|
|
536
647
|
}
|
|
537
648
|
|
|
649
|
+
/** The slice of the Web Storage API that {@link createStore} relies on. */
|
|
650
|
+
declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
|
|
651
|
+
|
|
538
652
|
/**
|
|
539
653
|
* Where a completed form is sent.
|
|
540
654
|
* - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
|