@useago/sdk 0.1.6 → 0.2.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.
Files changed (79) hide show
  1. package/dist/AgoClient-CNT-8sh_.js +905 -0
  2. package/dist/AgoClient-CNT-8sh_.js.map +1 -0
  3. package/dist/AgoClient-D0l1GTRs.cjs +976 -0
  4. package/dist/AgoClient-D0l1GTRs.cjs.map +1 -0
  5. package/dist/angular/ago.service.d.ts +98 -0
  6. package/dist/angular/index.d.ts +4 -0
  7. package/dist/angular/provide.d.ts +27 -0
  8. package/dist/angular.cjs +143 -0
  9. package/dist/angular.cjs.map +1 -0
  10. package/dist/angular.d.ts +2 -0
  11. package/dist/angular.js +141 -0
  12. package/dist/angular.js.map +1 -0
  13. package/dist/auto/createAgo.d.ts +39 -0
  14. package/dist/auto/index.d.ts +1 -0
  15. package/dist/client/AgoClient.d.ts +56 -0
  16. package/dist/client/types.d.ts +9 -7
  17. package/dist/createMockClient-Ci_N2tH8.cjs +104 -0
  18. package/dist/createMockClient-Ci_N2tH8.cjs.map +1 -0
  19. package/dist/createMockClient-U0ae_AYy.js +99 -0
  20. package/dist/createMockClient-U0ae_AYy.js.map +1 -0
  21. package/dist/functions--c6lx3ic.cjs +480 -0
  22. package/dist/functions--c6lx3ic.cjs.map +1 -0
  23. package/dist/functions-C9F1dnmh.js +398 -0
  24. package/dist/functions-C9F1dnmh.js.map +1 -0
  25. package/dist/helpers/factory.d.ts +20 -0
  26. package/dist/helpers/functions.d.ts +62 -0
  27. package/dist/helpers/index.d.ts +1 -0
  28. package/dist/helpers.cjs +15 -0
  29. package/dist/helpers.d.ts +2 -0
  30. package/dist/helpers.js +2 -0
  31. package/dist/index.cjs +312 -17
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.ts +6 -0
  34. package/dist/index.js +277 -19
  35. package/dist/index.js.map +1 -1
  36. package/dist/react/components/ChatWidget.d.ts +2 -0
  37. package/dist/react/components/Markdown.d.ts +12 -0
  38. package/dist/react/components/Message.d.ts +2 -0
  39. package/dist/react/components/index.d.ts +2 -0
  40. package/dist/react/context/AgoContext.d.ts +30 -4
  41. package/dist/react/context/index.d.ts +1 -1
  42. package/dist/react/hooks/index.d.ts +1 -0
  43. package/dist/react/hooks/useAgoContext.d.ts +40 -0
  44. package/dist/react/hooks/useAgoFunction.d.ts +14 -2
  45. package/dist/react/index.d.ts +4 -1
  46. package/dist/react.cjs +22104 -10273
  47. package/dist/react.cjs.map +1 -1
  48. package/dist/react.d.ts +1 -0
  49. package/dist/react.js +22103 -10289
  50. package/dist/react.js.map +1 -1
  51. package/dist/rolldown-runtime-BqCkTl7Q.cjs +50 -0
  52. package/dist/rolldown-runtime-CNZpIYwj.js +33 -0
  53. package/dist/state/ClientContextRegistry.d.ts +64 -0
  54. package/dist/streaming/helpers.d.ts +67 -0
  55. package/dist/vue/composables/useAgo.d.ts +17 -0
  56. package/dist/vue/composables/useAgoEvents.d.ts +11 -0
  57. package/dist/vue/composables/useAgoFunction.d.ts +34 -0
  58. package/dist/vue/composables/useChat.d.ts +251 -0
  59. package/dist/vue/composables/useConversation.d.ts +178 -0
  60. package/dist/vue/composables/useMessages.d.ts +89 -0
  61. package/dist/vue/index.d.ts +10 -0
  62. package/dist/vue/plugin.d.ts +16 -0
  63. package/dist/vue/symbols.d.ts +3 -0
  64. package/dist/vue.cjs +311 -0
  65. package/dist/vue.cjs.map +1 -0
  66. package/dist/vue.d.ts +2 -0
  67. package/dist/vue.js +301 -0
  68. package/dist/vue.js.map +1 -0
  69. package/dist/widget/types.d.ts +1 -0
  70. package/dist/widget.cjs +0 -2
  71. package/dist/widget.d.ts +1 -0
  72. package/dist/widget.js +0 -2
  73. package/package.json +29 -7
  74. package/dist/createMockClient-BZKh_1em.cjs +0 -941
  75. package/dist/createMockClient-BZKh_1em.cjs.map +0 -1
  76. package/dist/createMockClient-uGlVyjbL.js +0 -942
  77. package/dist/createMockClient-uGlVyjbL.js.map +0 -1
  78. package/dist/widget.cjs.map +0 -1
  79. package/dist/widget.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import type { ClientFunctionDefinition, ClientFunctionHandler, ClientFunctionSchema } from "../functions/types";
