@useago/sdk 1.0.6 → 1.0.7
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/README.md +53 -0
- package/dist/angular.d.cts +2 -0
- package/dist/angular.d.ts +2 -0
- package/dist/{createConversationSession-lJWANT6T.cjs → createConversationSession-BuMXp0Ia.cjs} +1 -1
- package/dist/{createConversationSession-Boi0PjDU.js → createConversationSession-CCT1hCf8.js} +1 -1
- package/dist/createFormCollector-BwM7qTrp.js +276 -0
- package/dist/createFormCollector-DWzGKDwO.cjs +1 -0
- package/dist/devtools.d.cts +2 -0
- package/dist/devtools.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +2 -2
- package/dist/react.cjs +2 -2
- package/dist/react.d.cts +19 -0
- package/dist/react.d.ts +19 -0
- package/dist/react.js +42 -40
- package/dist/testing.d.cts +2 -0
- package/dist/testing.d.ts +2 -0
- package/dist/vue.d.cts +2 -0
- package/dist/vue.d.ts +2 -0
- package/dist/widget.cjs +4 -4
- package/dist/widget.d.cts +22 -0
- package/dist/widget.d.ts +22 -0
- package/dist/widget.js +347 -297
- package/package.json +1 -1
- package/dist/createFormCollector-BUqSA2Qw.js +0 -257
- package/dist/createFormCollector-CSG5ioym.cjs +0 -1
package/README.md
CHANGED
|
@@ -81,6 +81,59 @@ guards, auth and layouts keep working exactly as they do today.
|
|
|
81
81
|
`react-router-dom` here is *your* router, not an SDK dependency:
|
|
82
82
|
`useAgoNavigation` accepts any `(path: string) => void` function.
|
|
83
83
|
|
|
84
|
+
## Turn a JavaScript function into an agent tool
|
|
85
|
+
|
|
86
|
+
Keep your application logic as a regular JavaScript function, then describe its
|
|
87
|
+
arguments with `defineFunction`. The description and JSON Schema tell the agent
|
|
88
|
+
when and how to call it:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { defineFunction } from "@useago/sdk";
|
|
92
|
+
|
|
93
|
+
async function getOrderStatus({ orderId }) {
|
|
94
|
+
const response = await fetch(`/api/orders/${orderId}`);
|
|
95
|
+
if (!response.ok) throw new Error("Order not found");
|
|
96
|
+
|
|
97
|
+
const order = await response.json();
|
|
98
|
+
|
|
99
|
+
return { orderId, status: order.status };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const getOrderStatusTool = defineFunction({
|
|
103
|
+
name: "getOrderStatus",
|
|
104
|
+
description: "Get the current status of an order from its ID.",
|
|
105
|
+
parameters: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
orderId: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "The order ID shown to the user",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
required: ["orderId"],
|
|
114
|
+
},
|
|
115
|
+
handler: getOrderStatus,
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Register the definition once to expose it to the agent. In React, pass it to
|
|
120
|
+
the provider:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<AgoProvider
|
|
124
|
+
baseUrl="https://api.example.com"
|
|
125
|
+
agent="support-agent"
|
|
126
|
+
tools={[getOrderStatusTool]}
|
|
127
|
+
>
|
|
128
|
+
<ChatWidget />
|
|
129
|
+
</AgoProvider>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
With the core client, use `client.registerFunction(getOrderStatusTool)`.
|
|
133
|
+
Whenever the agent calls the tool, the SDK runs your handler in the browser
|
|
134
|
+
with the generated arguments and sends its return value back to the agent. Keep
|
|
135
|
+
the return value small and structured so the agent can use it reliably.
|
|
136
|
+
|
|
84
137
|
## Show the source docs the agent retrieved
|
|
85
138
|
|
|
86
139
|
Each assistant message carries the knowledge sources it used in `m.sources`
|
package/dist/angular.d.cts
CHANGED
|
@@ -544,6 +544,8 @@ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
544
544
|
schema: FormCollectorSchema;
|
|
545
545
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
546
546
|
submit?: SubmitConfig<V>;
|
|
547
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
548
|
+
autoSubmit?: boolean;
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
/**
|
package/dist/angular.d.ts
CHANGED
|
@@ -544,6 +544,8 @@ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
544
544
|
schema: FormCollectorSchema;
|
|
545
545
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
546
546
|
submit?: SubmitConfig<V>;
|
|
547
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
548
|
+
autoSubmit?: boolean;
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
/**
|
package/dist/{createConversationSession-lJWANT6T.cjs → createConversationSession-BuMXp0Ia.cjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
const d=require("./createFormCollector-
|
|
1
|
+
const d=require("./createFormCollector-DWzGKDwO.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),c=o.get();c.value!==null&&s(c.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function s(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||s(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
|
package/dist/{createConversationSession-Boi0PjDU.js → createConversationSession-CCT1hCf8.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as d } from "./createFormCollector-
|
|
1
|
+
import { i as d } from "./createFormCollector-BwM7qTrp.js";
|
|
2
2
|
var f = "ago_widget_id", g = "ago_last_thread", y = 7200 * 1e3;
|
|
3
3
|
function v() {
|
|
4
4
|
return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (e) => {
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { c as N } from "./AgoClient-DYdIe_R4.js";
|
|
2
|
+
function W(n, e) {
|
|
3
|
+
const a = e ? e.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
|
|
4
|
+
let s = n;
|
|
5
|
+
if (e && a) try {
|
|
6
|
+
const f = a.getItem(e.key);
|
|
7
|
+
f != null && (s = JSON.parse(f));
|
|
8
|
+
} catch {
|
|
9
|
+
}
|
|
10
|
+
const i = /* @__PURE__ */ new Set(), c = () => i.forEach((f) => f(s));
|
|
11
|
+
function b() {
|
|
12
|
+
if (e && a) try {
|
|
13
|
+
a.setItem(e.key, JSON.stringify(s));
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
get: () => s,
|
|
19
|
+
set: (f) => {
|
|
20
|
+
s = f, b(), c();
|
|
21
|
+
},
|
|
22
|
+
subscribe: (f) => (i.add(f), () => {
|
|
23
|
+
i.delete(f);
|
|
24
|
+
})
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
var T = /^[a-zA-Z0-9_-]{1,40}$/, E = (n) => n == null || n === "";
|
|
28
|
+
function O(n, e) {
|
|
29
|
+
const a = e[n.property];
|
|
30
|
+
if (E(a)) return !1;
|
|
31
|
+
if (Array.isArray(n.value)) return n.value.some((c) => String(a) === String(c));
|
|
32
|
+
if (!n.op) return String(a) === String(n.value);
|
|
33
|
+
const s = Number(a), i = Number(n.value);
|
|
34
|
+
if (Number.isNaN(s) || Number.isNaN(i)) return !1;
|
|
35
|
+
switch (n.op) {
|
|
36
|
+
case ">=":
|
|
37
|
+
return s >= i;
|
|
38
|
+
case "<=":
|
|
39
|
+
return s <= i;
|
|
40
|
+
case ">":
|
|
41
|
+
return s > i;
|
|
42
|
+
case "<":
|
|
43
|
+
return s < i;
|
|
44
|
+
default:
|
|
45
|
+
return N.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`), !1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function p(n, e) {
|
|
49
|
+
const a = n.properties ?? {}, s = /* @__PURE__ */ new Set();
|
|
50
|
+
for (const c of n.required ?? []) {
|
|
51
|
+
const b = a[c]?.requiredWhen;
|
|
52
|
+
(!b || O(b, e)) && s.add(c);
|
|
53
|
+
}
|
|
54
|
+
for (const [c, b] of Object.entries(a)) b.requiredWhen && O(b.requiredWhen, e) && s.add(c);
|
|
55
|
+
const i = [...s].filter((c) => E(e[c]));
|
|
56
|
+
return {
|
|
57
|
+
missing: i,
|
|
58
|
+
complete: i.length === 0
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function j(n) {
|
|
62
|
+
const e = {};
|
|
63
|
+
for (const [a, s] of Object.entries(n.properties ?? {})) e[a] = {
|
|
64
|
+
type: s.type,
|
|
65
|
+
...s.description != null && { description: s.description },
|
|
66
|
+
...s.enum && { enum: s.enum },
|
|
67
|
+
...s.default !== void 0 && { default: s.default }
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: e,
|
|
72
|
+
required: []
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function I(n) {
|
|
76
|
+
const { name: e, description: a, schema: s } = n;
|
|
77
|
+
if (!T.test(e)) throw new Error(`Invalid form collector name "${e}": must match ${T} (it becomes the update_/submit_ function names).`);
|
|
78
|
+
const i = typeof n.submit == "string" ? n.submit ? {
|
|
79
|
+
via: "client",
|
|
80
|
+
url: n.submit
|
|
81
|
+
} : !1 : n.submit ?? !1;
|
|
82
|
+
n.autoSubmit === !0 && !i && N.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);
|
|
83
|
+
const c = (n.autoSubmit ?? !0) && !!i, b = s.properties ?? {}, f = (t) => {
|
|
84
|
+
const r = {};
|
|
85
|
+
for (const [u, o] of Object.entries(t)) {
|
|
86
|
+
const l = b[u];
|
|
87
|
+
if (l)
|
|
88
|
+
if (o == null) r[u] = o;
|
|
89
|
+
else if (l.type === "number" || l.type === "integer") {
|
|
90
|
+
const d = typeof o == "number" ? o : Number(o);
|
|
91
|
+
r[u] = Number.isNaN(d) ? o : d;
|
|
92
|
+
} else l.type === "boolean" ? r[u] = typeof o == "boolean" ? o : o === "true" ? !0 : o === "false" ? !1 : !!o : r[u] = o;
|
|
93
|
+
}
|
|
94
|
+
return r;
|
|
95
|
+
}, y = n.initialValues ?? {}, m = W({
|
|
96
|
+
values: y,
|
|
97
|
+
submitted: !1
|
|
98
|
+
}), $ = (t) => {
|
|
99
|
+
const r = m.get(), u = {
|
|
100
|
+
...r,
|
|
101
|
+
values: {
|
|
102
|
+
...r.values,
|
|
103
|
+
...t
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return m.set(u), u;
|
|
107
|
+
};
|
|
108
|
+
let h = null;
|
|
109
|
+
const v = async () => {
|
|
110
|
+
const { values: t } = m.get(), { complete: r, missing: u } = p(s, t);
|
|
111
|
+
if (!r) return {
|
|
112
|
+
ok: !1,
|
|
113
|
+
missing: u
|
|
114
|
+
};
|
|
115
|
+
if (!i) return {
|
|
116
|
+
ok: !1,
|
|
117
|
+
error: "No submit target configured for this form collector."
|
|
118
|
+
};
|
|
119
|
+
const o = t;
|
|
120
|
+
try {
|
|
121
|
+
let l;
|
|
122
|
+
if (i.via === "client") if ("handler" in i) l = await i.handler(o);
|
|
123
|
+
else {
|
|
124
|
+
const d = await fetch(i.url, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: { "Content-Type": "application/json" },
|
|
127
|
+
credentials: "include",
|
|
128
|
+
body: JSON.stringify(o)
|
|
129
|
+
});
|
|
130
|
+
if (!d.ok) return {
|
|
131
|
+
ok: !1,
|
|
132
|
+
error: `Submit failed: HTTP ${d.status}`
|
|
133
|
+
};
|
|
134
|
+
l = await d.json().catch(() => {
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (!h) return {
|
|
139
|
+
ok: !1,
|
|
140
|
+
error: "Backend submit requires install(client) (or useFormCollector) first."
|
|
141
|
+
};
|
|
142
|
+
l = await h.submitFormCollector(e, o);
|
|
143
|
+
}
|
|
144
|
+
return m.set({
|
|
145
|
+
...m.get(),
|
|
146
|
+
submitted: !0,
|
|
147
|
+
submitResult: l
|
|
148
|
+
}), {
|
|
149
|
+
ok: !0,
|
|
150
|
+
result: l
|
|
151
|
+
};
|
|
152
|
+
} catch (l) {
|
|
153
|
+
const d = l instanceof Error ? l.message : "Submit failed";
|
|
154
|
+
return N.error(`FormCollector "${e}" submit failed:`, l), {
|
|
155
|
+
ok: !1,
|
|
156
|
+
error: d
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}, w = async () => {
|
|
160
|
+
if (!c || !i) return null;
|
|
161
|
+
const { values: t, submitted: r } = m.get();
|
|
162
|
+
return r || !p(s, t).complete ? null : v();
|
|
163
|
+
}, C = {
|
|
164
|
+
name: `update_${e}`,
|
|
165
|
+
description: `Fill or update fields of the "${e}" form. ${a} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,
|
|
166
|
+
parameters: j(s),
|
|
167
|
+
handler: async (t) => {
|
|
168
|
+
const r = $(f(t)), { missing: u } = p(s, r.values), o = await w();
|
|
169
|
+
return o ? o.ok ? {
|
|
170
|
+
ok: !0,
|
|
171
|
+
values: r.values,
|
|
172
|
+
missing: u,
|
|
173
|
+
submitted: !0
|
|
174
|
+
} : {
|
|
175
|
+
ok: !0,
|
|
176
|
+
values: r.values,
|
|
177
|
+
missing: u,
|
|
178
|
+
submitted: !1,
|
|
179
|
+
submitError: o.error
|
|
180
|
+
} : {
|
|
181
|
+
ok: !0,
|
|
182
|
+
values: r.values,
|
|
183
|
+
missing: u
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}, g = [C];
|
|
187
|
+
i && !c && g.push({
|
|
188
|
+
name: `submit_${e}`,
|
|
189
|
+
description: `Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,
|
|
190
|
+
parameters: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {}
|
|
193
|
+
},
|
|
194
|
+
handler: () => v()
|
|
195
|
+
});
|
|
196
|
+
const x = "client__", k = i ? `submit_${e}` : null, P = (t) => {
|
|
197
|
+
const r = t.functionName ?? t.toolName;
|
|
198
|
+
if (r)
|
|
199
|
+
return r.startsWith(x) ? r.slice(8) : r;
|
|
200
|
+
}, F = (t) => {
|
|
201
|
+
let r = { ...y }, u = !1;
|
|
202
|
+
for (const o of t) {
|
|
203
|
+
const l = P(o);
|
|
204
|
+
l === C.name ? o.arguments && (r = {
|
|
205
|
+
...r,
|
|
206
|
+
...f(o.arguments)
|
|
207
|
+
}) : k && l === k && o.status?.toLowerCase() === "done" && (u = !0);
|
|
208
|
+
}
|
|
209
|
+
m.set({
|
|
210
|
+
values: r,
|
|
211
|
+
submitted: u
|
|
212
|
+
});
|
|
213
|
+
}, S = `form:${e}`, q = () => {
|
|
214
|
+
const { values: t, submitted: r } = m.get(), { missing: u, complete: o } = p(s, t), l = i ? c ? " The form is submitted automatically as soon as every required field is filled, so there is no submit function to call." : ` When nothing is missing and the user confirms, call submit_${e}.` : "", d = r ? `The "${e}" form has been submitted.` : `You are currently collecting information from the user to fill the "${e}" form.`;
|
|
215
|
+
return {
|
|
216
|
+
name: `Form: ${e}`,
|
|
217
|
+
description: `${d} ${a} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(s)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${l}`,
|
|
218
|
+
data: {
|
|
219
|
+
values: t,
|
|
220
|
+
missing: u,
|
|
221
|
+
complete: o,
|
|
222
|
+
submitted: r
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}, _ = (t) => {
|
|
226
|
+
F((t.messages ?? []).flatMap((r) => r.toolCalls ?? []));
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
name: e,
|
|
230
|
+
store: m,
|
|
231
|
+
functions: g,
|
|
232
|
+
contextKey: S,
|
|
233
|
+
contextProvider: q,
|
|
234
|
+
install: (t) => {
|
|
235
|
+
h = t;
|
|
236
|
+
for (const u of g) t.register(u);
|
|
237
|
+
t.addDynamicContext(S, q);
|
|
238
|
+
const r = m.subscribe(() => t.notifyContextChanged());
|
|
239
|
+
return t.on("conversation:loaded", _), () => {
|
|
240
|
+
r();
|
|
241
|
+
for (const u of g) t.unregisterFunction(u.name);
|
|
242
|
+
t.removeDynamicContext(S), t.off("conversation:loaded", _), h === t && (h = null);
|
|
243
|
+
};
|
|
244
|
+
},
|
|
245
|
+
hydrate: F,
|
|
246
|
+
submit: v,
|
|
247
|
+
getValues: () => m.get().values,
|
|
248
|
+
setValues: (t) => {
|
|
249
|
+
$(f(t)), w();
|
|
250
|
+
},
|
|
251
|
+
reset: () => {
|
|
252
|
+
m.set({
|
|
253
|
+
values: y,
|
|
254
|
+
submitted: !1
|
|
255
|
+
});
|
|
256
|
+
},
|
|
257
|
+
getStatus: () => p(s, m.get().values)
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
async function J(n, e) {
|
|
261
|
+
const a = await n.getFormCollector(e.name);
|
|
262
|
+
return I({
|
|
263
|
+
name: a.name,
|
|
264
|
+
description: e.description ?? a.description,
|
|
265
|
+
schema: e.schema ?? a.schema,
|
|
266
|
+
submit: e.submit ?? a.submit,
|
|
267
|
+
initialValues: e.initialValues,
|
|
268
|
+
autoSubmit: e.autoSubmit ?? a.autoSubmit
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
export {
|
|
272
|
+
W as i,
|
|
273
|
+
p as n,
|
|
274
|
+
J as r,
|
|
275
|
+
I as t
|
|
276
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const N=require("./AgoClient--y10UXUV.cjs");function T(s,e){const a=e?e.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let n=s;if(e&&a)try{const f=a.getItem(e.key);f!=null&&(n=JSON.parse(f))}catch{}const i=new Set,c=()=>i.forEach(f=>f(n));function b(){if(e&&a)try{a.setItem(e.key,JSON.stringify(n))}catch{}}return{get:()=>n,set:f=>{n=f,b(),c()},subscribe:f=>(i.add(f),()=>{i.delete(f)})}}var _=/^[a-zA-Z0-9_-]{1,40}$/,j=s=>s==null||s==="";function P(s,e){const a=e[s.property];if(j(a))return!1;if(Array.isArray(s.value))return s.value.some(c=>String(a)===String(c));if(!s.op)return String(a)===String(s.value);const n=Number(a),i=Number(s.value);if(Number.isNaN(n)||Number.isNaN(i))return!1;switch(s.op){case">=":return n>=i;case"<=":return n<=i;case">":return n>i;case"<":return n<i;default:return N.logger.warn(`Unknown requiredWhen op "${s.op}"; treating as not required.`),!1}}function g(s,e){const a=s.properties??{},n=new Set;for(const c of s.required??[]){const b=a[c]?.requiredWhen;(!b||P(b,e))&&n.add(c)}for(const[c,b]of Object.entries(a))b.requiredWhen&&P(b.requiredWhen,e)&&n.add(c);const i=[...n].filter(c=>j(e[c]));return{missing:i,complete:i.length===0}}function A(s){const e={};for(const[a,n]of Object.entries(s.properties??{}))e[a]={type:n.type,...n.description!=null&&{description:n.description},...n.enum&&{enum:n.enum},...n.default!==void 0&&{default:n.default}};return{type:"object",properties:e,required:[]}}function E(s){const{name:e,description:a,schema:n}=s;if(!_.test(e))throw new Error(`Invalid form collector name "${e}": must match ${_} (it becomes the update_/submit_ function names).`);const i=typeof s.submit=="string"?s.submit?{via:"client",url:s.submit}:!1:s.submit??!1;s.autoSubmit===!0&&!i&&N.logger.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);const c=(s.autoSubmit??!0)&&!!i,b=n.properties??{},f=t=>{const r={};for(const[u,o]of Object.entries(t)){const l=b[u];if(l)if(o==null)r[u]=o;else if(l.type==="number"||l.type==="integer"){const d=typeof o=="number"?o:Number(o);r[u]=Number.isNaN(d)?o:d}else l.type==="boolean"?r[u]=typeof o=="boolean"?o:o==="true"?!0:o==="false"?!1:!!o:r[u]=o}return r},y=s.initialValues??{},m=T({values:y,submitted:!1}),C=t=>{const r=m.get(),u={...r,values:{...r.values,...t}};return m.set(u),u};let h=null;const v=async()=>{const{values:t}=m.get(),{complete:r,missing:u}=g(n,t);if(!r)return{ok:!1,missing:u};if(!i)return{ok:!1,error:"No submit target configured for this form collector."};const o=t;try{let l;if(i.via==="client")if("handler"in i)l=await i.handler(o);else{const d=await fetch(i.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(o)});if(!d.ok)return{ok:!1,error:`Submit failed: HTTP ${d.status}`};l=await d.json().catch(()=>{})}else{if(!h)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};l=await h.submitFormCollector(e,o)}return m.set({...m.get(),submitted:!0,submitResult:l}),{ok:!0,result:l}}catch(l){const d=l instanceof Error?l.message:"Submit failed";return N.logger.error(`FormCollector "${e}" submit failed:`,l),{ok:!1,error:d}}},$=async()=>{if(!c||!i)return null;const{values:t,submitted:r}=m.get();return r||!g(n,t).complete?null:v()},w={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${a} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,parameters:A(n),handler:async t=>{const r=C(f(t)),{missing:u}=g(n,r.values),o=await $();return o?o.ok?{ok:!0,values:r.values,missing:u,submitted:!0}:{ok:!0,values:r.values,missing:u,submitted:!1,submitError:o.error}:{ok:!0,values:r.values,missing:u}}},p=[w];i&&!c&&p.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>v()});const W="client__",k=i?`submit_${e}`:null,x=t=>{const r=t.functionName??t.toolName;if(r)return r.startsWith(W)?r.slice(8):r},F=t=>{let r={...y},u=!1;for(const o of t){const l=x(o);l===w.name?o.arguments&&(r={...r,...f(o.arguments)}):k&&l===k&&o.status?.toLowerCase()==="done"&&(u=!0)}m.set({values:r,submitted:u})},S=`form:${e}`,q=()=>{const{values:t,submitted:r}=m.get(),{missing:u,complete:o}=g(n,t),l=i?c?" The form is submitted automatically as soon as every required field is filled, so there is no submit function to call.":` When nothing is missing and the user confirms, call submit_${e}.`:"",d=r?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${d} ${a} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(n)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${l}`,data:{values:t,missing:u,complete:o,submitted:r}}},O=t=>{F((t.messages??[]).flatMap(r=>r.toolCalls??[]))};return{name:e,store:m,functions:p,contextKey:S,contextProvider:q,install:t=>{h=t;for(const u of p)t.register(u);t.addDynamicContext(S,q);const r=m.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",O),()=>{r();for(const u of p)t.unregisterFunction(u.name);t.removeDynamicContext(S),t.off("conversation:loaded",O),h===t&&(h=null)}},hydrate:F,submit:v,getValues:()=>m.get().values,setValues:t=>{C(f(t)),$()},reset:()=>{m.set({values:y,submitted:!1})},getStatus:()=>g(n,m.get().values)}}async function I(s,e){const a=await s.getFormCollector(e.name);return E({name:a.name,description:e.description??a.description,schema:e.schema??a.schema,submit:e.submit??a.submit,initialValues:e.initialValues,autoSubmit:e.autoSubmit??a.autoSubmit})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return E}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return T}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return I}});
|
package/dist/devtools.d.cts
CHANGED
|
@@ -467,6 +467,8 @@ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
467
467
|
schema: FormCollectorSchema;
|
|
468
468
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
469
469
|
submit?: SubmitConfig<V>;
|
|
470
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
471
|
+
autoSubmit?: boolean;
|
|
470
472
|
}
|
|
471
473
|
|
|
472
474
|
/**
|
package/dist/devtools.d.ts
CHANGED
|
@@ -467,6 +467,8 @@ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
467
467
|
schema: FormCollectorSchema;
|
|
468
468
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
469
469
|
submit?: SubmitConfig<V>;
|
|
470
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
471
|
+
autoSubmit?: boolean;
|
|
470
472
|
}
|
|
471
473
|
|
|
472
474
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./AgoClient--y10UXUV.cjs"),m=require("./createFormCollector-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./AgoClient--y10UXUV.cjs"),m=require("./createFormCollector-DWzGKDwO.cjs"),p=require("./createConversationSession-BuMXp0Ia.cjs"),w=require("./createMockClient-zHQ0cjUH.cjs");require("./testing.cjs");const g=require("./functions-Djnq-JAo.cjs");function h(e){return e}function E(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function S(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function v(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function b(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function F(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*M(e,o,l){const a=[];let r=null,s=!1;const c=i=>{a.push(i),r?.()},f=i=>c({type:"start",data:i}),t=i=>c({type:"chunk",data:i}),u=i=>{c({type:"complete",data:i}),s=!0,r?.()},d=i=>{c({type:"error",data:i}),s=!0,r?.()},C=i=>c({type:"toolCall",data:i});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",d),e.on("toolCall:received",C),e.sendMessage(o,l).catch(()=>{s=!0,r?.()});try{for(;!s||a.length>0;)a.length>0?yield a.shift():(await new Promise(i=>{r=i}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",d),e.off("toolCall:received",C)}}function A(e){let o,l,a,r,s,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,a=t.agent||t.defaultAgent,r=t.permission,s=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),a=a||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),s=s||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,a=a||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,s=s||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,a=e?.agent||e?.defaultAgentId||a,r=e?.permission||r,s=e?.userEmail||s,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:a,permission:r,userEmail:s,userJwt:c,debug:f}:null}function k(e){const o=A(e);if(!o)throw new n.AgoError('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.',"config_missing_base_url");return new n.AgoClient(o)}function q(e,o){return{...e,handler:o}}exports.AgoApiError=n.AgoApiError;exports.AgoClient=n.AgoClient;exports.AgoError=n.AgoError;exports.AgoFunctionError=n.AgoFunctionError;exports.AgoNetworkError=n.AgoNetworkError;exports.AgoStreamError=n.AgoStreamError;exports.ClientContextRegistry=n.ClientContextRegistry;exports.EventEmitter=n.EventEmitter;exports.FunctionRegistry=n.FunctionRegistry;exports.SSEHandler=n.SSEHandler;exports.autoDetectConfig=A;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=k;exports.createConversationSession=p.createConversationSession;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=M;exports.createMockClient=w.createMockClient;exports.createStore=m.createStore;exports.defineFunction=h;exports.deriveFormStatus=m.deriveFormStatus;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=n.isStreamNetworkError;exports.loadFormCollector=m.loadFormCollector;exports.logger=n.logger;exports.onFunctionInvoke=F;exports.onMessage=E;exports.onMessageChunk=S;exports.onMessageError=v;exports.onMessageStart=y;exports.onToolCall=b;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.validateConfig=n.validateConfig;exports.withHandler=q;
|
package/dist/index.d.cts
CHANGED
|
@@ -742,6 +742,16 @@ export declare interface CreateFormCollectorOptions<V = Record<string, unknown>>
|
|
|
742
742
|
submit?: SubmitConfig<V>;
|
|
743
743
|
/** Pre-filled values. */
|
|
744
744
|
initialValues?: Partial<V>;
|
|
745
|
+
/**
|
|
746
|
+
* Submit on its own as soon as every required field is filled, without waiting
|
|
747
|
+
* for the agent or a UI button. The form submits at most once. Defaults to
|
|
748
|
+
* `true` whenever a `submit` target is set: when on, no `submit_<name>` function
|
|
749
|
+
* is exposed, the form submits itself, and the agent never confirms a submit.
|
|
750
|
+
* Pass `autoSubmit: false` to keep the manual flow (expose `submit_<name>` and
|
|
751
|
+
* submit only on an explicit call). Has no effect on a collect-only form (no
|
|
752
|
+
* `submit` target); setting it `true` there is ignored with a warning.
|
|
753
|
+
*/
|
|
754
|
+
autoSubmit?: boolean;
|
|
745
755
|
}
|
|
746
756
|
|
|
747
757
|
/**
|
|
@@ -897,6 +907,8 @@ export declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
897
907
|
schema: FormCollectorSchema;
|
|
898
908
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
899
909
|
submit?: SubmitConfig<V>;
|
|
910
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
911
|
+
autoSubmit?: boolean;
|
|
900
912
|
}
|
|
901
913
|
|
|
902
914
|
/**
|
|
@@ -915,6 +927,13 @@ export declare interface FormCollectorState<V = Record<string, unknown>> {
|
|
|
915
927
|
values: Partial<V>;
|
|
916
928
|
/** True once a submit succeeded. */
|
|
917
929
|
submitted: boolean;
|
|
930
|
+
/**
|
|
931
|
+
* The submit response, set once `submitted` is true: the resolved value of the
|
|
932
|
+
* client `handler`, the parsed JSON of a client `url` POST, or the backend
|
|
933
|
+
* relay result. Lets a UI surface a server-returned message. Undefined until
|
|
934
|
+
* a submit succeeds (and after `reset()`).
|
|
935
|
+
*/
|
|
936
|
+
submitResult?: unknown;
|
|
918
937
|
}
|
|
919
938
|
|
|
920
939
|
/** Completeness status derived from values + schema — computed on read, never stored. */
|
package/dist/index.d.ts
CHANGED
|
@@ -742,6 +742,16 @@ export declare interface CreateFormCollectorOptions<V = Record<string, unknown>>
|
|
|
742
742
|
submit?: SubmitConfig<V>;
|
|
743
743
|
/** Pre-filled values. */
|
|
744
744
|
initialValues?: Partial<V>;
|
|
745
|
+
/**
|
|
746
|
+
* Submit on its own as soon as every required field is filled, without waiting
|
|
747
|
+
* for the agent or a UI button. The form submits at most once. Defaults to
|
|
748
|
+
* `true` whenever a `submit` target is set: when on, no `submit_<name>` function
|
|
749
|
+
* is exposed, the form submits itself, and the agent never confirms a submit.
|
|
750
|
+
* Pass `autoSubmit: false` to keep the manual flow (expose `submit_<name>` and
|
|
751
|
+
* submit only on an explicit call). Has no effect on a collect-only form (no
|
|
752
|
+
* `submit` target); setting it `true` there is ignored with a warning.
|
|
753
|
+
*/
|
|
754
|
+
autoSubmit?: boolean;
|
|
745
755
|
}
|
|
746
756
|
|
|
747
757
|
/**
|
|
@@ -897,6 +907,8 @@ export declare interface FormCollectorDefinition<V = Record<string, unknown>> {
|
|
|
897
907
|
schema: FormCollectorSchema;
|
|
898
908
|
/** Server-stored submit target, if any. Absent means collect-only. */
|
|
899
909
|
submit?: SubmitConfig<V>;
|
|
910
|
+
/** Server-stored default for auto-submitting once the form is complete. */
|
|
911
|
+
autoSubmit?: boolean;
|
|
900
912
|
}
|
|
901
913
|
|
|
902
914
|
/**
|
|
@@ -915,6 +927,13 @@ export declare interface FormCollectorState<V = Record<string, unknown>> {
|
|
|
915
927
|
values: Partial<V>;
|
|
916
928
|
/** True once a submit succeeded. */
|
|
917
929
|
submitted: boolean;
|
|
930
|
+
/**
|
|
931
|
+
* The submit response, set once `submitted` is true: the resolved value of the
|
|
932
|
+
* client `handler`, the parsed JSON of a client `url` POST, or the backend
|
|
933
|
+
* relay result. Lets a UI surface a server-returned message. Undefined until
|
|
934
|
+
* a submit succeeds (and after `reset()`).
|
|
935
|
+
*/
|
|
936
|
+
submitResult?: unknown;
|
|
918
937
|
}
|
|
919
938
|
|
|
920
939
|
/** Completeness status derived from values + schema — computed on read, never stored. */
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as h, c as A, d as y, f as C, i as E, l as b, m as S, o as v, p as k, r as F, s as M, t as T, u as I } from "./functions-CApuQZ2b.js";
|
|
2
2
|
import { a as G, c as O, d as q, f as x, i as L, l as N, n as _, o as D, p as H, r as J, s as R, t as d, u as c } from "./AgoClient-DYdIe_R4.js";
|
|
3
|
-
import { i as B, n as P, r as $, t as z } from "./createFormCollector-
|
|
4
|
-
import { t as Q } from "./createConversationSession-
|
|
3
|
+
import { i as B, n as P, r as $, t as z } from "./createFormCollector-BwM7qTrp.js";
|
|
4
|
+
import { t as Q } from "./createConversationSession-CCT1hCf8.js";
|
|
5
5
|
import { t as W } from "./createMockClient-DwdxNwEn.js";
|
|
6
6
|
import "./testing.js";
|
|
7
7
|
function Y(e) {
|
package/dist/react.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-16Nf8qvH.cjs"),J=require("./AgoClient--y10UXUV.cjs"),M=require("./createFormCollector-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-16Nf8qvH.cjs"),J=require("./AgoClient--y10UXUV.cjs"),M=require("./createFormCollector-DWzGKDwO.cjs"),V=require("./createMockClient-zHQ0cjUH.cjs");let n=require("react");n=P.__toESM(n,1);let o=require("react/jsx-runtime"),F=require("react-markdown");F=P.__toESM(F,1);let N=require("remark-gfm");N=P.__toESM(N,1);function q(e){const[t,s]=(0,n.useState)(!1),r=(0,n.useRef)(null),a=(0,n.useMemo)(()=>{if(r.current&&(r.current.destroy(),r.current=null),!e)return null;const l=new J.AgoClient(e);return r.current=l,l},[e?.baseUrl,e?.widgetId]);return(0,n.useEffect)(()=>(s(!0),()=>{r.current?.destroy(),r.current=null}),[a]),(0,n.useEffect)(()=>{r.current&&e&&r.current.updateConfig({agent:e.agent,defaultAgentId:e.defaultAgentId,permission:e.permission,userEmail:e.userEmail,userJwt:e.userJwt,debug:e.debug,warnOnEmptyReply:e.warnOnEmptyReply})},[e?.agent,e?.defaultAgentId,e?.permission,e?.userEmail,e?.userJwt,e?.debug,e?.warnOnEmptyReply]),{client:a,isReady:t}}var T=(0,n.createContext)(null),G=({children:e,client:t,tools:s,helpers:r,pageContext:a,...l})=>{const{client:u}=q(t?null:l),i=t||u;return(0,n.useEffect)(()=>{if(!(!s||s.length===0)){for(const p of s)i.register(p);return()=>{for(const p of s)i.unregisterFunction(p.name)}}},[i,s]),(0,n.useEffect)(()=>{if(!r)return;const p=[];return Promise.resolve().then(()=>require("./functions-Djnq-JAo.cjs")).then(d=>d.functions_exports).then(d=>{for(const[h,C]of Object.entries(r)){const k=d[h];if(!k){console.warn(`[AGO] Unknown helper: "${h}"`);continue}const m=C===!0?k:{...k,handler:C};i.register(m),p.push(m.name)}}),()=>{for(const d of p)i.unregisterFunction(d)}},[i,r]),(0,n.useEffect)(()=>{a==="auto"&&i.enableAutoPageContext()},[i,a]),(0,o.jsx)(T.Provider,{value:i,children:e})};function A(){const e=(0,n.useContext)(T);if(!e)throw new Error('useAgoClient must be used within an <AgoProvider>. Wrap your component tree with <AgoProvider baseUrl="...">.');return e}function R(){return(0,n.useContext)(T)}function L({client:e,conversationId:t}={}){const s=R(),r=e||s;if(!r)throw new Error("useMessages requires an AgoClient. Either pass it as options.client or wrap your app in <AgoProvider>.");const[a,l]=(0,n.useState)([]),[u,i]=(0,n.useState)(t),[p,d]=(0,n.useState)(!1),[h,C]=(0,n.useState)(null);(0,n.useEffect)(()=>{t&&t!==u&&(i(t),k(t))},[t]);const k=async m=>{try{l(await r.getMessages(m))}catch(v){C(v instanceof Error?v:new Error("Failed to load messages"))}};return(0,n.useEffect)(()=>{const m=x=>{u||i(x.conversationId)},v=x=>{l(f=>{const w=f[f.length-1];return w&&w.id===x.messageId?[...f.slice(0,-1),{...w,content:w.content+x.content}]:f})},c=x=>{l(f=>{let w=-1;for(let S=f.length-1;S>=0;S--)if(f[S].role==="assistant"&&f[S].status==="IN_PROGRESS"){w=S;break}return w<0?f:[...f.slice(0,w),{...f[w],...x},...f.slice(w+1)]})},y=x=>{l(f=>{const w=f.findIndex(S=>S.id===x.id);return w>=0?[...f.slice(0,w),x,...f.slice(w+1)]:[...f,x]}),d(!1)},g=x=>{C(new Error(x.error)),d(!1)};return r.on("message:start",m),r.on("message:chunk",v),r.on("message:answer-complete",c),r.on("message:complete",y),r.on("message:error",g),()=>{r.off("message:start",m),r.off("message:chunk",v),r.off("message:answer-complete",c),r.off("message:complete",y),r.off("message:error",g)}},[r,u]),{messages:a,isLoading:p,error:h,sendMessage:(0,n.useCallback)(async(m,v)=>{d(!0),C(null);const c={id:`temp-${Date.now()}`,conversationId:u||"",content:m,role:"user",status:"DONE",createdAt:new Date},y={id:`temp-assistant-${Date.now()}`,conversationId:u||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date};l(g=>[...g,c,y]);try{const g=await r.sendMessage(m,{conversationId:u,files:v});return g.conversationId&&!u&&i(g.conversationId),l(x=>{const f=x.filter(S=>!S.id.startsWith("temp-")),w={...c,id:c.id.replace("temp-","user-"),conversationId:g.conversationId};return f.some(S=>S.id===g.id)?[...f,w].sort((S,_)=>new Date(S.createdAt).getTime()-new Date(_.createdAt).getTime()):[...f,w,g]}),g}catch(g){return C(g instanceof Error?g:new Error("Failed to send message")),d(!1),l(x=>x.filter(f=>!f.id.startsWith("temp-"))),null}},[r,u]),clearMessages:(0,n.useCallback)(()=>{l([]),i(void 0),C(null)},[]),conversationId:u}}var W=({onSend:e,disabled:t=!1,placeholder:s="Type a message...",allowFiles:r=!1,className:a=""})=>{const[l,u]=(0,n.useState)(""),[i,p]=(0,n.useState)([]),d=(0,n.useRef)(null),h=(0,n.useCallback)(c=>{c.preventDefault(),(l.trim()||i.length>0)&&(e(l.trim(),i.length>0?i:void 0),u(""),p([]))},[l,i,e]),C=(0,n.useCallback)(c=>{c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),h(c))},[h]),k=(0,n.useCallback)(c=>{const y=Array.from(c.target.files||[]);p(g=>[...g,...y])},[]),m=(0,n.useCallback)(c=>{p(y=>y.filter((g,x)=>x!==c))},[]),v=l.trim()||i.length>0;return(0,o.jsxs)("form",{onSubmit:h,className:`ago-chat-input ${a}`,style:{display:"flex",flexDirection:"column",gap:"8px",padding:"12px 16px",borderTop:"1px solid #dee3e8",backgroundColor:"#fff"},children:[i.length>0&&(0,o.jsx)("div",{className:"ago-chat-input__files",style:{display:"flex",flexWrap:"wrap",gap:"6px"},children:i.map((c,y)=>(0,o.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"6px",padding:"4px 10px",backgroundColor:"#f0f2f5",borderRadius:"6px",fontSize:"12px",color:"#30373e"},children:[(0,o.jsx)("span",{style:{maxWidth:"120px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:c.name}),(0,o.jsx)("button",{type:"button",onClick:()=>m(y),style:{border:"none",background:"none",cursor:"pointer",padding:"0",color:"#6b6d6f",fontSize:"14px",lineHeight:1},children:"×"})]},y))}),(0,o.jsxs)("div",{style:{display:"flex",gap:"8px",alignItems:"flex-end"},children:[r&&(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)("button",{type:"button",onClick:()=>d.current?.click(),disabled:t,style:{padding:"8px",border:"1px solid #dee3e8",borderRadius:"8px",backgroundColor:"#fff",cursor:t?"not-allowed":"pointer",color:"#6b6d6f",fontSize:"16px",lineHeight:1},children:"+"}),(0,o.jsx)("input",{ref:d,type:"file",multiple:!0,onChange:k,style:{display:"none"}})]}),(0,o.jsx)("textarea",{value:l,onChange:c=>u(c.target.value),onKeyDown:C,placeholder:s,disabled:t,rows:1,style:{flex:1,padding:"10px 14px",border:"1px solid #dee3e8",borderRadius:"20px",resize:"none",outline:"none",fontFamily:"inherit",fontSize:"16px",color:"#30373e",backgroundColor:"#f8f8f8",transition:"border-color 0.15s"},onFocus:c=>{c.currentTarget.style.borderColor="#1b5fc4"},onBlur:c=>{c.currentTarget.style.borderColor="#dee3e8"}}),(0,o.jsx)("button",{type:"submit",disabled:t||!v,style:{padding:"10px 18px",border:"none",borderRadius:"20px",backgroundColor:t||!v?"#b5bfc8":"#03182f",color:"#fff",cursor:t||!v?"not-allowed":"pointer",fontWeight:500,fontSize:"16px",transition:"background-color 0.15s"},children:"Send"})]})]})},X=({href:e,children:t,...s})=>(0,o.jsx)("a",{href:e,target:"_blank",rel:"noopener noreferrer",style:{color:"#1b5fc4",textDecoration:"underline"},...s,children:t}),Y=({children:e,...t})=>(0,o.jsx)("p",{style:{margin:"0 0 8px 0",lineHeight:"1.6"},...t,children:e}),I=(e,t)=>{const s=({children:r,...a})=>n.default.createElement(`h${e}`,{style:{margin:"16px 0 8px 0",fontSize:t,fontWeight:600,lineHeight:"1.3"},...a},r);return s.displayName=`MarkdownHeading${e}`,s},Q=({children:e,...t})=>(0,o.jsx)("ul",{style:{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:"disc",listStylePosition:"outside"},...t,children:e}),Z=({children:e,...t})=>(0,o.jsx)("ol",{style:{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:"decimal",listStylePosition:"outside"},...t,children:e}),ee=({children:e,...t})=>(0,o.jsx)("li",{style:{display:"list-item",margin:"2px 0",lineHeight:"1.6"},...t,children:e}),te=({className:e,children:t,...s})=>e!==void 0||String(t).includes(`
|
|
2
2
|
`)?(0,o.jsx)("code",{style:{display:"block",background:"#f5f5f5",padding:"8px 12px",borderRadius:"6px",fontSize:"13px",overflowX:"auto",fontFamily:'"IBM Plex Mono", monospace'},...s,children:t}):(0,o.jsx)("code",{style:{background:"#f0f2f5",padding:"2px 5px",borderRadius:"4px",fontSize:"13px",fontFamily:'"IBM Plex Mono", monospace'},...s,children:t}),re=({children:e,...t})=>(0,o.jsx)("pre",{style:{margin:"0 0 8px 0"},...t,children:e}),ne=({children:e,...t})=>(0,o.jsx)("blockquote",{style:{borderLeft:"4px solid #dee3e8",paddingLeft:"12px",margin:"0 0 8px 0",fontStyle:"italic",color:"#6b6d6f"},...t,children:e}),oe=({children:e,...t})=>(0,o.jsx)("div",{style:{overflowX:"auto",margin:"0 0 8px 0"},children:(0,o.jsx)("table",{style:{borderCollapse:"collapse",width:"100%",fontSize:"13px"},...t,children:e})}),se=({children:e,...t})=>(0,o.jsx)("th",{style:{border:"1px solid #dee3e8",padding:"6px 10px",textAlign:"left",backgroundColor:"#f5f7fa",fontWeight:600},...t,children:e}),ae=({children:e,...t})=>(0,o.jsx)("td",{style:{border:"1px solid #dee3e8",padding:"6px 10px"},...t,children:e}),le=({alt:e,...t})=>(0,o.jsx)("img",{alt:e??"",style:{maxWidth:"100%",borderRadius:"8px",margin:"4px 0"},...t}),ie=e=>(0,o.jsx)("hr",{style:{border:"none",borderTop:"1px solid #dee3e8",margin:"12px 0"},...e}),ce={a:X,p:Y,h1:I(1,"20px"),h2:I(2,"18px"),h3:I(3,"16px"),h4:I(4,"15px"),h5:I(5,"14px"),h6:I(6,"13px"),ul:Q,ol:Z,li:ee,code:te,pre:re,blockquote:ne,table:oe,th:se,td:ae,img:le,hr:ie},de=[N.default],z=({content:e})=>(0,o.jsx)(F.default,{remarkPlugins:de,components:ce,children:e}),ue=({source:e,index:t})=>{const s=(0,o.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"8px",width:"100%",minWidth:0},children:[(0,o.jsx)("div",{style:{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"},children:t+1}),(0,o.jsx)("div",{style:{fontSize:"12px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"#30373e"},title:e.title,children:e.title})]}),r={display:"flex",alignItems:"center",padding:"8px 10px",border:"1px solid #dee3e8",borderRadius:"8px",backgroundColor:"#fff",cursor:e.url?"pointer":"default",textDecoration:"none",color:"inherit",minWidth:0,transition:"border-color 0.15s"};return e.url?(0,o.jsx)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",style:r,onMouseEnter:a=>{a.currentTarget.style.borderColor="#1b5fc4"},onMouseLeave:a=>{a.currentTarget.style.borderColor="#dee3e8"},children:s}):(0,o.jsx)("div",{style:r,children:s})},fe=()=>(0,o.jsxs)("div",{style:{display:"flex",gap:"4px",padding:"4px 0"},children:[[0,1,2].map(e=>(0,o.jsx)("div",{style:{width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${e*.2}s`}},e)),(0,o.jsx)("style",{children:`
|
|
3
3
|
@keyframes ago-pulse {
|
|
4
4
|
0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
|
|
5
5
|
40% { opacity: 1; transform: scale(1); }
|
|
6
6
|
}
|
|
7
|
-
`})]}),O=({message:e,className:t="",showAgentName:s=!1,isLast:r=!1,onFollowUpClick:a})=>{const l=e.role==="user",u=e.status==="IN_PROGRESS";return(0,o.jsxs)("div",{className:`ago-message ago-message--${e.role} ${t}`,style:{display:"flex",flexDirection:"column",alignItems:l?"flex-end":"flex-start",marginBottom:"16px"},children:[!l&&s&&e.agent&&(0,o.jsx)("div",{className:"ago-message__agent",style:{display:"flex",alignItems:"center",gap:"6px",fontSize:"13px",fontWeight:500,color:"#30373e",marginBottom:"6px",padding:"0 4px"},children:e.agent.displayName||e.agent.name}),!l&&e.sources&&e.sources.length>0&&(0,o.jsx)("div",{className:"ago-message__sources",style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"},children:e.sources.map((i,p)=>(0,o.jsx)(ue,{source:i,index:p},i.id))}),(0,o.jsx)("div",{className:"ago-message__content",style:{maxWidth:l?"75%":"100%",padding:l?"10px 14px":"2px 8px",borderRadius:l?"16px":"0",backgroundColor:l?"#03182f":"transparent",color:l?"#fff":"#30373e",wordBreak:"break-word",fontSize:"
|
|
7
|
+
`})]}),O=({message:e,className:t="",showAgentName:s=!1,isLast:r=!1,onFollowUpClick:a})=>{const l=e.role==="user",u=e.status==="IN_PROGRESS";return(0,o.jsxs)("div",{className:`ago-message ago-message--${e.role} ${t}`,style:{display:"flex",flexDirection:"column",alignItems:l?"flex-end":"flex-start",marginBottom:"16px"},children:[!l&&s&&e.agent&&(0,o.jsx)("div",{className:"ago-message__agent",style:{display:"flex",alignItems:"center",gap:"6px",fontSize:"13px",fontWeight:500,color:"#30373e",marginBottom:"6px",padding:"0 4px"},children:e.agent.displayName||e.agent.name}),!l&&e.sources&&e.sources.length>0&&(0,o.jsx)("div",{className:"ago-message__sources",style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"},children:e.sources.map((i,p)=>(0,o.jsx)(ue,{source:i,index:p},i.id))}),(0,o.jsx)("div",{className:"ago-message__content",style:{maxWidth:l?"75%":"100%",padding:l?"10px 14px":"2px 8px",borderRadius:l?"16px":"0",backgroundColor:l?"#03182f":"transparent",color:l?"#fff":"#30373e",wordBreak:"break-word",fontSize:"16px",lineHeight:"1.6"},children:e.content?(0,o.jsx)(z,{content:e.content}):u&&(0,o.jsx)(fe,{})}),r&&e.followUpReplies&&e.followUpReplies.length>0&&(0,o.jsx)("div",{className:"ago-message__followups",style:{display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"},children:e.followUpReplies.map((i,p)=>(0,o.jsx)("button",{type:"button",className:"ago-message__followup-btn",disabled:!a,onClick:a?()=>a(i):void 0,style:{padding:"6px 14px",fontSize:"13px",borderRadius:"16px",border:"1px solid #dee3e8",backgroundColor:"#fff",color:"#30373e",cursor:a?"pointer":"default",transition:"border-color 0.15s"},onMouseEnter:d=>{d.currentTarget.style.borderColor="#1b5fc4"},onMouseLeave:d=>{d.currentTarget.style.borderColor="#dee3e8"},children:i},p))})]})},ge=({client:e,conversationId:t,title:s="Chat",welcomeMessage:r="Hello! How can I help you today?",placeholder:a="Type a message...",allowFiles:l=!1,height:u=500,logoUrl:i,showAgentName:p=!1,forms:d,onFollowUpClick:h,className:C="",onMessageSent:k,onMessageReceived:m})=>{const v=(0,n.useRef)(null),c=R(),y=e??c,{messages:g,isLoading:x,error:f,sendMessage:w}=L({client:e,conversationId:t});(0,n.useEffect)(()=>{if(!y||!d||d.length===0)return;let b=!1;const j=[];return Promise.all(d.map(E=>E.schema!=null?Promise.resolve(M.createFormCollector(E)):M.loadFormCollector(y,E))).then(E=>{if(!b)for(const U of E)j.push(U.install(y))}).catch(()=>{}),()=>{b=!0,j.forEach(E=>E())}},[y,d?JSON.stringify(d.map(b=>[b.name,b.schema??null,b.submit??!1,b.description??null])):""]),(0,n.useEffect)(()=>{v.current?.scrollIntoView({behavior:"smooth"})},[g]),(0,n.useEffect)(()=>{const b=g[g.length-1];b&&b.role==="assistant"&&b.status==="DONE"&&m&&m({id:b.id,content:b.content})},[g,m]);const S=async(b,j)=>{k?.(b),await w(b,j)},_=g[g.length-1],B=x&&_?.role==="assistant"&&_.status==="IN_PROGRESS",K=h===!1?void 0:h??(b=>S(b));return(0,o.jsxs)("div",{className:`ago-chat-widget ${C}`,style:{display:"flex",flexDirection:"column",height:typeof u=="number"?`${u}px`:u,border:"1px solid #dee3e8",borderRadius:"16px",overflow:"hidden",backgroundColor:"#fff",fontFamily:'"IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',textAlign:"left",boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"},children:[(0,o.jsxs)("div",{className:"ago-chat-widget__header",style:{padding:"14px 16px",borderBottom:"1px solid #dee3e8",backgroundColor:"#03182f",color:"#e8f0fe",display:"flex",alignItems:"center",gap:"10px"},children:[i&&(0,o.jsx)("img",{src:i,alt:"Logo",style:{height:"24px",width:"auto"}}),(0,o.jsx)("h3",{style:{margin:0,fontSize:"15px",fontWeight:600},children:s})]}),(0,o.jsxs)("div",{className:"ago-chat-widget__messages",style:{flex:1,overflow:"auto",padding:"16px",backgroundColor:"#fbfbfb"},children:[g.length===0?(0,o.jsx)("div",{style:{textAlign:"center",color:"#6b6d6f",padding:"24px 16px",fontSize:"16px",lineHeight:"1.5"},children:r}):g.map((b,j)=>(0,o.jsx)(O,{message:b,showAgentName:p,isLast:j===g.length-1,onFollowUpClick:K},b.id)),f&&(0,o.jsx)("div",{style:{padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"},children:f.message}),(0,o.jsx)("div",{ref:v})]}),(0,o.jsx)(W,{onSend:S,disabled:B,placeholder:a,allowFiles:l})]})};function H({client:e,autoLoad:t=!0}={}){const s=R(),r=e||s;if(!r)throw new Error("useConversation requires an AgoClient. Either pass it as options.client or wrap your app in <AgoProvider>.");const[a,l]=(0,n.useState)([]),[u,i]=(0,n.useState)(null),[p,d]=(0,n.useState)(!1),[h,C]=(0,n.useState)(null),k=(0,n.useCallback)(async()=>{d(!0),C(null);try{l(await r.getConversations())}catch(c){C(c instanceof Error?c:new Error("Failed to load conversations"))}finally{d(!1)}},[r]),m=(0,n.useCallback)(async c=>{d(!0),C(null);try{i(await r.getConversation(c))}catch(y){C(y instanceof Error?y:new Error("Failed to load conversation"))}finally{d(!1)}},[r]),v=(0,n.useCallback)(()=>{i(null)},[]);return(0,n.useEffect)(()=>{t&&k()},[t,k]),{conversations:a,currentConversation:u,isLoading:p,error:h,selectConversation:m,startNewConversation:v,refreshConversations:k}}function pe(e={}){const t=R(),s=e.client||t;if(!s)throw new Error("useChat requires an AgoClient. Either pass it as options.client or wrap your app in <AgoProvider>.");const r=L({client:s,conversationId:e.conversationId}),a=H({client:s,autoLoad:e.autoLoad});return{messages:r.messages,isLoading:r.isLoading,error:r.error||a.error,sendMessage:r.sendMessage,clearMessages:r.clearMessages,conversationId:r.conversationId,conversations:a.conversations,currentConversation:a.currentConversation,isConversationsLoading:a.isLoading,selectConversation:a.selectConversation,startNewConversation:a.startNewConversation,refreshConversations:a.refreshConversations}}function xe(e,t){const s=A(),{name:r,description:a,parameters:l,handler:u}=typeof e=="string"?{name:e,...t}:e,i=(0,n.useRef)(u);i.current=u,(0,n.useEffect)(()=>{const p=d=>i.current(d);return s.registerFunction(r,p,{description:a,parameters:l}),()=>{s.unregisterFunction(r)}},[s,r,a,l])}function me(e,t){const s=A(),r=(0,n.useRef)(e);r.current=e,(0,n.useEffect)(()=>(s.registerNavigationFunction(a=>r.current(a),t),()=>{s.unregisterFunction("navigateToPage")}),[s,t])}function he(e,t){const s=A(),r=(0,n.useId)(),a=t??r,l=(0,n.useRef)(e);l.current=e;const u=typeof e=="function";(0,n.useEffect)(()=>{if(typeof l.current=="function"){const i=()=>l.current();return s.addDynamicContext(a,i),()=>{s.removeDynamicContext(a)}}return s.setContext(a,l.current),()=>{s.removeContext(a)}},[s,a,u,u?"":JSON.stringify(e)])}function $(e){return(0,n.useSyncExternalStore)(e.subscribe,e.get,e.get)}var D={missing:[],complete:!1};function ye(e){const t=A(),s=e.schema!=null,r=JSON.stringify(e.schema??null),a=e.submit,l=a?typeof a=="string"?`client:${a}`:a.via==="backend"?"backend":"handler"in a?"client:handler":`client:${a.url}`:"none",u=JSON.stringify(e.initialValues??null),i=(0,n.useMemo)(()=>s?M.createFormCollector(e):null,[s,e.name,r,l,u,e.autoSubmit]),[p,d]=(0,n.useState)({collector:null,loading:!s,error:null});(0,n.useEffect)(()=>{if(s)return;let x=!1;return d({collector:null,loading:!0,error:null}),M.loadFormCollector(t,e).then(f=>{x||d({collector:f,loading:!1,error:null})}).catch(f=>{x||d({collector:null,loading:!1,error:f instanceof Error?f:new Error(String(f))})}),()=>{x=!0}},[t,s,e.name,l,u,e.autoSubmit]);const h=s?i:p.collector,C=s?!1:p.loading,k=s?null:p.error;(0,n.useEffect)(()=>{if(h)return h.install(t)},[t,h]);const m=(0,n.useMemo)(()=>M.createStore({values:e.initialValues??{},submitted:!1}),[u]),v=$(h?.store??m),c=(0,n.useMemo)(()=>h?.getStatus()??D,[v,h]),y=(0,n.useMemo)(()=>({...v,...c}),[v,c]),g=(0,n.useMemo)(()=>({name:e.name,store:m,functions:[],contextKey:`form:${e.name}`,contextProvider:()=>({name:`Form: ${e.name}`,description:""}),install:()=>()=>{},hydrate:()=>{},submit:async()=>({ok:!1,error:"Form definition not loaded yet."}),getValues:()=>m.get().values,setValues:()=>{},reset:()=>{},getStatus:()=>D}),[e.name,m]);return{...h??g,state:y,loading:C,error:k}}exports.AgoProvider=G;exports.ChatInput=W;exports.ChatWidget=ge;exports.Markdown=z;exports.Message=O;exports.createFormCollector=M.createFormCollector;exports.createMockClient=V.createMockClient;exports.deriveFormStatus=M.deriveFormStatus;exports.loadFormCollector=M.loadFormCollector;exports.useAgo=q;exports.useAgoClient=A;exports.useAgoContext=he;exports.useAgoFunction=xe;exports.useAgoNavigation=me;exports.useAgoStore=$;exports.useChat=pe;exports.useConversation=H;exports.useFormCollector=ye;exports.useMessages=L;exports.useOptionalAgoClient=R;
|