@useago/sdk 0.1.7 → 0.2.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.
Files changed (63) hide show
  1. package/README.md +101 -6
  2. package/dist/AgoClient-CNT-8sh_.js +905 -0
  3. package/dist/AgoClient-CNT-8sh_.js.map +1 -0
  4. package/dist/AgoClient-D0l1GTRs.cjs +976 -0
  5. package/dist/AgoClient-D0l1GTRs.cjs.map +1 -0
  6. package/dist/angular.cjs +138 -100
  7. package/dist/angular.cjs.map +1 -1
  8. package/dist/angular.d.ts +1 -0
  9. package/dist/angular.js +139 -103
  10. package/dist/angular.js.map +1 -1
  11. package/dist/client/types.d.ts +5 -1
  12. package/dist/createMockClient-Ci_N2tH8.cjs +104 -0
  13. package/dist/createMockClient-Ci_N2tH8.cjs.map +1 -0
  14. package/dist/createMockClient-U0ae_AYy.js +99 -0
  15. package/dist/createMockClient-U0ae_AYy.js.map +1 -0
  16. package/dist/functions--c6lx3ic.cjs +480 -0
  17. package/dist/functions--c6lx3ic.cjs.map +1 -0
  18. package/dist/functions-C9F1dnmh.js +398 -0
  19. package/dist/functions-C9F1dnmh.js.map +1 -0
  20. package/dist/helpers.cjs +14 -16
  21. package/dist/helpers.d.ts +1 -0
  22. package/dist/helpers.js +2 -17
  23. package/dist/index.cjs +281 -153
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +256 -166
  26. package/dist/index.js.map +1 -1
  27. package/dist/react/components/ChatWidget.d.ts +2 -0
  28. package/dist/react/components/Markdown.d.ts +12 -0
  29. package/dist/react/components/Message.d.ts +2 -0
  30. package/dist/react/components/index.d.ts +2 -0
  31. package/dist/react/index.d.ts +2 -0
  32. package/dist/react.cjs +22099 -10333
  33. package/dist/react.cjs.map +1 -1
  34. package/dist/react.d.ts +1 -0
  35. package/dist/react.js +22099 -10349
  36. package/dist/react.js.map +1 -1
  37. package/dist/rolldown-runtime-BqCkTl7Q.cjs +50 -0
  38. package/dist/rolldown-runtime-CNZpIYwj.js +33 -0
  39. package/dist/vue.cjs +287 -208
  40. package/dist/vue.cjs.map +1 -1
  41. package/dist/vue.d.ts +1 -0
  42. package/dist/vue.js +287 -218
  43. package/dist/vue.js.map +1 -1
  44. package/dist/widget.cjs +0 -2
  45. package/dist/widget.d.ts +1 -0
  46. package/dist/widget.js +0 -2
  47. package/package.json +8 -6
  48. package/dist/AgoClient-BDO4avLq.cjs +0 -1036
  49. package/dist/AgoClient-BDO4avLq.cjs.map +0 -1
  50. package/dist/AgoClient-D-c91tx5.js +0 -1037
  51. package/dist/AgoClient-D-c91tx5.js.map +0 -1
  52. package/dist/createMockClient-B1DcBiIK.js +0 -94
  53. package/dist/createMockClient-B1DcBiIK.js.map +0 -1
  54. package/dist/createMockClient-BqNSJUu4.cjs +0 -93
  55. package/dist/createMockClient-BqNSJUu4.cjs.map +0 -1
  56. package/dist/functions-B0Z0rNQW.cjs +0 -306
  57. package/dist/functions-B0Z0rNQW.cjs.map +0 -1
  58. package/dist/functions-C-wLEc8b.js +0 -306
  59. package/dist/functions-C-wLEc8b.js.map +0 -1
  60. package/dist/helpers.cjs.map +0 -1
  61. package/dist/helpers.js.map +0 -1
  62. package/dist/widget.cjs.map +0 -1
  63. package/dist/widget.js.map +0 -1