2
+ import type { ContextEntry, ContextSnapshot, DynamicContextProvider } from "../state/ClientContextRegistry";
2
3
  import type { AgoConfig, AgoClientEvents, AgoEventName, AgoEventHandler, AgoMessage, Conversation, SendMessageOptions } from "./types";
3
4
  /**
4
5
  * Main SDK client for AGO Chat integration
@@ -6,6 +7,7 @@ import type { AgoConfig, AgoClientEvents, AgoEventName, AgoEventHandler, AgoMess
6
7
  export declare class AgoClient {
7
8
  private httpClient;
8
9
  private functionRegistry;
10
+ private contextRegistry;
9
11
  private eventEmitter;
10
12
  private config;
11
13
  constructor(config: AgoConfig);
@@ -62,6 +64,15 @@ export declare class AgoClient {
62
64
  */
63
65
  registerFunction(definition: ClientFunctionDefinition): void;
64
66
  registerFunction(name: string, handler: ClientFunctionHandler, schema: Omit<ClientFunctionSchema, "name">): void;
67
+ /**
68
+ * Short alias for `registerFunction`. Also accepts an array of definitions.
69
+ *
70
+ * ```ts
71
+ * client.register(lookupOrder);
72
+ * client.register([lookupOrder, cancelOrder]);
73
+ * ```
74
+ */
75
+ register(definition: ClientFunctionDefinition | ClientFunctionDefinition[]): void;
65
76
  /**
66
77
  * Unregister a client-side function
67
78
  */
@@ -80,6 +91,51 @@ export declare class AgoClient {
80
91
  path: string;
81
92
  description: string;
82
93
  }>): void;
94
+ /**
95
+ * Register or update a piece of client-side context.
96
+ * This context is sent with every message so the AI understands the user's situation.
97
+ *
98
+ * ```ts
99
+ * client.setContext("order-page", {
100
+ * name: "Order detail",
101
+ * description: "User is viewing order #123",
102
+ * data: { orderId: "123", status: "shipped" },
103
+ * });
104
+ * ```
105
+ */
106
+ setContext(key: string, entry: ContextEntry): void;
107
+ /**
108
+ * Remove a previously registered context entry.
109
+ */
110
+ removeContext(key: string): boolean;
111
+ /**
112
+ * Register a dynamic context provider. The callback is invoked every time
113
+ * a message is sent, so the AI always gets the freshest data.
114
+ *
115
+ * Use this for context that lives outside React state — global stores,
116
+ * refs, or computed values.
117
+ *
118
+ * ```ts
119
+ * client.addDynamicContext("cart", () => ({
120
+ * name: "Checkout",
121
+ * data: { itemCount: cart.items.length, total: cart.total },
122
+ * }));
123
+ * ```
124
+ */
125
+ addDynamicContext(key: string, provider: DynamicContextProvider): void;
126
+ /**
127
+ * Remove a dynamic context provider.
128
+ */
129
+ removeDynamicContext(key: string): boolean;
130
+ /**
131
+ * Enable automatic capture of the current browser page (URL + title).
132
+ * Injected as a dynamic context entry named `browser-page`.
133
+ */
134
+ enableAutoPageContext(): void;
135
+ /**
136
+ * Get the current context snapshot.
137
+ */
138
+ getContextSnapshot(): ContextSnapshot | null;
83
139
  /**
84
140
  * Subscribe to an event
85
141
  */
