@useago/sdk 1.4.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -1
- package/dist/{AgoClient-S8oeNnAE.js → AgoClient-q39FIjSC.js} +105 -81
- package/dist/AgoClient-wcPRaIMs.cjs +8 -0
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +75 -5
- package/dist/angular.d.ts +75 -5
- package/dist/angular.js +5 -1
- package/dist/autoContinue-CcCTva-D.cjs +1 -0
- package/dist/autoContinue-D3Mmaaca.js +63 -0
- package/dist/{createConversationSession-CmBq7uGi.cjs → createConversationSession-BBYfQLLS.cjs} +1 -1
- package/dist/{createConversationSession-DoUHdVNR.js → createConversationSession-DCSWShaW.js} +1 -1
- package/dist/{createFormCollector-Bz_0IJ0Q.cjs → createFormCollector-eimwwWEi.cjs} +1 -1
- package/dist/{createFormCollector-vy-QvFja.js → createFormCollector-sB6rMccD.js} +1 -1
- package/dist/devtools.d.cts +32 -4
- package/dist/devtools.d.ts +32 -4
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.d.cts +6 -0
- package/dist/helpers.d.ts +6 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +101 -5
- package/dist/index.d.ts +101 -5
- package/dist/index.js +45 -43
- package/dist/react.cjs +3 -3
- package/dist/react.d.cts +40 -18
- package/dist/react.d.ts +40 -18
- package/dist/react.js +415 -471
- package/dist/testing.cjs +1 -1
- package/dist/testing.d.cts +32 -4
- package/dist/testing.d.ts +32 -4
- package/dist/testing.js +1 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +38 -4
- package/dist/vue.d.ts +38 -4
- package/dist/vue.js +22 -21
- package/dist/widget.cjs +1 -1
- package/dist/widget.d.cts +32 -4
- package/dist/widget.d.ts +32 -4
- package/dist/widget.js +3 -3
- package/llms-full.txt +1932 -0
- package/package.json +5 -3
- package/dist/AgoClient-CMDVqNaH.cjs +0 -8
- /package/dist/{createMockClient-bAZ9KBHC.js → createMockClient-BUc9PSbo.js} +0 -0
- /package/dist/{createMockClient-BSr-UV8R.cjs → createMockClient-CjdCqixj.cjs} +0 -0
- /package/dist/{functions-Djnq-JAo.cjs → functions-IGSjjvF4.cjs} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,10 +5,18 @@ All notable changes to `@useago/sdk` are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [1.5.0] - 2026-07-07
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- `attachAutoContinueAfterNavigation(client, options?)`: the auto-continue
|
|
13
|
+
behavior ("go to page B and change X" in one user message) is now a
|
|
14
|
+
framework-agnostic core export, returning a detach function. The React hook
|
|
15
|
+
keeps its API and delegates to it.
|
|
16
|
+
- Angular: `AgoService.enableAutoContinueAfterNavigation(options?)` enables
|
|
17
|
+
auto-continue after navigation and returns the disable function (call it in
|
|
18
|
+
`ngOnDestroy`). `AgoAutoContinueOptions` is exported from
|
|
19
|
+
`@useago/sdk/angular`.
|
|
12
20
|
- `AgoConfig.warnOnEmptyReply` (default `true`) and a `message:empty` event:
|
|
13
21
|
a reply that completes `DONE` with no content, tool calls, or follow-ups
|
|
14
22
|
(usually an unknown `agent` slug) now warns on the console once per
|
|
@@ -25,6 +33,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
25
33
|
|
|
26
34
|
### Changed
|
|
27
35
|
|
|
36
|
+
- `clientFunctionsMode` now defaults to `"pause"`: with client functions
|
|
37
|
+
registered, the turn stops on the client function call(s) and resumes the
|
|
38
|
+
SAME turn once the results are submitted, so the agent sees the real
|
|
39
|
+
results. Backends without pause/resume support ignore the flag and keep the
|
|
40
|
+
old placeholder behavior. Set `clientFunctionsMode: "placeholder"` (config
|
|
41
|
+
or per message) to opt back into the legacy mode.
|
|
28
42
|
- `new AgoClient({})` (or missing/empty `baseUrl`) now throws an actionable
|
|
29
43
|
`AgoError` (`config_missing_base_url`) instead of a raw `TypeError`.
|
|
30
44
|
Same-origin `/path` baseUrls remain supported; a baseUrl with no protocol
|
|
@@ -2,13 +2,13 @@ var d = class extends Error {
|
|
|
2
2
|
constructor(e, t, s) {
|
|
3
3
|
super(e), this.code = t, this.statusCode = s, this.name = "AgoError";
|
|
4
4
|
}
|
|
5
|
-
}, f = class
|
|
5
|
+
}, f = class k extends d {
|
|
6
6
|
constructor(t, s, i, n, o, a) {
|
|
7
7
|
super(t, s, i), this.type = n, this.param = o, this.docUrl = a, this.name = "AgoApiError";
|
|
8
8
|
}
|
|
9
9
|
static fromResponse(t, s) {
|
|
10
10
|
const i = t.error;
|
|
11
|
-
return new
|
|
11
|
+
return new k(i.doc_url ? `${i.message} See ${i.doc_url}` : i.message, i.code, s, i.type, i.param, i.doc_url);
|
|
12
12
|
}
|
|
13
13
|
}, y = class extends d {
|
|
14
14
|
constructor(e, t) {
|
|
@@ -22,7 +22,7 @@ var d = class extends Error {
|
|
|
22
22
|
constructor(e, t, s) {
|
|
23
23
|
super(e, "function_error"), this.functionName = t, this.originalError = s, this.name = "AgoFunctionError";
|
|
24
24
|
}
|
|
25
|
-
},
|
|
25
|
+
}, I = class {
|
|
26
26
|
constructor(e = !1) {
|
|
27
27
|
this.enabled = e;
|
|
28
28
|
}
|
|
@@ -44,15 +44,15 @@ var d = class extends Error {
|
|
|
44
44
|
debug(...e) {
|
|
45
45
|
this.enabled && console.debug("[AGO SDK]", ...e);
|
|
46
46
|
}
|
|
47
|
-
}, l = new
|
|
47
|
+
}, l = new I(), R = "ago_widget_id";
|
|
48
48
|
function F() {
|
|
49
49
|
if (typeof localStorage < "u") {
|
|
50
|
-
const t = localStorage.getItem(
|
|
50
|
+
const t = localStorage.getItem(R);
|
|
51
51
|
if (t) return t;
|
|
52
52
|
}
|
|
53
53
|
const e = typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `ago-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
54
54
|
if (typeof localStorage < "u") try {
|
|
55
|
-
localStorage.setItem(
|
|
55
|
+
localStorage.setItem(R, e);
|
|
56
56
|
} catch {
|
|
57
57
|
}
|
|
58
58
|
return e;
|
|
@@ -129,26 +129,33 @@ var U = class {
|
|
|
129
129
|
let s = "";
|
|
130
130
|
throw e.status === 401 || e.status === 403 ? s = " Check `userJwt` (and that it has not expired)." : e.status === 404 && (s = " Check that `baseUrl` points at your AGO API root."), new f(`HTTP ${e.status}: ${e.statusText}.${s}`, "http_error", e.status, "api_error");
|
|
131
131
|
}
|
|
132
|
-
}, N = class {
|
|
133
|
-
constructor() {
|
|
134
|
-
this.functions = /* @__PURE__ */ new Map();
|
|
132
|
+
}, T = 5e4, N = 2e4, D = 2e3, P = class {
|
|
133
|
+
constructor(e) {
|
|
134
|
+
this.functions = /* @__PURE__ */ new Map(), this.defaultMaxResultBytes = e?.maxResultBytes ?? T;
|
|
135
|
+
}
|
|
136
|
+
setDefaultMaxResultBytes(e) {
|
|
137
|
+
this.defaultMaxResultBytes = e;
|
|
135
138
|
}
|
|
136
139
|
register(e, t, s) {
|
|
137
140
|
if (typeof e == "object") {
|
|
138
|
-
const { name:
|
|
139
|
-
return this.register(
|
|
140
|
-
description:
|
|
141
|
-
parameters:
|
|
141
|
+
const { name: a, handler: r, description: c, parameters: u, maxResultBytes: h } = e;
|
|
142
|
+
return this.register(a, r, {
|
|
143
|
+
description: c,
|
|
144
|
+
parameters: u,
|
|
145
|
+
maxResultBytes: h
|
|
142
146
|
});
|
|
143
147
|
}
|
|
144
148
|
const i = e;
|
|
145
149
|
if (!t || !s) throw new d(`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");
|
|
146
|
-
this.functions.has(i) && l.warn(`Function "${i}" is being overwritten`)
|
|
150
|
+
this.functions.has(i) && l.warn(`Function "${i}" is being overwritten`);
|
|
151
|
+
const { maxResultBytes: n, ...o } = s;
|
|
152
|
+
this.functions.set(i, {
|
|
147
153
|
schema: {
|
|
148
|
-
...
|
|
154
|
+
...o,
|
|
149
155
|
name: i
|
|
150
156
|
},
|
|
151
|
-
handler: t
|
|
157
|
+
handler: t,
|
|
158
|
+
maxResultBytes: n
|
|
152
159
|
}), l.log(`Registered function: ${i}`);
|
|
153
160
|
}
|
|
154
161
|
unregister(e) {
|
|
@@ -170,18 +177,35 @@ var U = class {
|
|
|
170
177
|
l.log(`Executing function: ${e}`, t);
|
|
171
178
|
try {
|
|
172
179
|
const i = await s.handler(t);
|
|
173
|
-
return l.log(`Function ${e} completed:`, i), i;
|
|
180
|
+
return l.log(`Function ${e} completed:`, i), this.guardResultSize(e, i, s.maxResultBytes);
|
|
174
181
|
} catch (i) {
|
|
175
182
|
throw l.error(`Function ${e} failed:`, i), new E(`Function "${e}" execution failed: ${i instanceof Error ? i.message : "Unknown error"}`, e, i instanceof Error ? i : void 0);
|
|
176
183
|
}
|
|
177
184
|
}
|
|
185
|
+
guardResultSize(e, t, s) {
|
|
186
|
+
let i;
|
|
187
|
+
try {
|
|
188
|
+
i = JSON.stringify(t);
|
|
189
|
+
} catch {
|
|
190
|
+
return t;
|
|
191
|
+
}
|
|
192
|
+
if (i === void 0) return t;
|
|
193
|
+
const n = new TextEncoder().encode(i).length, o = s ?? this.defaultMaxResultBytes;
|
|
194
|
+
return n > o ? (l.warn(`Function "${e}" 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.`), {
|
|
195
|
+
truncated: !0,
|
|
196
|
+
originalBytes: n,
|
|
197
|
+
maxBytes: o,
|
|
198
|
+
preview: i.slice(0, D),
|
|
199
|
+
hint: `The result of "${e}" 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.`
|
|
200
|
+
}) : (n > N && l.warn(`Function "${e}" 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.`), t);
|
|
201
|
+
}
|
|
178
202
|
clear() {
|
|
179
203
|
this.functions.clear(), l.log("Cleared all registered functions");
|
|
180
204
|
}
|
|
181
205
|
get size() {
|
|
182
206
|
return this.functions.size;
|
|
183
207
|
}
|
|
184
|
-
},
|
|
208
|
+
}, M = class {
|
|
185
209
|
constructor() {
|
|
186
210
|
this.entries = /* @__PURE__ */ new Map(), this.dynamicProviders = /* @__PURE__ */ new Map();
|
|
187
211
|
}
|
|
@@ -218,7 +242,7 @@ var U = class {
|
|
|
218
242
|
function v(e) {
|
|
219
243
|
return e === null || typeof e != "object" ? JSON.stringify(e) ?? "null" : Array.isArray(e) ? `[${e.map(v).join(",")}]` : `{${Object.keys(e).sort().map((t) => `${JSON.stringify(t)}:${v(e[t])}`).join(",")}}`;
|
|
220
244
|
}
|
|
221
|
-
var
|
|
245
|
+
var O = class {
|
|
222
246
|
constructor(e) {
|
|
223
247
|
this.callbacks = e, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0, this.answerCompleteEmitted = !1, this.waitingClientEmitted = !1, this.firedClientFunctions = /* @__PURE__ */ new Set();
|
|
224
248
|
}
|
|
@@ -334,11 +358,11 @@ var D = class {
|
|
|
334
358
|
return e.status !== "WAITING_CLIENT" && this.callbacks.onComplete?.(e), e;
|
|
335
359
|
}
|
|
336
360
|
};
|
|
337
|
-
function
|
|
361
|
+
function H(e) {
|
|
338
362
|
const t = e.message.toLowerCase();
|
|
339
363
|
return t.includes("load failed") || t.includes("failed to fetch") || t.includes("network") || t.includes("abort");
|
|
340
364
|
}
|
|
341
|
-
var
|
|
365
|
+
var j = /* @__PURE__ */ new Set([
|
|
342
366
|
"image/jpeg",
|
|
343
367
|
"image/png",
|
|
344
368
|
"image/gif",
|
|
@@ -346,7 +370,7 @@ var P = /* @__PURE__ */ new Set([
|
|
|
346
370
|
"image/bmp",
|
|
347
371
|
"image/tiff"
|
|
348
372
|
]);
|
|
349
|
-
function
|
|
373
|
+
function B(e) {
|
|
350
374
|
if (!e) return;
|
|
351
375
|
const t = typeof window < "u" && window.location ? window.location.href : "https://ago.local/";
|
|
352
376
|
try {
|
|
@@ -355,16 +379,16 @@ function O(e) {
|
|
|
355
379
|
} catch {
|
|
356
380
|
}
|
|
357
381
|
}
|
|
358
|
-
function
|
|
359
|
-
return e.isSafeImage === !0 && typeof e.contentType == "string" && e.contentType.startsWith("image/") &&
|
|
382
|
+
function K(e) {
|
|
383
|
+
return e.isSafeImage === !0 && typeof e.contentType == "string" && e.contentType.startsWith("image/") && B(e.url) !== void 0;
|
|
360
384
|
}
|
|
361
|
-
function
|
|
385
|
+
function X(e) {
|
|
362
386
|
if (e == null || e < 0) return "";
|
|
363
387
|
if (e < 1024) return `${e} B`;
|
|
364
388
|
const t = e / 1024;
|
|
365
389
|
return t < 1024 ? `${t.toFixed(1)} KB` : `${(t / 1024).toFixed(1)} MB`;
|
|
366
390
|
}
|
|
367
|
-
function
|
|
391
|
+
function L(e) {
|
|
368
392
|
return {
|
|
369
393
|
id: String(e.id ?? ""),
|
|
370
394
|
name: typeof e.name == "string" && e.name ? e.name : "file",
|
|
@@ -374,17 +398,17 @@ function j(e) {
|
|
|
374
398
|
isSafeImage: e.is_safe_image === !0
|
|
375
399
|
};
|
|
376
400
|
}
|
|
377
|
-
function
|
|
401
|
+
function Y(e) {
|
|
378
402
|
return e.map((t, s) => ({
|
|
379
403
|
id: `local-${s}-${t.name}`,
|
|
380
404
|
name: t.name,
|
|
381
405
|
contentType: t.type || void 0,
|
|
382
406
|
fileSize: t.size,
|
|
383
407
|
url: typeof URL < "u" && URL.createObjectURL ? URL.createObjectURL(t) : void 0,
|
|
384
|
-
isSafeImage:
|
|
408
|
+
isSafeImage: j.has(t.type)
|
|
385
409
|
}));
|
|
386
410
|
}
|
|
387
|
-
var
|
|
411
|
+
var G = class {
|
|
388
412
|
constructor() {
|
|
389
413
|
this.handlers = /* @__PURE__ */ new Map();
|
|
390
414
|
}
|
|
@@ -425,20 +449,20 @@ var M = class {
|
|
|
425
449
|
removeAllListeners(e) {
|
|
426
450
|
e ? this.handlers.delete(e) : this.handlers.clear();
|
|
427
451
|
}
|
|
428
|
-
},
|
|
429
|
-
function
|
|
430
|
-
if (typeof e != "object" || e === null) throw new d(`${t}: ${
|
|
452
|
+
}, 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;
|
|
453
|
+
function x(e, t = "AgoClient") {
|
|
454
|
+
if (typeof e != "object" || e === null) throw new d(`${t}: ${S}`, "config_missing_base_url");
|
|
431
455
|
const s = e.baseUrl;
|
|
432
|
-
if (typeof s != "string" || s.trim() === "") throw new d(`${t}: ${
|
|
433
|
-
!s.startsWith("/") && !
|
|
456
|
+
if (typeof s != "string" || s.trim() === "") throw new d(`${t}: ${S}`, "config_missing_base_url");
|
|
457
|
+
!s.startsWith("/") && !W.test(s) && ($ || ($ = !0, console.warn(`[AGO] ${t}: \`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).`)));
|
|
434
458
|
}
|
|
435
|
-
function
|
|
459
|
+
function z(e) {
|
|
436
460
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
437
461
|
}
|
|
438
462
|
function w(e) {
|
|
439
463
|
return e.split("/").filter((t) => t.startsWith(":")).map((t) => t.slice(1));
|
|
440
464
|
}
|
|
441
|
-
function
|
|
465
|
+
function J(e, t) {
|
|
442
466
|
const s = [];
|
|
443
467
|
return {
|
|
444
468
|
path: e.split("/").map((i) => {
|
|
@@ -449,19 +473,19 @@ function W(e, t) {
|
|
|
449
473
|
missing: s
|
|
450
474
|
};
|
|
451
475
|
}
|
|
452
|
-
function
|
|
476
|
+
function q(e, t) {
|
|
453
477
|
const s = t.find((n) => n.path === e);
|
|
454
478
|
if (s) return s;
|
|
455
479
|
const i = t.find((n) => {
|
|
456
480
|
if (!n.path.includes(":")) return !1;
|
|
457
|
-
const o = "^" + n.path.split("/").map((a) => a.startsWith(":") ? "[^/]+" :
|
|
481
|
+
const o = "^" + n.path.split("/").map((a) => a.startsWith(":") ? "[^/]+" : z(a)).join("/") + "/?$";
|
|
458
482
|
return new RegExp(o).test(e);
|
|
459
483
|
});
|
|
460
484
|
return i || t.filter((n) => n.path !== "/" && e.startsWith(n.path)).sort((n, o) => o.path.length - n.path.length)[0];
|
|
461
485
|
}
|
|
462
|
-
var
|
|
486
|
+
var V = class A {
|
|
463
487
|
constructor(t) {
|
|
464
|
-
this.warnedEmptyConversations = /* @__PURE__ */ new Set(), this.pendingResumes = /* @__PURE__ */ new Map(), this.resumeGate = null,
|
|
488
|
+
this.warnedEmptyConversations = /* @__PURE__ */ new Set(), this.pendingResumes = /* @__PURE__ */ new Map(), this.resumeGate = null, x(t, "AgoClient"), this.config = t, this.httpClient = new U(t), this.functionRegistry = new P({ maxResultBytes: t.maxFunctionResultBytes }), this.contextRegistry = new M(), this.eventEmitter = new G(), t.debug && l.enable(), l.log("AgoClient initialized");
|
|
465
489
|
}
|
|
466
490
|
async sendMessage(t, s) {
|
|
467
491
|
const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), o = this.config.agent || this.config.defaultAgentId, a = this.resolveClientFunctionsMode(s), r = {
|
|
@@ -472,16 +496,16 @@ var K = class x {
|
|
|
472
496
|
i.length > 0 && (r.client_functions = i, a === "pause" && (r.client_functions_mode = a)), n && (r.client_context = n), s?.hidden && (r.hidden = !0);
|
|
473
497
|
let c;
|
|
474
498
|
if (s?.files && s.files.length > 0) {
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
for (const
|
|
478
|
-
c = await this.httpClient.postFormData("/api/sdk/v1/messages",
|
|
499
|
+
const u = new FormData();
|
|
500
|
+
u.append("content", t), 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");
|
|
501
|
+
for (const h of s.files) u.append("files", h);
|
|
502
|
+
c = await this.httpClient.postFormData("/api/sdk/v1/messages", u);
|
|
479
503
|
} else c = await this.httpClient.postStream("/api/sdk/v1/messages", r);
|
|
480
504
|
return this.processSSEResponse(c);
|
|
481
505
|
}
|
|
482
506
|
async processSSEResponse(t) {
|
|
483
507
|
let s = !1;
|
|
484
|
-
const i = await new
|
|
508
|
+
const i = await new O({
|
|
485
509
|
onRawChunk: (n) => {
|
|
486
510
|
this.eventEmitter.emit("stream:message", n);
|
|
487
511
|
},
|
|
@@ -516,7 +540,7 @@ var K = class x {
|
|
|
516
540
|
return i.status !== "WAITING_CLIENT" && this.maybeFlagEmptyReply(i, s), i;
|
|
517
541
|
}
|
|
518
542
|
resolveClientFunctionsMode(t) {
|
|
519
|
-
return t?.clientFunctionsMode ?? this.config.clientFunctionsMode ?? "
|
|
543
|
+
return t?.clientFunctionsMode ?? this.config.clientFunctionsMode ?? "pause";
|
|
520
544
|
}
|
|
521
545
|
registerResumeGate(t) {
|
|
522
546
|
return this.resumeGate = t, () => {
|
|
@@ -611,8 +635,8 @@ var K = class x {
|
|
|
611
635
|
status: n.status,
|
|
612
636
|
createdAt: new Date(n.created_at),
|
|
613
637
|
hidden: n.hidden,
|
|
614
|
-
toolCalls:
|
|
615
|
-
attachments: n.attachments && n.attachments.length > 0 ? n.attachments.map(
|
|
638
|
+
toolCalls: A.mapPersistedToolCalls(n.tool_call_data),
|
|
639
|
+
attachments: n.attachments && n.attachments.length > 0 ? n.attachments.map(L) : void 0
|
|
616
640
|
}))
|
|
617
641
|
};
|
|
618
642
|
return this.eventEmitter.emit("conversation:loaded", i), i;
|
|
@@ -643,15 +667,15 @@ var K = class x {
|
|
|
643
667
|
return l.warn("Cannot resume paused turn: function(s) not registered on this page:", o.map((r) => r.functionName)), null;
|
|
644
668
|
let a = i.length === 0;
|
|
645
669
|
for (const r of i) {
|
|
646
|
-
let c,
|
|
670
|
+
let c, u;
|
|
647
671
|
try {
|
|
648
672
|
c = await this.functionRegistry.execute(r.functionName, r.arguments ?? {});
|
|
649
|
-
} catch (
|
|
650
|
-
|
|
673
|
+
} catch (h) {
|
|
674
|
+
u = h instanceof Error ? h.message : "Unknown error", l.error("Client function execution failed:", h);
|
|
651
675
|
}
|
|
652
676
|
a = (await this.submitToolCallForm(r.id, {
|
|
653
677
|
result: c,
|
|
654
|
-
error:
|
|
678
|
+
error: u,
|
|
655
679
|
_type: "client_function_result"
|
|
656
680
|
}))?.resume?.ready ?? a;
|
|
657
681
|
}
|
|
@@ -699,8 +723,8 @@ var K = class x {
|
|
|
699
723
|
}
|
|
700
724
|
registerNavigationFunction(t, s) {
|
|
701
725
|
const i = s.map((r) => r.name), n = s.map((r) => {
|
|
702
|
-
const c = w(r.path),
|
|
703
|
-
return `- "${r.name}"${
|
|
726
|
+
const c = w(r.path), u = c.length > 0 ? ` (requires ${c.map((h) => `"${h}"`).join(", ")})` : "";
|
|
727
|
+
return `- "${r.name}"${u}: ${r.description}`;
|
|
704
728
|
}).join(`
|
|
705
729
|
`), o = /* @__PURE__ */ new Map();
|
|
706
730
|
for (const r of s) for (const c of w(r.path)) o.set(c, [...o.get(c) ?? [], r.name]);
|
|
@@ -716,24 +740,24 @@ var K = class x {
|
|
|
716
740
|
}
|
|
717
741
|
a[r] = {
|
|
718
742
|
type: "string",
|
|
719
|
-
description: `Value for ":${r}" in the page path. Required when page is ${c.map((
|
|
743
|
+
description: `Value for ":${r}" in the page path. Required when page is ${c.map((u) => `"${u}"`).join(" or ")}.`
|
|
720
744
|
};
|
|
721
745
|
}
|
|
722
746
|
this.registerFunction("navigateToPage", async (r) => {
|
|
723
|
-
const c = r.page,
|
|
724
|
-
if (!
|
|
747
|
+
const c = r.page, u = s.find((m) => m.name === c);
|
|
748
|
+
if (!u) return {
|
|
725
749
|
success: !1,
|
|
726
750
|
error: `Unknown page: ${c}`
|
|
727
751
|
};
|
|
728
|
-
let
|
|
752
|
+
let h = {};
|
|
729
753
|
if (typeof r.params == "string") try {
|
|
730
|
-
|
|
754
|
+
h = JSON.parse(r.params);
|
|
731
755
|
} catch {
|
|
732
756
|
}
|
|
733
|
-
else r.params && typeof r.params == "object" && (
|
|
757
|
+
else r.params && typeof r.params == "object" && (h = r.params);
|
|
734
758
|
const C = {};
|
|
735
|
-
for (const m of w(
|
|
736
|
-
const { path: b, missing: g } =
|
|
759
|
+
for (const m of w(u.path)) C[m] = r[m] ?? h[m];
|
|
760
|
+
const { path: b, missing: g } = J(u.path, C);
|
|
737
761
|
if (g.length > 0) {
|
|
738
762
|
const m = g.map((p) => `"${p}": "..."`).join(", ");
|
|
739
763
|
return {
|
|
@@ -755,11 +779,11 @@ ${n}`,
|
|
|
755
779
|
}
|
|
756
780
|
}), this.addDynamicContext("current-page", () => {
|
|
757
781
|
if (typeof window > "u" || !window.location) return null;
|
|
758
|
-
const r = window.location.href, c = typeof document < "u" ? document.title : void 0,
|
|
759
|
-
return
|
|
782
|
+
const r = window.location.href, c = typeof document < "u" ? document.title : void 0, u = q(window.location.pathname, s), h = { url: r };
|
|
783
|
+
return u && (h.page = u.name), c && (h.title = c), {
|
|
760
784
|
name: "Current page",
|
|
761
785
|
description: "The page the user is currently viewing.",
|
|
762
|
-
data:
|
|
786
|
+
data: h
|
|
763
787
|
};
|
|
764
788
|
});
|
|
765
789
|
}
|
|
@@ -771,10 +795,10 @@ ${n}`,
|
|
|
771
795
|
`);
|
|
772
796
|
this.registerFunction(i, async (a) => {
|
|
773
797
|
const r = {};
|
|
774
|
-
for (const [c,
|
|
775
|
-
if (
|
|
776
|
-
const
|
|
777
|
-
|
|
798
|
+
for (const [c, u] of Object.entries(a)) {
|
|
799
|
+
if (u === void 0) continue;
|
|
800
|
+
const h = n.get(c);
|
|
801
|
+
h && (await h.set(u), r[c] = u);
|
|
778
802
|
}
|
|
779
803
|
return {
|
|
780
804
|
success: !0,
|
|
@@ -861,7 +885,7 @@ ${o}`,
|
|
|
861
885
|
...this.config,
|
|
862
886
|
...s
|
|
863
887
|
};
|
|
864
|
-
|
|
888
|
+
x(i, "AgoClient.updateConfig"), this.config = i, this.httpClient.updateConfig(s), s.debug !== void 0 && (s.debug ? l.enable() : l.disable()), s.maxFunctionResultBytes !== void 0 && this.functionRegistry.setDefaultMaxResultBytes(s.maxFunctionResultBytes);
|
|
865
889
|
}
|
|
866
890
|
destroy() {
|
|
867
891
|
this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(), this.pendingResumes.clear(), this.resumeGate = null, l.log("AgoClient destroyed");
|
|
@@ -869,20 +893,20 @@ ${o}`,
|
|
|
869
893
|
};
|
|
870
894
|
export {
|
|
871
895
|
_,
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
896
|
+
K as a,
|
|
897
|
+
O as c,
|
|
898
|
+
P as d,
|
|
875
899
|
l as f,
|
|
876
900
|
y as g,
|
|
877
901
|
E as h,
|
|
878
|
-
|
|
879
|
-
|
|
902
|
+
Y as i,
|
|
903
|
+
H as l,
|
|
880
904
|
d as m,
|
|
881
|
-
|
|
882
|
-
|
|
905
|
+
x as n,
|
|
906
|
+
X as o,
|
|
883
907
|
f as p,
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
908
|
+
G as r,
|
|
909
|
+
B as s,
|
|
910
|
+
V as t,
|
|
911
|
+
M as u
|
|
888
912
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var d=class extends Error{constructor(e,t,n){super(e),this.code=t,this.statusCode=n,this.name="AgoError"}},f=class A extends d{constructor(t,n,i,s,o,a){super(t,n,i),this.type=s,this.param=o,this.docUrl=a,this.name="AgoApiError"}static fromResponse(t,n){const i=t.error;return new A(i.doc_url?`${i.message} See ${i.doc_url}`:i.message,i.code,n,i.type,i.param,i.doc_url)}},g=class extends d{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},v=class extends d{constructor(e,t="stream_error"){super(e,t),this.name="AgoStreamError"}},b=class extends d{constructor(e,t,n){super(e,"function_error"),this.functionName=t,this.originalError=n,this.name="AgoFunctionError"}},P=class{constructor(e=!1){this.enabled=e}enable(){this.enabled=!0}disable(){this.enabled=!1}log(...e){this.enabled&&console.log("[AGO SDK]",...e)}warn(...e){this.enabled&&console.warn("[AGO SDK]",...e)}error(...e){console.error("[AGO SDK]",...e)}debug(...e){this.enabled&&console.debug("[AGO SDK]",...e)}},l=new P,S="ago_widget_id";function O(){if(typeof localStorage<"u"){const t=localStorage.getItem(S);if(t)return t}const e=typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`ago-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,12)}`;if(typeof localStorage<"u")try{localStorage.setItem(S,e)}catch{}return e}var j=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-User-Anon-Id":e.widgetId||O()},e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission&&(this.headers["X-Widget-Permission"]=e.permission)}updateConfig(e){e.baseUrl&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),e.widgetId&&(this.headers["X-User-Anon-Id"]=e.widgetId),e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission!==void 0&&(e.permission?this.headers["X-Widget-Permission"]=e.permission:delete this.headers["X-Widget-Permission"])}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async postStream(e,t){const n=`${this.baseUrl}${e}`;l.debug("POST (stream)",n,t);try{const i=await fetch(n,{method:"POST",headers:{...this.headers,"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});return i.ok||await this.handleErrorResponse(i),i}catch(i){throw i instanceof f?i:new g(`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)}}async postFormData(e,t){const n=`${this.baseUrl}${e}`;l.debug("POST (formData)",n);const i={...this.headers};try{const s=await fetch(n,{method:"POST",headers:i,body:t});return s.ok||await this.handleErrorResponse(s),s}catch(s){throw s instanceof f?s:new g(`Network error: ${s instanceof Error?s.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,s instanceof Error?s:void 0)}}async request(e,t,n){const i=`${this.baseUrl}${t}`;l.debug(e,i,n);try{const s=await fetch(i,{method:e,headers:{...this.headers,"Content-Type":"application/json"},body:n?JSON.stringify(n):void 0});return s.ok||await this.handleErrorResponse(s),s.status===204?void 0:s.json()}catch(s){throw s instanceof f?s:new g(`Network error: ${s instanceof Error?s.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,s instanceof Error?s:void 0)}}async handleErrorResponse(e){let t;try{t=await e.json()}catch{}if(t?.error)throw f.fromResponse(t,e.status);let n="";throw e.status===401||e.status===403?n=" Check `userJwt` (and that it has not expired).":e.status===404&&(n=" Check that `baseUrl` points at your AGO API root."),new f(`HTTP ${e.status}: ${e.statusText}.${n}`,"http_error",e.status,"api_error")}},D=5e4,M=2e4,B=2e3,k=class{constructor(e){this.functions=new Map,this.defaultMaxResultBytes=e?.maxResultBytes??D}setDefaultMaxResultBytes(e){this.defaultMaxResultBytes=e}register(e,t,n){if(typeof e=="object"){const{name:a,handler:r,description:c,parameters:u,maxResultBytes:h}=e;return this.register(a,r,{description:c,parameters:u,maxResultBytes:h})}const i=e;if(!t||!n)throw new d(`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");this.functions.has(i)&&l.warn(`Function "${i}" is being overwritten`);const{maxResultBytes:s,...o}=n;this.functions.set(i,{schema:{...o,name:i},handler:t,maxResultBytes:s}),l.log(`Registered function: ${i}`)}unregister(e){const t=this.functions.delete(e);return t&&l.log(`Unregistered function: ${e}`),t}get(e){return this.functions.get(e)}has(e){return this.functions.has(e)}getSchemas(){return Array.from(this.functions.values()).map(e=>e.schema)}async execute(e,t){const n=this.functions.get(e);if(!n)throw new b(`Function "${e}" is not registered`,e);l.log(`Executing function: ${e}`,t);try{const i=await n.handler(t);return l.log(`Function ${e} completed:`,i),this.guardResultSize(e,i,n.maxResultBytes)}catch(i){throw l.error(`Function ${e} failed:`,i),new b(`Function "${e}" execution failed: ${i instanceof Error?i.message:"Unknown error"}`,e,i instanceof Error?i:void 0)}}guardResultSize(e,t,n){let i;try{i=JSON.stringify(t)}catch{return t}if(i===void 0)return t;const s=new TextEncoder().encode(i).length,o=n??this.defaultMaxResultBytes;return s>o?(l.warn(`Function "${e}" result is ${s} 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.`),{truncated:!0,originalBytes:s,maxBytes:o,preview:i.slice(0,B),hint:`The result of "${e}" 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.`}):(s>M&&l.warn(`Function "${e}" returned a large result (${Math.round(s/1024)} KB). Large results consume LLM context: return fewer fields, paginate, or push the data to the UI and return a summary.`),t)}clear(){this.functions.clear(),l.log("Cleared all registered functions")}get size(){return this.functions.size}},F=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),l.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&l.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),l.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&l.log(`DynamicContext provider removed: ${e}`),t}getSnapshot(){if(this.entries.size===0&&this.dynamicProviders.size===0)return null;const e={};for(const[t,n]of this.entries)e[t]=n;for(const[t,n]of this.dynamicProviders)try{const i=n();i&&(e[t]=i)}catch(i){l.error(`DynamicContext provider "${t}" threw:`,i)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),l.log("ClientContext cleared")}};function C(e){return e===null||typeof e!="object"?JSON.stringify(e)??"null":Array.isArray(e)?`[${e.map(C).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${C(e[t])}`).join(",")}}`}var I=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0,this.answerCompleteEmitted=!1,this.waitingClientEmitted=!1,this.firedClientFunctions=new Set}async processStream(e){if(!e.body)throw new v("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");const t=e.body.getReader(),n=new TextDecoder;try{for(;;){const{done:i,value:s}=await t.read();if(i)break;const o=n.decode(s,{stream:!0});this.buffer+=o,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(i){const s=i instanceof Error?i:new v("Stream processing failed mid-flight. The connection may have dropped; retry the message.");throw this.callbacks.onError?.(s),s}finally{t.releaseLock()}}processBuffer(){const e=this.buffer.split(`
|
|
2
|
+
|
|
3
|
+
`);this.buffer=e.pop()||"";for(const t of e){if(!t.trim())continue;const n=t.split(`
|
|
4
|
+
`);for(const i of n)if(!i.startsWith(": ")&&i.startsWith("data: ")){const s=i.slice(6);try{const o=JSON.parse(s);this.handleChunk(o)}catch(o){l.warn("Failed to parse SSE data:",s,o)}}}}handleChunk(e){if(this.callbacks.onRawChunk?.(e),e.message_id&&!this.message.id&&(this.message.id=e.message_id),e.thread?.id&&(this.message.conversationId=e.thread.id,this.isFirstChunk&&this.message.id&&(this.isFirstChunk=!1,this.callbacks.onStart?.({conversationId:this.message.conversationId,messageId:this.message.id}))),e.content!==void 0&&(this.message.content=(this.message.content||"")+e.content,this.message.conversationId&&this.message.id&&this.callbacks.onChunk?.({content:e.content,conversationId:this.message.conversationId,messageId:this.message.id})),e.full_content!==void 0&&(this.message.content=e.full_content),e.status&&(this.message.status=e.status),e.agent&&(this.message.agent={id:e.agent.id,name:e.agent.name,displayName:e.agent.display_name}),e.knowledge_sources&&(this.sources=e.knowledge_sources.map(t=>{const n=t.knowledge_document;return{id:n.id,title:n.title,url:n.use_external_link?n.external_link_url:n.internal_link_url}})),e.type==="client_function"&&e.function_name){const t=`${e.function_name}::${C(e.arguments??{})}`;this.firedClientFunctions.has(t)||(this.firedClientFunctions.add(t),this.callbacks.onClientFunction?.({invocationId:e.id||"",functionName:e.function_name,arguments:e.arguments||{},conversationId:this.message.conversationId||""}))}if(e.tool_call_data&&e.type&&e.type!=="client_function"){const t=this.parseToolCall(e);this.callbacks.onToolCall?.(t);const n=this.toolCalls.findIndex(i=>i.id===t.id);n>=0?this.toolCalls[n]=t:this.toolCalls.push(t)}e.follow_up_replies&&(this.followUpReplies=e.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?.({conversationId:this.message.conversationId||"",messageId:this.message.id,waitingToolCallIds:e.waiting_tool_call_ids??[]}))}parseToolCall(e){return{id:e.id||"",type:e.type||"status_message",status:e.status||"unknown",toolName:e.tool_name||"",toolDisplayName:e.tool_display_name,message:e.message,formSchema:e.form_schema,data:e.data,functionName:e.function_name,arguments:e.arguments}}buildMessage(){return{id:this.message.id||"",conversationId:this.message.conversationId||"",content:this.message.content||"",role:"assistant",status:this.message.status||"DONE",agent:this.message.agent,sources:this.sources.length>0?this.sources:void 0,toolCalls:this.toolCalls.length>0?this.toolCalls:void 0,followUpReplies:this.followUpReplies.length>0?this.followUpReplies:void 0,createdAt:new Date}}buildFinalMessage(){const e=this.buildMessage();return e.status!=="WAITING_CLIENT"&&this.callbacks.onComplete?.(e),e}};function L(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var G=new Set(["image/jpeg","image/png","image/gif","image/webp","image/bmp","image/tiff"]);function U(e){if(!e)return;const t=typeof window<"u"&&window.location?window.location.href:"https://ago.local/";try{const n=new URL(e,t);if(n.protocol==="http:"||n.protocol==="https:"||n.protocol==="blob:")return e}catch{}}function W(e){return e.isSafeImage===!0&&typeof e.contentType=="string"&&e.contentType.startsWith("image/")&&U(e.url)!==void 0}function z(e){if(e==null||e<0)return"";if(e<1024)return`${e} B`;const t=e/1024;return t<1024?`${t.toFixed(1)} KB`:`${(t/1024).toFixed(1)} MB`}function J(e){return{id:String(e.id??""),name:typeof e.name=="string"&&e.name?e.name:"file",contentType:typeof e.content_type=="string"?e.content_type:void 0,fileSize:typeof e.file_size=="number"?e.file_size:void 0,url:typeof e.file_url=="string"?e.file_url:void 0,isSafeImage:e.is_safe_image===!0}}function q(e){return e.map((t,n)=>({id:`local-${n}-${t.name}`,name:t.name,contentType:t.type||void 0,fileSize:t.size,url:typeof URL<"u"&&URL.createObjectURL?URL.createObjectURL(t):void 0,isSafeImage:G.has(t.type)}))}var N=class{constructor(){this.handlers=new Map}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const n=this.handlers.get(e);n&&n.delete(t)}emit(e,t){const n=this.handlers.get(e);n&&n.forEach(i=>{try{i(t)}catch(s){console.error(`Error in event handler for ${String(e)}:`,s)}})}once(e,t){const n=(i=>{this.off(e,n),t(i)});this.on(e,n)}waitFor(e,t){return new Promise((n,i)=>{let s;const o=(a=>{s&&clearTimeout(s),n(a)});this.once(e,o),t?.timeout&&(s=setTimeout(()=>{this.off(e,o),i(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},$='`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).',H=/^[a-z][a-z0-9+.-]*:\/\//i,x=!1;function E(e,t="AgoClient"){if(typeof e!="object"||e===null)throw new d(`${t}: ${$}`,"config_missing_base_url");const n=e.baseUrl;if(typeof n!="string"||n.trim()==="")throw new d(`${t}: ${$}`,"config_missing_base_url");!n.startsWith("/")&&!H.test(n)&&(x||(x=!0,console.warn(`[AGO] ${t}: \`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).`)))}function K(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function w(e){return e.split("/").filter(t=>t.startsWith(":")).map(t=>t.slice(1))}function X(e,t){const n=[];return{path:e.split("/").map(i=>{if(!i.startsWith(":"))return i;const s=i.slice(1),o=t[s];return o==null||o===""?(n.push(s),i):encodeURIComponent(String(o))}).join("/"),missing:n}}function Y(e,t){const n=t.find(s=>s.path===e);if(n)return n;const i=t.find(s=>{if(!s.path.includes(":"))return!1;const o="^"+s.path.split("/").map(a=>a.startsWith(":")?"[^/]+":K(a)).join("/")+"/?$";return new RegExp(o).test(e)});return i||t.filter(s=>s.path!=="/"&&e.startsWith(s.path)).sort((s,o)=>o.path.length-s.path.length)[0]}var V=class T{constructor(t){this.warnedEmptyConversations=new Set,this.pendingResumes=new Map,this.resumeGate=null,E(t,"AgoClient"),this.config=t,this.httpClient=new j(t),this.functionRegistry=new k({maxResultBytes:t.maxFunctionResultBytes}),this.contextRegistry=new F,this.eventEmitter=new N,t.debug&&l.enable(),l.log("AgoClient initialized")}async sendMessage(t,n){const i=this.functionRegistry.getSchemas(),s=this.contextRegistry.getSnapshot(),o=this.config.agent||this.config.defaultAgentId,a=this.resolveClientFunctionsMode(n),r={content:t,conversation_id:n?.conversationId,agent_id:n?.agentId||o};i.length>0&&(r.client_functions=i,a==="pause"&&(r.client_functions_mode=a)),s&&(r.client_context=s),n?.hidden&&(r.hidden=!0);let c;if(n?.files&&n.files.length>0){const u=new FormData;u.append("content",t),n.conversationId&&u.append("conversation_id",n.conversationId),(n.agentId||o)&&u.append("agent_id",n.agentId||o||""),i.length>0&&(u.append("client_functions",JSON.stringify(i)),a==="pause"&&u.append("client_functions_mode",a)),s&&u.append("client_context",JSON.stringify(s)),n.hidden&&u.append("hidden","true");for(const h of n.files)u.append("files",h);c=await this.httpClient.postFormData("/api/sdk/v1/messages",u)}else c=await this.httpClient.postStream("/api/sdk/v1/messages",r);return this.processSSEResponse(c)}async processSSEResponse(t){let n=!1;const i=await new I({onRawChunk:s=>{this.eventEmitter.emit("stream:message",s)},onStart:s=>{this.eventEmitter.emit("message:start",s)},onChunk:s=>{this.eventEmitter.emit("message:chunk",s)},onToolCall:s=>{this.eventEmitter.emit("toolCall:received",s),s.type==="form"&&this.eventEmitter.emit("toolCall:form",s)},onClientFunction:async s=>{n=!0,this.eventEmitter.emit("function:invoke",s),await this.handleClientFunctionInvocation(s)},onAnswerComplete:s=>{this.eventEmitter.emit("message:answer-complete",s)},onWaitingClient:s=>{this.eventEmitter.emit("message:waiting-client",s),this.markResumeSignal(s.messageId,s.conversationId,"waitingConfirmed")},onComplete:s=>{this.eventEmitter.emit("message:complete",s)},onError:s=>{this.eventEmitter.emit("message:error",{error:s.message,code:s instanceof d?s.code:void 0})}}).processStream(t);return i.status!=="WAITING_CLIENT"&&this.maybeFlagEmptyReply(i,n),i}resolveClientFunctionsMode(t){return t?.clientFunctionsMode??this.config.clientFunctionsMode??"pause"}registerResumeGate(t){return this.resumeGate=t,()=>{this.resumeGate===t&&(this.resumeGate=null)}}async continueMessage(t){const n=this.functionRegistry.getSchemas(),i=this.contextRegistry.getSnapshot(),s={};n.length>0&&(s.client_functions=n),i&&(s.client_context=i);const o=await this.httpClient.postStream(`/api/sdk/v1/messages/${t}/continue`,s);return this.processSSEResponse(o)}markResumeSignal(t,n,i){if(!t)return;const s=this.pendingResumes.get(t)??{conversationId:n,waitingConfirmed:!1,resultsReady:!1,started:!1};s[i]=!0,n&&(s.conversationId=n),this.pendingResumes.set(t,s),!(!s.waitingConfirmed||!s.resultsReady||s.started)&&(s.started=!0,this.runAutoResume(t,s.conversationId))}async runAutoResume(t,n){try{this.resumeGate&&await this.resumeGate({conversationId:n,messageId:t})}catch(i){l.warn("Resume gate threw; resuming anyway:",i)}this.pendingResumes.delete(t);try{await this.continueMessage(t)}catch(i){l.warn("Auto-resume of paused turn failed:",i)}}maybeFlagEmptyReply(t,n){t.status==="DONE"&&(t.content??"").trim()===""&&!n&&!(t.toolCalls&&t.toolCalls.length>0)&&!(t.followUpReplies&&t.followUpReplies.length>0)&&setTimeout(()=>{if(this.eventEmitter.emit("message:empty",{conversationId:t.conversationId??"",messageId:t.id??""}),this.config.warnOnEmptyReply===!1)return;const i=t.conversationId||"(no conversation)";if(this.warnedEmptyConversations.has(i))return;this.warnedEmptyConversations.add(i);const s=this.config.agent||this.config.defaultAgentId;t.id?console.warn("[AGO] Reply completed with empty content. Possible causes: "+(s?`the agent "${s}" 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: "+(s?`the agent "${s}" 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`.")},0)}async handleClientFunctionInvocation(t){let n,i;try{n=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(s){i=s instanceof Error?s.message:"Unknown error",l.error("Client function execution failed:",s)}if(t.invocationId)try{const s=await this.submitToolCallForm(t.invocationId,{result:n,error:i,_type:"client_function_result"});s?.resume?.ready&&this.markResumeSignal(s.resume.message_id,t.conversationId,"resultsReady")}catch(s){l.error("Failed to submit function result:",s)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:n,error:i})}async getConversations(){return(await this.httpClient.get("/api/sdk/v1/conversations")).items.map(t=>({id:t.id,title:t.title,lastMessageDate:new Date(t.last_message_date)}))}async getConversation(t){const n=await this.httpClient.get(`/api/sdk/v1/conversations/${t}`),i={id:n.id,title:n.title,lastMessageDate:new Date(n.last_message_date),messages:n.messages.map(s=>({id:s.id,conversationId:n.id,content:s.content,role:s.role,status:s.status,createdAt:new Date(s.created_at),hidden:s.hidden,toolCalls:T.mapPersistedToolCalls(s.tool_call_data),attachments:s.attachments&&s.attachments.length>0?s.attachments.map(J):void 0}))};return this.eventEmitter.emit("conversation:loaded",i),i}static mapPersistedToolCalls(t){if(!(!t||t.length===0))return t.map(n=>({id:String(n.id??""),type:n.type??"status_message",status:String(n.status??"unknown"),toolName:n.tool_name??"",toolDisplayName:n.tool_display_name,message:n.message,formSchema:n.form_schema,data:n.data,functionName:n.function_name,arguments:n.arguments}))}async getMessages(t){return(await this.getConversation(t)).messages||[]}async resumePendingClientFunctions(t){const n=[...t.messages??[]].reverse().find(r=>r.role==="assistant"&&r.status==="WAITING_CLIENT");if(!n)return null;const i=(n.toolCalls??[]).filter(r=>r.type==="client_function"&&r.status==="waiting_input"&&r.functionName),s=new Set(this.functionRegistry.getSchemas().map(r=>r.name)),o=i.filter(r=>!s.has(r.functionName));if(o.length>0)return l.warn("Cannot resume paused turn: function(s) not registered on this page:",o.map(r=>r.functionName)),null;let a=i.length===0;for(const r of i){let c,u;try{c=await this.functionRegistry.execute(r.functionName,r.arguments??{})}catch(h){u=h instanceof Error?h.message:"Unknown error",l.error("Client function execution failed:",h)}a=(await this.submitToolCallForm(r.id,{result:c,error:u,_type:"client_function_result"}))?.resume?.ready??a}return a?this.continueMessage(n.id):null}async submitToolCallForm(t,n){return this.httpClient.post(`/api/sdk/v1/tool-calls/${t}/submit`,{formData:n})}async confirmToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/confirm/`)}async rejectToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/reject/`)}async getFormCollector(t){const n=await this.httpClient.get(`/api/sdk/v1/forms/${encodeURIComponent(t)}`);return{name:n.name,description:n.description,schema:n.schema,submit:n.submit??void 0}}async submitFormCollector(t,n){return this.httpClient.post("/api/sdk/v1/forms/submit",{name:t,values:n})}async submitFeedback(t,n){await this.httpClient.post(`/api/sdk/v1/messages/${t}/feedback`,{rating:n})}registerFunction(t,n,i){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,n,i)}register(t){if(Array.isArray(t))for(const n of t)this.functionRegistry.register(n);else this.functionRegistry.register(t)}unregisterFunction(t){return this.functionRegistry.unregister(t)}getRegisteredFunctions(){return this.functionRegistry.getSchemas()}registerNavigationFunction(t,n){const i=n.map(r=>r.name),s=n.map(r=>{const c=w(r.path),u=c.length>0?` (requires ${c.map(h=>`"${h}"`).join(", ")})`:"";return`- "${r.name}"${u}: ${r.description}`}).join(`
|
|
5
|
+
`),o=new Map;for(const r of n)for(const c of w(r.path))o.set(c,[...o.get(c)??[],r.name]);const a={page:{type:"string",description:"The page to navigate to",enum:i}};for(const[r,c]of o){if(r==="page"){l.error('registerNavigationFunction: a ":page" placeholder collides with the "page" argument and is ignored. Rename the placeholder.');continue}a[r]={type:"string",description:`Value for ":${r}" in the page path. Required when page is ${c.map(u=>`"${u}"`).join(" or ")}.`}}this.registerFunction("navigateToPage",async r=>{const c=r.page,u=n.find(m=>m.name===c);if(!u)return{success:!1,error:`Unknown page: ${c}`};let h={};if(typeof r.params=="string")try{h=JSON.parse(r.params)}catch{}else r.params&&typeof r.params=="object"&&(h=r.params);const _={};for(const m of w(u.path))_[m]=r[m]??h[m];const{path:R,missing:p}=X(u.path,_);if(p.length>0){const m=p.map(y=>`"${y}": "..."`).join(", ");return{success:!1,error:`Page "${c}" needs ${p.map(y=>`"${y}"`).join(", ")}. Retry with { "page": "${c}", ${m} }.`}}return t(R),{success:!0,navigatedTo:R}},{description:`Navigate the user to a page in the application. Available pages:
|
|
6
|
+
${s}`,parameters:{type:"object",properties:a,required:["page"]}}),this.addDynamicContext("current-page",()=>{if(typeof window>"u"||!window.location)return null;const r=window.location.href,c=typeof document<"u"?document.title:void 0,u=Y(window.location.pathname,n),h={url:r};return u&&(h.page=u.name),c&&(h.title=c),{name:"Current page",description:"The page the user is currently viewing.",data:h}})}unregisterNavigationFunction(){this.unregisterFunction("navigateToPage"),this.removeDynamicContext("current-page")}registerPageStateFunction(t,n){const i=n?.functionName??"setPageState",s=new Map(t.map(a=>[a.name,a])),o=t.map(a=>`- "${a.name}": ${a.description}`).join(`
|
|
7
|
+
`);this.registerFunction(i,async a=>{const r={};for(const[c,u]of Object.entries(a)){if(u===void 0)continue;const h=s.get(c);h&&(await h.set(u),r[c]=u)}return{success:!0,applied:r}},{description:`Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
|
|
8
|
+
${o}`,parameters:{type:"object",properties:Object.fromEntries(t.map(a=>[a.name,{...a.schema,description:a.description}]))}}),this.addDynamicContext(`page-state:${i}`,()=>{const a=t.filter(c=>typeof c.get=="function");if(a.length===0)return null;const r={};for(const c of a)r[c.name]=c.get();return{name:"Page state",description:"Current, editable state of the page the user is viewing.",data:r}})}unregisterPageStateFunction(t){const n=t??"setPageState";this.unregisterFunction(n),this.removeDynamicContext(`page-state:${n}`)}setContext(t,n){this.contextRegistry.set(t,n),this.notifyContextChanged()}removeContext(t){const n=this.contextRegistry.remove(t);return n&&this.notifyContextChanged(),n}addDynamicContext(t,n){this.contextRegistry.addDynamicProvider(t,n),this.notifyContextChanged()}removeDynamicContext(t){const n=this.contextRegistry.removeDynamicProvider(t);return n&&this.notifyContextChanged(),n}notifyContextChanged(){this.eventEmitter.emit("context:changed",this.contextRegistry.getSnapshot())}emitFormEvent(t,n){this.eventEmitter.emit(t,n)}enableAutoPageContext(){this.addDynamicContext("browser-page",()=>{const t=typeof window<"u"?window.location.href:void 0,n=typeof document<"u"?document.title:void 0;return!t&&!n?null:{name:"Browser page",description:"Current page the user is viewing",data:{url:t,title:n}}})}getContextSnapshot(){return this.contextRegistry.getSnapshot()}on(t,n){this.eventEmitter.on(t,n)}off(t,n){this.eventEmitter.off(t,n)}once(t,n){this.eventEmitter.once(t,n)}waitFor(t,n){return this.eventEmitter.waitFor(t,n)}updateConfig(t){const n={};for(const[s,o]of Object.entries(t))o!==void 0&&(n[s]=o);const i={...this.config,...n};E(i,"AgoClient.updateConfig"),this.config=i,this.httpClient.updateConfig(n),n.debug!==void 0&&(n.debug?l.enable():l.disable()),n.maxFunctionResultBytes!==void 0&&this.functionRegistry.setDefaultMaxResultBytes(n.maxFunctionResultBytes)}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),this.pendingResumes.clear(),this.resumeGate=null,l.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return f}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return V}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return d}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return b}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return v}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return F}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return N}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return k}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return I}});Object.defineProperty(exports,"attachmentsFromFiles",{enumerable:!0,get:function(){return q}});Object.defineProperty(exports,"canInlineImage",{enumerable:!0,get:function(){return W}});Object.defineProperty(exports,"formatFileSize",{enumerable:!0,get:function(){return z}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return L}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return l}});Object.defineProperty(exports,"safeAttachmentUrl",{enumerable:!0,get:function(){return U}});Object.defineProperty(exports,"validateConfig",{enumerable:!0,get:function(){return E}});
|
package/dist/angular.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-wcPRaIMs.cjs"),c=require("./autoContinue-CcCTva-D.cjs");var n=class{constructor(t){this.client=new o.AgoClient(t),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(t){const e=this.client;return{subscribe(i){const r=s=>{i.next?.(s)};return e.on(t,r),{unsubscribe:()=>e.off(t,r)}}}}sendMessage(t,e){return this.client.sendMessage(t,e)}getConversations(){return this.client.getConversations()}getConversation(t){return this.client.getConversation(t)}getMessages(t){return this.client.getMessages(t)}submitToolCallForm(t,e){return this.client.submitToolCallForm(t,e)}confirmToolCall(t){return this.client.confirmToolCall(t)}rejectToolCall(t){return this.client.rejectToolCall(t)}submitFeedback(t,e){return this.client.submitFeedback(t,e)}registerFunction(t,e,i){typeof t=="object"?this.client.registerFunction(t):this.client.registerFunction(t,e,i)}unregisterFunction(t){return this.client.unregisterFunction(t)}registerNavigationFunction(t,e){this.client.registerNavigationFunction(t,e)}unregisterNavigationFunction(){this.client.unregisterNavigationFunction()}enableAutoContinueAfterNavigation(t){return c.attachAutoContinueAfterNavigation(this.client,t)}registerPageStateFunction(t,e){this.client.registerPageStateFunction(t,e)}unregisterPageStateFunction(t){this.client.unregisterPageStateFunction(t)}on(t,e){this.client.on(t,e)}off(t,e){this.client.off(t,e)}updateConfig(t){this.client.updateConfig(t)}getClient(){return this.client}destroy(){this.client.destroy()}};function u(t){return{provide:n,useValue:new n(t)}}exports.AgoService=n;exports.provideAgo=u;
|