@useago/sdk 1.3.2 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/{AgoClient-Cwx_eYSu.js → AgoClient-BdtuHX7k.js} +150 -85
- package/dist/AgoClient-CRAnT4qE.cjs +8 -0
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +99 -1
- package/dist/angular.d.ts +99 -1
- package/dist/angular.js +16 -7
- package/dist/{createConversationSession-DV0Xp_3O.cjs → createConversationSession-B8zfTL78.cjs} +1 -1
- package/dist/{createConversationSession-B3h567tt.js → createConversationSession-CWpf4u6I.js} +1 -1
- package/dist/{createFormCollector-CyWisAkI.js → createFormCollector-B4n0_diV.js} +1 -1
- package/dist/{createFormCollector-BB3Uscuo.cjs → createFormCollector-BB_l0Sia.cjs} +1 -1
- package/dist/{createMockClient-DwdxNwEn.js → createMockClient-d-arlmCq.js} +19 -17
- package/dist/createMockClient-ucPENDzz.cjs +1 -0
- package/dist/devtools.d.cts +93 -1
- package/dist/devtools.d.ts +93 -1
- package/dist/helpers.d.cts +5 -1
- package/dist/helpers.d.ts +5 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +93 -1
- package/dist/index.d.ts +93 -1
- package/dist/index.js +4 -4
- package/dist/react.cjs +3 -3
- package/dist/react.d.cts +158 -2
- package/dist/react.d.ts +158 -2
- package/dist/react.js +469 -391
- package/dist/testing.cjs +1 -1
- package/dist/testing.d.cts +93 -1
- package/dist/testing.d.ts +93 -1
- package/dist/testing.js +1 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +125 -1
- package/dist/vue.d.ts +125 -1
- package/dist/vue.js +73 -64
- package/dist/widget.cjs +1 -1
- package/dist/widget.d.cts +93 -1
- package/dist/widget.d.ts +93 -1
- package/dist/widget.js +3 -3
- package/package.json +1 -1
- package/dist/AgoClient-CzSmJQxl.cjs +0 -6
- package/dist/createMockClient-zHQ0cjUH.cjs +0 -1
package/README.md
CHANGED
|
@@ -92,6 +92,46 @@ guards, auth and layouts keep working exactly as they do today.
|
|
|
92
92
|
`react-router-dom` here is *your* router, not an SDK dependency:
|
|
93
93
|
`useAgoNavigation` accepts any `(path: string) => void` function.
|
|
94
94
|
|
|
95
|
+
## Let the agent change the page
|
|
96
|
+
|
|
97
|
+
The mirror of navigation. Same idea, applied to the page the user is already on:
|
|
98
|
+
describe its editable state (filters, sort, view mode…) and *"show me only the
|
|
99
|
+
overdue ones, newest first"* actually updates the view. The agent also reads the
|
|
100
|
+
current state, so it knows what to change.
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { useAgoPageState } from "@useago/sdk/react";
|
|
104
|
+
|
|
105
|
+
function InvoiceList() {
|
|
106
|
+
const [status, setStatus] = useState("all");
|
|
107
|
+
const [sort, setSort] = useState("newest");
|
|
108
|
+
|
|
109
|
+
useAgoPageState([
|
|
110
|
+
{
|
|
111
|
+
name: "statusFilter",
|
|
112
|
+
description: "Filter invoices by status",
|
|
113
|
+
schema: { type: "string", enum: ["all", "paid", "overdue"] },
|
|
114
|
+
get: () => status, // current value → the agent sees it
|
|
115
|
+
set: setStatus, // the agent changes it
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "sort",
|
|
119
|
+
description: "Sort order of the list",
|
|
120
|
+
schema: { type: "string", enum: ["newest", "oldest"] },
|
|
121
|
+
get: () => sort,
|
|
122
|
+
set: setSort,
|
|
123
|
+
},
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
return /* your existing list, driven by status + sort */;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Each control becomes one optional property of a single `setPageState` function,
|
|
131
|
+
so the agent changes only what the user asked for. The current value from each
|
|
132
|
+
`get()` is sent with every message, so the agent knows the state before it
|
|
133
|
+
changes it. Vue and Angular have the same helper.
|
|
134
|
+
|
|
95
135
|
## Turn a JavaScript function into an agent tool
|
|
96
136
|
|
|
97
137
|
Keep your application logic as a regular JavaScript function, then describe its
|
|
@@ -215,6 +255,7 @@ react-router navigation), Vue, Angular, plain TypeScript, and no-build HTML.
|
|
|
215
255
|
- [**Events & streaming**](docs/general/events-and-streaming.md): low-level hooks into the message stream
|
|
216
256
|
- [**Testing**](docs/general/testing.md): mock client for unit tests
|
|
217
257
|
- [**Configuration & auth**](docs/general/configuration.md): every `AgoConfig` option, headers, errors
|
|
258
|
+
- [**Custom domain (reverse proxy)**](docs/general/custom-domain.md): serve AGO from your own domain, same-origin
|
|
218
259
|
|
|
219
260
|
Full documentation: [ago.mintlify.app](https://ago.mintlify.app/)
|
|
220
261
|
|
|
@@ -2,27 +2,27 @@ var h = 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
|
-
},
|
|
6
|
-
constructor(t, s, i, n, r,
|
|
7
|
-
super(t, s, i), this.type = n, this.param = r, this.docUrl =
|
|
5
|
+
}, u = class E extends h {
|
|
6
|
+
constructor(t, s, i, n, r, o) {
|
|
7
|
+
super(t, s, i), this.type = n, this.param = r, this.docUrl = o, this.name = "AgoApiError";
|
|
8
8
|
}
|
|
9
9
|
static fromResponse(t, s) {
|
|
10
10
|
const i = t.error;
|
|
11
|
-
return new
|
|
11
|
+
return new E(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
|
+
}, m = class extends h {
|
|
14
14
|
constructor(e, t) {
|
|
15
15
|
super(e, "network_error"), this.originalError = t, this.name = "AgoNetworkError";
|
|
16
16
|
}
|
|
17
|
-
},
|
|
17
|
+
}, p = class extends h {
|
|
18
18
|
constructor(e, t = "stream_error") {
|
|
19
19
|
super(e, t), this.name = "AgoStreamError";
|
|
20
20
|
}
|
|
21
|
-
},
|
|
21
|
+
}, y = class extends h {
|
|
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
|
+
}, S = class {
|
|
26
26
|
constructor(e = !1) {
|
|
27
27
|
this.enabled = e;
|
|
28
28
|
}
|
|
@@ -44,22 +44,22 @@ var h = class extends Error {
|
|
|
44
44
|
debug(...e) {
|
|
45
45
|
this.enabled && console.debug("[AGO SDK]", ...e);
|
|
46
46
|
}
|
|
47
|
-
},
|
|
48
|
-
function
|
|
47
|
+
}, a = new S(), w = "ago_widget_id";
|
|
48
|
+
function $() {
|
|
49
49
|
if (typeof localStorage < "u") {
|
|
50
|
-
const t = localStorage.getItem(
|
|
50
|
+
const t = localStorage.getItem(w);
|
|
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(w, e);
|
|
56
56
|
} catch {
|
|
57
57
|
}
|
|
58
58
|
return e;
|
|
59
59
|
}
|
|
60
60
|
var k = class {
|
|
61
61
|
constructor(e) {
|
|
62
|
-
this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.headers = { "X-User-Anon-Id": e.widgetId ||
|
|
62
|
+
this.baseUrl = e.baseUrl.replace(/\/$/, ""), 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 && (this.headers["X-Widget-Permission"] = e.permission);
|
|
63
63
|
}
|
|
64
64
|
updateConfig(e) {
|
|
65
65
|
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"]);
|
|
@@ -72,7 +72,7 @@ var k = class {
|
|
|
72
72
|
}
|
|
73
73
|
async postStream(e, t) {
|
|
74
74
|
const s = `${this.baseUrl}${e}`;
|
|
75
|
-
|
|
75
|
+
a.debug("POST (stream)", s, t);
|
|
76
76
|
try {
|
|
77
77
|
const i = await fetch(s, {
|
|
78
78
|
method: "POST",
|
|
@@ -84,12 +84,12 @@ var k = class {
|
|
|
84
84
|
});
|
|
85
85
|
return i.ok || await this.handleErrorResponse(i), i;
|
|
86
86
|
} catch (i) {
|
|
87
|
-
throw i instanceof
|
|
87
|
+
throw i instanceof u ? i : new m(`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
88
|
}
|
|
89
89
|
}
|
|
90
90
|
async postFormData(e, t) {
|
|
91
91
|
const s = `${this.baseUrl}${e}`;
|
|
92
|
-
|
|
92
|
+
a.debug("POST (formData)", s);
|
|
93
93
|
const i = { ...this.headers };
|
|
94
94
|
try {
|
|
95
95
|
const n = await fetch(s, {
|
|
@@ -99,12 +99,12 @@ var k = class {
|
|
|
99
99
|
});
|
|
100
100
|
return n.ok || await this.handleErrorResponse(n), n;
|
|
101
101
|
} catch (n) {
|
|
102
|
-
throw n instanceof
|
|
102
|
+
throw n instanceof u ? n : new m(`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
103
|
}
|
|
104
104
|
}
|
|
105
105
|
async request(e, t, s) {
|
|
106
106
|
const i = `${this.baseUrl}${t}`;
|
|
107
|
-
|
|
107
|
+
a.debug(e, i, s);
|
|
108
108
|
try {
|
|
109
109
|
const n = await fetch(i, {
|
|
110
110
|
method: e,
|
|
@@ -116,7 +116,7 @@ var k = class {
|
|
|
116
116
|
});
|
|
117
117
|
return n.ok || await this.handleErrorResponse(n), n.status === 204 ? void 0 : n.json();
|
|
118
118
|
} catch (n) {
|
|
119
|
-
throw n instanceof
|
|
119
|
+
throw n instanceof u ? n : new m(`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
120
|
}
|
|
121
121
|
}
|
|
122
122
|
async handleErrorResponse(e) {
|
|
@@ -125,35 +125,35 @@ var k = class {
|
|
|
125
125
|
t = await e.json();
|
|
126
126
|
} catch {
|
|
127
127
|
}
|
|
128
|
-
if (t?.error) throw
|
|
128
|
+
if (t?.error) throw u.fromResponse(t, e.status);
|
|
129
129
|
let s = "";
|
|
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
|
|
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 u(`HTTP ${e.status}: ${e.statusText}.${s}`, "http_error", e.status, "api_error");
|
|
131
131
|
}
|
|
132
|
-
},
|
|
132
|
+
}, x = class {
|
|
133
133
|
constructor() {
|
|
134
134
|
this.functions = /* @__PURE__ */ new Map();
|
|
135
135
|
}
|
|
136
136
|
register(e, t, s) {
|
|
137
137
|
if (typeof e == "object") {
|
|
138
|
-
const { name: n, handler: r, description:
|
|
138
|
+
const { name: n, handler: r, description: o, parameters: l } = e;
|
|
139
139
|
return this.register(n, r, {
|
|
140
|
-
description:
|
|
140
|
+
description: o,
|
|
141
141
|
parameters: l
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
144
|
const i = e;
|
|
145
145
|
if (!t || !s) throw new h(`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) &&
|
|
146
|
+
this.functions.has(i) && a.warn(`Function "${i}" is being overwritten`), this.functions.set(i, {
|
|
147
147
|
schema: {
|
|
148
148
|
...s,
|
|
149
149
|
name: i
|
|
150
150
|
},
|
|
151
151
|
handler: t
|
|
152
|
-
}),
|
|
152
|
+
}), a.log(`Registered function: ${i}`);
|
|
153
153
|
}
|
|
154
154
|
unregister(e) {
|
|
155
155
|
const t = this.functions.delete(e);
|
|
156
|
-
return t &&
|
|
156
|
+
return t && a.log(`Unregistered function: ${e}`), t;
|
|
157
157
|
}
|
|
158
158
|
get(e) {
|
|
159
159
|
return this.functions.get(e);
|
|
@@ -166,17 +166,17 @@ var k = class {
|
|
|
166
166
|
}
|
|
167
167
|
async execute(e, t) {
|
|
168
168
|
const s = this.functions.get(e);
|
|
169
|
-
if (!s) throw new
|
|
170
|
-
|
|
169
|
+
if (!s) throw new y(`Function "${e}" is not registered`, e);
|
|
170
|
+
a.log(`Executing function: ${e}`, t);
|
|
171
171
|
try {
|
|
172
172
|
const i = await s.handler(t);
|
|
173
|
-
return
|
|
173
|
+
return a.log(`Function ${e} completed:`, i), i;
|
|
174
174
|
} catch (i) {
|
|
175
|
-
throw
|
|
175
|
+
throw a.error(`Function ${e} failed:`, i), new y(`Function "${e}" execution failed: ${i instanceof Error ? i.message : "Unknown error"}`, e, i instanceof Error ? i : void 0);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
clear() {
|
|
179
|
-
this.functions.clear(),
|
|
179
|
+
this.functions.clear(), a.log("Cleared all registered functions");
|
|
180
180
|
}
|
|
181
181
|
get size() {
|
|
182
182
|
return this.functions.size;
|
|
@@ -186,18 +186,18 @@ var k = class {
|
|
|
186
186
|
this.entries = /* @__PURE__ */ new Map(), this.dynamicProviders = /* @__PURE__ */ new Map();
|
|
187
187
|
}
|
|
188
188
|
set(e, t) {
|
|
189
|
-
this.entries.set(e, t),
|
|
189
|
+
this.entries.set(e, t), a.log(`ClientContext set: ${e}`);
|
|
190
190
|
}
|
|
191
191
|
remove(e) {
|
|
192
192
|
const t = this.entries.delete(e);
|
|
193
|
-
return t &&
|
|
193
|
+
return t && a.log(`ClientContext removed: ${e}`), t;
|
|
194
194
|
}
|
|
195
195
|
addDynamicProvider(e, t) {
|
|
196
|
-
this.dynamicProviders.set(e, t),
|
|
196
|
+
this.dynamicProviders.set(e, t), a.log(`DynamicContext provider added: ${e}`);
|
|
197
197
|
}
|
|
198
198
|
removeDynamicProvider(e) {
|
|
199
199
|
const t = this.dynamicProviders.delete(e);
|
|
200
|
-
return t &&
|
|
200
|
+
return t && a.log(`DynamicContext provider removed: ${e}`), t;
|
|
201
201
|
}
|
|
202
202
|
getSnapshot() {
|
|
203
203
|
if (this.entries.size === 0 && this.dynamicProviders.size === 0) return null;
|
|
@@ -207,23 +207,23 @@ var k = class {
|
|
|
207
207
|
const i = s();
|
|
208
208
|
i && (e[t] = i);
|
|
209
209
|
} catch (i) {
|
|
210
|
-
|
|
210
|
+
a.error(`DynamicContext provider "${t}" threw:`, i);
|
|
211
211
|
}
|
|
212
212
|
return Object.keys(e).length === 0 ? null : { entries: e };
|
|
213
213
|
}
|
|
214
214
|
clear() {
|
|
215
|
-
this.entries.clear(), this.dynamicProviders.clear(),
|
|
215
|
+
this.entries.clear(), this.dynamicProviders.clear(), a.log("ClientContext cleared");
|
|
216
216
|
}
|
|
217
217
|
};
|
|
218
|
-
function
|
|
219
|
-
return e === null || typeof e != "object" ? JSON.stringify(e) ?? "null" : Array.isArray(e) ? `[${e.map(
|
|
218
|
+
function f(e) {
|
|
219
|
+
return e === null || typeof e != "object" ? JSON.stringify(e) ?? "null" : Array.isArray(e) ? `[${e.map(f).join(",")}]` : `{${Object.keys(e).sort().map((t) => `${JSON.stringify(t)}:${f(e[t])}`).join(",")}}`;
|
|
220
220
|
}
|
|
221
221
|
var R = class {
|
|
222
222
|
constructor(e) {
|
|
223
223
|
this.callbacks = e, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0, this.answerCompleteEmitted = !1, this.firedClientFunctions = /* @__PURE__ */ new Set();
|
|
224
224
|
}
|
|
225
225
|
async processStream(e) {
|
|
226
|
-
if (!e.body) throw new
|
|
226
|
+
if (!e.body) throw new p("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");
|
|
227
227
|
const t = e.body.getReader(), s = new TextDecoder();
|
|
228
228
|
try {
|
|
229
229
|
for (; ; ) {
|
|
@@ -234,7 +234,7 @@ var R = class {
|
|
|
234
234
|
}
|
|
235
235
|
return this.buffer.trim() && this.processBuffer(), this.buildFinalMessage();
|
|
236
236
|
} catch (i) {
|
|
237
|
-
const n = i instanceof Error ? i : new
|
|
237
|
+
const n = i instanceof Error ? i : new p("Stream processing failed mid-flight. The connection may have dropped; retry the message.");
|
|
238
238
|
throw this.callbacks.onError?.(n), n;
|
|
239
239
|
} finally {
|
|
240
240
|
t.releaseLock();
|
|
@@ -256,7 +256,7 @@ var R = class {
|
|
|
256
256
|
const r = JSON.parse(n);
|
|
257
257
|
this.handleChunk(r);
|
|
258
258
|
} catch (r) {
|
|
259
|
-
|
|
259
|
+
a.warn("Failed to parse SSE data:", n, r);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
}
|
|
@@ -281,7 +281,7 @@ var R = class {
|
|
|
281
281
|
url: s.use_external_link ? s.external_link_url : s.internal_link_url
|
|
282
282
|
};
|
|
283
283
|
})), e.type === "client_function" && e.function_name) {
|
|
284
|
-
const t = `${e.function_name}::${
|
|
284
|
+
const t = `${e.function_name}::${f(e.arguments ?? {})}`;
|
|
285
285
|
this.firedClientFunctions.has(t) || (this.firedClientFunctions.add(t), this.callbacks.onClientFunction?.({
|
|
286
286
|
invocationId: e.id || "",
|
|
287
287
|
functionName: e.function_name,
|
|
@@ -330,11 +330,11 @@ var R = class {
|
|
|
330
330
|
return this.callbacks.onComplete?.(e), e;
|
|
331
331
|
}
|
|
332
332
|
};
|
|
333
|
-
function
|
|
333
|
+
function O(e) {
|
|
334
334
|
const t = e.message.toLowerCase();
|
|
335
335
|
return t.includes("load failed") || t.includes("failed to fetch") || t.includes("network") || t.includes("abort");
|
|
336
336
|
}
|
|
337
|
-
var
|
|
337
|
+
var F = /* @__PURE__ */ new Set([
|
|
338
338
|
"image/jpeg",
|
|
339
339
|
"image/png",
|
|
340
340
|
"image/gif",
|
|
@@ -351,10 +351,10 @@ function I(e) {
|
|
|
351
351
|
} catch {
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
|
-
function
|
|
354
|
+
function j(e) {
|
|
355
355
|
return e.isSafeImage === !0 && typeof e.contentType == "string" && e.contentType.startsWith("image/") && I(e.url) !== void 0;
|
|
356
356
|
}
|
|
357
|
-
function
|
|
357
|
+
function M(e) {
|
|
358
358
|
if (e == null || e < 0) return "";
|
|
359
359
|
if (e < 1024) return `${e} B`;
|
|
360
360
|
const t = e / 1024;
|
|
@@ -370,17 +370,17 @@ function U(e) {
|
|
|
370
370
|
isSafeImage: e.is_safe_image === !0
|
|
371
371
|
};
|
|
372
372
|
}
|
|
373
|
-
function
|
|
373
|
+
function L(e) {
|
|
374
374
|
return e.map((t, s) => ({
|
|
375
375
|
id: `local-${s}-${t.name}`,
|
|
376
376
|
name: t.name,
|
|
377
377
|
contentType: t.type || void 0,
|
|
378
378
|
fileSize: t.size,
|
|
379
379
|
url: typeof URL < "u" && URL.createObjectURL ? URL.createObjectURL(t) : void 0,
|
|
380
|
-
isSafeImage:
|
|
380
|
+
isSafeImage: F.has(t.type)
|
|
381
381
|
}));
|
|
382
382
|
}
|
|
383
|
-
var
|
|
383
|
+
var T = class {
|
|
384
384
|
constructor() {
|
|
385
385
|
this.handlers = /* @__PURE__ */ new Map();
|
|
386
386
|
}
|
|
@@ -410,8 +410,8 @@ var F = class {
|
|
|
410
410
|
waitFor(e, t) {
|
|
411
411
|
return new Promise((s, i) => {
|
|
412
412
|
let n;
|
|
413
|
-
const r = ((
|
|
414
|
-
n && clearTimeout(n), s(
|
|
413
|
+
const r = ((o) => {
|
|
414
|
+
n && clearTimeout(n), s(o);
|
|
415
415
|
});
|
|
416
416
|
this.once(e, r), t?.timeout && (n = setTimeout(() => {
|
|
417
417
|
this.off(e, r), i(/* @__PURE__ */ new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`));
|
|
@@ -421,31 +421,44 @@ var F = class {
|
|
|
421
421
|
removeAllListeners(e) {
|
|
422
422
|
e ? this.handlers.delete(e) : this.handlers.clear();
|
|
423
423
|
}
|
|
424
|
-
},
|
|
425
|
-
function
|
|
426
|
-
if (typeof e != "object" || e === null) throw new h(`${t}: ${
|
|
424
|
+
}, v = '`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).', D = /^[a-z][a-z0-9+.-]*:\/\//i, C = !1;
|
|
425
|
+
function b(e, t = "AgoClient") {
|
|
426
|
+
if (typeof e != "object" || e === null) throw new h(`${t}: ${v}`, "config_missing_base_url");
|
|
427
427
|
const s = e.baseUrl;
|
|
428
|
-
if (typeof s != "string" || s.trim() === "") throw new h(`${t}: ${
|
|
429
|
-
!s.startsWith("/") && !
|
|
428
|
+
if (typeof s != "string" || s.trim() === "") throw new h(`${t}: ${v}`, "config_missing_base_url");
|
|
429
|
+
!s.startsWith("/") && !D.test(s) && (C || (C = !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).`)));
|
|
430
|
+
}
|
|
431
|
+
function N(e) {
|
|
432
|
+
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
433
|
+
}
|
|
434
|
+
function P(e, t) {
|
|
435
|
+
const s = t.find((n) => n.path === e);
|
|
436
|
+
if (s) return s;
|
|
437
|
+
const i = t.find((n) => {
|
|
438
|
+
if (!n.path.includes(":")) return !1;
|
|
439
|
+
const r = "^" + n.path.split("/").map((o) => o.startsWith(":") ? "[^/]+" : N(o)).join("/") + "/?$";
|
|
440
|
+
return new RegExp(r).test(e);
|
|
441
|
+
});
|
|
442
|
+
return i || t.filter((n) => n.path !== "/" && e.startsWith(n.path)).sort((n, r) => r.path.length - n.path.length)[0];
|
|
430
443
|
}
|
|
431
|
-
var
|
|
444
|
+
var z = class _ {
|
|
432
445
|
constructor(t) {
|
|
433
|
-
this.warnedEmptyConversations = /* @__PURE__ */ new Set(),
|
|
446
|
+
this.warnedEmptyConversations = /* @__PURE__ */ new Set(), b(t, "AgoClient"), this.config = t, this.httpClient = new k(t), this.functionRegistry = new x(), this.contextRegistry = new A(), this.eventEmitter = new T(), t.debug && a.enable(), a.log("AgoClient initialized");
|
|
434
447
|
}
|
|
435
448
|
async sendMessage(t, s) {
|
|
436
|
-
const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), r = this.config.agent || this.config.defaultAgentId,
|
|
449
|
+
const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), r = this.config.agent || this.config.defaultAgentId, o = {
|
|
437
450
|
content: t,
|
|
438
451
|
conversation_id: s?.conversationId,
|
|
439
452
|
agent_id: s?.agentId || r
|
|
440
453
|
};
|
|
441
|
-
i.length > 0 && (
|
|
454
|
+
i.length > 0 && (o.client_functions = i), n && (o.client_context = n), s?.hidden && (o.hidden = !0);
|
|
442
455
|
let l;
|
|
443
456
|
if (s?.files && s.files.length > 0) {
|
|
444
457
|
const c = new FormData();
|
|
445
|
-
c.append("content", t), s.conversationId && c.append("conversation_id", s.conversationId), (s.agentId || r) && c.append("agent_id", s.agentId || r || ""), i.length > 0 && c.append("client_functions", JSON.stringify(i)), n && c.append("client_context", JSON.stringify(n));
|
|
446
|
-
for (const
|
|
458
|
+
c.append("content", t), s.conversationId && c.append("conversation_id", s.conversationId), (s.agentId || r) && c.append("agent_id", s.agentId || r || ""), i.length > 0 && c.append("client_functions", JSON.stringify(i)), n && c.append("client_context", JSON.stringify(n)), s.hidden && c.append("hidden", "true");
|
|
459
|
+
for (const d of s.files) c.append("files", d);
|
|
447
460
|
l = await this.httpClient.postFormData("/api/sdk/v1/messages", c);
|
|
448
|
-
} else l = await this.httpClient.postStream("/api/sdk/v1/messages",
|
|
461
|
+
} else l = await this.httpClient.postStream("/api/sdk/v1/messages", o);
|
|
449
462
|
return this.processSSEResponse(l);
|
|
450
463
|
}
|
|
451
464
|
async processSSEResponse(t) {
|
|
@@ -499,7 +512,7 @@ var j = class b {
|
|
|
499
512
|
try {
|
|
500
513
|
s = await this.functionRegistry.execute(t.functionName, t.arguments);
|
|
501
514
|
} catch (n) {
|
|
502
|
-
i = n instanceof Error ? n.message : "Unknown error",
|
|
515
|
+
i = n instanceof Error ? n.message : "Unknown error", a.error("Client function execution failed:", n);
|
|
503
516
|
}
|
|
504
517
|
if (t.invocationId) try {
|
|
505
518
|
await this.submitToolCallForm(t.invocationId, {
|
|
@@ -508,7 +521,7 @@ var j = class b {
|
|
|
508
521
|
_type: "client_function_result"
|
|
509
522
|
});
|
|
510
523
|
} catch (n) {
|
|
511
|
-
|
|
524
|
+
a.error("Failed to submit function result:", n);
|
|
512
525
|
}
|
|
513
526
|
this.eventEmitter.emit("function:result", {
|
|
514
527
|
invocationId: t.invocationId,
|
|
@@ -535,7 +548,8 @@ var j = class b {
|
|
|
535
548
|
role: n.role,
|
|
536
549
|
status: n.status,
|
|
537
550
|
createdAt: new Date(n.created_at),
|
|
538
|
-
|
|
551
|
+
hidden: n.hidden,
|
|
552
|
+
toolCalls: _.mapPersistedToolCalls(n.tool_call_data),
|
|
539
553
|
attachments: n.attachments && n.attachments.length > 0 ? n.attachments.map(U) : void 0
|
|
540
554
|
}))
|
|
541
555
|
};
|
|
@@ -603,13 +617,13 @@ var j = class b {
|
|
|
603
617
|
const i = s.map((r) => r.name), n = s.map((r) => `- "${r.name}": ${r.description}`).join(`
|
|
604
618
|
`);
|
|
605
619
|
this.registerFunction("navigateToPage", async (r) => {
|
|
606
|
-
const
|
|
620
|
+
const o = r.page, l = s.find((c) => c.name === o);
|
|
607
621
|
return l ? (t(l.path), {
|
|
608
622
|
success: !0,
|
|
609
623
|
navigatedTo: l.path
|
|
610
624
|
}) : {
|
|
611
625
|
success: !1,
|
|
612
|
-
error: `Unknown page: ${
|
|
626
|
+
error: `Unknown page: ${o}`
|
|
613
627
|
};
|
|
614
628
|
}, {
|
|
615
629
|
description: `Navigate the user to a page in the application. Available pages:
|
|
@@ -623,8 +637,59 @@ ${n}`,
|
|
|
623
637
|
} },
|
|
624
638
|
required: ["page"]
|
|
625
639
|
}
|
|
640
|
+
}), this.addDynamicContext("current-page", () => {
|
|
641
|
+
if (typeof window > "u" || !window.location) return null;
|
|
642
|
+
const r = window.location.href, o = typeof document < "u" ? document.title : void 0, l = P(window.location.pathname, s), c = { url: r };
|
|
643
|
+
return l && (c.page = l.name), o && (c.title = o), {
|
|
644
|
+
name: "Current page",
|
|
645
|
+
description: "The page the user is currently viewing.",
|
|
646
|
+
data: c
|
|
647
|
+
};
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
unregisterNavigationFunction() {
|
|
651
|
+
this.unregisterFunction("navigateToPage"), this.removeDynamicContext("current-page");
|
|
652
|
+
}
|
|
653
|
+
registerPageStateFunction(t, s) {
|
|
654
|
+
const i = s?.functionName ?? "setPageState", n = new Map(t.map((o) => [o.name, o])), r = t.map((o) => `- "${o.name}": ${o.description}`).join(`
|
|
655
|
+
`);
|
|
656
|
+
this.registerFunction(i, async (o) => {
|
|
657
|
+
const l = {};
|
|
658
|
+
for (const [c, d] of Object.entries(o)) {
|
|
659
|
+
if (d === void 0) continue;
|
|
660
|
+
const g = n.get(c);
|
|
661
|
+
g && (await g.set(d), l[c] = d);
|
|
662
|
+
}
|
|
663
|
+
return {
|
|
664
|
+
success: !0,
|
|
665
|
+
applied: l
|
|
666
|
+
};
|
|
667
|
+
}, {
|
|
668
|
+
description: `Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
|
|
669
|
+
${r}`,
|
|
670
|
+
parameters: {
|
|
671
|
+
type: "object",
|
|
672
|
+
properties: Object.fromEntries(t.map((o) => [o.name, {
|
|
673
|
+
...o.schema,
|
|
674
|
+
description: o.description
|
|
675
|
+
}]))
|
|
676
|
+
}
|
|
677
|
+
}), this.addDynamicContext(`page-state:${i}`, () => {
|
|
678
|
+
const o = t.filter((c) => typeof c.get == "function");
|
|
679
|
+
if (o.length === 0) return null;
|
|
680
|
+
const l = {};
|
|
681
|
+
for (const c of o) l[c.name] = c.get();
|
|
682
|
+
return {
|
|
683
|
+
name: "Page state",
|
|
684
|
+
description: "Current, editable state of the page the user is viewing.",
|
|
685
|
+
data: l
|
|
686
|
+
};
|
|
626
687
|
});
|
|
627
688
|
}
|
|
689
|
+
unregisterPageStateFunction(t) {
|
|
690
|
+
const s = t ?? "setPageState";
|
|
691
|
+
this.unregisterFunction(s), this.removeDynamicContext(`page-state:${s}`);
|
|
692
|
+
}
|
|
628
693
|
setContext(t, s) {
|
|
629
694
|
this.contextRegistry.set(t, s), this.notifyContextChanged();
|
|
630
695
|
}
|
|
@@ -680,28 +745,28 @@ ${n}`,
|
|
|
680
745
|
...this.config,
|
|
681
746
|
...s
|
|
682
747
|
};
|
|
683
|
-
|
|
748
|
+
b(i, "AgoClient.updateConfig"), this.config = i, this.httpClient.updateConfig(s), s.debug !== void 0 && (s.debug ? a.enable() : a.disable());
|
|
684
749
|
}
|
|
685
750
|
destroy() {
|
|
686
|
-
this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(),
|
|
751
|
+
this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(), a.log("AgoClient destroyed");
|
|
687
752
|
}
|
|
688
753
|
};
|
|
689
754
|
export {
|
|
690
|
-
|
|
691
|
-
|
|
755
|
+
p as _,
|
|
756
|
+
j as a,
|
|
692
757
|
R as c,
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
758
|
+
x as d,
|
|
759
|
+
a as f,
|
|
760
|
+
m as g,
|
|
761
|
+
y as h,
|
|
762
|
+
L as i,
|
|
763
|
+
O as l,
|
|
699
764
|
h as m,
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
765
|
+
b as n,
|
|
766
|
+
M as o,
|
|
767
|
+
u as p,
|
|
768
|
+
T as r,
|
|
704
769
|
I as s,
|
|
705
|
-
|
|
770
|
+
z as t,
|
|
706
771
|
A as u
|
|
707
772
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var u=class extends Error{constructor(e,t,n){super(e),this.code=t,this.statusCode=n,this.name="AgoError"}},h=class E extends u{constructor(t,n,r,s,i,o){super(t,n,r),this.type=s,this.param=i,this.docUrl=o,this.name="AgoApiError"}static fromResponse(t,n){const r=t.error;return new E(r.doc_url?`${r.message} See ${r.doc_url}`:r.message,r.code,n,r.type,r.param,r.doc_url)}},f=class extends u{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},m=class extends u{constructor(e,t="stream_error"){super(e,t),this.name="AgoStreamError"}},g=class extends u{constructor(e,t,n){super(e,"function_error"),this.functionName=t,this.originalError=n,this.name="AgoFunctionError"}},R=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)}},a=new R,v="ago_widget_id";function F(){if(typeof localStorage<"u"){const t=localStorage.getItem(v);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(v,e)}catch{}return e}var I=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-User-Anon-Id":e.widgetId||F()},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}`;a.debug("POST (stream)",n,t);try{const r=await fetch(n,{method:"POST",headers:{...this.headers,"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});return r.ok||await this.handleErrorResponse(r),r}catch(r){throw r instanceof h?r:new f(`Network error: ${r instanceof Error?r.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,r instanceof Error?r:void 0)}}async postFormData(e,t){const n=`${this.baseUrl}${e}`;a.debug("POST (formData)",n);const r={...this.headers};try{const s=await fetch(n,{method:"POST",headers:r,body:t});return s.ok||await this.handleErrorResponse(s),s}catch(s){throw s instanceof h?s:new f(`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 r=`${this.baseUrl}${t}`;a.debug(e,r,n);try{const s=await fetch(r,{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 h?s:new f(`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 h.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 h(`HTTP ${e.status}: ${e.statusText}.${n}`,"http_error",e.status,"api_error")}},_=class{constructor(){this.functions=new Map}register(e,t,n){if(typeof e=="object"){const{name:s,handler:i,description:o,parameters:l}=e;return this.register(s,i,{description:o,parameters:l})}const r=e;if(!t||!n)throw new u(`registerFunction("${r}"): 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(r)&&a.warn(`Function "${r}" is being overwritten`),this.functions.set(r,{schema:{...n,name:r},handler:t}),a.log(`Registered function: ${r}`)}unregister(e){const t=this.functions.delete(e);return t&&a.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 g(`Function "${e}" is not registered`,e);a.log(`Executing function: ${e}`,t);try{const r=await n.handler(t);return a.log(`Function ${e} completed:`,r),r}catch(r){throw a.error(`Function ${e} failed:`,r),new g(`Function "${e}" execution failed: ${r instanceof Error?r.message:"Unknown error"}`,e,r instanceof Error?r:void 0)}}clear(){this.functions.clear(),a.log("Cleared all registered functions")}get size(){return this.functions.size}},S=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),a.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&a.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),a.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&a.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 r=n();r&&(e[t]=r)}catch(r){a.error(`DynamicContext provider "${t}" threw:`,r)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),a.log("ClientContext cleared")}};function p(e){return e===null||typeof e!="object"?JSON.stringify(e)??"null":Array.isArray(e)?`[${e.map(p).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${p(e[t])}`).join(",")}}`}var $=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0,this.answerCompleteEmitted=!1,this.firedClientFunctions=new Set}async processStream(e){if(!e.body)throw new m("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:r,value:s}=await t.read();if(r)break;const i=n.decode(s,{stream:!0});this.buffer+=i,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(r){const s=r instanceof Error?r:new m("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 r of n)if(!r.startsWith(": ")&&r.startsWith("data: ")){const s=r.slice(6);try{const i=JSON.parse(s);this.handleChunk(i)}catch(i){a.warn("Failed to parse SSE data:",s,i)}}}}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}::${p(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(r=>r.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()))}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 this.callbacks.onComplete?.(e),e}};function U(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var P=new Set(["image/jpeg","image/png","image/gif","image/webp","image/bmp","image/tiff"]);function k(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 O(e){return e.isSafeImage===!0&&typeof e.contentType=="string"&&e.contentType.startsWith("image/")&&k(e.url)!==void 0}function j(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 N(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 T(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:P.has(t.type)}))}var A=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(r=>{try{r(t)}catch(s){console.error(`Error in event handler for ${String(e)}:`,s)}})}once(e,t){const n=(r=>{this.off(e,n),t(r)});this.on(e,n)}waitFor(e,t){return new Promise((n,r)=>{let s;const i=(o=>{s&&clearTimeout(s),n(o)});this.once(e,i),t?.timeout&&(s=setTimeout(()=>{this.off(e,i),r(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},b='`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).',D=/^[a-z][a-z0-9+.-]*:\/\//i,C=!1;function y(e,t="AgoClient"){if(typeof e!="object"||e===null)throw new u(`${t}: ${b}`,"config_missing_base_url");const n=e.baseUrl;if(typeof n!="string"||n.trim()==="")throw new u(`${t}: ${b}`,"config_missing_base_url");!n.startsWith("/")&&!D.test(n)&&(C||(C=!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 M(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function z(e,t){const n=t.find(s=>s.path===e);if(n)return n;const r=t.find(s=>{if(!s.path.includes(":"))return!1;const i="^"+s.path.split("/").map(o=>o.startsWith(":")?"[^/]+":M(o)).join("/")+"/?$";return new RegExp(i).test(e)});return r||t.filter(s=>s.path!=="/"&&e.startsWith(s.path)).sort((s,i)=>i.path.length-s.path.length)[0]}var L=class x{constructor(t){this.warnedEmptyConversations=new Set,y(t,"AgoClient"),this.config=t,this.httpClient=new I(t),this.functionRegistry=new _,this.contextRegistry=new S,this.eventEmitter=new A,t.debug&&a.enable(),a.log("AgoClient initialized")}async sendMessage(t,n){const r=this.functionRegistry.getSchemas(),s=this.contextRegistry.getSnapshot(),i=this.config.agent||this.config.defaultAgentId,o={content:t,conversation_id:n?.conversationId,agent_id:n?.agentId||i};r.length>0&&(o.client_functions=r),s&&(o.client_context=s),n?.hidden&&(o.hidden=!0);let l;if(n?.files&&n.files.length>0){const c=new FormData;c.append("content",t),n.conversationId&&c.append("conversation_id",n.conversationId),(n.agentId||i)&&c.append("agent_id",n.agentId||i||""),r.length>0&&c.append("client_functions",JSON.stringify(r)),s&&c.append("client_context",JSON.stringify(s)),n.hidden&&c.append("hidden","true");for(const d of n.files)c.append("files",d);l=await this.httpClient.postFormData("/api/sdk/v1/messages",c)}else l=await this.httpClient.postStream("/api/sdk/v1/messages",o);return this.processSSEResponse(l)}async processSSEResponse(t){let n=!1;const r=await new $({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)},onComplete:s=>{this.eventEmitter.emit("message:complete",s)},onError:s=>{this.eventEmitter.emit("message:error",{error:s.message,code:s instanceof u?s.code:void 0})}}).processStream(t);return this.maybeFlagEmptyReply(r,n),r}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 r=t.conversationId||"(no conversation)";if(this.warnedEmptyConversations.has(r))return;this.warnedEmptyConversations.add(r);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,r;try{n=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(s){r=s instanceof Error?s.message:"Unknown error",a.error("Client function execution failed:",s)}if(t.invocationId)try{await this.submitToolCallForm(t.invocationId,{result:n,error:r,_type:"client_function_result"})}catch(s){a.error("Failed to submit function result:",s)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:n,error:r})}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}`),r={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:x.mapPersistedToolCalls(s.tool_call_data),attachments:s.attachments&&s.attachments.length>0?s.attachments.map(N):void 0}))};return this.eventEmitter.emit("conversation:loaded",r),r}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 submitToolCallForm(t,n){await 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,r){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,n,r)}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 r=n.map(i=>i.name),s=n.map(i=>`- "${i.name}": ${i.description}`).join(`
|
|
5
|
+
`);this.registerFunction("navigateToPage",async i=>{const o=i.page,l=n.find(c=>c.name===o);return l?(t(l.path),{success:!0,navigatedTo:l.path}):{success:!1,error:`Unknown page: ${o}`}},{description:`Navigate the user to a page in the application. Available pages:
|
|
6
|
+
${s}`,parameters:{type:"object",properties:{page:{type:"string",description:"The page to navigate to",enum:r}},required:["page"]}}),this.addDynamicContext("current-page",()=>{if(typeof window>"u"||!window.location)return null;const i=window.location.href,o=typeof document<"u"?document.title:void 0,l=z(window.location.pathname,n),c={url:i};return l&&(c.page=l.name),o&&(c.title=o),{name:"Current page",description:"The page the user is currently viewing.",data:c}})}unregisterNavigationFunction(){this.unregisterFunction("navigateToPage"),this.removeDynamicContext("current-page")}registerPageStateFunction(t,n){const r=n?.functionName??"setPageState",s=new Map(t.map(o=>[o.name,o])),i=t.map(o=>`- "${o.name}": ${o.description}`).join(`
|
|
7
|
+
`);this.registerFunction(r,async o=>{const l={};for(const[c,d]of Object.entries(o)){if(d===void 0)continue;const w=s.get(c);w&&(await w.set(d),l[c]=d)}return{success:!0,applied:l}},{description:`Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
|
|
8
|
+
${i}`,parameters:{type:"object",properties:Object.fromEntries(t.map(o=>[o.name,{...o.schema,description:o.description}]))}}),this.addDynamicContext(`page-state:${r}`,()=>{const o=t.filter(c=>typeof c.get=="function");if(o.length===0)return null;const l={};for(const c of o)l[c.name]=c.get();return{name:"Page state",description:"Current, editable state of the page the user is viewing.",data:l}})}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,i]of Object.entries(t))i!==void 0&&(n[s]=i);const r={...this.config,...n};y(r,"AgoClient.updateConfig"),this.config=r,this.httpClient.updateConfig(n),n.debug!==void 0&&(n.debug?a.enable():a.disable())}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),a.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return L}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return u}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return f}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return m}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return S}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return $}});Object.defineProperty(exports,"attachmentsFromFiles",{enumerable:!0,get:function(){return T}});Object.defineProperty(exports,"canInlineImage",{enumerable:!0,get:function(){return O}});Object.defineProperty(exports,"formatFileSize",{enumerable:!0,get:function(){return j}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return U}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return a}});Object.defineProperty(exports,"safeAttachmentUrl",{enumerable:!0,get:function(){return k}});Object.defineProperty(exports,"validateConfig",{enumerable:!0,get:function(){return y}});
|
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-CRAnT4qE.cjs");var n=class{constructor(e){this.client=new o.AgoClient(e),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(e){const t=this.client;return{subscribe(i){const s=r=>{i.next?.(r)};return t.on(e,s),{unsubscribe:()=>t.off(e,s)}}}}sendMessage(e,t){return this.client.sendMessage(e,t)}getConversations(){return this.client.getConversations()}getConversation(e){return this.client.getConversation(e)}getMessages(e){return this.client.getMessages(e)}submitToolCallForm(e,t){return this.client.submitToolCallForm(e,t)}confirmToolCall(e){return this.client.confirmToolCall(e)}rejectToolCall(e){return this.client.rejectToolCall(e)}submitFeedback(e,t){return this.client.submitFeedback(e,t)}registerFunction(e,t,i){typeof e=="object"?this.client.registerFunction(e):this.client.registerFunction(e,t,i)}unregisterFunction(e){return this.client.unregisterFunction(e)}registerNavigationFunction(e,t){this.client.registerNavigationFunction(e,t)}unregisterNavigationFunction(){this.client.unregisterNavigationFunction()}registerPageStateFunction(e,t){this.client.registerPageStateFunction(e,t)}unregisterPageStateFunction(e){this.client.unregisterPageStateFunction(e)}on(e,t){this.client.on(e,t)}off(e,t){this.client.off(e,t)}updateConfig(e){this.client.updateConfig(e)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(e){return{provide:n,useValue:new n(e)}}exports.AgoService=n;exports.provideAgo=c;
|