@@ -2,14 +2,16 @@
2
2
  * SDK Configuration
3
3
  */
4
4
  export interface AgoConfig {
5
- /** Widget API key (X-Widget-Key header) */
6
- apiKey: string;
7
- /** Widget ID (X-Widget-Id header) */
8
- widgetId: string;
9
- /** API base URL (default: https://api.useago.com) */
10
- baseUrl?: string;
11
- /** Default agent ID for new conversations */
5
+ /** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
6
+ baseUrl: string;
7
+ /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
8
+ widgetId?: string;
9
+ /** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
10
+ agent?: string;
11
+ /** Default agent ID for new conversations. Prefer `agent`. */
12
12
  defaultAgentId?: string;
13
+ /** Permission name to apply to all requests (sent as `X-Widget-Permission`). Mirrors the widget's `window.AGO.permission`. */
14
+ permission?: string;
13
15
  /** User email for identification */
14
16
  userEmail?: string;
15
17
  /** JWT token for authenticated users */
@@ -0,0 +1,104 @@
1
+ //#region src/testing/createMockClient.ts
2
+ /**
3
+ * Create a mock AgoClient for testing. Works with any framework.
4
+ *
5
+ * ```ts
6
+ * import { createMockClient } from "@useago/sdk/testing";
7
+ *
8
+ * const mock = createMockClient();
9
+ * mock.__emitEvent("message:complete", someMessage);
10
+ * expect(mock.__callsFor("sendMessage")).toHaveLength(1);
11
+ * ```
12
+ */
13
+ function createMockClient(options = {}) {
14
+ const { overrides = {} } = options;
15
+ const noopMessage = {
16
+ id: "mock-msg-1",
17
+ conversationId: "mock-conv-1",
18
+ content: "Mock response",
19
+ role: "assistant",
20
+ status: "DONE",
21
+ createdAt: /* @__PURE__ */ new Date()
22
+ };
23
+ const noopConversation = {
24
+ id: "mock-conv-1",
25
+ title: "Mock Conversation",
26
+ lastMessageDate: /* @__PURE__ */ new Date()
27
+ };
28
+ const listeners = /* @__PURE__ */ new Map();
29
+ const calls = [];
30
+ const merged = {
31
+ sendMessage: async () => noopMessage,
32
+ getConversations: async () => [noopConversation],
33
+ getConversation: async () => noopConversation,
34
+ getMessages: async () => [noopMessage],
35
+ submitToolCallForm: async () => void 0,
36
+ confirmToolCall: async () => void 0,
37
+ rejectToolCall: async () => void 0,
38
+ submitFeedback: async () => void 0,
39
+ registerFunction: () => void 0,
40
+ unregisterFunction: () => true,
41
+ getRegisteredFunctions: () => [],
42
+ registerNavigationFunction: () => void 0,
43
+ on: (event, handler) => {
44
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
45
+ listeners.get(event).add(handler);
46
+ },
47
+ off: (event, handler) => {
48
+ listeners.get(event)?.delete(handler);
49
+ },
50
+ once: (event, handler) => {
51
+ const wrapper = (...args) => {
52
+ listeners.get(event)?.delete(wrapper);
53
+ handler(...args);
54
+ };
55
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
56
+ listeners.get(event).add(wrapper);
57
+ },
58
+ waitFor: (event, options) => {
59
+ return new Promise((resolve, reject) => {
60
+ let timer;
61
+ const handler = (data) => {
62
+ if (timer) clearTimeout(timer);
63
+ listeners.get(event)?.delete(handler);
64
+ resolve(data);
65
+ };
66
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
67
+ listeners.get(event).add(handler);
68
+ if (options?.timeout) timer = setTimeout(() => {
69
+ listeners.get(event)?.delete(handler);
70
+ reject(/* @__PURE__ */ new Error(`waitFor("${event}") timed out after ${options.timeout}ms`));
71
+ }, options.timeout);
72
+ });
73
+ },
74
+ updateConfig: () => void 0,
75
+ destroy: () => {
76
+ listeners.clear();
77
+ },
78
+ ...overrides
79
+ };
80
+ const mock = {};
81
+ for (const [key, fn] of Object.entries(merged)) mock[key] = (...args) => {
82
+ calls.push({
83
+ method: key,
84
+ args
85
+ });
86
+ return fn(...args);
87
+ };
88
+ mock.__calls = calls;
89
+ mock.__callsFor = (method) => calls.filter((c) => c.method === method);
90
+ mock.__emitEvent = (event, data) => {
91
+ const handlers = listeners.get(event);
92
+ if (handlers) [...handlers].forEach((h) => h(data));
93
+ };
94
+ return mock;
95
+ }
96
+ //#endregion
97
+ Object.defineProperty(exports, "createMockClient", {
98
+ enumerable: true,
99
+ get: function() {
100
+ return createMockClient;
101
+ }
102
+ });
103
+
104
+ //# sourceMappingURL=createMockClient-Ci_N2tH8.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMockClient-Ci_N2tH8.cjs","names":[],"sources":["../src/testing/createMockClient.ts"],"sourcesContent":["import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoClientEvents,\n AgoEventName,\n AgoMessage,\n Conversation,\n} from \"../client/types\";\nimport type { ClientFunctionSchema } from \"../functions/types\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype MockFn = (...args: any[]) => any;\n\nexport interface MockAgoClientOptions {\n overrides?: Partial<Record<string, MockFn>>;\n}\n\nexport interface MockAgoClient extends AgoClient {\n /**\n * Simulate a server-pushed event.\n * ```ts\n * mock.__emitEvent(\"message:complete\", { id: \"1\", content: \"hi\", ... });\n * ```\n */\n __emitEvent<K extends AgoEventName>(event: K, data: AgoClientEvents[K]): void;\n\n /**\n * All recorded method calls: `[methodName, ...args][]`\n */\n __calls: Array<{ method: string; args: unknown[] }>;\n\n /**\n * Get calls for a specific method.\n */\n __callsFor(method: string): Array<{ method: string; args: unknown[] }>;\n}\n\n/**\n * Create a mock AgoClient for testing. Works with any framework.\n *\n * ```ts\n * import { createMockClient } from \"@useago/sdk/testing\";\n *\n * const mock = createMockClient();\n * mock.__emitEvent(\"message:complete\", someMessage);\n * expect(mock.__callsFor(\"sendMessage\")).toHaveLength(1);\n * ```\n */\nexport function createMockClient(\n options: MockAgoClientOptions = {}\n): MockAgoClient {\n const { overrides = {} } = options;\n\n const noopMessage: AgoMessage = {\n id: \"mock-msg-1\",\n conversationId: \"mock-conv-1\",\n content: \"Mock response\",\n role: \"assistant\",\n status: \"DONE\",\n createdAt: new Date(),\n };\n\n const noopConversation: Conversation = {\n id: \"mock-conv-1\",\n title: \"Mock Conversation\",\n lastMessageDate: new Date(),\n };\n\n const listeners = new Map<string, Set<(...args: unknown[]) => void>>();\n const calls: Array<{ method: string; args: unknown[] }> = [];\n\n const defaults: Record<string, MockFn> = {\n sendMessage: async () => noopMessage,\n getConversations: async () => [noopConversation],\n getConversation: async () => noopConversation,\n getMessages: async () => [noopMessage],\n submitToolCallForm: async () => undefined,\n confirmToolCall: async () => undefined,\n rejectToolCall: async () => undefined,\n submitFeedback: async () => undefined,\n registerFunction: () => undefined,\n unregisterFunction: () => true,\n getRegisteredFunctions: () => [] as ClientFunctionSchema[],\n registerNavigationFunction: () => undefined,\n on: (event: string, handler: (...args: unknown[]) => void) => {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n },\n off: (event: string, handler: (...args: unknown[]) => void) => {\n listeners.get(event)?.delete(handler);\n },\n once: (event: string, handler: (...args: unknown[]) => void) => {\n const wrapper = (...args: unknown[]) => {\n listeners.get(event)?.delete(wrapper);\n handler(...args);\n };\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(wrapper);\n },\n waitFor: (event: string, options?: { timeout?: number }) => {\n return new Promise((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const handler = (data: unknown) => {\n if (timer) clearTimeout(timer);\n listeners.get(event)?.delete(handler);\n resolve(data);\n };\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n if (options?.timeout) {\n timer = setTimeout(() => {\n listeners.get(event)?.delete(handler);\n reject(new Error(`waitFor(\"${event}\") timed out after ${options.timeout}ms`));\n }, options.timeout);\n }\n });\n },\n updateConfig: () => undefined,\n destroy: () => {\n listeners.clear();\n },\n };\n\n const merged = { ...defaults, ...overrides } as Record<string, MockFn>;\n\n // Wrap all methods to record calls\n const mock: Record<string, unknown> = {};\n\n for (const [key, fn] of Object.entries(merged)) {\n mock[key] = (...args: unknown[]) => {\n calls.push({ method: key, args });\n return (fn as MockFn)(...args);\n };\n }\n\n // Test helpers (not recorded)\n mock.__calls = calls;\n mock.__callsFor = (method: string) => calls.filter((c) => c.method === method);\n mock.__emitEvent = (event: string, data: unknown) => {\n // Copy the set to avoid mutation during iteration (once handlers remove themselves)\n const handlers = listeners.get(event);\n if (handlers) {\n [...handlers].forEach((h) => h(data));\n }\n };\n\n return mock as unknown as MockAgoClient;\n}\n"],"mappings":";;;;;;;;;;;;AA+CA,SAAgB,iBACd,UAAgC,EAAE,EACnB;CACf,MAAM,EAAE,YAAY,EAAE,KAAK;CAE3B,MAAM,cAA0B;EAC9B,IAAI;EACJ,gBAAgB;EAChB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,2BAAW,IAAI,MAAM;EACtB;CAED,MAAM,mBAAiC;EACrC,IAAI;EACJ,OAAO;EACP,iCAAiB,IAAI,MAAM;EAC5B;CAED,MAAM,4BAAY,IAAI,KAAgD;CACtE,MAAM,QAAoD,EAAE;CAsD5D,MAAM,SAAS;EAnDb,aAAa,YAAY;EACzB,kBAAkB,YAAY,CAAC,iBAAiB;EAChD,iBAAiB,YAAY;EAC7B,aAAa,YAAY,CAAC,YAAY;EACtC,oBAAoB,YAAY,KAAA;EAChC,iBAAiB,YAAY,KAAA;EAC7B,gBAAgB,YAAY,KAAA;EAC5B,gBAAgB,YAAY,KAAA;EAC5B,wBAAwB,KAAA;EACxB,0BAA0B;EAC1B,8BAA8B,EAAE;EAChC,kCAAkC,KAAA;EAClC,KAAK,OAAe,YAA0C;AAC5D,OAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,aAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;;EAEpC,MAAM,OAAe,YAA0C;AAC7D,aAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;;EAEvC,OAAO,OAAe,YAA0C;GAC9D,MAAM,WAAW,GAAG,SAAoB;AACtC,cAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,YAAQ,GAAG,KAAK;;AAElB,OAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,aAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;;EAEpC,UAAU,OAAe,YAAmC;AAC1D,UAAO,IAAI,SAAS,SAAS,WAAW;IACtC,IAAI;IACJ,MAAM,WAAW,SAAkB;AACjC,SAAI,MAAO,cAAa,MAAM;AAC9B,eAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,aAAQ,KAAK;;AAEf,QAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,cAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;AAClC,QAAI,SAAS,QACX,SAAQ,iBAAiB;AACvB,eAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,4BAAO,IAAI,MAAM,YAAY,MAAM,qBAAqB,QAAQ,QAAQ,IAAI,CAAC;OAC5E,QAAQ,QAAQ;KAErB;;EAEJ,oBAAoB,KAAA;EACpB,eAAe;AACb,aAAU,OAAO;;EAIS,GAAG;EAAW;CAG5C,MAAM,OAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,OAAO,OAAO,QAAQ,OAAO,CAC5C,MAAK,QAAQ,GAAG,SAAoB;AAClC,QAAM,KAAK;GAAE,QAAQ;GAAK;GAAM,CAAC;AACjC,SAAQ,GAAc,GAAG,KAAK;;AAKlC,MAAK,UAAU;AACf,MAAK,cAAc,WAAmB,MAAM,QAAQ,MAAM,EAAE,WAAW,OAAO;AAC9E,MAAK,eAAe,OAAe,SAAkB;EAEnD,MAAM,WAAW,UAAU,IAAI,MAAM;AACrC,MAAI,SACF,EAAC,GAAG,SAAS,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC;;AAIzC,QAAO"}
@@ -0,0 +1,99 @@
1
+ //#region src/testing/createMockClient.ts
2
+ /**
3
+ * Create a mock AgoClient for testing. Works with any framework.
4
+ *
5
+ * ```ts
6
+ * import { createMockClient } from "@useago/sdk/testing";
7
+ *
8
+ * const mock = createMockClient();
9
+ * mock.__emitEvent("message:complete", someMessage);
10
+ * expect(mock.__callsFor("sendMessage")).toHaveLength(1);
11
+ * ```
12
+ */
13
+ function createMockClient(options = {}) {
14
+ const { overrides = {} } = options;
15
+ const noopMessage = {
16
+ id: "mock-msg-1",
17
+ conversationId: "mock-conv-1",
18
+ content: "Mock response",
19
+ role: "assistant",
20
+ status: "DONE",
21
+ createdAt: /* @__PURE__ */ new Date()
22
+ };
23
+ const noopConversation = {
24
+ id: "mock-conv-1",
25
+ title: "Mock Conversation",
26
+ lastMessageDate: /* @__PURE__ */ new Date()
27
+ };
28
+ const listeners = /* @__PURE__ */ new Map();
29
+ const calls = [];
30
+ const merged = {
31
+ sendMessage: async () => noopMessage,
32
+ getConversations: async () => [noopConversation],
33
+ getConversation: async () => noopConversation,
34
+ getMessages: async () => [noopMessage],
35
+ submitToolCallForm: async () => void 0,
36
+ confirmToolCall: async () => void 0,
37
+ rejectToolCall: async () => void 0,
38
+ submitFeedback: async () => void 0,
39
+ registerFunction: () => void 0,
40
+ unregisterFunction: () => true,
41
+ getRegisteredFunctions: () => [],
42
+ registerNavigationFunction: () => void 0,
43
+ on: (event, handler) => {
44
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
45
+ listeners.get(event).add(handler);
46
+ },
47
+ off: (event, handler) => {
48
+ listeners.get(event)?.delete(handler);
49
+ },
50
+ once: (event, handler) => {
51
+ const wrapper = (...args) => {
52
+ listeners.get(event)?.delete(wrapper);
53
+ handler(...args);
54
+ };
55
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
56
+ listeners.get(event).add(wrapper);
57
+ },
58
+ waitFor: (event, options) => {
59
+ return new Promise((resolve, reject) => {
60
+ let timer;
61
+ const handler = (data) => {
62
+ if (timer) clearTimeout(timer);
63
+ listeners.get(event)?.delete(handler);
64
+ resolve(data);
65
+ };
66
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
67
+ listeners.get(event).add(handler);
68
+ if (options?.timeout) timer = setTimeout(() => {
69
+ listeners.get(event)?.delete(handler);
70
+ reject(/* @__PURE__ */ new Error(`waitFor("${event}") timed out after ${options.timeout}ms`));
71
+ }, options.timeout);
72
+ });
73
+ },
74
+ updateConfig: () => void 0,
75
+ destroy: () => {
76
+ listeners.clear();
77
+ },
78
+ ...overrides
79
+ };
80
+ const mock = {};
81
+ for (const [key, fn] of Object.entries(merged)) mock[key] = (...args) => {
82
+ calls.push({
83
+ method: key,
84
+ args
85
+ });
86
+ return fn(...args);
87
+ };
88
+ mock.__calls = calls;
89
+ mock.__callsFor = (method) => calls.filter((c) => c.method === method);
90
+ mock.__emitEvent = (event, data) => {
91
+ const handlers = listeners.get(event);
92
+ if (handlers) [...handlers].forEach((h) => h(data));
93
+ };
94
+ return mock;
95
+ }
96
+ //#endregion
97
+ export { createMockClient as t };
98
+
99
+ //# sourceMappingURL=createMockClient-U0ae_AYy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMockClient-U0ae_AYy.js","names":[],"sources":["../src/testing/createMockClient.ts"],"sourcesContent":["import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoClientEvents,\n AgoEventName,\n AgoMessage,\n Conversation,\n} from \"../client/types\";\nimport type { ClientFunctionSchema } from \"../functions/types\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype MockFn = (...args: any[]) => any;\n\nexport interface MockAgoClientOptions {\n overrides?: Partial<Record<string, MockFn>>;\n}\n\nexport interface MockAgoClient extends AgoClient {\n /**\n * Simulate a server-pushed event.\n * ```ts\n * mock.__emitEvent(\"message:complete\", { id: \"1\", content: \"hi\", ... });\n * ```\n */\n __emitEvent<K extends AgoEventName>(event: K, data: AgoClientEvents[K]): void;\n\n /**\n * All recorded method calls: `[methodName, ...args][]`\n */\n __calls: Array<{ method: string; args: unknown[] }>;\n\n /**\n * Get calls for a specific method.\n */\n __callsFor(method: string): Array<{ method: string; args: unknown[] }>;\n}\n\n/**\n * Create a mock AgoClient for testing. Works with any framework.\n *\n * ```ts\n * import { createMockClient } from \"@useago/sdk/testing\";\n *\n * const mock = createMockClient();\n * mock.__emitEvent(\"message:complete\", someMessage);\n * expect(mock.__callsFor(\"sendMessage\")).toHaveLength(1);\n * ```\n */\nexport function createMockClient(\n options: MockAgoClientOptions = {}\n): MockAgoClient {\n const { overrides = {} } = options;\n\n const noopMessage: AgoMessage = {\n id: \"mock-msg-1\",\n conversationId: \"mock-conv-1\",\n content: \"Mock response\",\n role: \"assistant\",\n status: \"DONE\",\n createdAt: new Date(),\n };\n\n const noopConversation: Conversation = {\n id: \"mock-conv-1\",\n title: \"Mock Conversation\",\n lastMessageDate: new Date(),\n };\n\n const listeners = new Map<string, Set<(...args: unknown[]) => void>>();\n const calls: Array<{ method: string; args: unknown[] }> = [];\n\n const defaults: Record<string, MockFn> = {\n sendMessage: async () => noopMessage,\n getConversations: async () => [noopConversation],\n getConversation: async () => noopConversation,\n getMessages: async () => [noopMessage],\n submitToolCallForm: async () => undefined,\n confirmToolCall: async () => undefined,\n rejectToolCall: async () => undefined,\n submitFeedback: async () => undefined,\n registerFunction: () => undefined,\n unregisterFunction: () => true,\n getRegisteredFunctions: () => [] as ClientFunctionSchema[],\n registerNavigationFunction: () => undefined,\n on: (event: string, handler: (...args: unknown[]) => void) => {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n },\n off: (event: string, handler: (...args: unknown[]) => void) => {\n listeners.get(event)?.delete(handler);\n },\n once: (event: string, handler: (...args: unknown[]) => void) => {\n const wrapper = (...args: unknown[]) => {\n listeners.get(event)?.delete(wrapper);\n handler(...args);\n };\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(wrapper);\n },\n waitFor: (event: string, options?: { timeout?: number }) => {\n return new Promise((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const handler = (data: unknown) => {\n if (timer) clearTimeout(timer);\n listeners.get(event)?.delete(handler);\n resolve(data);\n };\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n if (options?.timeout) {\n timer = setTimeout(() => {\n listeners.get(event)?.delete(handler);\n reject(new Error(`waitFor(\"${event}\") timed out after ${options.timeout}ms`));\n }, options.timeout);\n }\n });\n },\n updateConfig: () => undefined,\n destroy: () => {\n listeners.clear();\n },\n };\n\n const merged = { ...defaults, ...overrides } as Record<string, MockFn>;\n\n // Wrap all methods to record calls\n const mock: Record<string, unknown> = {};\n\n for (const [key, fn] of Object.entries(merged)) {\n mock[key] = (...args: unknown[]) => {\n calls.push({ method: key, args });\n return (fn as MockFn)(...args);\n };\n }\n\n // Test helpers (not recorded)\n mock.__calls = calls;\n mock.__callsFor = (method: string) => calls.filter((c) => c.method === method);\n mock.__emitEvent = (event: string, data: unknown) => {\n // Copy the set to avoid mutation during iteration (once handlers remove themselves)\n const handlers = listeners.get(event);\n if (handlers) {\n [...handlers].forEach((h) => h(data));\n }\n };\n\n return mock as unknown as MockAgoClient;\n}\n"],"mappings":";;;;;;;;;;;;AA+CA,SAAgB,iBACd,UAAgC,EAAE,EACnB;CACf,MAAM,EAAE,YAAY,EAAE,KAAK;CAE3B,MAAM,cAA0B;EAC9B,IAAI;EACJ,gBAAgB;EAChB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,2BAAW,IAAI,MAAM;EACtB;CAED,MAAM,mBAAiC;EACrC,IAAI;EACJ,OAAO;EACP,iCAAiB,IAAI,MAAM;EAC5B;CAED,MAAM,4BAAY,IAAI,KAAgD;CACtE,MAAM,QAAoD,EAAE;CAsD5D,MAAM,SAAS;EAnDb,aAAa,YAAY;EACzB,kBAAkB,YAAY,CAAC,iBAAiB;EAChD,iBAAiB,YAAY;EAC7B,aAAa,YAAY,CAAC,YAAY;EACtC,oBAAoB,YAAY,KAAA;EAChC,iBAAiB,YAAY,KAAA;EAC7B,gBAAgB,YAAY,KAAA;EAC5B,gBAAgB,YAAY,KAAA;EAC5B,wBAAwB,KAAA;EACxB,0BAA0B;EAC1B,8BAA8B,EAAE;EAChC,kCAAkC,KAAA;EAClC,KAAK,OAAe,YAA0C;AAC5D,OAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,aAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;;EAEpC,MAAM,OAAe,YAA0C;AAC7D,aAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;;EAEvC,OAAO,OAAe,YAA0C;GAC9D,MAAM,WAAW,GAAG,SAAoB;AACtC,cAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,YAAQ,GAAG,KAAK;;AAElB,OAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,aAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;;EAEpC,UAAU,OAAe,YAAmC;AAC1D,UAAO,IAAI,SAAS,SAAS,WAAW;IACtC,IAAI;IACJ,MAAM,WAAW,SAAkB;AACjC,SAAI,MAAO,cAAa,MAAM;AAC9B,eAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,aAAQ,KAAK;;AAEf,QAAI,CAAC,UAAU,IAAI,MAAM,CAAE,WAAU,IAAI,uBAAO,IAAI,KAAK,CAAC;AAC1D,cAAU,IAAI,MAAM,CAAE,IAAI,QAAQ;AAClC,QAAI,SAAS,QACX,SAAQ,iBAAiB;AACvB,eAAU,IAAI,MAAM,EAAE,OAAO,QAAQ;AACrC,4BAAO,IAAI,MAAM,YAAY,MAAM,qBAAqB,QAAQ,QAAQ,IAAI,CAAC;OAC5E,QAAQ,QAAQ;KAErB;;EAEJ,oBAAoB,KAAA;EACpB,eAAe;AACb,aAAU,OAAO;;EAIS,GAAG;EAAW;CAG5C,MAAM,OAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,OAAO,OAAO,QAAQ,OAAO,CAC5C,MAAK,QAAQ,GAAG,SAAoB;AAClC,QAAM,KAAK;GAAE,QAAQ;GAAK;GAAM,CAAC;AACjC,SAAQ,GAAc,GAAG,KAAK;;AAKlC,MAAK,UAAU;AACf,MAAK,cAAc,WAAmB,MAAM,QAAQ,MAAM,EAAE,WAAW,OAAO;AAC9E,MAAK,eAAe,OAAe,SAAkB;EAEnD,MAAM,WAAW,UAAU,IAAI,MAAM;AACrC,MAAI,SACF,EAAC,GAAG,SAAS,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC;;AAIzC,QAAO"}