@useago/sdk 1.5.0 → 1.5.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/CHANGELOG.md +48 -0
- package/dist/AgoClient-5VGybmvz.cjs +8 -0
- package/dist/AgoClient-DXrH2AMi.js +964 -0
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +79 -2
- package/dist/angular.d.ts +79 -2
- package/dist/angular.js +2 -2
- package/dist/{createConversationSession-BBYfQLLS.cjs → createConversationSession-0WTqcCLK.cjs} +1 -1
- package/dist/{createConversationSession-DCSWShaW.js → createConversationSession-DPrrr70o.js} +1 -1
- package/dist/createFormCollector-1GKKwQV_.cjs +1 -0
- package/dist/{createFormCollector-sB6rMccD.js → createFormCollector-DYh90kiG.js} +97 -91
- package/dist/devtools.d.cts +79 -2
- package/dist/devtools.d.ts +79 -2
- package/dist/functions-CPs7omgM.cjs +1 -0
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.d.cts +5 -0
- package/dist/helpers.d.ts +5 -0
- package/dist/helpers.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +95 -4
- package/dist/index.d.ts +95 -4
- package/dist/index.js +6 -6
- package/dist/react.cjs +3 -3
- package/dist/react.d.cts +186 -4
- package/dist/react.d.ts +186 -4
- package/dist/react.js +670 -475
- package/dist/testing.cjs +1 -1
- package/dist/testing.d.cts +79 -2
- package/dist/testing.d.ts +79 -2
- package/dist/testing.js +1 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +79 -2
- package/dist/vue.d.ts +79 -2
- package/dist/vue.js +1 -1
- package/dist/widget.cjs +4 -4
- package/dist/widget.d.cts +79 -2
- package/dist/widget.d.ts +79 -2
- package/dist/widget.js +437 -423
- package/llms-full.txt +74 -2
- package/package.json +1 -1
- package/dist/AgoClient-q39FIjSC.js +0 -912
- package/dist/AgoClient-wcPRaIMs.cjs +0 -8
- package/dist/createFormCollector-eimwwWEi.cjs +0 -1
- package/dist/functions-IGSjjvF4.cjs +0 -1
- package/dist/rolldown-runtime-16Nf8qvH.cjs +0 -1
- /package/dist/{autoContinue-D3Mmaaca.js → autoContinue-CC8K9mBU.js} +0 -0
- /package/dist/{autoContinue-CcCTva-D.cjs → autoContinue-CP9pJR-V.cjs} +0 -0
- /package/dist/{createMockClient-CjdCqixj.cjs → createMockClient-C-wrjb2C.cjs} +0 -0
- /package/dist/{createMockClient-BUc9PSbo.js → createMockClient-we-XoPom.js} +0 -0
- /package/dist/{functions-CApuQZ2b.js → functions-tzyOZNp6.js} +0 -0
|
@@ -0,0 +1,964 @@
|
|
|
1
|
+
var m = class extends Error {
|
|
2
|
+
constructor(t, e, s) {
|
|
3
|
+
super(t), this.code = e, this.statusCode = s, this.name = "AgoError";
|
|
4
|
+
}
|
|
5
|
+
}, p = class x extends m {
|
|
6
|
+
constructor(e, s, i, n, o, a) {
|
|
7
|
+
super(e, s, i), this.type = n, this.param = o, this.docUrl = a, this.name = "AgoApiError";
|
|
8
|
+
}
|
|
9
|
+
static fromResponse(e, s) {
|
|
10
|
+
const i = e.error;
|
|
11
|
+
return new x(i.doc_url ? `${i.message} See ${i.doc_url}` : i.message, i.code, s, i.type, i.param, i.doc_url);
|
|
12
|
+
}
|
|
13
|
+
}, v = class extends m {
|
|
14
|
+
constructor(t, e) {
|
|
15
|
+
super(t, "network_error"), this.originalError = e, this.name = "AgoNetworkError";
|
|
16
|
+
}
|
|
17
|
+
}, _ = class extends m {
|
|
18
|
+
constructor(t, e = "stream_error") {
|
|
19
|
+
super(t, e), this.name = "AgoStreamError";
|
|
20
|
+
}
|
|
21
|
+
}, E = class extends m {
|
|
22
|
+
constructor(t, e, s) {
|
|
23
|
+
super(t, "function_error"), this.functionName = e, this.originalError = s, this.name = "AgoFunctionError";
|
|
24
|
+
}
|
|
25
|
+
}, F = class {
|
|
26
|
+
constructor(t = !1) {
|
|
27
|
+
this.enabled = t;
|
|
28
|
+
}
|
|
29
|
+
enable() {
|
|
30
|
+
this.enabled = !0;
|
|
31
|
+
}
|
|
32
|
+
disable() {
|
|
33
|
+
this.enabled = !1;
|
|
34
|
+
}
|
|
35
|
+
log(...t) {
|
|
36
|
+
this.enabled && console.log("[AGO SDK]", ...t);
|
|
37
|
+
}
|
|
38
|
+
warn(...t) {
|
|
39
|
+
this.enabled && console.warn("[AGO SDK]", ...t);
|
|
40
|
+
}
|
|
41
|
+
error(...t) {
|
|
42
|
+
console.error("[AGO SDK]", ...t);
|
|
43
|
+
}
|
|
44
|
+
debug(...t) {
|
|
45
|
+
this.enabled && console.debug("[AGO SDK]", ...t);
|
|
46
|
+
}
|
|
47
|
+
}, c = new F(), R = "ago_widget_id";
|
|
48
|
+
function I() {
|
|
49
|
+
if (typeof localStorage < "u") {
|
|
50
|
+
const e = localStorage.getItem(R);
|
|
51
|
+
if (e) return e;
|
|
52
|
+
}
|
|
53
|
+
const t = typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `ago-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
54
|
+
if (typeof localStorage < "u") try {
|
|
55
|
+
localStorage.setItem(R, t);
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
return t;
|
|
59
|
+
}
|
|
60
|
+
var U = class {
|
|
61
|
+
constructor(t) {
|
|
62
|
+
this.baseUrl = t.baseUrl.replace(/\/$/, ""), this.headers = { "X-User-Anon-Id": t.widgetId || I() }, t.userEmail && (this.headers["X-User-Email"] = t.userEmail), t.userJwt && (this.headers.Authorization = `Bearer ${t.userJwt}`), t.permission && (this.headers["X-Widget-Permission"] = t.permission);
|
|
63
|
+
}
|
|
64
|
+
updateConfig(t) {
|
|
65
|
+
t.baseUrl && (this.baseUrl = t.baseUrl.replace(/\/$/, "")), t.widgetId && (this.headers["X-User-Anon-Id"] = t.widgetId), t.userEmail && (this.headers["X-User-Email"] = t.userEmail), t.userJwt && (this.headers.Authorization = `Bearer ${t.userJwt}`), t.permission !== void 0 && (t.permission ? this.headers["X-Widget-Permission"] = t.permission : delete this.headers["X-Widget-Permission"]);
|
|
66
|
+
}
|
|
67
|
+
async get(t) {
|
|
68
|
+
return this.request("GET", t);
|
|
69
|
+
}
|
|
70
|
+
async post(t, e) {
|
|
71
|
+
return this.request("POST", t, e);
|
|
72
|
+
}
|
|
73
|
+
async postStream(t, e) {
|
|
74
|
+
const s = `${this.baseUrl}${t}`;
|
|
75
|
+
c.debug("POST (stream)", s, e);
|
|
76
|
+
try {
|
|
77
|
+
const i = await fetch(s, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
...this.headers,
|
|
81
|
+
"Content-Type": "application/json"
|
|
82
|
+
},
|
|
83
|
+
body: e ? JSON.stringify(e) : void 0
|
|
84
|
+
});
|
|
85
|
+
return i.ok || await this.handleErrorResponse(i), i;
|
|
86
|
+
} catch (i) {
|
|
87
|
+
throw i instanceof p ? i : new v(`Network error: ${i instanceof Error ? i.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, i instanceof Error ? i : void 0);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async postFormData(t, e) {
|
|
91
|
+
const s = `${this.baseUrl}${t}`;
|
|
92
|
+
c.debug("POST (formData)", s);
|
|
93
|
+
const i = { ...this.headers };
|
|
94
|
+
try {
|
|
95
|
+
const n = await fetch(s, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: i,
|
|
98
|
+
body: e
|
|
99
|
+
});
|
|
100
|
+
return n.ok || await this.handleErrorResponse(n), n;
|
|
101
|
+
} catch (n) {
|
|
102
|
+
throw n instanceof p ? n : new v(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async request(t, e, s) {
|
|
106
|
+
const i = `${this.baseUrl}${e}`;
|
|
107
|
+
c.debug(t, i, s);
|
|
108
|
+
try {
|
|
109
|
+
const n = await fetch(i, {
|
|
110
|
+
method: t,
|
|
111
|
+
headers: {
|
|
112
|
+
...this.headers,
|
|
113
|
+
"Content-Type": "application/json"
|
|
114
|
+
},
|
|
115
|
+
body: s ? JSON.stringify(s) : void 0
|
|
116
|
+
});
|
|
117
|
+
return n.ok || await this.handleErrorResponse(n), n.status === 204 ? void 0 : n.json();
|
|
118
|
+
} catch (n) {
|
|
119
|
+
throw n instanceof p ? n : new v(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async handleErrorResponse(t) {
|
|
123
|
+
let e;
|
|
124
|
+
try {
|
|
125
|
+
e = await t.json();
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
if (e?.error) throw p.fromResponse(e, t.status);
|
|
129
|
+
let s = "";
|
|
130
|
+
throw t.status === 401 || t.status === 403 ? s = " Check `userJwt` (and that it has not expired)." : t.status === 404 && (s = " Check that `baseUrl` points at your AGO API root."), new p(`HTTP ${t.status}: ${t.statusText}.${s}`, "http_error", t.status, "api_error");
|
|
131
|
+
}
|
|
132
|
+
}, N = 5e4, T = 2e4, D = 2e3, P = class {
|
|
133
|
+
constructor(t) {
|
|
134
|
+
this.functions = /* @__PURE__ */ new Map(), this.defaultMaxResultBytes = t?.maxResultBytes ?? N;
|
|
135
|
+
}
|
|
136
|
+
setDefaultMaxResultBytes(t) {
|
|
137
|
+
this.defaultMaxResultBytes = t;
|
|
138
|
+
}
|
|
139
|
+
register(t, e, s) {
|
|
140
|
+
if (typeof t == "object") {
|
|
141
|
+
const { name: r, handler: l, description: u, parameters: h, maxResultBytes: d, requiresApproval: g } = t;
|
|
142
|
+
return this.register(r, l, {
|
|
143
|
+
description: u,
|
|
144
|
+
parameters: h,
|
|
145
|
+
maxResultBytes: d,
|
|
146
|
+
requiresApproval: g
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const i = t;
|
|
150
|
+
if (!e || !s) throw new m(`registerFunction("${i}"): both a handler and a schema are required. Pass them as arguments or use the single-object form: registerFunction({ name, parameters, handler }).`, "function_invalid_registration");
|
|
151
|
+
this.functions.has(i) && c.warn(`Function "${i}" is being overwritten`);
|
|
152
|
+
const { maxResultBytes: n, requiresApproval: o, ...a } = s;
|
|
153
|
+
this.functions.set(i, {
|
|
154
|
+
schema: {
|
|
155
|
+
...a,
|
|
156
|
+
name: i
|
|
157
|
+
},
|
|
158
|
+
handler: e,
|
|
159
|
+
maxResultBytes: n,
|
|
160
|
+
requiresApproval: o
|
|
161
|
+
}), c.log(`Registered function: ${i}`);
|
|
162
|
+
}
|
|
163
|
+
unregister(t) {
|
|
164
|
+
const e = this.functions.delete(t);
|
|
165
|
+
return e && c.log(`Unregistered function: ${t}`), e;
|
|
166
|
+
}
|
|
167
|
+
get(t) {
|
|
168
|
+
return this.functions.get(t);
|
|
169
|
+
}
|
|
170
|
+
has(t) {
|
|
171
|
+
return this.functions.has(t);
|
|
172
|
+
}
|
|
173
|
+
getSchemas() {
|
|
174
|
+
return Array.from(this.functions.values()).map((t) => t.schema);
|
|
175
|
+
}
|
|
176
|
+
async execute(t, e) {
|
|
177
|
+
const s = this.functions.get(t);
|
|
178
|
+
if (!s) throw new E(`Function "${t}" is not registered`, t);
|
|
179
|
+
c.log(`Executing function: ${t}`, e);
|
|
180
|
+
try {
|
|
181
|
+
const i = await s.handler(e);
|
|
182
|
+
return c.log(`Function ${t} completed:`, i), this.guardResultSize(t, i, s.maxResultBytes);
|
|
183
|
+
} catch (i) {
|
|
184
|
+
throw c.error(`Function ${t} failed:`, i), new E(`Function "${t}" execution failed: ${i instanceof Error ? i.message : "Unknown error"}`, t, i instanceof Error ? i : void 0);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
guardResultSize(t, e, s) {
|
|
188
|
+
let i;
|
|
189
|
+
try {
|
|
190
|
+
i = JSON.stringify(e);
|
|
191
|
+
} catch {
|
|
192
|
+
return e;
|
|
193
|
+
}
|
|
194
|
+
if (i === void 0) return e;
|
|
195
|
+
const n = new TextEncoder().encode(i).length, o = s ?? this.defaultMaxResultBytes;
|
|
196
|
+
return n > o ? (c.warn(`Function "${t}" result is ${n} bytes, over the ${o}-byte limit; a truncated preview was sent to the agent instead. Return fewer fields, paginate, or raise maxResultBytes for this function.`), {
|
|
197
|
+
truncated: !0,
|
|
198
|
+
originalBytes: n,
|
|
199
|
+
maxBytes: o,
|
|
200
|
+
preview: i.slice(0, D),
|
|
201
|
+
hint: `The result of "${t}" exceeded the ${o}-byte limit and was truncated. Request less data (use limit or filter parameters if available), or tell the user the result is too large to process.`
|
|
202
|
+
}) : (n > T && c.warn(`Function "${t}" returned a large result (${Math.round(n / 1024)} KB). Large results consume LLM context: return fewer fields, paginate, or push the data to the UI and return a summary.`), e);
|
|
203
|
+
}
|
|
204
|
+
clear() {
|
|
205
|
+
this.functions.clear(), c.log("Cleared all registered functions");
|
|
206
|
+
}
|
|
207
|
+
get size() {
|
|
208
|
+
return this.functions.size;
|
|
209
|
+
}
|
|
210
|
+
}, j = class {
|
|
211
|
+
constructor() {
|
|
212
|
+
this.entries = /* @__PURE__ */ new Map(), this.dynamicProviders = /* @__PURE__ */ new Map();
|
|
213
|
+
}
|
|
214
|
+
set(t, e) {
|
|
215
|
+
this.entries.set(t, e), c.log(`ClientContext set: ${t}`);
|
|
216
|
+
}
|
|
217
|
+
remove(t) {
|
|
218
|
+
const e = this.entries.delete(t);
|
|
219
|
+
return e && c.log(`ClientContext removed: ${t}`), e;
|
|
220
|
+
}
|
|
221
|
+
addDynamicProvider(t, e) {
|
|
222
|
+
this.dynamicProviders.set(t, e), c.log(`DynamicContext provider added: ${t}`);
|
|
223
|
+
}
|
|
224
|
+
removeDynamicProvider(t) {
|
|
225
|
+
const e = this.dynamicProviders.delete(t);
|
|
226
|
+
return e && c.log(`DynamicContext provider removed: ${t}`), e;
|
|
227
|
+
}
|
|
228
|
+
getSnapshot() {
|
|
229
|
+
if (this.entries.size === 0 && this.dynamicProviders.size === 0) return null;
|
|
230
|
+
const t = {};
|
|
231
|
+
for (const [e, s] of this.entries) t[e] = s;
|
|
232
|
+
for (const [e, s] of this.dynamicProviders) try {
|
|
233
|
+
const i = s();
|
|
234
|
+
i && (t[e] = i);
|
|
235
|
+
} catch (i) {
|
|
236
|
+
c.error(`DynamicContext provider "${e}" threw:`, i);
|
|
237
|
+
}
|
|
238
|
+
return Object.keys(t).length === 0 ? null : { entries: t };
|
|
239
|
+
}
|
|
240
|
+
clear() {
|
|
241
|
+
this.entries.clear(), this.dynamicProviders.clear(), c.log("ClientContext cleared");
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
function b(t) {
|
|
245
|
+
return t === null || typeof t != "object" ? JSON.stringify(t) ?? "null" : Array.isArray(t) ? `[${t.map(b).join(",")}]` : `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${b(t[e])}`).join(",")}}`;
|
|
246
|
+
}
|
|
247
|
+
var M = class {
|
|
248
|
+
constructor(t) {
|
|
249
|
+
this.callbacks = t, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0, this.answerCompleteEmitted = !1, this.waitingClientEmitted = !1, this.firedClientFunctions = /* @__PURE__ */ new Set();
|
|
250
|
+
}
|
|
251
|
+
async processStream(t) {
|
|
252
|
+
if (!t.body) throw new _("Response has no body. The endpoint did not return a stream: check that `baseUrl` points at an AGO API and nothing (proxy, mock) strips the SSE body.", "stream_no_body");
|
|
253
|
+
const e = t.body.getReader(), s = new TextDecoder();
|
|
254
|
+
try {
|
|
255
|
+
for (; ; ) {
|
|
256
|
+
const { done: i, value: n } = await e.read();
|
|
257
|
+
if (i) break;
|
|
258
|
+
const o = s.decode(n, { stream: !0 });
|
|
259
|
+
this.buffer += o, this.processBuffer();
|
|
260
|
+
}
|
|
261
|
+
return this.buffer.trim() && this.processBuffer(), this.buildFinalMessage();
|
|
262
|
+
} catch (i) {
|
|
263
|
+
const n = i instanceof Error ? i : new _("Stream processing failed mid-flight. The connection may have dropped; retry the message.");
|
|
264
|
+
throw this.callbacks.onError?.(n), n;
|
|
265
|
+
} finally {
|
|
266
|
+
e.releaseLock();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
processBuffer() {
|
|
270
|
+
const t = this.buffer.split(`
|
|
271
|
+
|
|
272
|
+
`);
|
|
273
|
+
this.buffer = t.pop() || "";
|
|
274
|
+
for (const e of t) {
|
|
275
|
+
if (!e.trim()) continue;
|
|
276
|
+
const s = e.split(`
|
|
277
|
+
`);
|
|
278
|
+
for (const i of s)
|
|
279
|
+
if (!i.startsWith(": ") && i.startsWith("data: ")) {
|
|
280
|
+
const n = i.slice(6);
|
|
281
|
+
try {
|
|
282
|
+
const o = JSON.parse(n);
|
|
283
|
+
this.handleChunk(o);
|
|
284
|
+
} catch (o) {
|
|
285
|
+
c.warn("Failed to parse SSE data:", n, o);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
handleChunk(t) {
|
|
291
|
+
if (this.callbacks.onRawChunk?.(t), t.message_id && !this.message.id && (this.message.id = t.message_id), t.thread?.id && (this.message.conversationId = t.thread.id, this.isFirstChunk && this.message.id && (this.isFirstChunk = !1, this.callbacks.onStart?.({
|
|
292
|
+
conversationId: this.message.conversationId,
|
|
293
|
+
messageId: this.message.id
|
|
294
|
+
}))), t.content !== void 0 && (this.message.content = (this.message.content || "") + t.content, this.message.conversationId && this.message.id && this.callbacks.onChunk?.({
|
|
295
|
+
content: t.content,
|
|
296
|
+
conversationId: this.message.conversationId,
|
|
297
|
+
messageId: this.message.id
|
|
298
|
+
})), t.full_content !== void 0 && (this.message.content = t.full_content), t.status && (this.message.status = t.status), t.agent && (this.message.agent = {
|
|
299
|
+
id: t.agent.id,
|
|
300
|
+
name: t.agent.name,
|
|
301
|
+
displayName: t.agent.display_name
|
|
302
|
+
}), t.knowledge_sources && (this.sources = t.knowledge_sources.map((e) => {
|
|
303
|
+
const s = e.knowledge_document;
|
|
304
|
+
return {
|
|
305
|
+
id: s.id,
|
|
306
|
+
title: s.title,
|
|
307
|
+
url: s.use_external_link ? s.external_link_url : s.internal_link_url
|
|
308
|
+
};
|
|
309
|
+
})), t.type === "client_function" && t.function_name) {
|
|
310
|
+
const e = `${t.function_name}::${b(t.arguments ?? {})}`;
|
|
311
|
+
this.firedClientFunctions.has(e) || (this.firedClientFunctions.add(e), this.callbacks.onClientFunction?.({
|
|
312
|
+
invocationId: t.id || "",
|
|
313
|
+
functionName: t.function_name,
|
|
314
|
+
arguments: t.arguments || {},
|
|
315
|
+
conversationId: this.message.conversationId || ""
|
|
316
|
+
}));
|
|
317
|
+
}
|
|
318
|
+
if (t.tool_call_data && t.type && t.type !== "client_function") {
|
|
319
|
+
const e = this.parseToolCall(t);
|
|
320
|
+
this.callbacks.onToolCall?.(e);
|
|
321
|
+
const s = this.toolCalls.findIndex((i) => i.id === e.id);
|
|
322
|
+
s >= 0 ? this.toolCalls[s] = e : this.toolCalls.push(e);
|
|
323
|
+
}
|
|
324
|
+
t.follow_up_replies && (this.followUpReplies = t.follow_up_replies), this.message.status === "DONE" && !this.answerCompleteEmitted && this.message.id && (this.answerCompleteEmitted = !0, this.callbacks.onAnswerComplete?.(this.buildMessage())), this.message.status === "WAITING_CLIENT" && !this.waitingClientEmitted && this.message.id && (this.waitingClientEmitted = !0, this.callbacks.onWaitingClient?.({
|
|
325
|
+
conversationId: this.message.conversationId || "",
|
|
326
|
+
messageId: this.message.id,
|
|
327
|
+
waitingToolCallIds: t.waiting_tool_call_ids ?? []
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
330
|
+
parseToolCall(t) {
|
|
331
|
+
return {
|
|
332
|
+
id: t.id || "",
|
|
333
|
+
type: t.type || "status_message",
|
|
334
|
+
status: t.status || "unknown",
|
|
335
|
+
toolName: t.tool_name || "",
|
|
336
|
+
toolDisplayName: t.tool_display_name,
|
|
337
|
+
message: t.message,
|
|
338
|
+
formSchema: t.form_schema,
|
|
339
|
+
data: t.data,
|
|
340
|
+
functionName: t.function_name,
|
|
341
|
+
arguments: t.arguments
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
buildMessage() {
|
|
345
|
+
return {
|
|
346
|
+
id: this.message.id || "",
|
|
347
|
+
conversationId: this.message.conversationId || "",
|
|
348
|
+
content: this.message.content || "",
|
|
349
|
+
role: "assistant",
|
|
350
|
+
status: this.message.status || "DONE",
|
|
351
|
+
agent: this.message.agent,
|
|
352
|
+
sources: this.sources.length > 0 ? this.sources : void 0,
|
|
353
|
+
toolCalls: this.toolCalls.length > 0 ? this.toolCalls : void 0,
|
|
354
|
+
followUpReplies: this.followUpReplies.length > 0 ? this.followUpReplies : void 0,
|
|
355
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
buildFinalMessage() {
|
|
359
|
+
const t = this.buildMessage();
|
|
360
|
+
return t.status !== "WAITING_CLIENT" && this.callbacks.onComplete?.(t), t;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
function H(t) {
|
|
364
|
+
const e = t.message.toLowerCase();
|
|
365
|
+
return e.includes("load failed") || e.includes("failed to fetch") || e.includes("network") || e.includes("abort");
|
|
366
|
+
}
|
|
367
|
+
var O = /* @__PURE__ */ new Set([
|
|
368
|
+
"image/jpeg",
|
|
369
|
+
"image/png",
|
|
370
|
+
"image/gif",
|
|
371
|
+
"image/webp",
|
|
372
|
+
"image/bmp",
|
|
373
|
+
"image/tiff"
|
|
374
|
+
]);
|
|
375
|
+
function B(t) {
|
|
376
|
+
if (!t) return;
|
|
377
|
+
const e = typeof window < "u" && window.location ? window.location.href : "https://ago.local/";
|
|
378
|
+
try {
|
|
379
|
+
const s = new URL(t, e);
|
|
380
|
+
if (s.protocol === "http:" || s.protocol === "https:" || s.protocol === "blob:") return t;
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function K(t) {
|
|
385
|
+
return t.isSafeImage === !0 && typeof t.contentType == "string" && t.contentType.startsWith("image/") && B(t.url) !== void 0;
|
|
386
|
+
}
|
|
387
|
+
function X(t) {
|
|
388
|
+
if (t == null || t < 0) return "";
|
|
389
|
+
if (t < 1024) return `${t} B`;
|
|
390
|
+
const e = t / 1024;
|
|
391
|
+
return e < 1024 ? `${e.toFixed(1)} KB` : `${(e / 1024).toFixed(1)} MB`;
|
|
392
|
+
}
|
|
393
|
+
function L(t) {
|
|
394
|
+
return {
|
|
395
|
+
id: String(t.id ?? ""),
|
|
396
|
+
name: typeof t.name == "string" && t.name ? t.name : "file",
|
|
397
|
+
contentType: typeof t.content_type == "string" ? t.content_type : void 0,
|
|
398
|
+
fileSize: typeof t.file_size == "number" ? t.file_size : void 0,
|
|
399
|
+
url: typeof t.file_url == "string" ? t.file_url : void 0,
|
|
400
|
+
isSafeImage: t.is_safe_image === !0
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
function Y(t) {
|
|
404
|
+
return t.map((e, s) => ({
|
|
405
|
+
id: `local-${s}-${e.name}`,
|
|
406
|
+
name: e.name,
|
|
407
|
+
contentType: e.type || void 0,
|
|
408
|
+
fileSize: e.size,
|
|
409
|
+
url: typeof URL < "u" && URL.createObjectURL ? URL.createObjectURL(e) : void 0,
|
|
410
|
+
isSafeImage: O.has(e.type)
|
|
411
|
+
}));
|
|
412
|
+
}
|
|
413
|
+
var G = class {
|
|
414
|
+
constructor() {
|
|
415
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
416
|
+
}
|
|
417
|
+
on(t, e) {
|
|
418
|
+
this.handlers.has(t) || this.handlers.set(t, /* @__PURE__ */ new Set()), this.handlers.get(t).add(e);
|
|
419
|
+
}
|
|
420
|
+
off(t, e) {
|
|
421
|
+
const s = this.handlers.get(t);
|
|
422
|
+
s && s.delete(e);
|
|
423
|
+
}
|
|
424
|
+
emit(t, e) {
|
|
425
|
+
const s = this.handlers.get(t);
|
|
426
|
+
s && s.forEach((i) => {
|
|
427
|
+
try {
|
|
428
|
+
i(e);
|
|
429
|
+
} catch (n) {
|
|
430
|
+
console.error(`Error in event handler for ${String(t)}:`, n);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
once(t, e) {
|
|
435
|
+
const s = ((i) => {
|
|
436
|
+
this.off(t, s), e(i);
|
|
437
|
+
});
|
|
438
|
+
this.on(t, s);
|
|
439
|
+
}
|
|
440
|
+
waitFor(t, e) {
|
|
441
|
+
return new Promise((s, i) => {
|
|
442
|
+
let n;
|
|
443
|
+
const o = ((a) => {
|
|
444
|
+
n && clearTimeout(n), s(a);
|
|
445
|
+
});
|
|
446
|
+
this.once(t, o), e?.timeout && (n = setTimeout(() => {
|
|
447
|
+
this.off(t, o), i(/* @__PURE__ */ new Error(`waitFor("${String(t)}") timed out after ${e.timeout}ms`));
|
|
448
|
+
}, e.timeout));
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
removeAllListeners(t) {
|
|
452
|
+
t ? this.handlers.delete(t) : this.handlers.clear();
|
|
453
|
+
}
|
|
454
|
+
}, S = '`baseUrl` is required, e.g. new AgoClient({ baseUrl: "https://YOUR-DOMAIN.api.useago.com" }). Try the live demo endpoint https://playground.api.useago.com. See docs/general/configuration.md#error-codes (config_missing_base_url).', W = /^[a-z][a-z0-9+.-]*:\/\//i, $ = !1;
|
|
455
|
+
function A(t, e = "AgoClient") {
|
|
456
|
+
if (typeof t != "object" || t === null) throw new m(`${e}: ${S}`, "config_missing_base_url");
|
|
457
|
+
const s = t.baseUrl;
|
|
458
|
+
if (typeof s != "string" || s.trim() === "") throw new m(`${e}: ${S}`, "config_missing_base_url");
|
|
459
|
+
!s.startsWith("/") && !W.test(s) && ($ || ($ = !0, console.warn(`[AGO] ${e}: \`baseUrl\` has no protocol and is not a relative path (config_suspect_base_url). Requests will fail: Node throws a URL parse error, browsers fetch it as a relative path. Use "https://..." (or a "/path" for a same-origin proxy).`)));
|
|
460
|
+
}
|
|
461
|
+
function q(t) {
|
|
462
|
+
return t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
463
|
+
}
|
|
464
|
+
function C(t) {
|
|
465
|
+
return t.split("/").filter((e) => e.startsWith(":")).map((e) => e.slice(1));
|
|
466
|
+
}
|
|
467
|
+
function z(t, e) {
|
|
468
|
+
const s = [];
|
|
469
|
+
return {
|
|
470
|
+
path: t.split("/").map((i) => {
|
|
471
|
+
if (!i.startsWith(":")) return i;
|
|
472
|
+
const n = i.slice(1), o = e[n];
|
|
473
|
+
return o == null || o === "" ? (s.push(n), i) : encodeURIComponent(String(o));
|
|
474
|
+
}).join("/"),
|
|
475
|
+
missing: s
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function J(t, e) {
|
|
479
|
+
const s = e.find((n) => n.path === t);
|
|
480
|
+
if (s) return s;
|
|
481
|
+
const i = e.find((n) => {
|
|
482
|
+
if (!n.path.includes(":")) return !1;
|
|
483
|
+
const o = "^" + n.path.split("/").map((a) => a.startsWith(":") ? "[^/]+" : q(a)).join("/") + "/?$";
|
|
484
|
+
return new RegExp(o).test(t);
|
|
485
|
+
});
|
|
486
|
+
return i || e.filter((n) => n.path !== "/" && t.startsWith(n.path)).sort((n, o) => o.path.length - n.path.length)[0];
|
|
487
|
+
}
|
|
488
|
+
var V = class k {
|
|
489
|
+
constructor(e) {
|
|
490
|
+
this.warnedEmptyConversations = /* @__PURE__ */ new Set(), this.pendingResumes = /* @__PURE__ */ new Map(), this.pendingApprovals = /* @__PURE__ */ new Map(), this.resumeGate = null, A(e, "AgoClient"), this.config = e, this.httpClient = new U(e), this.functionRegistry = new P({ maxResultBytes: e.maxFunctionResultBytes }), this.contextRegistry = new j(), this.eventEmitter = new G(), e.debug && c.enable(), c.log("AgoClient initialized");
|
|
491
|
+
}
|
|
492
|
+
async sendMessage(e, s) {
|
|
493
|
+
const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), o = this.config.agent || this.config.defaultAgentId, a = this.resolveClientFunctionsMode(s), r = {
|
|
494
|
+
content: e,
|
|
495
|
+
conversation_id: s?.conversationId,
|
|
496
|
+
agent_id: s?.agentId || o
|
|
497
|
+
};
|
|
498
|
+
i.length > 0 && (r.client_functions = i, a === "pause" && (r.client_functions_mode = a)), n && (r.client_context = n), s?.hidden && (r.hidden = !0);
|
|
499
|
+
let l;
|
|
500
|
+
if (s?.files && s.files.length > 0) {
|
|
501
|
+
const u = new FormData();
|
|
502
|
+
u.append("content", e), s.conversationId && u.append("conversation_id", s.conversationId), (s.agentId || o) && u.append("agent_id", s.agentId || o || ""), i.length > 0 && (u.append("client_functions", JSON.stringify(i)), a === "pause" && u.append("client_functions_mode", a)), n && u.append("client_context", JSON.stringify(n)), s.hidden && u.append("hidden", "true");
|
|
503
|
+
for (const h of s.files) u.append("files", h);
|
|
504
|
+
l = await this.httpClient.postFormData("/api/sdk/v1/messages", u);
|
|
505
|
+
} else l = await this.httpClient.postStream("/api/sdk/v1/messages", r);
|
|
506
|
+
return this.processSSEResponse(l);
|
|
507
|
+
}
|
|
508
|
+
async processSSEResponse(e) {
|
|
509
|
+
let s = !1;
|
|
510
|
+
const i = await new M({
|
|
511
|
+
onRawChunk: (n) => {
|
|
512
|
+
this.eventEmitter.emit("stream:message", n);
|
|
513
|
+
},
|
|
514
|
+
onStart: (n) => {
|
|
515
|
+
this.eventEmitter.emit("message:start", n);
|
|
516
|
+
},
|
|
517
|
+
onChunk: (n) => {
|
|
518
|
+
this.eventEmitter.emit("message:chunk", n);
|
|
519
|
+
},
|
|
520
|
+
onToolCall: (n) => {
|
|
521
|
+
this.eventEmitter.emit("toolCall:received", n), n.type === "form" && this.eventEmitter.emit("toolCall:form", n);
|
|
522
|
+
},
|
|
523
|
+
onClientFunction: async (n) => {
|
|
524
|
+
if (s = !0, this.eventEmitter.emit("function:invoke", n), n.invocationId && this.requiresApproval(n)) {
|
|
525
|
+
this.pendingApprovals.set(n.invocationId, n), this.eventEmitter.emit("function:awaiting-approval", n);
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
await this.handleClientFunctionInvocation(n);
|
|
529
|
+
},
|
|
530
|
+
onAnswerComplete: (n) => {
|
|
531
|
+
this.eventEmitter.emit("message:answer-complete", n);
|
|
532
|
+
},
|
|
533
|
+
onWaitingClient: (n) => {
|
|
534
|
+
this.eventEmitter.emit("message:waiting-client", n), this.markResumeSignal(n.messageId, n.conversationId, "waitingConfirmed");
|
|
535
|
+
},
|
|
536
|
+
onComplete: (n) => {
|
|
537
|
+
this.eventEmitter.emit("message:complete", n);
|
|
538
|
+
},
|
|
539
|
+
onError: (n) => {
|
|
540
|
+
this.eventEmitter.emit("message:error", {
|
|
541
|
+
error: n.message,
|
|
542
|
+
code: n instanceof m ? n.code : void 0
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}).processStream(e);
|
|
546
|
+
return i.status !== "WAITING_CLIENT" && this.maybeFlagEmptyReply(i, s), i;
|
|
547
|
+
}
|
|
548
|
+
resolveClientFunctionsMode(e) {
|
|
549
|
+
return e?.clientFunctionsMode ?? this.config.clientFunctionsMode ?? "pause";
|
|
550
|
+
}
|
|
551
|
+
registerResumeGate(e) {
|
|
552
|
+
return this.resumeGate = e, () => {
|
|
553
|
+
this.resumeGate === e && (this.resumeGate = null);
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
async continueMessage(e) {
|
|
557
|
+
const s = this.functionRegistry.getSchemas(), i = this.contextRegistry.getSnapshot(), n = {};
|
|
558
|
+
s.length > 0 && (n.client_functions = s), i && (n.client_context = i);
|
|
559
|
+
const o = await this.httpClient.postStream(`/api/sdk/v1/messages/${e}/continue`, n);
|
|
560
|
+
return this.processSSEResponse(o);
|
|
561
|
+
}
|
|
562
|
+
markResumeSignal(e, s, i) {
|
|
563
|
+
if (!e) return;
|
|
564
|
+
const n = this.pendingResumes.get(e) ?? {
|
|
565
|
+
conversationId: s,
|
|
566
|
+
waitingConfirmed: !1,
|
|
567
|
+
resultsReady: !1,
|
|
568
|
+
started: !1
|
|
569
|
+
};
|
|
570
|
+
n[i] = !0, s && (n.conversationId = s), this.pendingResumes.set(e, n), !(!n.waitingConfirmed || !n.resultsReady || n.started) && (n.started = !0, this.runAutoResume(e, n.conversationId));
|
|
571
|
+
}
|
|
572
|
+
async runAutoResume(e, s) {
|
|
573
|
+
try {
|
|
574
|
+
this.resumeGate && await this.resumeGate({
|
|
575
|
+
conversationId: s,
|
|
576
|
+
messageId: e
|
|
577
|
+
});
|
|
578
|
+
} catch (i) {
|
|
579
|
+
c.warn("Resume gate threw; resuming anyway:", i);
|
|
580
|
+
}
|
|
581
|
+
this.pendingResumes.delete(e);
|
|
582
|
+
try {
|
|
583
|
+
await this.continueMessage(e);
|
|
584
|
+
} catch (i) {
|
|
585
|
+
c.warn("Auto-resume of paused turn failed:", i);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
maybeFlagEmptyReply(e, s) {
|
|
589
|
+
e.status === "DONE" && (e.content ?? "").trim() === "" && !s && !(e.toolCalls && e.toolCalls.length > 0) && !(e.followUpReplies && e.followUpReplies.length > 0) && setTimeout(() => {
|
|
590
|
+
if (this.eventEmitter.emit("message:empty", {
|
|
591
|
+
conversationId: e.conversationId ?? "",
|
|
592
|
+
messageId: e.id ?? ""
|
|
593
|
+
}), this.config.warnOnEmptyReply === !1) return;
|
|
594
|
+
const i = e.conversationId || "(no conversation)";
|
|
595
|
+
if (this.warnedEmptyConversations.has(i)) return;
|
|
596
|
+
this.warnedEmptyConversations.add(i);
|
|
597
|
+
const n = this.config.agent || this.config.defaultAgentId;
|
|
598
|
+
e.id ? console.warn("[AGO] Reply completed with empty content. Possible causes: " + (n ? `the agent "${n}" may not exist for this tenant, ` : "an unknown `agent` slug, ") + "or the agent replied with no text. Listen for the `message:empty` event to handle this in your app; silence this warning with `warnOnEmptyReply: false`.") : console.warn("[AGO] The stream completed without any message data. Possible causes: " + (n ? `the agent "${n}" may not exist for this tenant, or ` : "") + "`baseUrl` does not point at an AGO endpoint that returns server-sent events. Listen for the `message:empty` event to handle this in your app; silence this warning with `warnOnEmptyReply: false`.");
|
|
599
|
+
}, 0);
|
|
600
|
+
}
|
|
601
|
+
async handleClientFunctionInvocation(e) {
|
|
602
|
+
let s, i;
|
|
603
|
+
try {
|
|
604
|
+
s = await this.functionRegistry.execute(e.functionName, e.arguments);
|
|
605
|
+
} catch (n) {
|
|
606
|
+
i = n instanceof Error ? n.message : "Unknown error", c.error("Client function execution failed:", n);
|
|
607
|
+
}
|
|
608
|
+
if (e.invocationId) try {
|
|
609
|
+
const n = await this.submitToolCallForm(e.invocationId, {
|
|
610
|
+
result: s,
|
|
611
|
+
error: i,
|
|
612
|
+
_type: "client_function_result"
|
|
613
|
+
});
|
|
614
|
+
n?.resume?.ready && this.markResumeSignal(n.resume.message_id, e.conversationId, "resultsReady");
|
|
615
|
+
} catch (n) {
|
|
616
|
+
c.error("Failed to submit function result:", n);
|
|
617
|
+
}
|
|
618
|
+
this.eventEmitter.emit("function:result", {
|
|
619
|
+
invocationId: e.invocationId,
|
|
620
|
+
result: s,
|
|
621
|
+
error: i
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
requiresApproval(e) {
|
|
625
|
+
const s = this.config.approvalPolicy;
|
|
626
|
+
if (s) try {
|
|
627
|
+
if (s(e)) return !0;
|
|
628
|
+
} catch (i) {
|
|
629
|
+
c.warn("approvalPolicy threw; not gating this call:", i);
|
|
630
|
+
}
|
|
631
|
+
return this.functionRegistry.get(e.functionName)?.requiresApproval === !0;
|
|
632
|
+
}
|
|
633
|
+
async approveFunction(e) {
|
|
634
|
+
const s = this.pendingApprovals.get(e);
|
|
635
|
+
s && (this.pendingApprovals.delete(e), await this.handleClientFunctionInvocation(s));
|
|
636
|
+
}
|
|
637
|
+
async rejectFunction(e) {
|
|
638
|
+
const s = this.pendingApprovals.get(e);
|
|
639
|
+
if (!s) return;
|
|
640
|
+
this.pendingApprovals.delete(e);
|
|
641
|
+
const i = {
|
|
642
|
+
approved: !1,
|
|
643
|
+
reason: "user_rejected"
|
|
644
|
+
};
|
|
645
|
+
try {
|
|
646
|
+
const n = await this.submitToolCallForm(e, {
|
|
647
|
+
result: i,
|
|
648
|
+
_type: "client_function_result"
|
|
649
|
+
});
|
|
650
|
+
n?.resume?.ready && this.markResumeSignal(n.resume.message_id, s.conversationId, "resultsReady");
|
|
651
|
+
} catch (n) {
|
|
652
|
+
c.error("Failed to submit function rejection:", n);
|
|
653
|
+
}
|
|
654
|
+
this.eventEmitter.emit("function:result", {
|
|
655
|
+
invocationId: e,
|
|
656
|
+
result: i
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
async getConversations() {
|
|
660
|
+
return (await this.httpClient.get("/api/sdk/v1/conversations")).items.map((e) => ({
|
|
661
|
+
id: e.id,
|
|
662
|
+
title: e.title,
|
|
663
|
+
lastMessageDate: new Date(e.last_message_date)
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
async getConversation(e) {
|
|
667
|
+
const s = await this.httpClient.get(`/api/sdk/v1/conversations/${e}`), i = {
|
|
668
|
+
id: s.id,
|
|
669
|
+
title: s.title,
|
|
670
|
+
lastMessageDate: new Date(s.last_message_date),
|
|
671
|
+
messages: s.messages.map((n) => ({
|
|
672
|
+
id: n.id,
|
|
673
|
+
conversationId: s.id,
|
|
674
|
+
content: n.content,
|
|
675
|
+
role: n.role,
|
|
676
|
+
status: n.status,
|
|
677
|
+
createdAt: new Date(n.created_at),
|
|
678
|
+
hidden: n.hidden,
|
|
679
|
+
toolCalls: k.mapPersistedToolCalls(n.tool_call_data),
|
|
680
|
+
attachments: n.attachments && n.attachments.length > 0 ? n.attachments.map(L) : void 0
|
|
681
|
+
}))
|
|
682
|
+
};
|
|
683
|
+
return this.eventEmitter.emit("conversation:loaded", i), i;
|
|
684
|
+
}
|
|
685
|
+
static mapPersistedToolCalls(e) {
|
|
686
|
+
if (!(!e || e.length === 0))
|
|
687
|
+
return e.map((s) => ({
|
|
688
|
+
id: String(s.id ?? ""),
|
|
689
|
+
type: s.type ?? "status_message",
|
|
690
|
+
status: String(s.status ?? "unknown"),
|
|
691
|
+
toolName: s.tool_name ?? "",
|
|
692
|
+
toolDisplayName: s.tool_display_name,
|
|
693
|
+
message: s.message,
|
|
694
|
+
formSchema: s.form_schema,
|
|
695
|
+
data: s.data,
|
|
696
|
+
functionName: s.function_name,
|
|
697
|
+
arguments: s.arguments
|
|
698
|
+
}));
|
|
699
|
+
}
|
|
700
|
+
async getMessages(e) {
|
|
701
|
+
return (await this.getConversation(e)).messages || [];
|
|
702
|
+
}
|
|
703
|
+
async resumePendingClientFunctions(e) {
|
|
704
|
+
const s = [...e.messages ?? []].reverse().find((r) => r.role === "assistant" && r.status === "WAITING_CLIENT");
|
|
705
|
+
if (!s) return null;
|
|
706
|
+
const i = (s.toolCalls ?? []).filter((r) => r.type === "client_function" && r.status === "waiting_input" && r.functionName), n = new Set(this.functionRegistry.getSchemas().map((r) => r.name)), o = i.filter((r) => !n.has(r.functionName));
|
|
707
|
+
if (o.length > 0)
|
|
708
|
+
return c.warn("Cannot resume paused turn: function(s) not registered on this page:", o.map((r) => r.functionName)), null;
|
|
709
|
+
let a = i.length === 0;
|
|
710
|
+
for (const r of i) {
|
|
711
|
+
const l = {
|
|
712
|
+
invocationId: r.id,
|
|
713
|
+
functionName: r.functionName,
|
|
714
|
+
arguments: r.arguments ?? {},
|
|
715
|
+
conversationId: e.id
|
|
716
|
+
};
|
|
717
|
+
if (this.requiresApproval(l)) {
|
|
718
|
+
this.pendingApprovals.set(r.id, l), this.markResumeSignal(s.id, e.id, "waitingConfirmed"), this.eventEmitter.emit("function:awaiting-approval", l), a = !1;
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
let u, h;
|
|
722
|
+
try {
|
|
723
|
+
u = await this.functionRegistry.execute(r.functionName, r.arguments ?? {});
|
|
724
|
+
} catch (d) {
|
|
725
|
+
h = d instanceof Error ? d.message : "Unknown error", c.error("Client function execution failed:", d);
|
|
726
|
+
}
|
|
727
|
+
a = (await this.submitToolCallForm(r.id, {
|
|
728
|
+
result: u,
|
|
729
|
+
error: h,
|
|
730
|
+
_type: "client_function_result"
|
|
731
|
+
}))?.resume?.ready ?? a;
|
|
732
|
+
}
|
|
733
|
+
return a ? this.continueMessage(s.id) : null;
|
|
734
|
+
}
|
|
735
|
+
async submitToolCallForm(e, s) {
|
|
736
|
+
return this.httpClient.post(`/api/sdk/v1/tool-calls/${e}/submit`, { formData: s });
|
|
737
|
+
}
|
|
738
|
+
async confirmToolCall(e) {
|
|
739
|
+
await this.httpClient.post(`/api/tool-calls/${e}/confirm/`);
|
|
740
|
+
}
|
|
741
|
+
async rejectToolCall(e) {
|
|
742
|
+
await this.httpClient.post(`/api/tool-calls/${e}/reject/`);
|
|
743
|
+
}
|
|
744
|
+
async getFormCollector(e) {
|
|
745
|
+
const s = await this.httpClient.get(`/api/sdk/v1/forms/${encodeURIComponent(e)}`);
|
|
746
|
+
return {
|
|
747
|
+
name: s.name,
|
|
748
|
+
description: s.description,
|
|
749
|
+
schema: s.schema,
|
|
750
|
+
submit: s.submit ?? void 0
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
async submitFormCollector(e, s) {
|
|
754
|
+
return this.httpClient.post("/api/sdk/v1/forms/submit", {
|
|
755
|
+
name: e,
|
|
756
|
+
values: s
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
async submitFeedback(e, s) {
|
|
760
|
+
await this.httpClient.post(`/api/sdk/v1/messages/${e}/feedback`, { rating: s });
|
|
761
|
+
}
|
|
762
|
+
registerFunction(e, s, i) {
|
|
763
|
+
typeof e == "object" ? this.functionRegistry.register(e) : this.functionRegistry.register(e, s, i);
|
|
764
|
+
}
|
|
765
|
+
register(e) {
|
|
766
|
+
if (Array.isArray(e)) for (const s of e) this.functionRegistry.register(s);
|
|
767
|
+
else this.functionRegistry.register(e);
|
|
768
|
+
}
|
|
769
|
+
unregisterFunction(e) {
|
|
770
|
+
return this.functionRegistry.unregister(e);
|
|
771
|
+
}
|
|
772
|
+
getRegisteredFunctions() {
|
|
773
|
+
return this.functionRegistry.getSchemas();
|
|
774
|
+
}
|
|
775
|
+
registerNavigationFunction(e, s) {
|
|
776
|
+
const i = s.map((r) => r.name), n = s.map((r) => {
|
|
777
|
+
const l = C(r.path), u = l.length > 0 ? ` (requires ${l.map((h) => `"${h}"`).join(", ")})` : "";
|
|
778
|
+
return `- "${r.name}"${u}: ${r.description}`;
|
|
779
|
+
}).join(`
|
|
780
|
+
`), o = /* @__PURE__ */ new Map();
|
|
781
|
+
for (const r of s) for (const l of C(r.path)) o.set(l, [...o.get(l) ?? [], r.name]);
|
|
782
|
+
const a = { page: {
|
|
783
|
+
type: "string",
|
|
784
|
+
description: "The page to navigate to",
|
|
785
|
+
enum: i
|
|
786
|
+
} };
|
|
787
|
+
for (const [r, l] of o) {
|
|
788
|
+
if (r === "page") {
|
|
789
|
+
c.error('registerNavigationFunction: a ":page" placeholder collides with the "page" argument and is ignored. Rename the placeholder.');
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
a[r] = {
|
|
793
|
+
type: "string",
|
|
794
|
+
description: `Value for ":${r}" in the page path. Required when page is ${l.map((u) => `"${u}"`).join(" or ")}.`
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
this.registerFunction("navigateToPage", async (r) => {
|
|
798
|
+
const l = r.page, u = s.find((f) => f.name === l);
|
|
799
|
+
if (!u) return {
|
|
800
|
+
success: !1,
|
|
801
|
+
error: `Unknown page: ${l}`
|
|
802
|
+
};
|
|
803
|
+
let h = {};
|
|
804
|
+
if (typeof r.params == "string") try {
|
|
805
|
+
h = JSON.parse(r.params);
|
|
806
|
+
} catch {
|
|
807
|
+
}
|
|
808
|
+
else r.params && typeof r.params == "object" && (h = r.params);
|
|
809
|
+
const d = {};
|
|
810
|
+
for (const f of C(u.path)) d[f] = r[f] ?? h[f];
|
|
811
|
+
const { path: g, missing: y } = z(u.path, d);
|
|
812
|
+
if (y.length > 0) {
|
|
813
|
+
const f = y.map((w) => `"${w}": "..."`).join(", ");
|
|
814
|
+
return {
|
|
815
|
+
success: !1,
|
|
816
|
+
error: `Page "${l}" needs ${y.map((w) => `"${w}"`).join(", ")}. Retry with { "page": "${l}", ${f} }.`
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
return e(g), {
|
|
820
|
+
success: !0,
|
|
821
|
+
navigatedTo: g
|
|
822
|
+
};
|
|
823
|
+
}, {
|
|
824
|
+
description: `Navigate the user to a page in the application. Available pages:
|
|
825
|
+
${n}`,
|
|
826
|
+
parameters: {
|
|
827
|
+
type: "object",
|
|
828
|
+
properties: a,
|
|
829
|
+
required: ["page"]
|
|
830
|
+
}
|
|
831
|
+
}), this.addDynamicContext("current-page", () => {
|
|
832
|
+
if (typeof window > "u" || !window.location) return null;
|
|
833
|
+
const r = window.location.href, l = typeof document < "u" ? document.title : void 0, u = J(window.location.pathname, s), h = { url: r };
|
|
834
|
+
return u && (h.page = u.name), l && (h.title = l), {
|
|
835
|
+
name: "Current page",
|
|
836
|
+
description: "The page the user is currently viewing.",
|
|
837
|
+
data: h
|
|
838
|
+
};
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
unregisterNavigationFunction() {
|
|
842
|
+
this.unregisterFunction("navigateToPage"), this.removeDynamicContext("current-page");
|
|
843
|
+
}
|
|
844
|
+
registerPageStateFunction(e, s) {
|
|
845
|
+
const i = s?.functionName ?? "setPageState", n = new Map(e.map((a) => [a.name, a])), o = e.map((a) => `- "${a.name}": ${a.description}`).join(`
|
|
846
|
+
`);
|
|
847
|
+
this.registerFunction(i, async (a) => {
|
|
848
|
+
const r = {};
|
|
849
|
+
for (const [l, u] of Object.entries(a)) {
|
|
850
|
+
if (u === void 0) continue;
|
|
851
|
+
const h = n.get(l);
|
|
852
|
+
h && (await h.set(u), r[l] = u);
|
|
853
|
+
}
|
|
854
|
+
return {
|
|
855
|
+
success: !0,
|
|
856
|
+
applied: r
|
|
857
|
+
};
|
|
858
|
+
}, {
|
|
859
|
+
description: `Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
|
|
860
|
+
${o}`,
|
|
861
|
+
parameters: {
|
|
862
|
+
type: "object",
|
|
863
|
+
properties: Object.fromEntries(e.map((a) => [a.name, {
|
|
864
|
+
...a.schema,
|
|
865
|
+
description: a.description
|
|
866
|
+
}]))
|
|
867
|
+
},
|
|
868
|
+
requiresApproval: s?.requiresApproval
|
|
869
|
+
}), this.addDynamicContext(`page-state:${i}`, () => {
|
|
870
|
+
const a = e.filter((l) => typeof l.get == "function");
|
|
871
|
+
if (a.length === 0) return null;
|
|
872
|
+
const r = {};
|
|
873
|
+
for (const l of a) r[l.name] = l.get();
|
|
874
|
+
return {
|
|
875
|
+
name: "Page state",
|
|
876
|
+
description: "Current, editable state of the page the user is viewing.",
|
|
877
|
+
data: r
|
|
878
|
+
};
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
unregisterPageStateFunction(e) {
|
|
882
|
+
const s = e ?? "setPageState";
|
|
883
|
+
this.unregisterFunction(s), this.removeDynamicContext(`page-state:${s}`);
|
|
884
|
+
}
|
|
885
|
+
setContext(e, s) {
|
|
886
|
+
this.contextRegistry.set(e, s), this.notifyContextChanged();
|
|
887
|
+
}
|
|
888
|
+
removeContext(e) {
|
|
889
|
+
const s = this.contextRegistry.remove(e);
|
|
890
|
+
return s && this.notifyContextChanged(), s;
|
|
891
|
+
}
|
|
892
|
+
addDynamicContext(e, s) {
|
|
893
|
+
this.contextRegistry.addDynamicProvider(e, s), this.notifyContextChanged();
|
|
894
|
+
}
|
|
895
|
+
removeDynamicContext(e) {
|
|
896
|
+
const s = this.contextRegistry.removeDynamicProvider(e);
|
|
897
|
+
return s && this.notifyContextChanged(), s;
|
|
898
|
+
}
|
|
899
|
+
notifyContextChanged() {
|
|
900
|
+
this.eventEmitter.emit("context:changed", this.contextRegistry.getSnapshot());
|
|
901
|
+
}
|
|
902
|
+
emitFormEvent(e, s) {
|
|
903
|
+
this.eventEmitter.emit(e, s);
|
|
904
|
+
}
|
|
905
|
+
enableAutoPageContext() {
|
|
906
|
+
this.addDynamicContext("browser-page", () => {
|
|
907
|
+
const e = typeof window < "u" ? window.location.href : void 0, s = typeof document < "u" ? document.title : void 0;
|
|
908
|
+
return !e && !s ? null : {
|
|
909
|
+
name: "Browser page",
|
|
910
|
+
description: "Current page the user is viewing",
|
|
911
|
+
data: {
|
|
912
|
+
url: e,
|
|
913
|
+
title: s
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
getContextSnapshot() {
|
|
919
|
+
return this.contextRegistry.getSnapshot();
|
|
920
|
+
}
|
|
921
|
+
on(e, s) {
|
|
922
|
+
this.eventEmitter.on(e, s);
|
|
923
|
+
}
|
|
924
|
+
off(e, s) {
|
|
925
|
+
this.eventEmitter.off(e, s);
|
|
926
|
+
}
|
|
927
|
+
once(e, s) {
|
|
928
|
+
this.eventEmitter.once(e, s);
|
|
929
|
+
}
|
|
930
|
+
waitFor(e, s) {
|
|
931
|
+
return this.eventEmitter.waitFor(e, s);
|
|
932
|
+
}
|
|
933
|
+
updateConfig(e) {
|
|
934
|
+
const s = {};
|
|
935
|
+
for (const [n, o] of Object.entries(e)) o !== void 0 && (s[n] = o);
|
|
936
|
+
const i = {
|
|
937
|
+
...this.config,
|
|
938
|
+
...s
|
|
939
|
+
};
|
|
940
|
+
A(i, "AgoClient.updateConfig"), this.config = i, this.httpClient.updateConfig(s), s.debug !== void 0 && (s.debug ? c.enable() : c.disable()), s.maxFunctionResultBytes !== void 0 && this.functionRegistry.setDefaultMaxResultBytes(s.maxFunctionResultBytes);
|
|
941
|
+
}
|
|
942
|
+
destroy() {
|
|
943
|
+
this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(), this.pendingResumes.clear(), this.pendingApprovals.clear(), this.resumeGate = null, c.log("AgoClient destroyed");
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
export {
|
|
947
|
+
_,
|
|
948
|
+
K as a,
|
|
949
|
+
M as c,
|
|
950
|
+
P as d,
|
|
951
|
+
c as f,
|
|
952
|
+
v as g,
|
|
953
|
+
E as h,
|
|
954
|
+
Y as i,
|
|
955
|
+
H as l,
|
|
956
|
+
m,
|
|
957
|
+
A as n,
|
|
958
|
+
X as o,
|
|
959
|
+
p,
|
|
960
|
+
G as r,
|
|
961
|
+
B as s,
|
|
962
|
+
V as t,
|
|
963
|
+
j as u
|
|
964
|
+
};
|