@@ -1,1036 +0,0 @@
1
- "use strict";
2
- class AgoError extends Error {
3
- constructor(message, code, statusCode) {
4
- super(message);
5
- this.code = code;
6
- this.statusCode = statusCode;
7
- this.name = "AgoError";
8
- }
9
- }
10
- class AgoApiError extends AgoError {
11
- constructor(message, code, statusCode, type, param, docUrl) {
12
- super(message, code, statusCode);
13
- this.type = type;
14
- this.param = param;
15
- this.docUrl = docUrl;
16
- this.name = "AgoApiError";
17
- }
18
- static fromResponse(data, statusCode) {
19
- const error = data.error;
20
- return new AgoApiError(
21
- error.message,
22
- error.code,
23
- statusCode,
24
- error.type,
25
- error.param,
26
- error.doc_url
27
- );
28
- }
29
- }
30
- class AgoNetworkError extends AgoError {
31
- constructor(message, originalError) {
32
- super(message, "network_error");
33
- this.originalError = originalError;
34
- this.name = "AgoNetworkError";
35
- }
36
- }
37
- class AgoStreamError extends AgoError {
38
- constructor(message) {
39
- super(message, "stream_error");
40
- this.name = "AgoStreamError";
41
- }
42
- }
43
- class AgoFunctionError extends AgoError {
44
- constructor(message, functionName, originalError) {
45
- super(message, "function_error");
46
- this.functionName = functionName;
47
- this.originalError = originalError;
48
- this.name = "AgoFunctionError";
49
- }
50
- }
51
- class Logger {
52
- constructor(enabled = false) {
53
- this.enabled = enabled;
54
- }
55
- enable() {
56
- this.enabled = true;
57
- }
58
- disable() {
59
- this.enabled = false;
60
- }
61
- log(...args) {
62
- if (this.enabled) {
63
- console.log("[AGO SDK]", ...args);
64
- }
65
- }
66
- warn(...args) {
67
- if (this.enabled) {
68
- console.warn("[AGO SDK]", ...args);
69
- }
70
- }
71
- error(...args) {
72
- console.error("[AGO SDK]", ...args);
73
- }
74
- debug(...args) {
75
- if (this.enabled) {
76
- console.debug("[AGO SDK]", ...args);
77
- }
78
- }
79
- }
80
- const logger = new Logger();
81
- const WIDGET_ID_KEY = "ago_widget_id";
82
- function generateWidgetId() {
83
- if (typeof localStorage !== "undefined") {
84
- const stored = localStorage.getItem(WIDGET_ID_KEY);
85
- if (stored) return stored;
86
- }
87
- const id = crypto.randomUUID();
88
- if (typeof localStorage !== "undefined") {
89
- try {
90
- localStorage.setItem(WIDGET_ID_KEY, id);
91
- } catch {
92
- }
93
- }
94
- return id;
95
- }
96
- class HttpClient {
97
- constructor(config) {
98
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
99
- this.headers = {
100
- "X-Widget-Id": config.widgetId || generateWidgetId()
101
- };
102
- if (config.userEmail) {
103
- this.headers["X-User-Email"] = config.userEmail;
104
- }
105
- if (config.userJwt) {
106
- this.headers["Authorization"] = `Bearer ${config.userJwt}`;
107
- }
108
- }
109
- /**
110
- * Update configuration (e.g., JWT token)
111
- */
112
- updateConfig(config) {
113
- if (config.baseUrl) {
114
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
115
- }
116
- if (config.widgetId) {
117
- this.headers["X-Widget-Id"] = config.widgetId;
118
- }
119
- if (config.userEmail) {
120
- this.headers["X-User-Email"] = config.userEmail;
121
- }
122
- if (config.userJwt) {
123
- this.headers["Authorization"] = `Bearer ${config.userJwt}`;
124
- }
125
- }
126
- /**
127
- * Make a GET request
128
- */
129
- async get(path) {
130
- return this.request("GET", path);
131
- }
132
- /**
133
- * Make a POST request with JSON body
134
- */
135
- async post(path, body) {
136
- return this.request("POST", path, body);
137
- }
138
- /**
139
- * Make a POST request and return the raw Response (for streaming)
140
- */
141
- async postStream(path, body) {
142
- const url = `${this.baseUrl}${path}`;
143
- logger.debug("POST (stream)", url, body);
144
- try {
145
- const response = await fetch(url, {
146
- method: "POST",
147
- headers: {
148
- ...this.headers,
149
- "Content-Type": "application/json"
150
- },
151
- body: body ? JSON.stringify(body) : void 0
152
- });
153
- if (!response.ok) {
154
- await this.handleErrorResponse(response);
155
- }
156
- return response;
157
- } catch (error) {
158
- if (error instanceof AgoApiError) {
159
- throw error;
160
- }
161
- throw new AgoNetworkError(
162
- `Network error: ${error instanceof Error ? error.message : "Unknown error"}`,
163
- error instanceof Error ? error : void 0
164
- );
165
- }
166
- }
167
- /**
168
- * Make a POST request with FormData (for file uploads)
169
- */
170
- async postFormData(path, formData) {
171
- const url = `${this.baseUrl}${path}`;
172
- logger.debug("POST (formData)", url);
173
- const headers = { ...this.headers };
174
- try {
175
- const response = await fetch(url, {
176
- method: "POST",
177
- headers,
178
- body: formData
179
- });
180
- if (!response.ok) {
181
- await this.handleErrorResponse(response);
182
- }
183
- return response;
184
- } catch (error) {
185
- if (error instanceof AgoApiError) {
186
- throw error;
187
- }
188
- throw new AgoNetworkError(
189
- `Network error: ${error instanceof Error ? error.message : "Unknown error"}`,
190
- error instanceof Error ? error : void 0
191
- );
192
- }
193
- }
194
- async request(method, path, body) {
195
- const url = `${this.baseUrl}${path}`;
196
- logger.debug(method, url, body);
197
- try {
198
- const response = await fetch(url, {
199
- method,
200
- headers: {
201
- ...this.headers,
202
- "Content-Type": "application/json"
203
- },
204
- body: body ? JSON.stringify(body) : void 0
205
- });
206
- if (!response.ok) {
207
- await this.handleErrorResponse(response);
208
- }
209
- if (response.status === 204) {
210
- return void 0;
211
- }
212
- return response.json();
213
- } catch (error) {
214
- if (error instanceof AgoApiError) {
215
- throw error;
216
- }
217
- throw new AgoNetworkError(
218
- `Network error: ${error instanceof Error ? error.message : "Unknown error"}`,
219
- error instanceof Error ? error : void 0
220
- );
221
- }
222
- }
223
- async handleErrorResponse(response) {
224
- let errorData;
225
- try {
226
- errorData = await response.json();
227
- } catch {
228
- }
229
- if (errorData == null ? void 0 : errorData.error) {
230
- throw AgoApiError.fromResponse(errorData, response.status);
231
- }
232
- throw new AgoApiError(
233
- `HTTP ${response.status}: ${response.statusText}`,
234
- "http_error",
235
- response.status,
236
- "api_error"
237
- );
238
- }
239
- }
240
- class FunctionRegistry {
241
- constructor() {
242
- this.functions = /* @__PURE__ */ new Map();
243
- }
244
- register(nameOrDef, handler, schema) {
245
- if (typeof nameOrDef === "object") {
246
- const { name: name2, handler: h, description, parameters } = nameOrDef;
247
- return this.register(name2, h, { description, parameters });
248
- }
249
- const name = nameOrDef;
250
- if (!handler || !schema) {
251
- throw new Error("handler and schema are required");
252
- }
253
- if (this.functions.has(name)) {
254
- logger.warn(`Function "${name}" is being overwritten`);
255
- }
256
- this.functions.set(name, {
257
- schema: { ...schema, name },
258
- handler
259
- });
260
- logger.log(`Registered function: ${name}`);
261
- }
262
- /**
263
- * Unregister a function
264
- */
265
- unregister(name) {
266
- const deleted = this.functions.delete(name);
267
- if (deleted) {
268
- logger.log(`Unregistered function: ${name}`);
269
- }
270
- return deleted;
271
- }
272
- /**
273
- * Get a registered function
274
- */
275
- get(name) {
276
- return this.functions.get(name);
277
- }
278
- /**
279
- * Check if a function is registered
280
- */
281
- has(name) {
282
- return this.functions.has(name);
283
- }
284
- /**
285
- * Get all registered function schemas (for sending to backend)
286
- */
287
- getSchemas() {
288
- return Array.from(this.functions.values()).map((f) => f.schema);
289
- }
290
- /**
291
- * Execute a registered function
292
- */
293
- async execute(name, args) {
294
- const registration = this.functions.get(name);
295
- if (!registration) {
296
- throw new AgoFunctionError(
297
- `Function "${name}" is not registered`,
298
- name
299
- );
300
- }
301
- logger.log(`Executing function: ${name}`, args);
302
- try {
303
- const result = await registration.handler(args);
304
- logger.log(`Function ${name} completed:`, result);
305
- return result;
306
- } catch (error) {
307
- logger.error(`Function ${name} failed:`, error);
308
- throw new AgoFunctionError(
309
- `Function "${name}" execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
310
- name,
311
- error instanceof Error ? error : void 0
312
- );
313
- }
314
- }
315
- /**
316
- * Clear all registered functions
317
- */
318
- clear() {
319
- this.functions.clear();
320
- logger.log("Cleared all registered functions");
321
- }
322
- /**
323
- * Get the number of registered functions
324
- */
325
- get size() {
326
- return this.functions.size;
327
- }
328
- }
329
- class ClientContextRegistry {
330
- constructor() {
331
- this.entries = /* @__PURE__ */ new Map();
332
- this.dynamicProviders = /* @__PURE__ */ new Map();
333
- }
334
- /**
335
- * Register or update a static context entry.
336
- */
337
- set(key, entry) {
338
- this.entries.set(key, entry);
339
- logger.log(`ClientContext set: ${key}`);
340
- }
341
- /**
342
- * Remove a static context entry (typically on component unmount).
343
- */
344
- remove(key) {
345
- const deleted = this.entries.delete(key);
346
- if (deleted) {
347
- logger.log(`ClientContext removed: ${key}`);
348
- }
349
- return deleted;
350
- }
351
- /**
352
- * Register a dynamic context provider. The function is called every time
353
- * a message is sent, so it always returns the freshest data.
354
- *
355
- * Use this for context that lives outside React state — global stores,
356
- * refs, or computed values that shouldn't trigger re-renders.
357
- */
358
- addDynamicProvider(key, provider) {
359
- this.dynamicProviders.set(key, provider);
360
- logger.log(`DynamicContext provider added: ${key}`);
361
- }
362
- /**
363
- * Remove a dynamic context provider.
364
- */
365
- removeDynamicProvider(key) {
366
- const deleted = this.dynamicProviders.delete(key);
367
- if (deleted) {
368
- logger.log(`DynamicContext provider removed: ${key}`);
369
- }
370
- return deleted;
371
- }
372
- /**
373
- * Build a snapshot of the current client context.
374
- * Evaluates every registered dynamic provider. Returns `null` when there is
375
- * nothing to report.
376
- */
377
- getSnapshot() {
378
- if (this.entries.size === 0 && this.dynamicProviders.size === 0) {
379
- return null;
380
- }
381
- const entries = {};
382
- for (const [key, entry] of this.entries) {
383
- entries[key] = entry;
384
- }
385
- for (const [key, provider] of this.dynamicProviders) {
386
- try {
387
- const entry = provider();
388
- if (entry) {
389
- entries[key] = entry;
390
- }
391
- } catch (err) {
392
- logger.error(`DynamicContext provider "${key}" threw:`, err);
393
- }
394
- }
395
- if (Object.keys(entries).length === 0) {
396
- return null;
397
- }
398
- return { entries };
399
- }
400
- /**
401
- * Remove all entries and dynamic providers.
402
- */
403
- clear() {
404
- this.entries.clear();
405
- this.dynamicProviders.clear();
406
- logger.log("ClientContext cleared");
407
- }
408
- }
409
- class SSEHandler {
410
- constructor(callbacks) {
411
- this.callbacks = callbacks;
412
- this.buffer = "";
413
- this.message = {};
414
- this.toolCalls = [];
415
- this.sources = [];
416
- this.followUpReplies = [];
417
- this.isFirstChunk = true;
418
- }
419
- /**
420
- * Process a streaming response
421
- */
422
- async processStream(response) {
423
- var _a, _b;
424
- if (!response.body) {
425
- throw new AgoStreamError("Response has no body");
426
- }
427
- const reader = response.body.getReader();
428
- const decoder = new TextDecoder();
429
- try {
430
- while (true) {
431
- const { done, value } = await reader.read();
432
- if (done) {
433
- break;
434
- }
435
- const text = decoder.decode(value, { stream: true });
436
- this.buffer += text;
437
- this.processBuffer();
438
- }
439
- if (this.buffer.trim()) {
440
- this.processBuffer();
441
- }
442
- return this.buildFinalMessage();
443
- } catch (error) {
444
- const streamError = error instanceof Error ? error : new AgoStreamError("Stream processing failed");
445
- (_b = (_a = this.callbacks).onError) == null ? void 0 : _b.call(_a, streamError);
446
- throw streamError;
447
- } finally {
448
- reader.releaseLock();
449
- }
450
- }
451
- processBuffer() {
452
- const parts = this.buffer.split("\n\n");
453
- this.buffer = parts.pop() || "";
454
- for (const part of parts) {
455
- if (!part.trim()) continue;
456
- const lines = part.split("\n");
457
- for (const line of lines) {
458
- if (line.startsWith(": ")) {
459
- continue;
460
- }
461
- if (line.startsWith("data: ")) {
462
- const jsonStr = line.slice(6);
463
- try {
464
- const data = JSON.parse(jsonStr);
465
- this.handleChunk(data);
466
- } catch (error) {
467
- logger.warn("Failed to parse SSE data:", jsonStr, error);
468
- }
469
- }
470
- }
471
- }
472
- }
473
- handleChunk(data) {
474
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
475
- if (data.message_id && !this.message.id) {
476
- this.message.id = data.message_id;
477
- }
478
- if ((_a = data.thread) == null ? void 0 : _a.id) {
479
- this.message.conversationId = data.thread.id;
480
- if (this.isFirstChunk && this.message.id) {
481
- this.isFirstChunk = false;
482
- (_c = (_b = this.callbacks).onStart) == null ? void 0 : _c.call(_b, {
483
- conversationId: this.message.conversationId,
484
- messageId: this.message.id
485
- });
486
- }
487
- }
488
- if (data.content !== void 0) {
489
- this.message.content = (this.message.content || "") + data.content;
490
- if (this.message.conversationId && this.message.id) {
491
- (_e = (_d = this.callbacks).onChunk) == null ? void 0 : _e.call(_d, {
492
- content: data.content,
493
- conversationId: this.message.conversationId,
494
- messageId: this.message.id
495
- });
496
- }
497
- }
498
- if (data.full_content !== void 0) {
499
- this.message.content = data.full_content;
500
- }
501
- if (data.status) {
502
- this.message.status = data.status;
503
- }
504
- if (data.agent) {
505
- this.message.agent = {
506
- id: data.agent.id,
507
- name: data.agent.name,
508
- displayName: data.agent.display_name
509
- };
510
- }
511
- if (data.knowledge_sources) {
512
- this.sources = data.knowledge_sources.map((s) => {
513
- const doc = s.knowledge_document;
514
- return {
515
- id: doc.id,
516
- title: doc.title,
517
- url: doc.use_external_link ? doc.external_link_url : doc.internal_link_url
518
- };
519
- });
520
- }
521
- if (data.type === "client_function" && data.function_name) {
522
- (_g = (_f = this.callbacks).onClientFunction) == null ? void 0 : _g.call(_f, {
523
- invocationId: data.id || "",
524
- functionName: data.function_name,
525
- arguments: data.arguments || {},
526
- conversationId: this.message.conversationId || ""
527
- });
528
- }
529
- if (data.tool_call_data && data.type && data.type !== "client_function") {
530
- const toolCall = this.parseToolCall(data);
531
- (_i = (_h = this.callbacks).onToolCall) == null ? void 0 : _i.call(_h, toolCall);
532
- const existingIndex = this.toolCalls.findIndex((t) => t.id === toolCall.id);
533
- if (existingIndex >= 0) {
534
- this.toolCalls[existingIndex] = toolCall;
535
- } else {
536
- this.toolCalls.push(toolCall);
537
- }
538
- }
539
- if (data.follow_up_replies) {
540
- this.followUpReplies = data.follow_up_replies;
541
- }
542
- }
543
- parseToolCall(data) {
544
- return {
545
- id: data.id || "",
546
- type: data.type || "status_message",
547
- status: data.status || "unknown",
548
- toolName: data.tool_name || "",
549
- toolDisplayName: data.tool_display_name,
550
- message: data.message,
551
- formSchema: data.form_schema,
552
- data: data.data,
553
- functionName: data.function_name,
554
- arguments: data.arguments
555
- };
556
- }
557
- buildFinalMessage() {
558
- var _a, _b;
559
- const message = {
560
- id: this.message.id || "",
561
- conversationId: this.message.conversationId || "",
562
- content: this.message.content || "",
563
- role: "assistant",
564
- status: this.message.status || "DONE",
565
- agent: this.message.agent,
566
- sources: this.sources.length > 0 ? this.sources : void 0,
567
- toolCalls: this.toolCalls.length > 0 ? this.toolCalls : void 0,
568
- followUpReplies: this.followUpReplies.length > 0 ? this.followUpReplies : void 0,
569
- createdAt: /* @__PURE__ */ new Date()
570
- };
571
- (_b = (_a = this.callbacks).onComplete) == null ? void 0 : _b.call(_a, message);
572
- return message;
573
- }
574
- }
575
- function isStreamNetworkError(error) {
576
- const message = error.message.toLowerCase();
577
- return message.includes("load failed") || message.includes("failed to fetch") || message.includes("network") || message.includes("abort");
578
- }
579
- class EventEmitter {
580
- constructor() {
581
- this.handlers = /* @__PURE__ */ new Map();
582
- }
583
- on(event, handler) {
584
- if (!this.handlers.has(event)) {
585
- this.handlers.set(event, /* @__PURE__ */ new Set());
586
- }
587
- this.handlers.get(event).add(handler);
588
- }
589
- off(event, handler) {
590
- const eventHandlers = this.handlers.get(event);
591
- if (eventHandlers) {
592
- eventHandlers.delete(handler);
593
- }
594
- }
595
- emit(event, data) {
596
- const eventHandlers = this.handlers.get(event);
597
- if (eventHandlers) {
598
- eventHandlers.forEach((handler) => {
599
- try {
600
- handler(data);
601
- } catch (error) {
602
- console.error(`Error in event handler for ${String(event)}:`, error);
603
- }
604
- });
605
- }
606
- }
607
- /**
608
- * Subscribe to an event and auto-unsubscribe after the first call.
609
- */
610
- once(event, handler) {
611
- const wrapper = (data) => {
612
- this.off(event, wrapper);
613
- handler(data);
614
- };
615
- this.on(event, wrapper);
616
- }
617
- /**
618
- * Returns a Promise that resolves the next time `event` fires.
619
- * Rejects if `timeout` (ms) is reached first.
620
- */
621
- waitFor(event, options) {
622
- return new Promise((resolve, reject) => {
623
- let timer;
624
- const handler = (data) => {
625
- if (timer) clearTimeout(timer);
626
- resolve(data);
627
- };
628
- this.once(event, handler);
629
- if (options == null ? void 0 : options.timeout) {
630
- timer = setTimeout(() => {
631
- this.off(event, handler);
632
- reject(new Error(`waitFor("${String(event)}") timed out after ${options.timeout}ms`));
633
- }, options.timeout);
634
- }
635
- });
636
- }
637
- removeAllListeners(event) {
638
- if (event) {
639
- this.handlers.delete(event);
640
- } else {
641
- this.handlers.clear();
642
- }
643
- }
644
- }
645
- class AgoClient {
646
- constructor(config) {
647
- this.config = config;
648
- this.httpClient = new HttpClient(config);
649
- this.functionRegistry = new FunctionRegistry();
650
- this.contextRegistry = new ClientContextRegistry();
651
- this.eventEmitter = new EventEmitter();
652
- if (config.debug) {
653
- logger.enable();
654
- }
655
- logger.log("AgoClient initialized");
656
- }
657
- // ─────────────────────────────────────────────────────────────────
658
- // Messaging
659
- // ─────────────────────────────────────────────────────────────────
660
- /**
661
- * Send a message and receive a streaming response
662
- */
663
- async sendMessage(content, options) {
664
- const clientFunctions = this.functionRegistry.getSchemas();
665
- const clientContext = this.contextRegistry.getSnapshot();
666
- const body = {
667
- content,
668
- conversation_id: options == null ? void 0 : options.conversationId,
669
- agent_id: (options == null ? void 0 : options.agentId) || this.config.defaultAgentId
670
- };
671
- if (clientFunctions.length > 0) {
672
- body.client_functions = clientFunctions;
673
- }
674
- if (clientContext) {
675
- body.client_context = clientContext;
676
- }
677
- let response;
678
- if ((options == null ? void 0 : options.files) && options.files.length > 0) {
679
- const formData = new FormData();
680
- formData.append("content", content);
681
- if (options.conversationId) {
682
- formData.append("conversation_id", options.conversationId);
683
- }
684
- if (options.agentId || this.config.defaultAgentId) {
685
- formData.append("agent_id", options.agentId || this.config.defaultAgentId || "");
686
- }
687
- if (clientFunctions.length > 0) {
688
- formData.append("client_functions", JSON.stringify(clientFunctions));
689
- }
690
- if (clientContext) {
691
- formData.append("client_context", JSON.stringify(clientContext));
692
- }
693
- for (const file of options.files) {
694
- formData.append("files", file);
695
- }
696
- response = await this.httpClient.postFormData("/api/sdk/v1/messages", formData);
697
- } else {
698
- response = await this.httpClient.postStream("/api/sdk/v1/messages", body);
699
- }
700
- return this.processSSEResponse(response);
701
- }
702
- async processSSEResponse(response) {
703
- const handler = new SSEHandler({
704
- onStart: (data) => {
705
- this.eventEmitter.emit("message:start", data);
706
- },
707
- onChunk: (data) => {
708
- this.eventEmitter.emit("message:chunk", data);
709
- },
710
- onToolCall: (toolCall) => {
711
- this.eventEmitter.emit("toolCall:received", toolCall);
712
- if (toolCall.type === "form") {
713
- this.eventEmitter.emit("toolCall:form", toolCall);
714
- }
715
- },
716
- onClientFunction: async (data) => {
717
- this.eventEmitter.emit("function:invoke", data);
718
- await this.handleClientFunctionInvocation(data);
719
- },
720
- onComplete: (message) => {
721
- this.eventEmitter.emit("message:complete", message);
722
- },
723
- onError: (error) => {
724
- this.eventEmitter.emit("message:error", { error: error.message });
725
- }
726
- });
727
- return handler.processStream(response);
728
- }
729
- async handleClientFunctionInvocation(data) {
730
- let result;
731
- let error;
732
- try {
733
- result = await this.functionRegistry.execute(data.functionName, data.arguments);
734
- } catch (err) {
735
- error = err instanceof Error ? err.message : "Unknown error";
736
- logger.error("Client function execution failed:", err);
737
- }
738
- if (data.invocationId) {
739
- try {
740
- await this.submitToolCallForm(data.invocationId, {
741
- result,
742
- error,
743
- _type: "client_function_result"
744
- });
745
- } catch (submitError) {
746
- logger.error("Failed to submit function result:", submitError);
747
- }
748
- }
749
- this.eventEmitter.emit("function:result", {
750
- invocationId: data.invocationId,
751
- result,
752
- error
753
- });
754
- }
755
- // ─────────────────────────────────────────────────────────────────
756
- // Conversations
757
- // ─────────────────────────────────────────────────────────────────
758
- /**
759
- * Get list of conversations
760
- */
761
- async getConversations() {
762
- const response = await this.httpClient.get("/api/sdk/v1/conversations");
763
- return response.items.map((item) => ({
764
- id: item.id,
765
- title: item.title,
766
- lastMessageDate: new Date(item.last_message_date)
767
- }));
768
- }
769
- /**
770
- * Get a specific conversation with messages
771
- */
772
- async getConversation(conversationId) {
773
- const response = await this.httpClient.get(`/api/sdk/v1/conversations/${conversationId}`);
774
- return {
775
- id: response.id,
776
- title: response.title,
777
- lastMessageDate: new Date(response.last_message_date),
778
- messages: response.messages.map((m) => ({
779
- id: m.id,
780
- conversationId: response.id,
781
- content: m.content,
782
- role: m.role,
783
- status: m.status,
784
- createdAt: new Date(m.created_at)
785
- }))
786
- };
787
- }
788
- /**
789
- * Get messages for a conversation
790
- */
791
- async getMessages(conversationId) {
792
- const conversation = await this.getConversation(conversationId);
793
- return conversation.messages || [];
794
- }
795
- // ─────────────────────────────────────────────────────────────────
796
- // Tool Calls
797
- // ─────────────────────────────────────────────────────────────────
798
- /**
799
- * Submit form data for a tool call
800
- */
801
- async submitToolCallForm(toolCallId, formData) {
802
- await this.httpClient.post(`/api/tool-calls/${toolCallId}/submit/`, {
803
- formData
804
- });
805
- }
806
- /**
807
- * Confirm a tool call
808
- */
809
- async confirmToolCall(toolCallId) {
810
- await this.httpClient.post(`/api/tool-calls/${toolCallId}/confirm/`);
811
- }
812
- /**
813
- * Reject a tool call
814
- */
815
- async rejectToolCall(toolCallId) {
816
- await this.httpClient.post(`/api/tool-calls/${toolCallId}/reject/`);
817
- }
818
- // ─────────────────────────────────────────────────────────────────
819
- // Feedback
820
- // ─────────────────────────────────────────────────────────────────
821
- /**
822
- * Submit feedback for a message
823
- */
824
- async submitFeedback(messageId, rating) {
825
- await this.httpClient.post(`/api/sdk/v1/messages/${messageId}/feedback`, {
826
- rating
827
- });
828
- }
829
- registerFunction(nameOrDef, handler, schema) {
830
- if (typeof nameOrDef === "object") {
831
- this.functionRegistry.register(nameOrDef);
832
- } else {
833
- this.functionRegistry.register(nameOrDef, handler, schema);
834
- }
835
- }
836
- /**
837
- * Short alias for `registerFunction`. Also accepts an array of definitions.
838
- *
839
- * ```ts
840
- * client.register(lookupOrder);
841
- * client.register([lookupOrder, cancelOrder]);
842
- * ```
843
- */
844
- register(definition) {
845
- if (Array.isArray(definition)) {
846
- for (const def of definition) {
847
- this.functionRegistry.register(def);
848
- }
849
- } else {
850
- this.functionRegistry.register(definition);
851
- }
852
- }
853
- /**
854
- * Unregister a client-side function
855
- */
856
- unregisterFunction(name) {
857
- return this.functionRegistry.unregister(name);
858
- }
859
- /**
860
- * Get all registered function schemas
861
- */
862
- getRegisteredFunctions() {
863
- return this.functionRegistry.getSchemas();
864
- }
865
- /**
866
- * Register a navigation function that lets AGO navigate users to different pages.
867
- * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
868
- * @param routes - Map of route names to paths, with descriptions for the LLM
869
- */
870
- registerNavigationFunction(navigate, routes) {
871
- const routeNames = routes.map((r) => r.name);
872
- const routeDescriptions = routes.map((r) => `- "${r.name}": ${r.description}`).join("\n");
873
- this.registerFunction(
874
- "navigateToPage",
875
- async (args) => {
876
- const pageName = args.page;
877
- const route = routes.find((r) => r.name === pageName);
878
- if (!route) {
879
- return { success: false, error: `Unknown page: ${pageName}` };
880
- }
881
- navigate(route.path);
882
- return { success: true, navigatedTo: route.path };
883
- },
884
- {
885
- description: `Navigate the user to a page in the application. Available pages:
886
- ${routeDescriptions}`,
887
- parameters: {
888
- type: "object",
889
- properties: {
890
- page: {
891
- type: "string",
892
- description: "The page to navigate to",
893
- enum: routeNames
894
- }
895
- },
896
- required: ["page"]
897
- }
898
- }
899
- );
900
- }
901
- // ─────────────────────────────────────────────────────────────────
902
- // Client Context
903
- // ─────────────────────────────────────────────────────────────────
904
- /**
905
- * Register or update a piece of client-side context.
906
- * This context is sent with every message so the AI understands the user's situation.
907
- *
908
- * ```ts
909
- * client.setContext("order-page", {
910
- * name: "Order detail",
911
- * description: "User is viewing order #123",
912
- * data: { orderId: "123", status: "shipped" },
913
- * });
914
- * ```
915
- */
916
- setContext(key, entry) {
917
- this.contextRegistry.set(key, entry);
918
- }
919
- /**
920
- * Remove a previously registered context entry.
921
- */
922
- removeContext(key) {
923
- return this.contextRegistry.remove(key);
924
- }
925
- /**
926
- * Register a dynamic context provider. The callback is invoked every time
927
- * a message is sent, so the AI always gets the freshest data.
928
- *
929
- * Use this for context that lives outside React state — global stores,
930
- * refs, or computed values.
931
- *
932
- * ```ts
933
- * client.addDynamicContext("cart", () => ({
934
- * name: "Checkout",
935
- * data: { itemCount: cart.items.length, total: cart.total },
936
- * }));
937
- * ```
938
- */
939
- addDynamicContext(key, provider) {
940
- this.contextRegistry.addDynamicProvider(key, provider);
941
- }
942
- /**
943
- * Remove a dynamic context provider.
944
- */
945
- removeDynamicContext(key) {
946
- return this.contextRegistry.removeDynamicProvider(key);
947
- }
948
- /**
949
- * Enable automatic capture of the current browser page (URL + title).
950
- * Injected as a dynamic context entry named `browser-page`.
951
- */
952
- enableAutoPageContext() {
953
- this.contextRegistry.addDynamicProvider("browser-page", () => {
954
- const url = typeof window !== "undefined" ? window.location.href : void 0;
955
- const title = typeof document !== "undefined" ? document.title : void 0;
956
- if (!url && !title) return null;
957
- return {
958
- name: "Browser page",
959
- description: "Current page the user is viewing",
960
- data: { url, title }
961
- };
962
- });
963
- }
964
- /**
965
- * Get the current context snapshot.
966
- */
967
- getContextSnapshot() {
968
- return this.contextRegistry.getSnapshot();
969
- }
970
- // ─────────────────────────────────────────────────────────────────
971
- // Events
972
- // ─────────────────────────────────────────────────────────────────
973
- /**
974
- * Subscribe to an event
975
- */
976
- on(event, handler) {
977
- this.eventEmitter.on(event, handler);
978
- }
979
- /**
980
- * Unsubscribe from an event
981
- */
982
- off(event, handler) {
983
- this.eventEmitter.off(event, handler);
984
- }
985
- /**
986
- * Subscribe to an event once — auto-unsubscribes after the first call.
987
- */
988
- once(event, handler) {
989
- this.eventEmitter.once(event, handler);
990
- }
991
- /**
992
- * Returns a Promise that resolves the next time `event` fires.
993
- *
994
- * ```ts
995
- * const msg = await client.waitFor("message:complete", { timeout: 10000 });
996
- * ```
997
- */
998
- waitFor(event, options) {
999
- return this.eventEmitter.waitFor(event, options);
1000
- }
1001
- // ─────────────────────────────────────────────────────────────────
1002
- // Configuration
1003
- // ─────────────────────────────────────────────────────────────────
1004
- /**
1005
- * Update client configuration
1006
- */
1007
- updateConfig(config) {
1008
- this.config = { ...this.config, ...config };
1009
- this.httpClient.updateConfig(config);
1010
- if (config.debug !== void 0) {
1011
- config.debug ? logger.enable() : logger.disable();
1012
- }
1013
- }
1014
- /**
1015
- * Clean up resources
1016
- */
1017
- destroy() {
1018
- this.eventEmitter.removeAllListeners();
1019
- this.functionRegistry.clear();
1020
- this.contextRegistry.clear();
1021
- logger.log("AgoClient destroyed");
1022
- }
1023
- }
1024
- exports.AgoApiError = AgoApiError;
1025
- exports.AgoClient = AgoClient;
1026
- exports.AgoError = AgoError;
1027
- exports.AgoFunctionError = AgoFunctionError;
1028
- exports.AgoNetworkError = AgoNetworkError;
1029
- exports.AgoStreamError = AgoStreamError;
1030
- exports.ClientContextRegistry = ClientContextRegistry;
1031
- exports.EventEmitter = EventEmitter;
1032
- exports.FunctionRegistry = FunctionRegistry;
1033
- exports.SSEHandler = SSEHandler;
1034
- exports.isStreamNetworkError = isStreamNetworkError;
1035
- exports.logger = logger;
1036
- //# sourceMappingURL=AgoClient-BDO4avLq.cjs.map