@copilotkitnext/core 1.51.4 → 1.51.5-next.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/dist/index.mjs CHANGED
@@ -1,2131 +1,1718 @@
1
- // src/core/agent-registry.ts
2
- import { HttpAgent as HttpAgent2 } from "@ag-ui/client";
3
- import { logger } from "@copilotkitnext/shared";
4
-
5
- // src/agent.ts
6
- import {
7
- HttpAgent,
8
- runHttpRequest,
9
- transformHttpEventStream
10
- } from "@ag-ui/client";
1
+ import { HttpAgent, runHttpRequest, transformHttpEventStream } from "@ag-ui/client";
2
+ import { logger, partialJSONParse, randomUUID } from "@copilotkitnext/shared";
11
3
  import { EMPTY } from "rxjs";
12
4
  import { catchError } from "rxjs/operators";
5
+ import { zodToJsonSchema } from "zod-to-json-schema";
6
+
7
+ //#region src/agent.ts
8
+ /**
9
+ * Check if an error is a ZodError (validation error).
10
+ * These can occur when the SSE stream is aborted/truncated mid-event.
11
+ */
13
12
  function isZodError(error) {
14
- return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
13
+ return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
15
14
  }
15
+ /**
16
+ * Wrap an Observable to catch and suppress ZodErrors that occur during stream abort.
17
+ * These errors are expected when the connection is cancelled mid-stream.
18
+ */
16
19
  function withAbortErrorHandling(observable) {
17
- return observable.pipe(
18
- catchError((error) => {
19
- if (isZodError(error)) {
20
- return EMPTY;
21
- }
22
- throw error;
23
- })
24
- );
20
+ return observable.pipe(catchError((error) => {
21
+ if (isZodError(error)) return EMPTY;
22
+ throw error;
23
+ }));
25
24
  }
26
25
  var ProxiedCopilotRuntimeAgent = class extends HttpAgent {
27
- runtimeUrl;
28
- credentials;
29
- transport;
30
- singleEndpointUrl;
31
- constructor(config) {
32
- const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
33
- const transport = config.transport ?? "rest";
34
- const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(config.agentId ?? "")}/run`;
35
- if (!runUrl) {
36
- throw new Error(
37
- "ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'."
38
- );
39
- }
40
- super({
41
- ...config,
42
- url: runUrl
43
- });
44
- this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;
45
- this.credentials = config.credentials;
46
- this.transport = transport;
47
- if (this.transport === "single") {
48
- this.singleEndpointUrl = this.runtimeUrl;
49
- }
50
- }
51
- abortRun() {
52
- if (!this.agentId || !this.threadId) {
53
- return;
54
- }
55
- if (typeof fetch === "undefined") {
56
- return;
57
- }
58
- if (this.transport === "single") {
59
- if (!this.singleEndpointUrl) {
60
- return;
61
- }
62
- const headers = new Headers({
63
- ...this.headers,
64
- "Content-Type": "application/json"
65
- });
66
- void fetch(this.singleEndpointUrl, {
67
- method: "POST",
68
- headers,
69
- body: JSON.stringify({
70
- method: "agent/stop",
71
- params: {
72
- agentId: this.agentId,
73
- threadId: this.threadId
74
- }
75
- }),
76
- ...this.credentials ? { credentials: this.credentials } : {}
77
- }).catch((error) => {
78
- console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
79
- });
80
- return;
81
- }
82
- if (!this.runtimeUrl) {
83
- return;
84
- }
85
- const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(this.agentId)}/stop/${encodeURIComponent(this.threadId)}`;
86
- const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
87
- const base = new URL(this.runtimeUrl, origin);
88
- const stopUrl = new URL(stopPath, base);
89
- void fetch(stopUrl.toString(), {
90
- method: "POST",
91
- headers: {
92
- "Content-Type": "application/json",
93
- ...this.headers
94
- },
95
- ...this.credentials ? { credentials: this.credentials } : {}
96
- }).catch((error) => {
97
- console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
98
- });
99
- }
100
- connect(input) {
101
- if (this.transport === "single") {
102
- if (!this.singleEndpointUrl) {
103
- throw new Error("Single endpoint transport requires a runtimeUrl");
104
- }
105
- const requestInit = this.createSingleRouteRequestInit(
106
- input,
107
- "agent/connect",
108
- {
109
- agentId: this.agentId
110
- }
111
- );
112
- const httpEvents2 = runHttpRequest(this.singleEndpointUrl, requestInit);
113
- return withAbortErrorHandling(transformHttpEventStream(httpEvents2));
114
- }
115
- const httpEvents = runHttpRequest(
116
- `${this.runtimeUrl}/agent/${this.agentId}/connect`,
117
- this.requestInit(input)
118
- );
119
- return withAbortErrorHandling(transformHttpEventStream(httpEvents));
120
- }
121
- run(input) {
122
- if (this.transport === "single") {
123
- if (!this.singleEndpointUrl) {
124
- throw new Error("Single endpoint transport requires a runtimeUrl");
125
- }
126
- const requestInit = this.createSingleRouteRequestInit(
127
- input,
128
- "agent/run",
129
- {
130
- agentId: this.agentId
131
- }
132
- );
133
- const httpEvents = runHttpRequest(this.singleEndpointUrl, requestInit);
134
- return withAbortErrorHandling(transformHttpEventStream(httpEvents));
135
- }
136
- return withAbortErrorHandling(super.run(input));
137
- }
138
- clone() {
139
- const cloned = super.clone();
140
- cloned.runtimeUrl = this.runtimeUrl;
141
- cloned.credentials = this.credentials;
142
- cloned.transport = this.transport;
143
- cloned.singleEndpointUrl = this.singleEndpointUrl;
144
- return cloned;
145
- }
146
- createSingleRouteRequestInit(input, method, params) {
147
- if (!this.agentId) {
148
- throw new Error(
149
- "ProxiedCopilotRuntimeAgent requires agentId to make runtime requests"
150
- );
151
- }
152
- const baseInit = super.requestInit(input);
153
- const headers = new Headers(baseInit.headers ?? {});
154
- headers.set("Content-Type", "application/json");
155
- headers.set("Accept", headers.get("Accept") ?? "text/event-stream");
156
- let originalBody = void 0;
157
- if (typeof baseInit.body === "string") {
158
- try {
159
- originalBody = JSON.parse(baseInit.body);
160
- } catch (error) {
161
- console.warn(
162
- "ProxiedCopilotRuntimeAgent: failed to parse request body for single route transport",
163
- error
164
- );
165
- originalBody = void 0;
166
- }
167
- }
168
- const envelope = {
169
- method
170
- };
171
- if (params && Object.keys(params).length > 0) {
172
- envelope.params = params;
173
- }
174
- if (originalBody !== void 0) {
175
- envelope.body = originalBody;
176
- }
177
- return {
178
- ...baseInit,
179
- headers,
180
- body: JSON.stringify(envelope),
181
- ...this.credentials ? { credentials: this.credentials } : {}
182
- };
183
- }
26
+ runtimeUrl;
27
+ credentials;
28
+ transport;
29
+ singleEndpointUrl;
30
+ constructor(config) {
31
+ const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
32
+ const transport = config.transport ?? "rest";
33
+ const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(config.agentId ?? "")}/run`;
34
+ if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
35
+ super({
36
+ ...config,
37
+ url: runUrl
38
+ });
39
+ this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;
40
+ this.credentials = config.credentials;
41
+ this.transport = transport;
42
+ if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
43
+ }
44
+ abortRun() {
45
+ if (!this.agentId || !this.threadId) return;
46
+ if (typeof fetch === "undefined") return;
47
+ if (this.transport === "single") {
48
+ if (!this.singleEndpointUrl) return;
49
+ const headers = new Headers({
50
+ ...this.headers,
51
+ "Content-Type": "application/json"
52
+ });
53
+ fetch(this.singleEndpointUrl, {
54
+ method: "POST",
55
+ headers,
56
+ body: JSON.stringify({
57
+ method: "agent/stop",
58
+ params: {
59
+ agentId: this.agentId,
60
+ threadId: this.threadId
61
+ }
62
+ }),
63
+ ...this.credentials ? { credentials: this.credentials } : {}
64
+ }).catch((error) => {
65
+ console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
66
+ });
67
+ return;
68
+ }
69
+ if (!this.runtimeUrl) return;
70
+ const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(this.agentId)}/stop/${encodeURIComponent(this.threadId)}`;
71
+ const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
72
+ const base = new URL(this.runtimeUrl, origin);
73
+ const stopUrl = new URL(stopPath, base);
74
+ fetch(stopUrl.toString(), {
75
+ method: "POST",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ ...this.headers
79
+ },
80
+ ...this.credentials ? { credentials: this.credentials } : {}
81
+ }).catch((error) => {
82
+ console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
83
+ });
84
+ }
85
+ connect(input) {
86
+ if (this.transport === "single") {
87
+ if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
88
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
89
+ return withAbortErrorHandling(transformHttpEventStream(runHttpRequest(this.singleEndpointUrl, requestInit)));
90
+ }
91
+ return withAbortErrorHandling(transformHttpEventStream(runHttpRequest(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
92
+ }
93
+ run(input) {
94
+ if (this.transport === "single") {
95
+ if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
96
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
97
+ return withAbortErrorHandling(transformHttpEventStream(runHttpRequest(this.singleEndpointUrl, requestInit)));
98
+ }
99
+ return withAbortErrorHandling(super.run(input));
100
+ }
101
+ clone() {
102
+ const cloned = super.clone();
103
+ cloned.runtimeUrl = this.runtimeUrl;
104
+ cloned.credentials = this.credentials;
105
+ cloned.transport = this.transport;
106
+ cloned.singleEndpointUrl = this.singleEndpointUrl;
107
+ return cloned;
108
+ }
109
+ createSingleRouteRequestInit(input, method, params) {
110
+ if (!this.agentId) throw new Error("ProxiedCopilotRuntimeAgent requires agentId to make runtime requests");
111
+ const baseInit = super.requestInit(input);
112
+ const headers = new Headers(baseInit.headers ?? {});
113
+ headers.set("Content-Type", "application/json");
114
+ headers.set("Accept", headers.get("Accept") ?? "text/event-stream");
115
+ let originalBody = void 0;
116
+ if (typeof baseInit.body === "string") try {
117
+ originalBody = JSON.parse(baseInit.body);
118
+ } catch (error) {
119
+ console.warn("ProxiedCopilotRuntimeAgent: failed to parse request body for single route transport", error);
120
+ originalBody = void 0;
121
+ }
122
+ const envelope = { method };
123
+ if (params && Object.keys(params).length > 0) envelope.params = params;
124
+ if (originalBody !== void 0) envelope.body = originalBody;
125
+ return {
126
+ ...baseInit,
127
+ headers,
128
+ body: JSON.stringify(envelope),
129
+ ...this.credentials ? { credentials: this.credentials } : {}
130
+ };
131
+ }
184
132
  };
185
133
 
186
- // src/core/agent-registry.ts
134
+ //#endregion
135
+ //#region src/core/agent-registry.ts
136
+ /**
137
+ * Manages agent registration, lifecycle, and runtime connectivity for CopilotKitCore.
138
+ * Handles both local development agents and remote runtime agents.
139
+ */
187
140
  var AgentRegistry = class {
188
- constructor(core) {
189
- this.core = core;
190
- }
191
- _agents = {};
192
- localAgents = {};
193
- remoteAgents = {};
194
- _runtimeUrl;
195
- _runtimeVersion;
196
- _runtimeConnectionStatus = "disconnected" /* Disconnected */;
197
- _runtimeTransport = "rest";
198
- _audioFileTranscriptionEnabled = false;
199
- /**
200
- * Get all agents as a readonly record
201
- */
202
- get agents() {
203
- return this._agents;
204
- }
205
- get runtimeUrl() {
206
- return this._runtimeUrl;
207
- }
208
- get runtimeVersion() {
209
- return this._runtimeVersion;
210
- }
211
- get runtimeConnectionStatus() {
212
- return this._runtimeConnectionStatus;
213
- }
214
- get runtimeTransport() {
215
- return this._runtimeTransport;
216
- }
217
- get audioFileTranscriptionEnabled() {
218
- return this._audioFileTranscriptionEnabled;
219
- }
220
- /**
221
- * Initialize agents from configuration
222
- */
223
- initialize(agents) {
224
- this.localAgents = this.assignAgentIds(agents);
225
- this.applyHeadersToAgents(this.localAgents);
226
- this._agents = this.localAgents;
227
- }
228
- /**
229
- * Set the runtime URL and update connection
230
- */
231
- setRuntimeUrl(runtimeUrl) {
232
- const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
233
- if (this._runtimeUrl === normalizedRuntimeUrl) {
234
- return;
235
- }
236
- this._runtimeUrl = normalizedRuntimeUrl;
237
- void this.updateRuntimeConnection();
238
- }
239
- setRuntimeTransport(runtimeTransport) {
240
- if (this._runtimeTransport === runtimeTransport) {
241
- return;
242
- }
243
- this._runtimeTransport = runtimeTransport;
244
- void this.updateRuntimeConnection();
245
- }
246
- /**
247
- * Set all agents at once (for development use)
248
- */
249
- setAgents__unsafe_dev_only(agents) {
250
- Object.entries(agents).forEach(([id, agent]) => {
251
- if (agent) {
252
- this.validateAndAssignAgentId(id, agent);
253
- }
254
- });
255
- this.localAgents = agents;
256
- this._agents = { ...this.localAgents, ...this.remoteAgents };
257
- this.applyHeadersToAgents(this._agents);
258
- void this.notifyAgentsChanged();
259
- }
260
- /**
261
- * Add a single agent (for development use)
262
- */
263
- addAgent__unsafe_dev_only({ id, agent }) {
264
- this.validateAndAssignAgentId(id, agent);
265
- this.localAgents[id] = agent;
266
- this.applyHeadersToAgent(agent);
267
- this._agents = { ...this.localAgents, ...this.remoteAgents };
268
- void this.notifyAgentsChanged();
269
- }
270
- /**
271
- * Remove an agent by ID (for development use)
272
- */
273
- removeAgent__unsafe_dev_only(id) {
274
- delete this.localAgents[id];
275
- this._agents = { ...this.localAgents, ...this.remoteAgents };
276
- void this.notifyAgentsChanged();
277
- }
278
- /**
279
- * Get an agent by ID
280
- */
281
- getAgent(id) {
282
- if (id in this._agents) {
283
- return this._agents[id];
284
- }
285
- if (this.runtimeUrl !== void 0 && (this.runtimeConnectionStatus === "disconnected" /* Disconnected */ || this.runtimeConnectionStatus === "connecting" /* Connecting */)) {
286
- return void 0;
287
- }
288
- console.warn(`Agent ${id} not found`);
289
- return void 0;
290
- }
291
- /**
292
- * Apply current headers to an agent
293
- */
294
- applyHeadersToAgent(agent) {
295
- if (agent instanceof HttpAgent2) {
296
- agent.headers = {
297
- ...this.core.headers
298
- };
299
- }
300
- }
301
- /**
302
- * Apply current headers to all agents
303
- */
304
- applyHeadersToAgents(agents) {
305
- Object.values(agents).forEach((agent) => {
306
- this.applyHeadersToAgent(agent);
307
- });
308
- }
309
- /**
310
- * Apply current credentials to an agent
311
- */
312
- applyCredentialsToAgent(agent) {
313
- if (agent instanceof ProxiedCopilotRuntimeAgent) {
314
- agent.credentials = this.core.credentials;
315
- }
316
- }
317
- /**
318
- * Apply current credentials to all agents
319
- */
320
- applyCredentialsToAgents(agents) {
321
- Object.values(agents).forEach((agent) => {
322
- this.applyCredentialsToAgent(agent);
323
- });
324
- }
325
- /**
326
- * Update runtime connection and fetch remote agents
327
- */
328
- async updateRuntimeConnection() {
329
- if (typeof window === "undefined") {
330
- return;
331
- }
332
- if (!this.runtimeUrl) {
333
- this._runtimeConnectionStatus = "disconnected" /* Disconnected */;
334
- this._runtimeVersion = void 0;
335
- this._audioFileTranscriptionEnabled = false;
336
- this.remoteAgents = {};
337
- this._agents = this.localAgents;
338
- await this.notifyRuntimeStatusChanged(
339
- "disconnected" /* Disconnected */
340
- );
341
- await this.notifyAgentsChanged();
342
- return;
343
- }
344
- this._runtimeConnectionStatus = "connecting" /* Connecting */;
345
- await this.notifyRuntimeStatusChanged(
346
- "connecting" /* Connecting */
347
- );
348
- try {
349
- const runtimeInfoResponse = await this.fetchRuntimeInfo();
350
- const {
351
- version,
352
- ...runtimeInfo
353
- } = runtimeInfoResponse;
354
- const credentials = this.core.credentials;
355
- const agents = Object.fromEntries(
356
- Object.entries(runtimeInfo.agents).map(([id, { description }]) => {
357
- const agent = new ProxiedCopilotRuntimeAgent({
358
- runtimeUrl: this.runtimeUrl,
359
- agentId: id,
360
- // Runtime agents always have their ID set correctly
361
- description,
362
- transport: this._runtimeTransport,
363
- credentials
364
- });
365
- this.applyHeadersToAgent(agent);
366
- return [id, agent];
367
- })
368
- );
369
- this.remoteAgents = agents;
370
- this._agents = { ...this.localAgents, ...this.remoteAgents };
371
- this._runtimeConnectionStatus = "connected" /* Connected */;
372
- this._runtimeVersion = version;
373
- this._audioFileTranscriptionEnabled = runtimeInfoResponse.audioFileTranscriptionEnabled ?? false;
374
- await this.notifyRuntimeStatusChanged(
375
- "connected" /* Connected */
376
- );
377
- await this.notifyAgentsChanged();
378
- } catch (error) {
379
- this._runtimeConnectionStatus = "error" /* Error */;
380
- this._runtimeVersion = void 0;
381
- this._audioFileTranscriptionEnabled = false;
382
- this.remoteAgents = {};
383
- this._agents = this.localAgents;
384
- await this.notifyRuntimeStatusChanged(
385
- "error" /* Error */
386
- );
387
- await this.notifyAgentsChanged();
388
- const message = error instanceof Error ? error.message : JSON.stringify(error);
389
- logger.warn(
390
- `Failed to load runtime info (${this.runtimeUrl}/info): ${message}`
391
- );
392
- const runtimeError = error instanceof Error ? error : new Error(String(error));
393
- await this.core.emitError({
394
- error: runtimeError,
395
- code: "runtime_info_fetch_failed" /* RUNTIME_INFO_FETCH_FAILED */,
396
- context: {
397
- runtimeUrl: this.runtimeUrl
398
- }
399
- });
400
- }
401
- }
402
- async fetchRuntimeInfo() {
403
- if (!this.runtimeUrl) {
404
- throw new Error("Runtime URL is not set");
405
- }
406
- const baseHeaders = this.core.headers;
407
- const credentials = this.core.credentials;
408
- const headers = {
409
- ...baseHeaders
410
- };
411
- if (this._runtimeTransport === "single") {
412
- if (!headers["Content-Type"]) {
413
- headers["Content-Type"] = "application/json";
414
- }
415
- const response2 = await fetch(this.runtimeUrl, {
416
- method: "POST",
417
- headers,
418
- body: JSON.stringify({ method: "info" }),
419
- ...credentials ? { credentials } : {}
420
- });
421
- if ("ok" in response2 && !response2.ok) {
422
- throw new Error(
423
- `Runtime info request failed with status ${response2.status}`
424
- );
425
- }
426
- return await response2.json();
427
- }
428
- const response = await fetch(`${this.runtimeUrl}/info`, {
429
- headers,
430
- ...credentials ? { credentials } : {}
431
- });
432
- if ("ok" in response && !response.ok) {
433
- throw new Error(
434
- `Runtime info request failed with status ${response.status}`
435
- );
436
- }
437
- return await response.json();
438
- }
439
- /**
440
- * Assign agent IDs to a record of agents
441
- */
442
- assignAgentIds(agents) {
443
- Object.entries(agents).forEach(([id, agent]) => {
444
- if (agent) {
445
- this.validateAndAssignAgentId(id, agent);
446
- }
447
- });
448
- return agents;
449
- }
450
- /**
451
- * Validate and assign an agent ID
452
- */
453
- validateAndAssignAgentId(registrationId, agent) {
454
- if (agent.agentId && agent.agentId !== registrationId) {
455
- throw new Error(
456
- `Agent registration mismatch: Agent with ID "${agent.agentId}" cannot be registered under key "${registrationId}". The agent ID must match the registration key or be undefined.`
457
- );
458
- }
459
- if (!agent.agentId) {
460
- agent.agentId = registrationId;
461
- }
462
- }
463
- /**
464
- * Notify subscribers of runtime status changes
465
- */
466
- async notifyRuntimeStatusChanged(status) {
467
- await this.core.notifySubscribers(
468
- (subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
469
- copilotkit: this.core,
470
- status
471
- }),
472
- "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):"
473
- );
474
- }
475
- /**
476
- * Notify subscribers of agent changes
477
- */
478
- async notifyAgentsChanged() {
479
- await this.core.notifySubscribers(
480
- (subscriber) => subscriber.onAgentsChanged?.({
481
- copilotkit: this.core,
482
- agents: this._agents
483
- }),
484
- "Subscriber onAgentsChanged error:"
485
- );
486
- }
141
+ _agents = {};
142
+ localAgents = {};
143
+ remoteAgents = {};
144
+ _runtimeUrl;
145
+ _runtimeVersion;
146
+ _runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
147
+ _runtimeTransport = "rest";
148
+ _audioFileTranscriptionEnabled = false;
149
+ constructor(core) {
150
+ this.core = core;
151
+ }
152
+ /**
153
+ * Get all agents as a readonly record
154
+ */
155
+ get agents() {
156
+ return this._agents;
157
+ }
158
+ get runtimeUrl() {
159
+ return this._runtimeUrl;
160
+ }
161
+ get runtimeVersion() {
162
+ return this._runtimeVersion;
163
+ }
164
+ get runtimeConnectionStatus() {
165
+ return this._runtimeConnectionStatus;
166
+ }
167
+ get runtimeTransport() {
168
+ return this._runtimeTransport;
169
+ }
170
+ get audioFileTranscriptionEnabled() {
171
+ return this._audioFileTranscriptionEnabled;
172
+ }
173
+ /**
174
+ * Initialize agents from configuration
175
+ */
176
+ initialize(agents) {
177
+ this.localAgents = this.assignAgentIds(agents);
178
+ this.applyHeadersToAgents(this.localAgents);
179
+ this._agents = this.localAgents;
180
+ }
181
+ /**
182
+ * Set the runtime URL and update connection
183
+ */
184
+ setRuntimeUrl(runtimeUrl) {
185
+ const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
186
+ if (this._runtimeUrl === normalizedRuntimeUrl) return;
187
+ this._runtimeUrl = normalizedRuntimeUrl;
188
+ this.updateRuntimeConnection();
189
+ }
190
+ setRuntimeTransport(runtimeTransport) {
191
+ if (this._runtimeTransport === runtimeTransport) return;
192
+ this._runtimeTransport = runtimeTransport;
193
+ this.updateRuntimeConnection();
194
+ }
195
+ /**
196
+ * Set all agents at once (for development use)
197
+ */
198
+ setAgents__unsafe_dev_only(agents) {
199
+ Object.entries(agents).forEach(([id, agent]) => {
200
+ if (agent) this.validateAndAssignAgentId(id, agent);
201
+ });
202
+ this.localAgents = agents;
203
+ this._agents = {
204
+ ...this.localAgents,
205
+ ...this.remoteAgents
206
+ };
207
+ this.applyHeadersToAgents(this._agents);
208
+ this.notifyAgentsChanged();
209
+ }
210
+ /**
211
+ * Add a single agent (for development use)
212
+ */
213
+ addAgent__unsafe_dev_only({ id, agent }) {
214
+ this.validateAndAssignAgentId(id, agent);
215
+ this.localAgents[id] = agent;
216
+ this.applyHeadersToAgent(agent);
217
+ this._agents = {
218
+ ...this.localAgents,
219
+ ...this.remoteAgents
220
+ };
221
+ this.notifyAgentsChanged();
222
+ }
223
+ /**
224
+ * Remove an agent by ID (for development use)
225
+ */
226
+ removeAgent__unsafe_dev_only(id) {
227
+ delete this.localAgents[id];
228
+ this._agents = {
229
+ ...this.localAgents,
230
+ ...this.remoteAgents
231
+ };
232
+ this.notifyAgentsChanged();
233
+ }
234
+ /**
235
+ * Get an agent by ID
236
+ */
237
+ getAgent(id) {
238
+ if (id in this._agents) return this._agents[id];
239
+ if (this.runtimeUrl !== void 0 && (this.runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Disconnected || this.runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connecting)) return;
240
+ console.warn(`Agent ${id} not found`);
241
+ }
242
+ /**
243
+ * Apply current headers to an agent
244
+ */
245
+ applyHeadersToAgent(agent) {
246
+ if (agent instanceof HttpAgent) agent.headers = { ...this.core.headers };
247
+ }
248
+ /**
249
+ * Apply current headers to all agents
250
+ */
251
+ applyHeadersToAgents(agents) {
252
+ Object.values(agents).forEach((agent) => {
253
+ this.applyHeadersToAgent(agent);
254
+ });
255
+ }
256
+ /**
257
+ * Apply current credentials to an agent
258
+ */
259
+ applyCredentialsToAgent(agent) {
260
+ if (agent instanceof ProxiedCopilotRuntimeAgent) agent.credentials = this.core.credentials;
261
+ }
262
+ /**
263
+ * Apply current credentials to all agents
264
+ */
265
+ applyCredentialsToAgents(agents) {
266
+ Object.values(agents).forEach((agent) => {
267
+ this.applyCredentialsToAgent(agent);
268
+ });
269
+ }
270
+ /**
271
+ * Update runtime connection and fetch remote agents
272
+ */
273
+ async updateRuntimeConnection() {
274
+ if (typeof window === "undefined") return;
275
+ if (!this.runtimeUrl) {
276
+ this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
277
+ this._runtimeVersion = void 0;
278
+ this._audioFileTranscriptionEnabled = false;
279
+ this.remoteAgents = {};
280
+ this._agents = this.localAgents;
281
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Disconnected);
282
+ await this.notifyAgentsChanged();
283
+ return;
284
+ }
285
+ this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connecting;
286
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connecting);
287
+ try {
288
+ const runtimeInfoResponse = await this.fetchRuntimeInfo();
289
+ const { version, ...runtimeInfo } = runtimeInfoResponse;
290
+ const credentials = this.core.credentials;
291
+ this.remoteAgents = Object.fromEntries(Object.entries(runtimeInfo.agents).map(([id, { description }]) => {
292
+ const agent = new ProxiedCopilotRuntimeAgent({
293
+ runtimeUrl: this.runtimeUrl,
294
+ agentId: id,
295
+ description,
296
+ transport: this._runtimeTransport,
297
+ credentials
298
+ });
299
+ this.applyHeadersToAgent(agent);
300
+ return [id, agent];
301
+ }));
302
+ this._agents = {
303
+ ...this.localAgents,
304
+ ...this.remoteAgents
305
+ };
306
+ this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connected;
307
+ this._runtimeVersion = version;
308
+ this._audioFileTranscriptionEnabled = runtimeInfoResponse.audioFileTranscriptionEnabled ?? false;
309
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connected);
310
+ await this.notifyAgentsChanged();
311
+ } catch (error) {
312
+ this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Error;
313
+ this._runtimeVersion = void 0;
314
+ this._audioFileTranscriptionEnabled = false;
315
+ this.remoteAgents = {};
316
+ this._agents = this.localAgents;
317
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
318
+ await this.notifyAgentsChanged();
319
+ const message = error instanceof Error ? error.message : JSON.stringify(error);
320
+ logger.warn(`Failed to load runtime info (${this.runtimeUrl}/info): ${message}`);
321
+ const runtimeError = error instanceof Error ? error : new Error(String(error));
322
+ await this.core.emitError({
323
+ error: runtimeError,
324
+ code: CopilotKitCoreErrorCode.RUNTIME_INFO_FETCH_FAILED,
325
+ context: { runtimeUrl: this.runtimeUrl }
326
+ });
327
+ }
328
+ }
329
+ async fetchRuntimeInfo() {
330
+ if (!this.runtimeUrl) throw new Error("Runtime URL is not set");
331
+ const baseHeaders = this.core.headers;
332
+ const credentials = this.core.credentials;
333
+ const headers = { ...baseHeaders };
334
+ if (this._runtimeTransport === "single") {
335
+ if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
336
+ const response = await fetch(this.runtimeUrl, {
337
+ method: "POST",
338
+ headers,
339
+ body: JSON.stringify({ method: "info" }),
340
+ ...credentials ? { credentials } : {}
341
+ });
342
+ if ("ok" in response && !response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
343
+ return await response.json();
344
+ }
345
+ const response = await fetch(`${this.runtimeUrl}/info`, {
346
+ headers,
347
+ ...credentials ? { credentials } : {}
348
+ });
349
+ if ("ok" in response && !response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
350
+ return await response.json();
351
+ }
352
+ /**
353
+ * Assign agent IDs to a record of agents
354
+ */
355
+ assignAgentIds(agents) {
356
+ Object.entries(agents).forEach(([id, agent]) => {
357
+ if (agent) this.validateAndAssignAgentId(id, agent);
358
+ });
359
+ return agents;
360
+ }
361
+ /**
362
+ * Validate and assign an agent ID
363
+ */
364
+ validateAndAssignAgentId(registrationId, agent) {
365
+ if (agent.agentId && agent.agentId !== registrationId) throw new Error(`Agent registration mismatch: Agent with ID "${agent.agentId}" cannot be registered under key "${registrationId}". The agent ID must match the registration key or be undefined.`);
366
+ if (!agent.agentId) agent.agentId = registrationId;
367
+ }
368
+ /**
369
+ * Notify subscribers of runtime status changes
370
+ */
371
+ async notifyRuntimeStatusChanged(status) {
372
+ await this.core.notifySubscribers((subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
373
+ copilotkit: this.core,
374
+ status
375
+ }), "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):");
376
+ }
377
+ /**
378
+ * Notify subscribers of agent changes
379
+ */
380
+ async notifyAgentsChanged() {
381
+ await this.core.notifySubscribers((subscriber) => subscriber.onAgentsChanged?.({
382
+ copilotkit: this.core,
383
+ agents: this._agents
384
+ }), "Subscriber onAgentsChanged error:");
385
+ }
487
386
  };
488
387
 
489
- // src/core/context-store.ts
490
- import { randomUUID } from "@copilotkitnext/shared";
388
+ //#endregion
389
+ //#region src/core/context-store.ts
390
+ /**
391
+ * Manages context storage and lifecycle for CopilotKitCore.
392
+ * Context represents additional information available to agents during execution.
393
+ */
491
394
  var ContextStore = class {
492
- constructor(core) {
493
- this.core = core;
494
- }
495
- _context = {};
496
- /**
497
- * Get all context entries as a readonly record
498
- */
499
- get context() {
500
- return this._context;
501
- }
502
- /**
503
- * Add a new context entry
504
- * @returns The ID of the created context entry
505
- */
506
- addContext({ description, value }) {
507
- const id = randomUUID();
508
- this._context[id] = { description, value };
509
- void this.notifySubscribers();
510
- return id;
511
- }
512
- /**
513
- * Remove a context entry by ID
514
- */
515
- removeContext(id) {
516
- delete this._context[id];
517
- void this.notifySubscribers();
518
- }
519
- /**
520
- * Notify all subscribers of context changes
521
- */
522
- async notifySubscribers() {
523
- await this.core.notifySubscribers(
524
- (subscriber) => subscriber.onContextChanged?.({
525
- copilotkit: this.core,
526
- context: this._context
527
- }),
528
- "Subscriber onContextChanged error:"
529
- );
530
- }
395
+ _context = {};
396
+ constructor(core) {
397
+ this.core = core;
398
+ }
399
+ /**
400
+ * Get all context entries as a readonly record
401
+ */
402
+ get context() {
403
+ return this._context;
404
+ }
405
+ /**
406
+ * Add a new context entry
407
+ * @returns The ID of the created context entry
408
+ */
409
+ addContext({ description, value }) {
410
+ const id = randomUUID();
411
+ this._context[id] = {
412
+ description,
413
+ value
414
+ };
415
+ this.notifySubscribers();
416
+ return id;
417
+ }
418
+ /**
419
+ * Remove a context entry by ID
420
+ */
421
+ removeContext(id) {
422
+ delete this._context[id];
423
+ this.notifySubscribers();
424
+ }
425
+ /**
426
+ * Notify all subscribers of context changes
427
+ */
428
+ async notifySubscribers() {
429
+ await this.core.notifySubscribers((subscriber) => subscriber.onContextChanged?.({
430
+ copilotkit: this.core,
431
+ context: this._context
432
+ }), "Subscriber onContextChanged error:");
433
+ }
531
434
  };
532
435
 
533
- // src/core/suggestion-engine.ts
534
- import { randomUUID as randomUUID2, partialJSONParse } from "@copilotkitnext/shared";
436
+ //#endregion
437
+ //#region src/core/suggestion-engine.ts
438
+ /**
439
+ * Manages suggestion generation, streaming, and lifecycle for CopilotKitCore.
440
+ * Handles both dynamic (AI-generated) and static suggestions.
441
+ */
535
442
  var SuggestionEngine = class {
536
- constructor(core) {
537
- this.core = core;
538
- }
539
- _suggestionsConfig = {};
540
- _suggestions = {};
541
- _runningSuggestions = {};
542
- /**
543
- * Initialize with suggestion configs
544
- */
545
- initialize(suggestionsConfig) {
546
- for (const config of suggestionsConfig) {
547
- this._suggestionsConfig[randomUUID2()] = config;
548
- }
549
- }
550
- /**
551
- * Add a suggestion configuration
552
- * @returns The ID of the created config
553
- */
554
- addSuggestionsConfig(config) {
555
- const id = randomUUID2();
556
- this._suggestionsConfig[id] = config;
557
- void this.notifySuggestionsConfigChanged();
558
- return id;
559
- }
560
- /**
561
- * Remove a suggestion configuration by ID
562
- */
563
- removeSuggestionsConfig(id) {
564
- delete this._suggestionsConfig[id];
565
- void this.notifySuggestionsConfigChanged();
566
- }
567
- /**
568
- * Reload suggestions for a specific agent
569
- * This triggers generation of new suggestions based on current configs
570
- */
571
- reloadSuggestions(agentId) {
572
- this.clearSuggestions(agentId);
573
- const agent = this.core.getAgent(agentId);
574
- if (!agent) {
575
- return;
576
- }
577
- const messageCount = agent.messages?.length ?? 0;
578
- let hasAnySuggestions = false;
579
- for (const config of Object.values(this._suggestionsConfig)) {
580
- if (config.consumerAgentId !== void 0 && config.consumerAgentId !== "*" && config.consumerAgentId !== agentId) {
581
- continue;
582
- }
583
- if (!this.shouldShowSuggestions(config, messageCount)) {
584
- continue;
585
- }
586
- const suggestionId = randomUUID2();
587
- if (isDynamicSuggestionsConfig(config)) {
588
- if (!hasAnySuggestions) {
589
- hasAnySuggestions = true;
590
- void this.notifySuggestionsStartedLoading(agentId);
591
- }
592
- void this.generateSuggestions(suggestionId, config, agentId);
593
- } else if (isStaticSuggestionsConfig(config)) {
594
- this.addStaticSuggestions(suggestionId, config, agentId);
595
- }
596
- }
597
- }
598
- /**
599
- * Clear all suggestions for a specific agent
600
- */
601
- clearSuggestions(agentId) {
602
- const runningAgents = this._runningSuggestions[agentId];
603
- if (runningAgents) {
604
- for (const agent of runningAgents) {
605
- agent.abortRun();
606
- }
607
- delete this._runningSuggestions[agentId];
608
- }
609
- this._suggestions[agentId] = {};
610
- void this.notifySuggestionsChanged(agentId, []);
611
- }
612
- /**
613
- * Get current suggestions for an agent
614
- */
615
- getSuggestions(agentId) {
616
- const suggestions = Object.values(this._suggestions[agentId] ?? {}).flat();
617
- const isLoading = (this._runningSuggestions[agentId]?.length ?? 0) > 0;
618
- return { suggestions, isLoading };
619
- }
620
- /**
621
- * Generate suggestions using a provider agent
622
- */
623
- async generateSuggestions(suggestionId, config, consumerAgentId) {
624
- let agent = void 0;
625
- try {
626
- const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
627
- if (!suggestionsProviderAgent) {
628
- throw new Error(
629
- `Suggestions provider agent not found: ${config.providerAgentId}`
630
- );
631
- }
632
- const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
633
- if (!suggestionsConsumerAgent) {
634
- throw new Error(
635
- `Suggestions consumer agent not found: ${consumerAgentId}`
636
- );
637
- }
638
- const clonedAgent = suggestionsProviderAgent.clone();
639
- agent = clonedAgent;
640
- agent.threadId = suggestionId;
641
- agent.messages = JSON.parse(
642
- JSON.stringify(suggestionsConsumerAgent.messages)
643
- );
644
- agent.state = JSON.parse(JSON.stringify(suggestionsConsumerAgent.state));
645
- this._suggestions[consumerAgentId] = {
646
- ...this._suggestions[consumerAgentId] ?? {},
647
- [suggestionId]: []
648
- };
649
- this._runningSuggestions[consumerAgentId] = [
650
- ...this._runningSuggestions[consumerAgentId] ?? [],
651
- agent
652
- ];
653
- agent.addMessage({
654
- id: suggestionId,
655
- role: "user",
656
- content: [
657
- `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
658
- `Provide at least ${config.minSuggestions ?? 1} and at most ${config.maxSuggestions ?? 3} suggestions.`,
659
- `The user has the following tools available: ${JSON.stringify(this.core.buildFrontendTools(consumerAgentId))}.`,
660
- ` ${config.instructions}`
661
- ].join("\n")
662
- });
663
- await agent.runAgent(
664
- {
665
- context: Object.values(
666
- this.core.context
667
- ),
668
- forwardedProps: {
669
- ...this.core.properties,
670
- toolChoice: {
671
- type: "function",
672
- function: { name: "copilotkitSuggest" }
673
- }
674
- },
675
- tools: [SUGGEST_TOOL]
676
- },
677
- {
678
- onMessagesChanged: ({ messages }) => {
679
- this.extractSuggestions(
680
- messages,
681
- suggestionId,
682
- consumerAgentId,
683
- true
684
- );
685
- }
686
- }
687
- );
688
- } catch (error) {
689
- console.warn("Error generating suggestions:", error);
690
- } finally {
691
- this.finalizeSuggestions(suggestionId, consumerAgentId);
692
- const runningAgents = this._runningSuggestions[consumerAgentId];
693
- if (agent && runningAgents) {
694
- const filteredAgents = runningAgents.filter((a) => a !== agent);
695
- this._runningSuggestions[consumerAgentId] = filteredAgents;
696
- if (filteredAgents.length === 0) {
697
- delete this._runningSuggestions[consumerAgentId];
698
- await this.notifySuggestionsFinishedLoading(consumerAgentId);
699
- }
700
- }
701
- }
702
- }
703
- /**
704
- * Finalize suggestions by marking them as no longer loading
705
- */
706
- finalizeSuggestions(suggestionId, consumerAgentId) {
707
- const agentSuggestions = this._suggestions[consumerAgentId];
708
- const currentSuggestions = agentSuggestions?.[suggestionId];
709
- if (agentSuggestions && currentSuggestions && currentSuggestions.length > 0) {
710
- const finalizedSuggestions = currentSuggestions.filter(
711
- (suggestion) => suggestion.title !== "" || suggestion.message !== ""
712
- ).map((suggestion) => ({
713
- ...suggestion,
714
- isLoading: false
715
- }));
716
- if (finalizedSuggestions.length > 0) {
717
- agentSuggestions[suggestionId] = finalizedSuggestions;
718
- } else {
719
- delete agentSuggestions[suggestionId];
720
- }
721
- const allSuggestions = Object.values(
722
- this._suggestions[consumerAgentId] ?? {}
723
- ).flat();
724
- void this.notifySuggestionsChanged(
725
- consumerAgentId,
726
- allSuggestions,
727
- "finalized"
728
- );
729
- }
730
- }
731
- /**
732
- * Extract suggestions from messages (called during streaming)
733
- */
734
- extractSuggestions(messages, suggestionId, consumerAgentId, isRunning) {
735
- const idx = messages.findIndex((message) => message.id === suggestionId);
736
- if (idx == -1) {
737
- return;
738
- }
739
- const suggestions = [];
740
- const newMessages = messages.slice(idx + 1);
741
- for (const message of newMessages) {
742
- if (message.role === "assistant" && message.toolCalls) {
743
- for (const toolCall of message.toolCalls) {
744
- if (toolCall.function.name === "copilotkitSuggest") {
745
- const fullArgs = Array.isArray(toolCall.function.arguments) ? toolCall.function.arguments.join("") : toolCall.function.arguments;
746
- const parsed = partialJSONParse(fullArgs);
747
- if (parsed && typeof parsed === "object" && "suggestions" in parsed) {
748
- const parsedSuggestions = parsed.suggestions;
749
- if (Array.isArray(parsedSuggestions)) {
750
- for (const item of parsedSuggestions) {
751
- if (item && typeof item === "object" && "title" in item) {
752
- suggestions.push({
753
- title: item.title ?? "",
754
- message: item.message ?? "",
755
- isLoading: false
756
- // Will be set correctly below
757
- });
758
- }
759
- }
760
- }
761
- }
762
- }
763
- }
764
- }
765
- }
766
- if (isRunning && suggestions.length > 0) {
767
- suggestions[suggestions.length - 1].isLoading = true;
768
- }
769
- const agentSuggestions = this._suggestions[consumerAgentId];
770
- if (agentSuggestions) {
771
- agentSuggestions[suggestionId] = suggestions;
772
- const allSuggestions = Object.values(
773
- this._suggestions[consumerAgentId] ?? {}
774
- ).flat();
775
- void this.notifySuggestionsChanged(
776
- consumerAgentId,
777
- allSuggestions,
778
- "suggestions changed"
779
- );
780
- }
781
- }
782
- /**
783
- * Notify subscribers of suggestions config changes
784
- */
785
- async notifySuggestionsConfigChanged() {
786
- await this.core.notifySubscribers(
787
- (subscriber) => subscriber.onSuggestionsConfigChanged?.({
788
- copilotkit: this.core,
789
- suggestionsConfig: this._suggestionsConfig
790
- }),
791
- "Subscriber onSuggestionsConfigChanged error:"
792
- );
793
- }
794
- /**
795
- * Notify subscribers of suggestions changes
796
- */
797
- async notifySuggestionsChanged(agentId, suggestions, context = "") {
798
- await this.core.notifySubscribers(
799
- (subscriber) => subscriber.onSuggestionsChanged?.({
800
- copilotkit: this.core,
801
- agentId,
802
- suggestions
803
- }),
804
- `Subscriber onSuggestionsChanged error: ${context}`
805
- );
806
- }
807
- /**
808
- * Notify subscribers that suggestions started loading
809
- */
810
- async notifySuggestionsStartedLoading(agentId) {
811
- await this.core.notifySubscribers(
812
- (subscriber) => subscriber.onSuggestionsStartedLoading?.({
813
- copilotkit: this.core,
814
- agentId
815
- }),
816
- "Subscriber onSuggestionsStartedLoading error:"
817
- );
818
- }
819
- /**
820
- * Notify subscribers that suggestions finished loading
821
- */
822
- async notifySuggestionsFinishedLoading(agentId) {
823
- await this.core.notifySubscribers(
824
- (subscriber) => subscriber.onSuggestionsFinishedLoading?.({
825
- copilotkit: this.core,
826
- agentId
827
- }),
828
- "Subscriber onSuggestionsFinishedLoading error:"
829
- );
830
- }
831
- /**
832
- * Check if suggestions should be shown based on availability and message count
833
- */
834
- shouldShowSuggestions(config, messageCount) {
835
- const availability = config.available;
836
- if (!availability) {
837
- if (isDynamicSuggestionsConfig(config)) {
838
- return messageCount > 0;
839
- } else {
840
- return messageCount === 0;
841
- }
842
- }
843
- switch (availability) {
844
- case "disabled":
845
- return false;
846
- case "before-first-message":
847
- return messageCount === 0;
848
- case "after-first-message":
849
- return messageCount > 0;
850
- case "always":
851
- return true;
852
- default:
853
- return false;
854
- }
855
- }
856
- /**
857
- * Add static suggestions directly without AI generation
858
- */
859
- addStaticSuggestions(suggestionId, config, consumerAgentId) {
860
- const suggestions = config.suggestions.map((s) => ({
861
- ...s,
862
- isLoading: false
863
- }));
864
- this._suggestions[consumerAgentId] = {
865
- ...this._suggestions[consumerAgentId] ?? {},
866
- [suggestionId]: suggestions
867
- };
868
- const allSuggestions = Object.values(
869
- this._suggestions[consumerAgentId] ?? {}
870
- ).flat();
871
- void this.notifySuggestionsChanged(
872
- consumerAgentId,
873
- allSuggestions,
874
- "static suggestions added"
875
- );
876
- }
443
+ _suggestionsConfig = {};
444
+ _suggestions = {};
445
+ _runningSuggestions = {};
446
+ constructor(core) {
447
+ this.core = core;
448
+ }
449
+ /**
450
+ * Initialize with suggestion configs
451
+ */
452
+ initialize(suggestionsConfig) {
453
+ for (const config of suggestionsConfig) this._suggestionsConfig[randomUUID()] = config;
454
+ }
455
+ /**
456
+ * Add a suggestion configuration
457
+ * @returns The ID of the created config
458
+ */
459
+ addSuggestionsConfig(config) {
460
+ const id = randomUUID();
461
+ this._suggestionsConfig[id] = config;
462
+ this.notifySuggestionsConfigChanged();
463
+ return id;
464
+ }
465
+ /**
466
+ * Remove a suggestion configuration by ID
467
+ */
468
+ removeSuggestionsConfig(id) {
469
+ delete this._suggestionsConfig[id];
470
+ this.notifySuggestionsConfigChanged();
471
+ }
472
+ /**
473
+ * Reload suggestions for a specific agent
474
+ * This triggers generation of new suggestions based on current configs
475
+ */
476
+ reloadSuggestions(agentId) {
477
+ this.clearSuggestions(agentId);
478
+ const agent = this.core.getAgent(agentId);
479
+ if (!agent) return;
480
+ const messageCount = agent.messages?.length ?? 0;
481
+ let hasAnySuggestions = false;
482
+ for (const config of Object.values(this._suggestionsConfig)) {
483
+ if (config.consumerAgentId !== void 0 && config.consumerAgentId !== "*" && config.consumerAgentId !== agentId) continue;
484
+ if (!this.shouldShowSuggestions(config, messageCount)) continue;
485
+ const suggestionId = randomUUID();
486
+ if (isDynamicSuggestionsConfig(config)) {
487
+ if (!hasAnySuggestions) {
488
+ hasAnySuggestions = true;
489
+ this.notifySuggestionsStartedLoading(agentId);
490
+ }
491
+ this.generateSuggestions(suggestionId, config, agentId);
492
+ } else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
493
+ }
494
+ }
495
+ /**
496
+ * Clear all suggestions for a specific agent
497
+ */
498
+ clearSuggestions(agentId) {
499
+ const runningAgents = this._runningSuggestions[agentId];
500
+ if (runningAgents) {
501
+ for (const agent of runningAgents) agent.abortRun();
502
+ delete this._runningSuggestions[agentId];
503
+ }
504
+ this._suggestions[agentId] = {};
505
+ this.notifySuggestionsChanged(agentId, []);
506
+ }
507
+ /**
508
+ * Get current suggestions for an agent
509
+ */
510
+ getSuggestions(agentId) {
511
+ return {
512
+ suggestions: Object.values(this._suggestions[agentId] ?? {}).flat(),
513
+ isLoading: (this._runningSuggestions[agentId]?.length ?? 0) > 0
514
+ };
515
+ }
516
+ /**
517
+ * Generate suggestions using a provider agent
518
+ */
519
+ async generateSuggestions(suggestionId, config, consumerAgentId) {
520
+ let agent = void 0;
521
+ try {
522
+ const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
523
+ if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
524
+ const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
525
+ if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
526
+ agent = suggestionsProviderAgent.clone();
527
+ agent.threadId = suggestionId;
528
+ agent.messages = JSON.parse(JSON.stringify(suggestionsConsumerAgent.messages));
529
+ agent.state = JSON.parse(JSON.stringify(suggestionsConsumerAgent.state));
530
+ this._suggestions[consumerAgentId] = {
531
+ ...this._suggestions[consumerAgentId] ?? {},
532
+ [suggestionId]: []
533
+ };
534
+ this._runningSuggestions[consumerAgentId] = [...this._runningSuggestions[consumerAgentId] ?? [], agent];
535
+ agent.addMessage({
536
+ id: suggestionId,
537
+ role: "user",
538
+ content: [
539
+ `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
540
+ `Provide at least ${config.minSuggestions ?? 1} and at most ${config.maxSuggestions ?? 3} suggestions.`,
541
+ `The user has the following tools available: ${JSON.stringify(this.core.buildFrontendTools(consumerAgentId))}.`,
542
+ ` ${config.instructions}`
543
+ ].join("\n")
544
+ });
545
+ await agent.runAgent({
546
+ context: Object.values(this.core.context),
547
+ forwardedProps: {
548
+ ...this.core.properties,
549
+ toolChoice: {
550
+ type: "function",
551
+ function: { name: "copilotkitSuggest" }
552
+ }
553
+ },
554
+ tools: [SUGGEST_TOOL]
555
+ }, { onMessagesChanged: ({ messages }) => {
556
+ this.extractSuggestions(messages, suggestionId, consumerAgentId, true);
557
+ } });
558
+ } catch (error) {
559
+ console.warn("Error generating suggestions:", error);
560
+ } finally {
561
+ this.finalizeSuggestions(suggestionId, consumerAgentId);
562
+ const runningAgents = this._runningSuggestions[consumerAgentId];
563
+ if (agent && runningAgents) {
564
+ const filteredAgents = runningAgents.filter((a) => a !== agent);
565
+ this._runningSuggestions[consumerAgentId] = filteredAgents;
566
+ if (filteredAgents.length === 0) {
567
+ delete this._runningSuggestions[consumerAgentId];
568
+ await this.notifySuggestionsFinishedLoading(consumerAgentId);
569
+ }
570
+ }
571
+ }
572
+ }
573
+ /**
574
+ * Finalize suggestions by marking them as no longer loading
575
+ */
576
+ finalizeSuggestions(suggestionId, consumerAgentId) {
577
+ const agentSuggestions = this._suggestions[consumerAgentId];
578
+ const currentSuggestions = agentSuggestions?.[suggestionId];
579
+ if (agentSuggestions && currentSuggestions && currentSuggestions.length > 0) {
580
+ const finalizedSuggestions = currentSuggestions.filter((suggestion) => suggestion.title !== "" || suggestion.message !== "").map((suggestion) => ({
581
+ ...suggestion,
582
+ isLoading: false
583
+ }));
584
+ if (finalizedSuggestions.length > 0) agentSuggestions[suggestionId] = finalizedSuggestions;
585
+ else delete agentSuggestions[suggestionId];
586
+ const allSuggestions = Object.values(this._suggestions[consumerAgentId] ?? {}).flat();
587
+ this.notifySuggestionsChanged(consumerAgentId, allSuggestions, "finalized");
588
+ }
589
+ }
590
+ /**
591
+ * Extract suggestions from messages (called during streaming)
592
+ */
593
+ extractSuggestions(messages, suggestionId, consumerAgentId, isRunning) {
594
+ const idx = messages.findIndex((message) => message.id === suggestionId);
595
+ if (idx == -1) return;
596
+ const suggestions = [];
597
+ const newMessages = messages.slice(idx + 1);
598
+ for (const message of newMessages) if (message.role === "assistant" && message.toolCalls) {
599
+ for (const toolCall of message.toolCalls) if (toolCall.function.name === "copilotkitSuggest") {
600
+ const parsed = partialJSONParse(Array.isArray(toolCall.function.arguments) ? toolCall.function.arguments.join("") : toolCall.function.arguments);
601
+ if (parsed && typeof parsed === "object" && "suggestions" in parsed) {
602
+ const parsedSuggestions = parsed.suggestions;
603
+ if (Array.isArray(parsedSuggestions)) {
604
+ for (const item of parsedSuggestions) if (item && typeof item === "object" && "title" in item) suggestions.push({
605
+ title: item.title ?? "",
606
+ message: item.message ?? "",
607
+ isLoading: false
608
+ });
609
+ }
610
+ }
611
+ }
612
+ }
613
+ if (isRunning && suggestions.length > 0) suggestions[suggestions.length - 1].isLoading = true;
614
+ const agentSuggestions = this._suggestions[consumerAgentId];
615
+ if (agentSuggestions) {
616
+ agentSuggestions[suggestionId] = suggestions;
617
+ const allSuggestions = Object.values(this._suggestions[consumerAgentId] ?? {}).flat();
618
+ this.notifySuggestionsChanged(consumerAgentId, allSuggestions, "suggestions changed");
619
+ }
620
+ }
621
+ /**
622
+ * Notify subscribers of suggestions config changes
623
+ */
624
+ async notifySuggestionsConfigChanged() {
625
+ await this.core.notifySubscribers((subscriber) => subscriber.onSuggestionsConfigChanged?.({
626
+ copilotkit: this.core,
627
+ suggestionsConfig: this._suggestionsConfig
628
+ }), "Subscriber onSuggestionsConfigChanged error:");
629
+ }
630
+ /**
631
+ * Notify subscribers of suggestions changes
632
+ */
633
+ async notifySuggestionsChanged(agentId, suggestions, context = "") {
634
+ await this.core.notifySubscribers((subscriber) => subscriber.onSuggestionsChanged?.({
635
+ copilotkit: this.core,
636
+ agentId,
637
+ suggestions
638
+ }), `Subscriber onSuggestionsChanged error: ${context}`);
639
+ }
640
+ /**
641
+ * Notify subscribers that suggestions started loading
642
+ */
643
+ async notifySuggestionsStartedLoading(agentId) {
644
+ await this.core.notifySubscribers((subscriber) => subscriber.onSuggestionsStartedLoading?.({
645
+ copilotkit: this.core,
646
+ agentId
647
+ }), "Subscriber onSuggestionsStartedLoading error:");
648
+ }
649
+ /**
650
+ * Notify subscribers that suggestions finished loading
651
+ */
652
+ async notifySuggestionsFinishedLoading(agentId) {
653
+ await this.core.notifySubscribers((subscriber) => subscriber.onSuggestionsFinishedLoading?.({
654
+ copilotkit: this.core,
655
+ agentId
656
+ }), "Subscriber onSuggestionsFinishedLoading error:");
657
+ }
658
+ /**
659
+ * Check if suggestions should be shown based on availability and message count
660
+ */
661
+ shouldShowSuggestions(config, messageCount) {
662
+ const availability = config.available;
663
+ if (!availability) if (isDynamicSuggestionsConfig(config)) return messageCount > 0;
664
+ else return messageCount === 0;
665
+ switch (availability) {
666
+ case "disabled": return false;
667
+ case "before-first-message": return messageCount === 0;
668
+ case "after-first-message": return messageCount > 0;
669
+ case "always": return true;
670
+ default: return false;
671
+ }
672
+ }
673
+ /**
674
+ * Add static suggestions directly without AI generation
675
+ */
676
+ addStaticSuggestions(suggestionId, config, consumerAgentId) {
677
+ const suggestions = config.suggestions.map((s) => ({
678
+ ...s,
679
+ isLoading: false
680
+ }));
681
+ this._suggestions[consumerAgentId] = {
682
+ ...this._suggestions[consumerAgentId] ?? {},
683
+ [suggestionId]: suggestions
684
+ };
685
+ const allSuggestions = Object.values(this._suggestions[consumerAgentId] ?? {}).flat();
686
+ this.notifySuggestionsChanged(consumerAgentId, allSuggestions, "static suggestions added");
687
+ }
877
688
  };
689
+ /**
690
+ * Type guard for dynamic suggestions config
691
+ */
878
692
  function isDynamicSuggestionsConfig(config) {
879
- return "instructions" in config;
693
+ return "instructions" in config;
880
694
  }
695
+ /**
696
+ * Type guard for static suggestions config
697
+ */
881
698
  function isStaticSuggestionsConfig(config) {
882
- return "suggestions" in config;
699
+ return "suggestions" in config;
883
700
  }
884
- var SUGGEST_TOOL = {
885
- name: "copilotkitSuggest",
886
- description: "Suggest what the user could say next",
887
- parameters: {
888
- type: "object",
889
- properties: {
890
- suggestions: {
891
- type: "array",
892
- description: "List of suggestions shown to the user as buttons.",
893
- items: {
894
- type: "object",
895
- properties: {
896
- title: {
897
- type: "string",
898
- description: "The title of the suggestion. This is shown as a button and should be short."
899
- },
900
- message: {
901
- type: "string",
902
- description: "The message to send when the suggestion is clicked. This should be a clear, complete sentence and will be sent as an instruction to the AI."
903
- }
904
- },
905
- required: ["title", "message"]
906
- }
907
- }
908
- },
909
- required: ["suggestions"]
910
- }
701
+ /**
702
+ * The tool definition for AI-generated suggestions
703
+ */
704
+ const SUGGEST_TOOL = {
705
+ name: "copilotkitSuggest",
706
+ description: "Suggest what the user could say next",
707
+ parameters: {
708
+ type: "object",
709
+ properties: { suggestions: {
710
+ type: "array",
711
+ description: "List of suggestions shown to the user as buttons.",
712
+ items: {
713
+ type: "object",
714
+ properties: {
715
+ title: {
716
+ type: "string",
717
+ description: "The title of the suggestion. This is shown as a button and should be short."
718
+ },
719
+ message: {
720
+ type: "string",
721
+ description: "The message to send when the suggestion is clicked. This should be a clear, complete sentence and will be sent as an instruction to the AI."
722
+ }
723
+ },
724
+ required: ["title", "message"]
725
+ }
726
+ } },
727
+ required: ["suggestions"]
728
+ }
911
729
  };
912
730
 
913
- // src/core/run-handler.ts
914
- import {
915
- HttpAgent as HttpAgent3
916
- } from "@ag-ui/client";
917
- import { randomUUID as randomUUID3, logger as logger2 } from "@copilotkitnext/shared";
918
- import { zodToJsonSchema } from "zod-to-json-schema";
731
+ //#endregion
732
+ //#region src/core/run-handler.ts
733
+ /**
734
+ * Handles agent execution, tool calling, and agent connectivity for CopilotKitCore.
735
+ * Manages the complete lifecycle of agent runs including tool execution and follow-ups.
736
+ */
919
737
  var RunHandler = class {
920
- constructor(core) {
921
- this.core = core;
922
- }
923
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
924
- _tools = [];
925
- /**
926
- * Get all tools as a readonly array
927
- */
928
- get tools() {
929
- return this._tools;
930
- }
931
- /**
932
- * Initialize with tools
933
- */
934
- initialize(tools) {
935
- this._tools = tools;
936
- }
937
- /**
938
- * Add a tool to the registry
939
- */
940
- addTool(tool) {
941
- const existingToolIndex = this._tools.findIndex(
942
- (t) => t.name === tool.name && t.agentId === tool.agentId
943
- );
944
- if (existingToolIndex !== -1) {
945
- logger2.warn(
946
- `Tool already exists: '${tool.name}' for agent '${tool.agentId || "global"}', skipping.`
947
- );
948
- return;
949
- }
950
- this._tools.push(tool);
951
- }
952
- /**
953
- * Remove a tool by name and optionally by agentId
954
- */
955
- removeTool(id, agentId) {
956
- this._tools = this._tools.filter((tool) => {
957
- if (agentId !== void 0) {
958
- return !(tool.name === id && tool.agentId === agentId);
959
- }
960
- return !(tool.name === id && !tool.agentId);
961
- });
962
- }
963
- /**
964
- * Get a tool by name and optionally by agentId.
965
- * If agentId is provided, it will first look for an agent-specific tool,
966
- * then fall back to a global tool with the same name.
967
- */
968
- getTool(params) {
969
- const { toolName, agentId } = params;
970
- if (agentId) {
971
- const agentTool = this._tools.find(
972
- (tool) => tool.name === toolName && tool.agentId === agentId
973
- );
974
- if (agentTool) {
975
- return agentTool;
976
- }
977
- }
978
- return this._tools.find((tool) => tool.name === toolName && !tool.agentId);
979
- }
980
- /**
981
- * Set all tools at once. Replaces existing tools.
982
- */
983
- setTools(tools) {
984
- this._tools = [...tools];
985
- }
986
- /**
987
- * Connect an agent (establish initial connection)
988
- */
989
- async connectAgent({
990
- agent
991
- }) {
992
- try {
993
- await agent.detachActiveRun();
994
- agent.setMessages([]);
995
- agent.setState({});
996
- if (agent instanceof HttpAgent3) {
997
- agent.headers = {
998
- ...this.core.headers
999
- };
1000
- }
1001
- const runAgentResult = await agent.connectAgent(
1002
- {
1003
- forwardedProps: this.core.properties,
1004
- tools: this.buildFrontendTools(agent.agentId)
1005
- },
1006
- this.createAgentErrorSubscriber(agent)
1007
- );
1008
- return this.processAgentResult({ runAgentResult, agent });
1009
- } catch (error) {
1010
- const connectError = error instanceof Error ? error : new Error(String(error));
1011
- const context = {};
1012
- if (agent.agentId) {
1013
- context.agentId = agent.agentId;
1014
- }
1015
- await this.core.emitError({
1016
- error: connectError,
1017
- code: "agent_connect_failed" /* AGENT_CONNECT_FAILED */,
1018
- context
1019
- });
1020
- throw error;
1021
- }
1022
- }
1023
- /**
1024
- * Run an agent
1025
- */
1026
- async runAgent({
1027
- agent
1028
- }) {
1029
- if (agent.agentId) {
1030
- void this.core.suggestionEngine.clearSuggestions(agent.agentId);
1031
- }
1032
- if (agent instanceof HttpAgent3) {
1033
- agent.headers = {
1034
- ...this.core.headers
1035
- };
1036
- }
1037
- try {
1038
- const runAgentResult = await agent.runAgent(
1039
- {
1040
- forwardedProps: this.core.properties,
1041
- tools: this.buildFrontendTools(agent.agentId),
1042
- context: Object.values(
1043
- this.core.context
1044
- )
1045
- },
1046
- this.createAgentErrorSubscriber(agent)
1047
- );
1048
- return this.processAgentResult({ runAgentResult, agent });
1049
- } catch (error) {
1050
- const runError = error instanceof Error ? error : new Error(String(error));
1051
- const context = {};
1052
- if (agent.agentId) {
1053
- context.agentId = agent.agentId;
1054
- }
1055
- await this.core.emitError({
1056
- error: runError,
1057
- code: "agent_run_failed" /* AGENT_RUN_FAILED */,
1058
- context
1059
- });
1060
- throw error;
1061
- }
1062
- }
1063
- /**
1064
- * Process agent result and execute tools
1065
- */
1066
- async processAgentResult({
1067
- runAgentResult,
1068
- agent
1069
- }) {
1070
- const { newMessages } = runAgentResult;
1071
- const agentId = agent.agentId;
1072
- let needsFollowUp = false;
1073
- for (const message of newMessages) {
1074
- if (message.role === "assistant") {
1075
- for (const toolCall of message.toolCalls || []) {
1076
- if (newMessages.findIndex(
1077
- (m) => m.role === "tool" && m.toolCallId === toolCall.id
1078
- ) === -1) {
1079
- const tool = this.getTool({
1080
- toolName: toolCall.function.name,
1081
- agentId: agent.agentId
1082
- });
1083
- if (tool) {
1084
- const followUp = await this.executeSpecificTool(
1085
- tool,
1086
- toolCall,
1087
- message,
1088
- agent,
1089
- agentId
1090
- );
1091
- if (followUp) {
1092
- needsFollowUp = true;
1093
- }
1094
- } else {
1095
- const wildcardTool = this.getTool({
1096
- toolName: "*",
1097
- agentId: agent.agentId
1098
- });
1099
- if (wildcardTool) {
1100
- const followUp = await this.executeWildcardTool(
1101
- wildcardTool,
1102
- toolCall,
1103
- message,
1104
- agent,
1105
- agentId
1106
- );
1107
- if (followUp) {
1108
- needsFollowUp = true;
1109
- }
1110
- }
1111
- }
1112
- }
1113
- }
1114
- }
1115
- }
1116
- if (needsFollowUp) {
1117
- return await this.runAgent({ agent });
1118
- }
1119
- void this.core.suggestionEngine.reloadSuggestions(agentId);
1120
- return runAgentResult;
1121
- }
1122
- /**
1123
- * Execute a specific tool
1124
- */
1125
- async executeSpecificTool(tool, toolCall, message, agent, agentId) {
1126
- if (tool?.agentId && tool.agentId !== agent.agentId) {
1127
- return false;
1128
- }
1129
- let toolCallResult = "";
1130
- let errorMessage;
1131
- let isArgumentError = false;
1132
- if (tool?.handler) {
1133
- let parsedArgs;
1134
- try {
1135
- parsedArgs = JSON.parse(toolCall.function.arguments);
1136
- } catch (error) {
1137
- const parseError = error instanceof Error ? error : new Error(String(error));
1138
- errorMessage = parseError.message;
1139
- isArgumentError = true;
1140
- await this.core.emitError({
1141
- error: parseError,
1142
- code: "tool_argument_parse_failed" /* TOOL_ARGUMENT_PARSE_FAILED */,
1143
- context: {
1144
- agentId,
1145
- toolCallId: toolCall.id,
1146
- toolName: toolCall.function.name,
1147
- rawArguments: toolCall.function.arguments,
1148
- toolType: "specific",
1149
- messageId: message.id
1150
- }
1151
- });
1152
- }
1153
- await this.core.notifySubscribers(
1154
- (subscriber) => subscriber.onToolExecutionStart?.({
1155
- copilotkit: this.core,
1156
- toolCallId: toolCall.id,
1157
- agentId,
1158
- toolName: toolCall.function.name,
1159
- args: parsedArgs
1160
- }),
1161
- "Subscriber onToolExecutionStart error:"
1162
- );
1163
- if (!errorMessage) {
1164
- try {
1165
- const result = await tool.handler(parsedArgs, {
1166
- toolCall,
1167
- agent
1168
- });
1169
- if (result === void 0 || result === null) {
1170
- toolCallResult = "";
1171
- } else if (typeof result === "string") {
1172
- toolCallResult = result;
1173
- } else {
1174
- toolCallResult = JSON.stringify(result);
1175
- }
1176
- } catch (error) {
1177
- const handlerError = error instanceof Error ? error : new Error(String(error));
1178
- errorMessage = handlerError.message;
1179
- await this.core.emitError(
1180
- {
1181
- error: handlerError,
1182
- code: "tool_handler_failed" /* TOOL_HANDLER_FAILED */,
1183
- context: {
1184
- agentId,
1185
- toolCallId: toolCall.id,
1186
- toolName: toolCall.function.name,
1187
- parsedArgs,
1188
- toolType: "specific",
1189
- messageId: message.id
1190
- }
1191
- }
1192
- );
1193
- }
1194
- }
1195
- if (errorMessage) {
1196
- toolCallResult = `Error: ${errorMessage}`;
1197
- }
1198
- await this.core.notifySubscribers(
1199
- (subscriber) => subscriber.onToolExecutionEnd?.({
1200
- copilotkit: this.core,
1201
- toolCallId: toolCall.id,
1202
- agentId,
1203
- toolName: toolCall.function.name,
1204
- result: errorMessage ? "" : toolCallResult,
1205
- error: errorMessage
1206
- }),
1207
- "Subscriber onToolExecutionEnd error:"
1208
- );
1209
- if (isArgumentError) {
1210
- throw new Error(errorMessage ?? "Tool execution failed");
1211
- }
1212
- }
1213
- if (!errorMessage || !isArgumentError) {
1214
- const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
1215
- if (messageIndex === -1) {
1216
- return false;
1217
- }
1218
- const toolMessage = {
1219
- id: randomUUID3(),
1220
- role: "tool",
1221
- toolCallId: toolCall.id,
1222
- content: toolCallResult
1223
- };
1224
- agent.messages.splice(messageIndex + 1, 0, toolMessage);
1225
- if (!errorMessage && tool?.followUp !== false) {
1226
- return true;
1227
- }
1228
- }
1229
- return false;
1230
- }
1231
- /**
1232
- * Execute a wildcard tool
1233
- */
1234
- async executeWildcardTool(wildcardTool, toolCall, message, agent, agentId) {
1235
- if (wildcardTool?.agentId && wildcardTool.agentId !== agent.agentId) {
1236
- return false;
1237
- }
1238
- let toolCallResult = "";
1239
- let errorMessage;
1240
- let isArgumentError = false;
1241
- if (wildcardTool?.handler) {
1242
- let parsedArgs;
1243
- try {
1244
- parsedArgs = JSON.parse(toolCall.function.arguments);
1245
- } catch (error) {
1246
- const parseError = error instanceof Error ? error : new Error(String(error));
1247
- errorMessage = parseError.message;
1248
- isArgumentError = true;
1249
- await this.core.emitError({
1250
- error: parseError,
1251
- code: "tool_argument_parse_failed" /* TOOL_ARGUMENT_PARSE_FAILED */,
1252
- context: {
1253
- agentId,
1254
- toolCallId: toolCall.id,
1255
- toolName: toolCall.function.name,
1256
- rawArguments: toolCall.function.arguments,
1257
- toolType: "wildcard",
1258
- messageId: message.id
1259
- }
1260
- });
1261
- }
1262
- const wildcardArgs = {
1263
- toolName: toolCall.function.name,
1264
- args: parsedArgs
1265
- };
1266
- await this.core.notifySubscribers(
1267
- (subscriber) => subscriber.onToolExecutionStart?.({
1268
- copilotkit: this.core,
1269
- toolCallId: toolCall.id,
1270
- agentId,
1271
- toolName: toolCall.function.name,
1272
- args: wildcardArgs
1273
- }),
1274
- "Subscriber onToolExecutionStart error:"
1275
- );
1276
- if (!errorMessage) {
1277
- try {
1278
- const result = await wildcardTool.handler(wildcardArgs, {
1279
- toolCall,
1280
- agent
1281
- });
1282
- if (result === void 0 || result === null) {
1283
- toolCallResult = "";
1284
- } else if (typeof result === "string") {
1285
- toolCallResult = result;
1286
- } else {
1287
- toolCallResult = JSON.stringify(result);
1288
- }
1289
- } catch (error) {
1290
- const handlerError = error instanceof Error ? error : new Error(String(error));
1291
- errorMessage = handlerError.message;
1292
- await this.core.emitError(
1293
- {
1294
- error: handlerError,
1295
- code: "tool_handler_failed" /* TOOL_HANDLER_FAILED */,
1296
- context: {
1297
- agentId,
1298
- toolCallId: toolCall.id,
1299
- toolName: toolCall.function.name,
1300
- parsedArgs: wildcardArgs,
1301
- toolType: "wildcard",
1302
- messageId: message.id
1303
- }
1304
- }
1305
- );
1306
- }
1307
- }
1308
- if (errorMessage) {
1309
- toolCallResult = `Error: ${errorMessage}`;
1310
- }
1311
- await this.core.notifySubscribers(
1312
- (subscriber) => subscriber.onToolExecutionEnd?.({
1313
- copilotkit: this.core,
1314
- toolCallId: toolCall.id,
1315
- agentId,
1316
- toolName: toolCall.function.name,
1317
- result: errorMessage ? "" : toolCallResult,
1318
- error: errorMessage
1319
- }),
1320
- "Subscriber onToolExecutionEnd error:"
1321
- );
1322
- if (isArgumentError) {
1323
- throw new Error(errorMessage ?? "Tool execution failed");
1324
- }
1325
- }
1326
- if (!errorMessage || !isArgumentError) {
1327
- const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
1328
- if (messageIndex === -1) {
1329
- return false;
1330
- }
1331
- const toolMessage = {
1332
- id: randomUUID3(),
1333
- role: "tool",
1334
- toolCallId: toolCall.id,
1335
- content: toolCallResult
1336
- };
1337
- agent.messages.splice(messageIndex + 1, 0, toolMessage);
1338
- if (!errorMessage && wildcardTool?.followUp !== false) {
1339
- return true;
1340
- }
1341
- }
1342
- return false;
1343
- }
1344
- /**
1345
- * Build frontend tools for an agent
1346
- */
1347
- buildFrontendTools(agentId) {
1348
- return this._tools.filter((tool) => !tool.agentId || tool.agentId === agentId).map((tool) => ({
1349
- name: tool.name,
1350
- description: tool.description ?? "",
1351
- parameters: createToolSchema(tool)
1352
- }));
1353
- }
1354
- /**
1355
- * Create an agent error subscriber
1356
- */
1357
- createAgentErrorSubscriber(agent) {
1358
- const emitAgentError = async (error, code, extraContext = {}) => {
1359
- const context = { ...extraContext };
1360
- if (agent.agentId) {
1361
- context.agentId = agent.agentId;
1362
- }
1363
- await this.core.emitError({
1364
- error,
1365
- code,
1366
- context
1367
- });
1368
- };
1369
- return {
1370
- onRunFailed: async ({ error }) => {
1371
- await emitAgentError(
1372
- error,
1373
- "agent_run_failed_event" /* AGENT_RUN_FAILED_EVENT */,
1374
- {
1375
- source: "onRunFailed"
1376
- }
1377
- );
1378
- },
1379
- onRunErrorEvent: async ({ event }) => {
1380
- const eventError = event?.rawEvent instanceof Error ? event.rawEvent : event?.rawEvent?.error instanceof Error ? event.rawEvent.error : void 0;
1381
- const errorMessage = typeof event?.rawEvent?.error === "string" ? event.rawEvent.error : event?.message ?? "Agent run error";
1382
- const rawError = eventError ?? new Error(errorMessage);
1383
- if (event?.code && !rawError.code) {
1384
- rawError.code = event.code;
1385
- }
1386
- await emitAgentError(
1387
- rawError,
1388
- "agent_run_error_event" /* AGENT_RUN_ERROR_EVENT */,
1389
- {
1390
- source: "onRunErrorEvent",
1391
- event,
1392
- runtimeErrorCode: event?.code
1393
- }
1394
- );
1395
- }
1396
- };
1397
- }
738
+ _tools = [];
739
+ constructor(core) {
740
+ this.core = core;
741
+ }
742
+ /**
743
+ * Get all tools as a readonly array
744
+ */
745
+ get tools() {
746
+ return this._tools;
747
+ }
748
+ /**
749
+ * Initialize with tools
750
+ */
751
+ initialize(tools) {
752
+ this._tools = tools;
753
+ }
754
+ /**
755
+ * Add a tool to the registry
756
+ */
757
+ addTool(tool) {
758
+ if (this._tools.findIndex((t) => t.name === tool.name && t.agentId === tool.agentId) !== -1) {
759
+ logger.warn(`Tool already exists: '${tool.name}' for agent '${tool.agentId || "global"}', skipping.`);
760
+ return;
761
+ }
762
+ this._tools.push(tool);
763
+ }
764
+ /**
765
+ * Remove a tool by name and optionally by agentId
766
+ */
767
+ removeTool(id, agentId) {
768
+ this._tools = this._tools.filter((tool) => {
769
+ if (agentId !== void 0) return !(tool.name === id && tool.agentId === agentId);
770
+ return !(tool.name === id && !tool.agentId);
771
+ });
772
+ }
773
+ /**
774
+ * Get a tool by name and optionally by agentId.
775
+ * If agentId is provided, it will first look for an agent-specific tool,
776
+ * then fall back to a global tool with the same name.
777
+ */
778
+ getTool(params) {
779
+ const { toolName, agentId } = params;
780
+ if (agentId) {
781
+ const agentTool = this._tools.find((tool) => tool.name === toolName && tool.agentId === agentId);
782
+ if (agentTool) return agentTool;
783
+ }
784
+ return this._tools.find((tool) => tool.name === toolName && !tool.agentId);
785
+ }
786
+ /**
787
+ * Set all tools at once. Replaces existing tools.
788
+ */
789
+ setTools(tools) {
790
+ this._tools = [...tools];
791
+ }
792
+ /**
793
+ * Connect an agent (establish initial connection)
794
+ */
795
+ async connectAgent({ agent }) {
796
+ try {
797
+ await agent.detachActiveRun();
798
+ agent.setMessages([]);
799
+ agent.setState({});
800
+ if (agent instanceof HttpAgent) agent.headers = { ...this.core.headers };
801
+ const runAgentResult = await agent.connectAgent({
802
+ forwardedProps: this.core.properties,
803
+ tools: this.buildFrontendTools(agent.agentId)
804
+ }, this.createAgentErrorSubscriber(agent));
805
+ return this.processAgentResult({
806
+ runAgentResult,
807
+ agent
808
+ });
809
+ } catch (error) {
810
+ const connectError = error instanceof Error ? error : new Error(String(error));
811
+ const context = {};
812
+ if (agent.agentId) context.agentId = agent.agentId;
813
+ await this.core.emitError({
814
+ error: connectError,
815
+ code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
816
+ context
817
+ });
818
+ throw error;
819
+ }
820
+ }
821
+ /**
822
+ * Run an agent
823
+ */
824
+ async runAgent({ agent }) {
825
+ if (agent.agentId) this.core.suggestionEngine.clearSuggestions(agent.agentId);
826
+ if (agent instanceof HttpAgent) agent.headers = { ...this.core.headers };
827
+ try {
828
+ const runAgentResult = await agent.runAgent({
829
+ forwardedProps: this.core.properties,
830
+ tools: this.buildFrontendTools(agent.agentId),
831
+ context: Object.values(this.core.context)
832
+ }, this.createAgentErrorSubscriber(agent));
833
+ return this.processAgentResult({
834
+ runAgentResult,
835
+ agent
836
+ });
837
+ } catch (error) {
838
+ const runError = error instanceof Error ? error : new Error(String(error));
839
+ const context = {};
840
+ if (agent.agentId) context.agentId = agent.agentId;
841
+ await this.core.emitError({
842
+ error: runError,
843
+ code: CopilotKitCoreErrorCode.AGENT_RUN_FAILED,
844
+ context
845
+ });
846
+ throw error;
847
+ }
848
+ }
849
+ /**
850
+ * Process agent result and execute tools
851
+ */
852
+ async processAgentResult({ runAgentResult, agent }) {
853
+ const { newMessages } = runAgentResult;
854
+ const agentId = agent.agentId;
855
+ let needsFollowUp = false;
856
+ for (const message of newMessages) if (message.role === "assistant") {
857
+ for (const toolCall of message.toolCalls || []) if (newMessages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id) === -1) {
858
+ const tool = this.getTool({
859
+ toolName: toolCall.function.name,
860
+ agentId: agent.agentId
861
+ });
862
+ if (tool) {
863
+ if (await this.executeSpecificTool(tool, toolCall, message, agent, agentId)) needsFollowUp = true;
864
+ } else {
865
+ const wildcardTool = this.getTool({
866
+ toolName: "*",
867
+ agentId: agent.agentId
868
+ });
869
+ if (wildcardTool) {
870
+ if (await this.executeWildcardTool(wildcardTool, toolCall, message, agent, agentId)) needsFollowUp = true;
871
+ }
872
+ }
873
+ }
874
+ }
875
+ if (needsFollowUp) return await this.runAgent({ agent });
876
+ this.core.suggestionEngine.reloadSuggestions(agentId);
877
+ return runAgentResult;
878
+ }
879
+ /**
880
+ * Execute a specific tool
881
+ */
882
+ async executeSpecificTool(tool, toolCall, message, agent, agentId) {
883
+ if (tool?.agentId && tool.agentId !== agent.agentId) return false;
884
+ let toolCallResult = "";
885
+ let errorMessage;
886
+ let isArgumentError = false;
887
+ if (tool?.handler) {
888
+ let parsedArgs;
889
+ try {
890
+ parsedArgs = JSON.parse(toolCall.function.arguments);
891
+ } catch (error) {
892
+ const parseError = error instanceof Error ? error : new Error(String(error));
893
+ errorMessage = parseError.message;
894
+ isArgumentError = true;
895
+ await this.core.emitError({
896
+ error: parseError,
897
+ code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,
898
+ context: {
899
+ agentId,
900
+ toolCallId: toolCall.id,
901
+ toolName: toolCall.function.name,
902
+ rawArguments: toolCall.function.arguments,
903
+ toolType: "specific",
904
+ messageId: message.id
905
+ }
906
+ });
907
+ }
908
+ await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
909
+ copilotkit: this.core,
910
+ toolCallId: toolCall.id,
911
+ agentId,
912
+ toolName: toolCall.function.name,
913
+ args: parsedArgs
914
+ }), "Subscriber onToolExecutionStart error:");
915
+ if (!errorMessage) try {
916
+ const result = await tool.handler(parsedArgs, {
917
+ toolCall,
918
+ agent
919
+ });
920
+ if (result === void 0 || result === null) toolCallResult = "";
921
+ else if (typeof result === "string") toolCallResult = result;
922
+ else toolCallResult = JSON.stringify(result);
923
+ } catch (error) {
924
+ const handlerError = error instanceof Error ? error : new Error(String(error));
925
+ errorMessage = handlerError.message;
926
+ await this.core.emitError({
927
+ error: handlerError,
928
+ code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
929
+ context: {
930
+ agentId,
931
+ toolCallId: toolCall.id,
932
+ toolName: toolCall.function.name,
933
+ parsedArgs,
934
+ toolType: "specific",
935
+ messageId: message.id
936
+ }
937
+ });
938
+ }
939
+ if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
940
+ await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
941
+ copilotkit: this.core,
942
+ toolCallId: toolCall.id,
943
+ agentId,
944
+ toolName: toolCall.function.name,
945
+ result: errorMessage ? "" : toolCallResult,
946
+ error: errorMessage
947
+ }), "Subscriber onToolExecutionEnd error:");
948
+ if (isArgumentError) throw new Error(errorMessage ?? "Tool execution failed");
949
+ }
950
+ if (!errorMessage || !isArgumentError) {
951
+ const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
952
+ if (messageIndex === -1) return false;
953
+ const toolMessage = {
954
+ id: randomUUID(),
955
+ role: "tool",
956
+ toolCallId: toolCall.id,
957
+ content: toolCallResult
958
+ };
959
+ agent.messages.splice(messageIndex + 1, 0, toolMessage);
960
+ if (!errorMessage && tool?.followUp !== false) return true;
961
+ }
962
+ return false;
963
+ }
964
+ /**
965
+ * Execute a wildcard tool
966
+ */
967
+ async executeWildcardTool(wildcardTool, toolCall, message, agent, agentId) {
968
+ if (wildcardTool?.agentId && wildcardTool.agentId !== agent.agentId) return false;
969
+ let toolCallResult = "";
970
+ let errorMessage;
971
+ let isArgumentError = false;
972
+ if (wildcardTool?.handler) {
973
+ let parsedArgs;
974
+ try {
975
+ parsedArgs = JSON.parse(toolCall.function.arguments);
976
+ } catch (error) {
977
+ const parseError = error instanceof Error ? error : new Error(String(error));
978
+ errorMessage = parseError.message;
979
+ isArgumentError = true;
980
+ await this.core.emitError({
981
+ error: parseError,
982
+ code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,
983
+ context: {
984
+ agentId,
985
+ toolCallId: toolCall.id,
986
+ toolName: toolCall.function.name,
987
+ rawArguments: toolCall.function.arguments,
988
+ toolType: "wildcard",
989
+ messageId: message.id
990
+ }
991
+ });
992
+ }
993
+ const wildcardArgs = {
994
+ toolName: toolCall.function.name,
995
+ args: parsedArgs
996
+ };
997
+ await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
998
+ copilotkit: this.core,
999
+ toolCallId: toolCall.id,
1000
+ agentId,
1001
+ toolName: toolCall.function.name,
1002
+ args: wildcardArgs
1003
+ }), "Subscriber onToolExecutionStart error:");
1004
+ if (!errorMessage) try {
1005
+ const result = await wildcardTool.handler(wildcardArgs, {
1006
+ toolCall,
1007
+ agent
1008
+ });
1009
+ if (result === void 0 || result === null) toolCallResult = "";
1010
+ else if (typeof result === "string") toolCallResult = result;
1011
+ else toolCallResult = JSON.stringify(result);
1012
+ } catch (error) {
1013
+ const handlerError = error instanceof Error ? error : new Error(String(error));
1014
+ errorMessage = handlerError.message;
1015
+ await this.core.emitError({
1016
+ error: handlerError,
1017
+ code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
1018
+ context: {
1019
+ agentId,
1020
+ toolCallId: toolCall.id,
1021
+ toolName: toolCall.function.name,
1022
+ parsedArgs: wildcardArgs,
1023
+ toolType: "wildcard",
1024
+ messageId: message.id
1025
+ }
1026
+ });
1027
+ }
1028
+ if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
1029
+ await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
1030
+ copilotkit: this.core,
1031
+ toolCallId: toolCall.id,
1032
+ agentId,
1033
+ toolName: toolCall.function.name,
1034
+ result: errorMessage ? "" : toolCallResult,
1035
+ error: errorMessage
1036
+ }), "Subscriber onToolExecutionEnd error:");
1037
+ if (isArgumentError) throw new Error(errorMessage ?? "Tool execution failed");
1038
+ }
1039
+ if (!errorMessage || !isArgumentError) {
1040
+ const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
1041
+ if (messageIndex === -1) return false;
1042
+ const toolMessage = {
1043
+ id: randomUUID(),
1044
+ role: "tool",
1045
+ toolCallId: toolCall.id,
1046
+ content: toolCallResult
1047
+ };
1048
+ agent.messages.splice(messageIndex + 1, 0, toolMessage);
1049
+ if (!errorMessage && wildcardTool?.followUp !== false) return true;
1050
+ }
1051
+ return false;
1052
+ }
1053
+ /**
1054
+ * Build frontend tools for an agent
1055
+ */
1056
+ buildFrontendTools(agentId) {
1057
+ return this._tools.filter((tool) => tool.available !== false && (!tool.agentId || tool.agentId === agentId)).map((tool) => ({
1058
+ name: tool.name,
1059
+ description: tool.description ?? "",
1060
+ parameters: createToolSchema(tool)
1061
+ }));
1062
+ }
1063
+ /**
1064
+ * Create an agent error subscriber
1065
+ */
1066
+ createAgentErrorSubscriber(agent) {
1067
+ const emitAgentError = async (error, code, extraContext = {}) => {
1068
+ const context = { ...extraContext };
1069
+ if (agent.agentId) context.agentId = agent.agentId;
1070
+ await this.core.emitError({
1071
+ error,
1072
+ code,
1073
+ context
1074
+ });
1075
+ };
1076
+ return {
1077
+ onRunFailed: async ({ error }) => {
1078
+ await emitAgentError(error, CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT, { source: "onRunFailed" });
1079
+ },
1080
+ onRunErrorEvent: async ({ event }) => {
1081
+ const eventError = event?.rawEvent instanceof Error ? event.rawEvent : event?.rawEvent?.error instanceof Error ? event.rawEvent.error : void 0;
1082
+ const errorMessage = typeof event?.rawEvent?.error === "string" ? event.rawEvent.error : event?.message ?? "Agent run error";
1083
+ const rawError = eventError ?? new Error(errorMessage);
1084
+ if (event?.code && !rawError.code) rawError.code = event.code;
1085
+ await emitAgentError(rawError, CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT, {
1086
+ source: "onRunErrorEvent",
1087
+ event,
1088
+ runtimeErrorCode: event?.code
1089
+ });
1090
+ }
1091
+ };
1092
+ }
1398
1093
  };
1399
- var EMPTY_TOOL_SCHEMA = {
1400
- type: "object",
1401
- properties: {}
1094
+ /**
1095
+ * Empty tool schema constant
1096
+ */
1097
+ const EMPTY_TOOL_SCHEMA = {
1098
+ type: "object",
1099
+ properties: {}
1402
1100
  };
1101
+ /**
1102
+ * Create a JSON schema from a tool's parameters
1103
+ */
1403
1104
  function createToolSchema(tool) {
1404
- if (!tool.parameters) {
1405
- return { ...EMPTY_TOOL_SCHEMA };
1406
- }
1407
- const rawSchema = zodToJsonSchema(tool.parameters, {
1408
- $refStrategy: "none"
1409
- });
1410
- if (!rawSchema || typeof rawSchema !== "object") {
1411
- return { ...EMPTY_TOOL_SCHEMA };
1412
- }
1413
- const { $schema, ...schema } = rawSchema;
1414
- if (typeof schema.type !== "string") {
1415
- schema.type = "object";
1416
- }
1417
- if (typeof schema.properties !== "object" || schema.properties === null) {
1418
- schema.properties = {};
1419
- }
1420
- stripAdditionalProperties(schema);
1421
- return schema;
1105
+ if (!tool.parameters) return { ...EMPTY_TOOL_SCHEMA };
1106
+ const rawSchema = zodToJsonSchema(tool.parameters, { $refStrategy: "none" });
1107
+ if (!rawSchema || typeof rawSchema !== "object") return { ...EMPTY_TOOL_SCHEMA };
1108
+ const { $schema, ...schema } = rawSchema;
1109
+ if (typeof schema.type !== "string") schema.type = "object";
1110
+ if (typeof schema.properties !== "object" || schema.properties === null) schema.properties = {};
1111
+ stripAdditionalProperties(schema);
1112
+ return schema;
1422
1113
  }
1423
1114
  function stripAdditionalProperties(schema) {
1424
- if (!schema || typeof schema !== "object") {
1425
- return;
1426
- }
1427
- if (Array.isArray(schema)) {
1428
- schema.forEach(stripAdditionalProperties);
1429
- return;
1430
- }
1431
- const record = schema;
1432
- if (record.additionalProperties !== void 0) {
1433
- delete record.additionalProperties;
1434
- }
1435
- for (const value of Object.values(record)) {
1436
- stripAdditionalProperties(value);
1437
- }
1115
+ if (!schema || typeof schema !== "object") return;
1116
+ if (Array.isArray(schema)) {
1117
+ schema.forEach(stripAdditionalProperties);
1118
+ return;
1119
+ }
1120
+ const record = schema;
1121
+ if (record.additionalProperties !== void 0) delete record.additionalProperties;
1122
+ for (const value of Object.values(record)) stripAdditionalProperties(value);
1438
1123
  }
1439
1124
 
1440
- // src/core/state-manager.ts
1125
+ //#endregion
1126
+ //#region src/core/state-manager.ts
1127
+ /**
1128
+ * Manages state and message tracking by run for CopilotKitCore.
1129
+ * Tracks agent state snapshots and message-to-run associations.
1130
+ */
1441
1131
  var StateManager = class {
1442
- constructor(core) {
1443
- this.core = core;
1444
- }
1445
- // State tracking: agentId -> threadId -> runId -> state
1446
- stateByRun = /* @__PURE__ */ new Map();
1447
- // Message tracking: agentId -> threadId -> messageId -> runId
1448
- messageToRun = /* @__PURE__ */ new Map();
1449
- // Agent subscriptions for cleanup
1450
- agentSubscriptions = /* @__PURE__ */ new Map();
1451
- /**
1452
- * Initialize state tracking for an agent
1453
- */
1454
- initialize() {
1455
- }
1456
- /**
1457
- * Subscribe to an agent's events to track state and messages
1458
- */
1459
- subscribeToAgent(agent) {
1460
- if (!agent.agentId) {
1461
- return;
1462
- }
1463
- const agentId = agent.agentId;
1464
- this.unsubscribeFromAgent(agentId);
1465
- const { unsubscribe } = agent.subscribe({
1466
- onRunStartedEvent: ({ event, state }) => {
1467
- this.handleRunStarted(agent, event, state);
1468
- },
1469
- onRunFinishedEvent: ({ event, state }) => {
1470
- this.handleRunFinished(agent, event, state);
1471
- },
1472
- onStateSnapshotEvent: ({ event, input, state }) => {
1473
- this.handleStateSnapshot(agent, event, input, state);
1474
- },
1475
- onStateDeltaEvent: ({ event, input, state }) => {
1476
- this.handleStateDelta(agent, event, input, state);
1477
- },
1478
- onMessagesSnapshotEvent: ({ event, input, messages }) => {
1479
- this.handleMessagesSnapshot(agent, event, input, messages);
1480
- },
1481
- onNewMessage: ({ message, input }) => {
1482
- this.handleNewMessage(agent, message, input);
1483
- }
1484
- });
1485
- this.agentSubscriptions.set(agentId, unsubscribe);
1486
- }
1487
- /**
1488
- * Unsubscribe from an agent's events
1489
- */
1490
- unsubscribeFromAgent(agentId) {
1491
- const unsubscribe = this.agentSubscriptions.get(agentId);
1492
- if (unsubscribe) {
1493
- unsubscribe();
1494
- this.agentSubscriptions.delete(agentId);
1495
- }
1496
- }
1497
- /**
1498
- * Get state for a specific run
1499
- * Returns a deep copy to prevent external mutations
1500
- */
1501
- getStateByRun(agentId, threadId, runId) {
1502
- const state = this.stateByRun.get(agentId)?.get(threadId)?.get(runId);
1503
- if (!state) return void 0;
1504
- return JSON.parse(JSON.stringify(state));
1505
- }
1506
- /**
1507
- * Get runId associated with a message
1508
- */
1509
- getRunIdForMessage(agentId, threadId, messageId) {
1510
- return this.messageToRun.get(agentId)?.get(threadId)?.get(messageId);
1511
- }
1512
- /**
1513
- * Get all states for an agent's thread
1514
- */
1515
- getStatesForThread(agentId, threadId) {
1516
- return this.stateByRun.get(agentId)?.get(threadId) ?? /* @__PURE__ */ new Map();
1517
- }
1518
- /**
1519
- * Get all run IDs for an agent's thread
1520
- */
1521
- getRunIdsForThread(agentId, threadId) {
1522
- const threadStates = this.stateByRun.get(agentId)?.get(threadId);
1523
- return threadStates ? Array.from(threadStates.keys()) : [];
1524
- }
1525
- /**
1526
- * Handle run started event
1527
- */
1528
- handleRunStarted(agent, event, state) {
1529
- if (!agent.agentId) return;
1530
- const { threadId, runId } = event;
1531
- this.saveState(agent.agentId, threadId, runId, state);
1532
- }
1533
- /**
1534
- * Handle run finished event
1535
- */
1536
- handleRunFinished(agent, event, state) {
1537
- if (!agent.agentId) return;
1538
- const { threadId, runId } = event;
1539
- this.saveState(agent.agentId, threadId, runId, state);
1540
- }
1541
- /**
1542
- * Handle state snapshot event
1543
- */
1544
- handleStateSnapshot(agent, event, input, state) {
1545
- if (!agent.agentId) return;
1546
- const { threadId, runId } = input;
1547
- const mergedState = { ...state, ...event.snapshot };
1548
- this.saveState(agent.agentId, threadId, runId, mergedState);
1549
- }
1550
- /**
1551
- * Handle state delta event
1552
- */
1553
- handleStateDelta(agent, event, input, state) {
1554
- if (!agent.agentId) return;
1555
- const { threadId, runId } = input;
1556
- this.saveState(agent.agentId, threadId, runId, state);
1557
- }
1558
- /**
1559
- * Handle messages snapshot event
1560
- */
1561
- handleMessagesSnapshot(agent, event, input, messages) {
1562
- if (!agent.agentId) return;
1563
- const { threadId, runId } = input;
1564
- for (const message of event.messages) {
1565
- this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
1566
- }
1567
- }
1568
- /**
1569
- * Handle new message event
1570
- */
1571
- handleNewMessage(agent, message, input) {
1572
- if (!agent.agentId || !input) return;
1573
- const { threadId, runId } = input;
1574
- this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
1575
- }
1576
- /**
1577
- * Save state for a specific run
1578
- */
1579
- saveState(agentId, threadId, runId, state) {
1580
- if (!this.stateByRun.has(agentId)) {
1581
- this.stateByRun.set(agentId, /* @__PURE__ */ new Map());
1582
- }
1583
- const agentStates = this.stateByRun.get(agentId);
1584
- if (!agentStates.has(threadId)) {
1585
- agentStates.set(threadId, /* @__PURE__ */ new Map());
1586
- }
1587
- const threadStates = agentStates.get(threadId);
1588
- threadStates.set(runId, JSON.parse(JSON.stringify(state)));
1589
- }
1590
- /**
1591
- * Associate a message with a run
1592
- */
1593
- associateMessageWithRun(agentId, threadId, messageId, runId) {
1594
- if (!this.messageToRun.has(agentId)) {
1595
- this.messageToRun.set(agentId, /* @__PURE__ */ new Map());
1596
- }
1597
- const agentMessages = this.messageToRun.get(agentId);
1598
- if (!agentMessages.has(threadId)) {
1599
- agentMessages.set(threadId, /* @__PURE__ */ new Map());
1600
- }
1601
- const threadMessages = agentMessages.get(threadId);
1602
- threadMessages.set(messageId, runId);
1603
- }
1604
- /**
1605
- * Clear all state for an agent
1606
- */
1607
- clearAgentState(agentId) {
1608
- this.stateByRun.delete(agentId);
1609
- this.messageToRun.delete(agentId);
1610
- }
1611
- /**
1612
- * Clear all state for a thread
1613
- */
1614
- clearThreadState(agentId, threadId) {
1615
- this.stateByRun.get(agentId)?.delete(threadId);
1616
- this.messageToRun.get(agentId)?.delete(threadId);
1617
- }
1132
+ stateByRun = /* @__PURE__ */ new Map();
1133
+ messageToRun = /* @__PURE__ */ new Map();
1134
+ agentSubscriptions = /* @__PURE__ */ new Map();
1135
+ constructor(core) {
1136
+ this.core = core;
1137
+ }
1138
+ /**
1139
+ * Initialize state tracking for an agent
1140
+ */
1141
+ initialize() {}
1142
+ /**
1143
+ * Subscribe to an agent's events to track state and messages
1144
+ */
1145
+ subscribeToAgent(agent) {
1146
+ if (!agent.agentId) return;
1147
+ const agentId = agent.agentId;
1148
+ this.unsubscribeFromAgent(agentId);
1149
+ const { unsubscribe } = agent.subscribe({
1150
+ onRunStartedEvent: ({ event, state }) => {
1151
+ this.handleRunStarted(agent, event, state);
1152
+ },
1153
+ onRunFinishedEvent: ({ event, state }) => {
1154
+ this.handleRunFinished(agent, event, state);
1155
+ },
1156
+ onStateSnapshotEvent: ({ event, input, state }) => {
1157
+ this.handleStateSnapshot(agent, event, input, state);
1158
+ },
1159
+ onStateDeltaEvent: ({ event, input, state }) => {
1160
+ this.handleStateDelta(agent, event, input, state);
1161
+ },
1162
+ onMessagesSnapshotEvent: ({ event, input, messages }) => {
1163
+ this.handleMessagesSnapshot(agent, event, input, messages);
1164
+ },
1165
+ onNewMessage: ({ message, input }) => {
1166
+ this.handleNewMessage(agent, message, input);
1167
+ }
1168
+ });
1169
+ this.agentSubscriptions.set(agentId, unsubscribe);
1170
+ }
1171
+ /**
1172
+ * Unsubscribe from an agent's events
1173
+ */
1174
+ unsubscribeFromAgent(agentId) {
1175
+ const unsubscribe = this.agentSubscriptions.get(agentId);
1176
+ if (unsubscribe) {
1177
+ unsubscribe();
1178
+ this.agentSubscriptions.delete(agentId);
1179
+ }
1180
+ }
1181
+ /**
1182
+ * Get state for a specific run
1183
+ * Returns a deep copy to prevent external mutations
1184
+ */
1185
+ getStateByRun(agentId, threadId, runId) {
1186
+ const state = this.stateByRun.get(agentId)?.get(threadId)?.get(runId);
1187
+ if (!state) return void 0;
1188
+ return JSON.parse(JSON.stringify(state));
1189
+ }
1190
+ /**
1191
+ * Get runId associated with a message
1192
+ */
1193
+ getRunIdForMessage(agentId, threadId, messageId) {
1194
+ return this.messageToRun.get(agentId)?.get(threadId)?.get(messageId);
1195
+ }
1196
+ /**
1197
+ * Get all states for an agent's thread
1198
+ */
1199
+ getStatesForThread(agentId, threadId) {
1200
+ return this.stateByRun.get(agentId)?.get(threadId) ?? /* @__PURE__ */ new Map();
1201
+ }
1202
+ /**
1203
+ * Get all run IDs for an agent's thread
1204
+ */
1205
+ getRunIdsForThread(agentId, threadId) {
1206
+ const threadStates = this.stateByRun.get(agentId)?.get(threadId);
1207
+ return threadStates ? Array.from(threadStates.keys()) : [];
1208
+ }
1209
+ /**
1210
+ * Handle run started event
1211
+ */
1212
+ handleRunStarted(agent, event, state) {
1213
+ if (!agent.agentId) return;
1214
+ const { threadId, runId } = event;
1215
+ this.saveState(agent.agentId, threadId, runId, state);
1216
+ }
1217
+ /**
1218
+ * Handle run finished event
1219
+ */
1220
+ handleRunFinished(agent, event, state) {
1221
+ if (!agent.agentId) return;
1222
+ const { threadId, runId } = event;
1223
+ this.saveState(agent.agentId, threadId, runId, state);
1224
+ }
1225
+ /**
1226
+ * Handle state snapshot event
1227
+ */
1228
+ handleStateSnapshot(agent, event, input, state) {
1229
+ if (!agent.agentId) return;
1230
+ const { threadId, runId } = input;
1231
+ const mergedState = {
1232
+ ...state,
1233
+ ...event.snapshot
1234
+ };
1235
+ this.saveState(agent.agentId, threadId, runId, mergedState);
1236
+ }
1237
+ /**
1238
+ * Handle state delta event
1239
+ */
1240
+ handleStateDelta(agent, event, input, state) {
1241
+ if (!agent.agentId) return;
1242
+ const { threadId, runId } = input;
1243
+ this.saveState(agent.agentId, threadId, runId, state);
1244
+ }
1245
+ /**
1246
+ * Handle messages snapshot event
1247
+ */
1248
+ handleMessagesSnapshot(agent, event, input, messages) {
1249
+ if (!agent.agentId) return;
1250
+ const { threadId, runId } = input;
1251
+ for (const message of event.messages) this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
1252
+ }
1253
+ /**
1254
+ * Handle new message event
1255
+ */
1256
+ handleNewMessage(agent, message, input) {
1257
+ if (!agent.agentId || !input) return;
1258
+ const { threadId, runId } = input;
1259
+ this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
1260
+ }
1261
+ /**
1262
+ * Save state for a specific run
1263
+ */
1264
+ saveState(agentId, threadId, runId, state) {
1265
+ if (!this.stateByRun.has(agentId)) this.stateByRun.set(agentId, /* @__PURE__ */ new Map());
1266
+ const agentStates = this.stateByRun.get(agentId);
1267
+ if (!agentStates.has(threadId)) agentStates.set(threadId, /* @__PURE__ */ new Map());
1268
+ agentStates.get(threadId).set(runId, JSON.parse(JSON.stringify(state)));
1269
+ }
1270
+ /**
1271
+ * Associate a message with a run
1272
+ */
1273
+ associateMessageWithRun(agentId, threadId, messageId, runId) {
1274
+ if (!this.messageToRun.has(agentId)) this.messageToRun.set(agentId, /* @__PURE__ */ new Map());
1275
+ const agentMessages = this.messageToRun.get(agentId);
1276
+ if (!agentMessages.has(threadId)) agentMessages.set(threadId, /* @__PURE__ */ new Map());
1277
+ agentMessages.get(threadId).set(messageId, runId);
1278
+ }
1279
+ /**
1280
+ * Clear all state for an agent
1281
+ */
1282
+ clearAgentState(agentId) {
1283
+ this.stateByRun.delete(agentId);
1284
+ this.messageToRun.delete(agentId);
1285
+ }
1286
+ /**
1287
+ * Clear all state for a thread
1288
+ */
1289
+ clearThreadState(agentId, threadId) {
1290
+ this.stateByRun.get(agentId)?.delete(threadId);
1291
+ this.messageToRun.get(agentId)?.delete(threadId);
1292
+ }
1618
1293
  };
1619
1294
 
1620
- // src/core/core.ts
1621
- var CopilotKitCoreErrorCode = /* @__PURE__ */ ((CopilotKitCoreErrorCode2) => {
1622
- CopilotKitCoreErrorCode2["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
1623
- CopilotKitCoreErrorCode2["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
1624
- CopilotKitCoreErrorCode2["AGENT_RUN_FAILED"] = "agent_run_failed";
1625
- CopilotKitCoreErrorCode2["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
1626
- CopilotKitCoreErrorCode2["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
1627
- CopilotKitCoreErrorCode2["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
1628
- CopilotKitCoreErrorCode2["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
1629
- CopilotKitCoreErrorCode2["TRANSCRIPTION_FAILED"] = "transcription_failed";
1630
- CopilotKitCoreErrorCode2["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
1631
- CopilotKitCoreErrorCode2["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
1632
- CopilotKitCoreErrorCode2["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
1633
- CopilotKitCoreErrorCode2["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
1634
- CopilotKitCoreErrorCode2["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
1635
- return CopilotKitCoreErrorCode2;
1636
- })(CopilotKitCoreErrorCode || {});
1637
- var CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ ((CopilotKitCoreRuntimeConnectionStatus2) => {
1638
- CopilotKitCoreRuntimeConnectionStatus2["Disconnected"] = "disconnected";
1639
- CopilotKitCoreRuntimeConnectionStatus2["Connected"] = "connected";
1640
- CopilotKitCoreRuntimeConnectionStatus2["Connecting"] = "connecting";
1641
- CopilotKitCoreRuntimeConnectionStatus2["Error"] = "error";
1642
- return CopilotKitCoreRuntimeConnectionStatus2;
1643
- })(CopilotKitCoreRuntimeConnectionStatus || {});
1295
+ //#endregion
1296
+ //#region src/core/core.ts
1297
+ let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
1298
+ CopilotKitCoreErrorCode["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
1299
+ CopilotKitCoreErrorCode["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
1300
+ CopilotKitCoreErrorCode["AGENT_RUN_FAILED"] = "agent_run_failed";
1301
+ CopilotKitCoreErrorCode["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
1302
+ CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
1303
+ CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
1304
+ CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
1305
+ CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
1306
+ CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
1307
+ CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
1308
+ CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
1309
+ CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
1310
+ CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
1311
+ return CopilotKitCoreErrorCode;
1312
+ }({});
1313
+ let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
1314
+ CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
1315
+ CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
1316
+ CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
1317
+ CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
1318
+ return CopilotKitCoreRuntimeConnectionStatus;
1319
+ }({});
1644
1320
  var CopilotKitCore = class {
1645
- _headers;
1646
- _credentials;
1647
- _properties;
1648
- subscribers = /* @__PURE__ */ new Set();
1649
- // Delegate classes
1650
- agentRegistry;
1651
- contextStore;
1652
- suggestionEngine;
1653
- runHandler;
1654
- stateManager;
1655
- constructor({
1656
- runtimeUrl,
1657
- runtimeTransport = "rest",
1658
- headers = {},
1659
- credentials,
1660
- properties = {},
1661
- agents__unsafe_dev_only = {},
1662
- tools = [],
1663
- suggestionsConfig = []
1664
- }) {
1665
- this._headers = headers;
1666
- this._credentials = credentials;
1667
- this._properties = properties;
1668
- this.agentRegistry = new AgentRegistry(this);
1669
- this.contextStore = new ContextStore(this);
1670
- this.suggestionEngine = new SuggestionEngine(this);
1671
- this.runHandler = new RunHandler(this);
1672
- this.stateManager = new StateManager(this);
1673
- this.agentRegistry.initialize(agents__unsafe_dev_only);
1674
- this.runHandler.initialize(tools);
1675
- this.suggestionEngine.initialize(suggestionsConfig);
1676
- this.stateManager.initialize();
1677
- this.agentRegistry.setRuntimeTransport(runtimeTransport);
1678
- this.agentRegistry.setRuntimeUrl(runtimeUrl);
1679
- this.subscribe({
1680
- onAgentsChanged: ({ agents }) => {
1681
- Object.values(agents).forEach((agent) => {
1682
- if (agent.agentId) {
1683
- this.stateManager.subscribeToAgent(agent);
1684
- }
1685
- });
1686
- }
1687
- });
1688
- }
1689
- /**
1690
- * Internal method used by delegate classes and subclasses to notify subscribers
1691
- */
1692
- async notifySubscribers(handler, errorMessage) {
1693
- await Promise.all(
1694
- Array.from(this.subscribers).map(async (subscriber) => {
1695
- try {
1696
- await handler(subscriber);
1697
- } catch (error) {
1698
- console.error(errorMessage, error);
1699
- }
1700
- })
1701
- );
1702
- }
1703
- /**
1704
- * Internal method used by delegate classes to emit errors
1705
- */
1706
- async emitError({
1707
- error,
1708
- code,
1709
- context = {}
1710
- }) {
1711
- await this.notifySubscribers(
1712
- (subscriber) => subscriber.onError?.({
1713
- copilotkit: this,
1714
- error,
1715
- code,
1716
- context
1717
- }),
1718
- "Subscriber onError error:"
1719
- );
1720
- }
1721
- /**
1722
- * Snapshot accessors
1723
- */
1724
- get context() {
1725
- return this.contextStore.context;
1726
- }
1727
- get agents() {
1728
- return this.agentRegistry.agents;
1729
- }
1730
- get tools() {
1731
- return this.runHandler.tools;
1732
- }
1733
- get runtimeUrl() {
1734
- return this.agentRegistry.runtimeUrl;
1735
- }
1736
- setRuntimeUrl(runtimeUrl) {
1737
- this.agentRegistry.setRuntimeUrl(runtimeUrl);
1738
- }
1739
- get runtimeTransport() {
1740
- return this.agentRegistry.runtimeTransport;
1741
- }
1742
- setRuntimeTransport(runtimeTransport) {
1743
- this.agentRegistry.setRuntimeTransport(runtimeTransport);
1744
- }
1745
- get runtimeVersion() {
1746
- return this.agentRegistry.runtimeVersion;
1747
- }
1748
- get headers() {
1749
- return this._headers;
1750
- }
1751
- get credentials() {
1752
- return this._credentials;
1753
- }
1754
- get properties() {
1755
- return this._properties;
1756
- }
1757
- get runtimeConnectionStatus() {
1758
- return this.agentRegistry.runtimeConnectionStatus;
1759
- }
1760
- get audioFileTranscriptionEnabled() {
1761
- return this.agentRegistry.audioFileTranscriptionEnabled;
1762
- }
1763
- /**
1764
- * Configuration updates
1765
- */
1766
- setHeaders(headers) {
1767
- this._headers = headers;
1768
- this.agentRegistry.applyHeadersToAgents(
1769
- this.agentRegistry.agents
1770
- );
1771
- void this.notifySubscribers(
1772
- (subscriber) => subscriber.onHeadersChanged?.({
1773
- copilotkit: this,
1774
- headers: this.headers
1775
- }),
1776
- "Subscriber onHeadersChanged error:"
1777
- );
1778
- }
1779
- setCredentials(credentials) {
1780
- this._credentials = credentials;
1781
- this.agentRegistry.applyCredentialsToAgents(
1782
- this.agentRegistry.agents
1783
- );
1784
- }
1785
- setProperties(properties) {
1786
- this._properties = properties;
1787
- void this.notifySubscribers(
1788
- (subscriber) => subscriber.onPropertiesChanged?.({
1789
- copilotkit: this,
1790
- properties: this.properties
1791
- }),
1792
- "Subscriber onPropertiesChanged error:"
1793
- );
1794
- }
1795
- /**
1796
- * Agent management (delegated to AgentRegistry)
1797
- */
1798
- setAgents__unsafe_dev_only(agents) {
1799
- this.agentRegistry.setAgents__unsafe_dev_only(agents);
1800
- }
1801
- addAgent__unsafe_dev_only(params) {
1802
- this.agentRegistry.addAgent__unsafe_dev_only(params);
1803
- }
1804
- removeAgent__unsafe_dev_only(id) {
1805
- this.agentRegistry.removeAgent__unsafe_dev_only(id);
1806
- }
1807
- getAgent(id) {
1808
- return this.agentRegistry.getAgent(id);
1809
- }
1810
- /**
1811
- * Context management (delegated to ContextStore)
1812
- */
1813
- addContext(context) {
1814
- return this.contextStore.addContext(context);
1815
- }
1816
- removeContext(id) {
1817
- this.contextStore.removeContext(id);
1818
- }
1819
- /**
1820
- * Suggestions management (delegated to SuggestionEngine)
1821
- */
1822
- addSuggestionsConfig(config) {
1823
- return this.suggestionEngine.addSuggestionsConfig(config);
1824
- }
1825
- removeSuggestionsConfig(id) {
1826
- this.suggestionEngine.removeSuggestionsConfig(id);
1827
- }
1828
- reloadSuggestions(agentId) {
1829
- this.suggestionEngine.reloadSuggestions(agentId);
1830
- }
1831
- clearSuggestions(agentId) {
1832
- this.suggestionEngine.clearSuggestions(agentId);
1833
- }
1834
- getSuggestions(agentId) {
1835
- return this.suggestionEngine.getSuggestions(agentId);
1836
- }
1837
- /**
1838
- * Tool management (delegated to RunHandler)
1839
- */
1840
- addTool(tool) {
1841
- this.runHandler.addTool(tool);
1842
- }
1843
- removeTool(id, agentId) {
1844
- this.runHandler.removeTool(id, agentId);
1845
- }
1846
- getTool(params) {
1847
- return this.runHandler.getTool(params);
1848
- }
1849
- setTools(tools) {
1850
- this.runHandler.setTools(tools);
1851
- }
1852
- /**
1853
- * Subscription lifecycle
1854
- */
1855
- subscribe(subscriber) {
1856
- this.subscribers.add(subscriber);
1857
- return {
1858
- unsubscribe: () => {
1859
- this.subscribers.delete(subscriber);
1860
- }
1861
- };
1862
- }
1863
- /**
1864
- * Agent connectivity (delegated to RunHandler)
1865
- */
1866
- async connectAgent(params) {
1867
- return this.runHandler.connectAgent(params);
1868
- }
1869
- stopAgent(params) {
1870
- params.agent.abortRun();
1871
- }
1872
- async runAgent(params) {
1873
- return this.runHandler.runAgent(params);
1874
- }
1875
- /**
1876
- * State management (delegated to StateManager)
1877
- */
1878
- getStateByRun(agentId, threadId, runId) {
1879
- return this.stateManager.getStateByRun(agentId, threadId, runId);
1880
- }
1881
- getRunIdForMessage(agentId, threadId, messageId) {
1882
- return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
1883
- }
1884
- getRunIdsForThread(agentId, threadId) {
1885
- return this.stateManager.getRunIdsForThread(agentId, threadId);
1886
- }
1887
- /**
1888
- * Internal method used by RunHandler to build frontend tools
1889
- */
1890
- buildFrontendTools(agentId) {
1891
- return this.runHandler.buildFrontendTools(agentId);
1892
- }
1321
+ _headers;
1322
+ _credentials;
1323
+ _properties;
1324
+ subscribers = /* @__PURE__ */ new Set();
1325
+ agentRegistry;
1326
+ contextStore;
1327
+ suggestionEngine;
1328
+ runHandler;
1329
+ stateManager;
1330
+ constructor({ runtimeUrl, runtimeTransport = "rest", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [] }) {
1331
+ this._headers = headers;
1332
+ this._credentials = credentials;
1333
+ this._properties = properties;
1334
+ this.agentRegistry = new AgentRegistry(this);
1335
+ this.contextStore = new ContextStore(this);
1336
+ this.suggestionEngine = new SuggestionEngine(this);
1337
+ this.runHandler = new RunHandler(this);
1338
+ this.stateManager = new StateManager(this);
1339
+ this.agentRegistry.initialize(agents__unsafe_dev_only);
1340
+ this.runHandler.initialize(tools);
1341
+ this.suggestionEngine.initialize(suggestionsConfig);
1342
+ this.stateManager.initialize();
1343
+ this.agentRegistry.setRuntimeTransport(runtimeTransport);
1344
+ this.agentRegistry.setRuntimeUrl(runtimeUrl);
1345
+ this.subscribe({ onAgentsChanged: ({ agents }) => {
1346
+ Object.values(agents).forEach((agent) => {
1347
+ if (agent.agentId) this.stateManager.subscribeToAgent(agent);
1348
+ });
1349
+ } });
1350
+ }
1351
+ /**
1352
+ * Internal method used by delegate classes and subclasses to notify subscribers
1353
+ */
1354
+ async notifySubscribers(handler, errorMessage) {
1355
+ await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
1356
+ try {
1357
+ await handler(subscriber);
1358
+ } catch (error) {
1359
+ console.error(errorMessage, error);
1360
+ }
1361
+ }));
1362
+ }
1363
+ /**
1364
+ * Internal method used by delegate classes to emit errors
1365
+ */
1366
+ async emitError({ error, code, context = {} }) {
1367
+ await this.notifySubscribers((subscriber) => subscriber.onError?.({
1368
+ copilotkit: this,
1369
+ error,
1370
+ code,
1371
+ context
1372
+ }), "Subscriber onError error:");
1373
+ }
1374
+ /**
1375
+ * Snapshot accessors
1376
+ */
1377
+ get context() {
1378
+ return this.contextStore.context;
1379
+ }
1380
+ get agents() {
1381
+ return this.agentRegistry.agents;
1382
+ }
1383
+ get tools() {
1384
+ return this.runHandler.tools;
1385
+ }
1386
+ get runtimeUrl() {
1387
+ return this.agentRegistry.runtimeUrl;
1388
+ }
1389
+ setRuntimeUrl(runtimeUrl) {
1390
+ this.agentRegistry.setRuntimeUrl(runtimeUrl);
1391
+ }
1392
+ get runtimeTransport() {
1393
+ return this.agentRegistry.runtimeTransport;
1394
+ }
1395
+ setRuntimeTransport(runtimeTransport) {
1396
+ this.agentRegistry.setRuntimeTransport(runtimeTransport);
1397
+ }
1398
+ get runtimeVersion() {
1399
+ return this.agentRegistry.runtimeVersion;
1400
+ }
1401
+ get headers() {
1402
+ return this._headers;
1403
+ }
1404
+ get credentials() {
1405
+ return this._credentials;
1406
+ }
1407
+ get properties() {
1408
+ return this._properties;
1409
+ }
1410
+ get runtimeConnectionStatus() {
1411
+ return this.agentRegistry.runtimeConnectionStatus;
1412
+ }
1413
+ get audioFileTranscriptionEnabled() {
1414
+ return this.agentRegistry.audioFileTranscriptionEnabled;
1415
+ }
1416
+ /**
1417
+ * Configuration updates
1418
+ */
1419
+ setHeaders(headers) {
1420
+ this._headers = headers;
1421
+ this.agentRegistry.applyHeadersToAgents(this.agentRegistry.agents);
1422
+ this.notifySubscribers((subscriber) => subscriber.onHeadersChanged?.({
1423
+ copilotkit: this,
1424
+ headers: this.headers
1425
+ }), "Subscriber onHeadersChanged error:");
1426
+ }
1427
+ setCredentials(credentials) {
1428
+ this._credentials = credentials;
1429
+ this.agentRegistry.applyCredentialsToAgents(this.agentRegistry.agents);
1430
+ }
1431
+ setProperties(properties) {
1432
+ this._properties = properties;
1433
+ this.notifySubscribers((subscriber) => subscriber.onPropertiesChanged?.({
1434
+ copilotkit: this,
1435
+ properties: this.properties
1436
+ }), "Subscriber onPropertiesChanged error:");
1437
+ }
1438
+ /**
1439
+ * Agent management (delegated to AgentRegistry)
1440
+ */
1441
+ setAgents__unsafe_dev_only(agents) {
1442
+ this.agentRegistry.setAgents__unsafe_dev_only(agents);
1443
+ }
1444
+ addAgent__unsafe_dev_only(params) {
1445
+ this.agentRegistry.addAgent__unsafe_dev_only(params);
1446
+ }
1447
+ removeAgent__unsafe_dev_only(id) {
1448
+ this.agentRegistry.removeAgent__unsafe_dev_only(id);
1449
+ }
1450
+ getAgent(id) {
1451
+ return this.agentRegistry.getAgent(id);
1452
+ }
1453
+ /**
1454
+ * Context management (delegated to ContextStore)
1455
+ */
1456
+ addContext(context) {
1457
+ return this.contextStore.addContext(context);
1458
+ }
1459
+ removeContext(id) {
1460
+ this.contextStore.removeContext(id);
1461
+ }
1462
+ /**
1463
+ * Suggestions management (delegated to SuggestionEngine)
1464
+ */
1465
+ addSuggestionsConfig(config) {
1466
+ return this.suggestionEngine.addSuggestionsConfig(config);
1467
+ }
1468
+ removeSuggestionsConfig(id) {
1469
+ this.suggestionEngine.removeSuggestionsConfig(id);
1470
+ }
1471
+ reloadSuggestions(agentId) {
1472
+ this.suggestionEngine.reloadSuggestions(agentId);
1473
+ }
1474
+ clearSuggestions(agentId) {
1475
+ this.suggestionEngine.clearSuggestions(agentId);
1476
+ }
1477
+ getSuggestions(agentId) {
1478
+ return this.suggestionEngine.getSuggestions(agentId);
1479
+ }
1480
+ /**
1481
+ * Tool management (delegated to RunHandler)
1482
+ */
1483
+ addTool(tool) {
1484
+ this.runHandler.addTool(tool);
1485
+ }
1486
+ removeTool(id, agentId) {
1487
+ this.runHandler.removeTool(id, agentId);
1488
+ }
1489
+ getTool(params) {
1490
+ return this.runHandler.getTool(params);
1491
+ }
1492
+ setTools(tools) {
1493
+ this.runHandler.setTools(tools);
1494
+ }
1495
+ /**
1496
+ * Subscription lifecycle
1497
+ */
1498
+ subscribe(subscriber) {
1499
+ this.subscribers.add(subscriber);
1500
+ return { unsubscribe: () => {
1501
+ this.subscribers.delete(subscriber);
1502
+ } };
1503
+ }
1504
+ /**
1505
+ * Agent connectivity (delegated to RunHandler)
1506
+ */
1507
+ async connectAgent(params) {
1508
+ return this.runHandler.connectAgent(params);
1509
+ }
1510
+ stopAgent(params) {
1511
+ params.agent.abortRun();
1512
+ }
1513
+ async runAgent(params) {
1514
+ return this.runHandler.runAgent(params);
1515
+ }
1516
+ /**
1517
+ * State management (delegated to StateManager)
1518
+ */
1519
+ getStateByRun(agentId, threadId, runId) {
1520
+ return this.stateManager.getStateByRun(agentId, threadId, runId);
1521
+ }
1522
+ getRunIdForMessage(agentId, threadId, messageId) {
1523
+ return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
1524
+ }
1525
+ getRunIdsForThread(agentId, threadId) {
1526
+ return this.stateManager.getRunIdsForThread(agentId, threadId);
1527
+ }
1528
+ /**
1529
+ * Internal method used by RunHandler to build frontend tools
1530
+ */
1531
+ buildFrontendTools(agentId) {
1532
+ return this.runHandler.buildFrontendTools(agentId);
1533
+ }
1893
1534
  };
1894
1535
 
1895
- // src/types.ts
1896
- var ToolCallStatus = /* @__PURE__ */ ((ToolCallStatus2) => {
1897
- ToolCallStatus2["InProgress"] = "inProgress";
1898
- ToolCallStatus2["Executing"] = "executing";
1899
- ToolCallStatus2["Complete"] = "complete";
1900
- return ToolCallStatus2;
1901
- })(ToolCallStatus || {});
1536
+ //#endregion
1537
+ //#region src/types.ts
1538
+ /**
1539
+ * Status of a tool call execution
1540
+ */
1541
+ let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
1542
+ ToolCallStatus["InProgress"] = "inProgress";
1543
+ ToolCallStatus["Executing"] = "executing";
1544
+ ToolCallStatus["Complete"] = "complete";
1545
+ return ToolCallStatus;
1546
+ }({});
1902
1547
 
1903
- // src/utils/markdown.ts
1548
+ //#endregion
1549
+ //#region src/utils/markdown.ts
1904
1550
  function completePartialMarkdown(input) {
1905
- let s = input;
1906
- const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
1907
- if (fenceMatches.length % 2 === 1) {
1908
- const [, indent, fence] = fenceMatches[0];
1909
- s += `
1910
- ${indent}${fence}`;
1911
- }
1912
- const incompleteLinkMatch = s.match(/\[([^\]]*)\]\(([^)]*)$/);
1913
- if (incompleteLinkMatch) {
1914
- s += ")";
1915
- }
1916
- const openElements = [];
1917
- const chars = Array.from(s);
1918
- const codeBlockRanges = [];
1919
- const inlineCodeRanges = [];
1920
- let tempCodeFenceCount = 0;
1921
- let currentCodeBlockStart = -1;
1922
- for (let i = 0; i < chars.length; i++) {
1923
- if (i === 0 || chars[i - 1] === "\n") {
1924
- const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
1925
- if (lineMatch) {
1926
- tempCodeFenceCount++;
1927
- if (tempCodeFenceCount % 2 === 1) {
1928
- currentCodeBlockStart = i;
1929
- } else if (currentCodeBlockStart !== -1) {
1930
- codeBlockRanges.push({
1931
- start: currentCodeBlockStart,
1932
- end: i + lineMatch[0].length
1933
- });
1934
- currentCodeBlockStart = -1;
1935
- }
1936
- i += lineMatch[0].length - 1;
1937
- }
1938
- }
1939
- }
1940
- for (let i = 0; i < chars.length; i++) {
1941
- if (chars[i] === "`") {
1942
- let backslashCount = 0;
1943
- for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) {
1944
- backslashCount++;
1945
- }
1946
- if (backslashCount % 2 === 0) {
1947
- for (let j = i + 1; j < chars.length; j++) {
1948
- if (chars[j] === "`") {
1949
- let closingBackslashCount = 0;
1950
- for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) {
1951
- closingBackslashCount++;
1952
- }
1953
- if (closingBackslashCount % 2 === 0) {
1954
- inlineCodeRanges.push({ start: i, end: j + 1 });
1955
- i = j;
1956
- break;
1957
- }
1958
- }
1959
- }
1960
- }
1961
- }
1962
- }
1963
- const isInCode = (pos) => {
1964
- return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
1965
- };
1966
- for (let i = 0; i < chars.length; i++) {
1967
- const char = chars[i];
1968
- const nextChar = chars[i + 1];
1969
- const prevChar = chars[i - 1];
1970
- if (isInCode(i)) {
1971
- continue;
1972
- }
1973
- if (char === "[") {
1974
- let isCompleteLink = false;
1975
- let bracketDepth = 1;
1976
- let j = i + 1;
1977
- while (j < chars.length && bracketDepth > 0) {
1978
- if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
1979
- if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
1980
- j++;
1981
- }
1982
- if (bracketDepth === 0 && chars[j] === "(") {
1983
- let parenDepth = 1;
1984
- j++;
1985
- while (j < chars.length && parenDepth > 0) {
1986
- if (chars[j] === "(" && !isInCode(j)) parenDepth++;
1987
- if (chars[j] === ")" && !isInCode(j)) parenDepth--;
1988
- j++;
1989
- }
1990
- if (parenDepth === 0) {
1991
- isCompleteLink = true;
1992
- i = j - 1;
1993
- continue;
1994
- }
1995
- }
1996
- if (!isCompleteLink) {
1997
- const existingIndex = openElements.findIndex(
1998
- (el) => el.type === "bracket"
1999
- );
2000
- if (existingIndex !== -1) {
2001
- openElements.splice(existingIndex, 1);
2002
- } else {
2003
- openElements.push({ type: "bracket", marker: "[", position: i });
2004
- }
2005
- }
2006
- } else if (char === "*" && nextChar === "*") {
2007
- const existingIndex = openElements.findIndex(
2008
- (el) => el.type === "bold_star"
2009
- );
2010
- if (existingIndex !== -1) {
2011
- openElements.splice(existingIndex, 1);
2012
- } else {
2013
- openElements.push({ type: "bold_star", marker: "**", position: i });
2014
- }
2015
- i++;
2016
- } else if (char === "_" && nextChar === "_") {
2017
- const existingIndex = openElements.findIndex(
2018
- (el) => el.type === "bold_underscore"
2019
- );
2020
- if (existingIndex !== -1) {
2021
- openElements.splice(existingIndex, 1);
2022
- } else {
2023
- openElements.push({
2024
- type: "bold_underscore",
2025
- marker: "__",
2026
- position: i
2027
- });
2028
- }
2029
- i++;
2030
- } else if (char === "~" && nextChar === "~") {
2031
- const existingIndex = openElements.findIndex(
2032
- (el) => el.type === "strike"
2033
- );
2034
- if (existingIndex !== -1) {
2035
- openElements.splice(existingIndex, 1);
2036
- } else {
2037
- openElements.push({ type: "strike", marker: "~~", position: i });
2038
- }
2039
- i++;
2040
- } else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
2041
- const existingIndex = openElements.findIndex(
2042
- (el) => el.type === "italic_star"
2043
- );
2044
- if (existingIndex !== -1) {
2045
- openElements.splice(existingIndex, 1);
2046
- } else {
2047
- openElements.push({ type: "italic_star", marker: "*", position: i });
2048
- }
2049
- } else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
2050
- const existingIndex = openElements.findIndex(
2051
- (el) => el.type === "italic_underscore"
2052
- );
2053
- if (existingIndex !== -1) {
2054
- openElements.splice(existingIndex, 1);
2055
- } else {
2056
- openElements.push({
2057
- type: "italic_underscore",
2058
- marker: "_",
2059
- position: i
2060
- });
2061
- }
2062
- }
2063
- }
2064
- let backtickCount = 0;
2065
- for (let i = 0; i < chars.length; i++) {
2066
- if (chars[i] === "`" && !isInCode(i)) {
2067
- backtickCount++;
2068
- }
2069
- }
2070
- if (backtickCount % 2 === 1) {
2071
- s += "`";
2072
- }
2073
- openElements.sort((a, b) => b.position - a.position);
2074
- const closers = openElements.map((el) => {
2075
- switch (el.type) {
2076
- case "bracket":
2077
- return "]";
2078
- case "bold_star":
2079
- return "**";
2080
- case "bold_underscore":
2081
- return "__";
2082
- case "strike":
2083
- return "~~";
2084
- case "italic_star":
2085
- return "*";
2086
- case "italic_underscore":
2087
- return "_";
2088
- default:
2089
- return "";
2090
- }
2091
- });
2092
- let result = s + closers.join("");
2093
- const finalFenceMatches = Array.from(
2094
- result.matchAll(/^(\s*)(`{3,}|~{3,})/gm)
2095
- );
2096
- const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
2097
- const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
2098
- let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
2099
- if (shouldCloseParens) {
2100
- const lastOpenParen = result.lastIndexOf("(");
2101
- if (lastOpenParen !== -1) {
2102
- const beforeParen = result.substring(0, lastOpenParen);
2103
- const backticksBeforeParen = (beforeParen.match(/`/g) || []).length;
2104
- if (backticksBeforeParen % 2 === 1) {
2105
- shouldCloseParens = false;
2106
- }
2107
- }
2108
- }
2109
- if (shouldCloseParens) {
2110
- const openParens = (result.match(/\(/g) || []).length;
2111
- const closeParens = (result.match(/\)/g) || []).length;
2112
- if (openParens > closeParens) {
2113
- result += ")".repeat(openParens - closeParens);
2114
- }
2115
- }
2116
- return result;
1551
+ let s = input;
1552
+ const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
1553
+ if (fenceMatches.length % 2 === 1) {
1554
+ const [, indent, fence] = fenceMatches[0];
1555
+ s += `\n${indent}${fence}`;
1556
+ }
1557
+ if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
1558
+ const openElements = [];
1559
+ const chars = Array.from(s);
1560
+ const codeBlockRanges = [];
1561
+ const inlineCodeRanges = [];
1562
+ let tempCodeFenceCount = 0;
1563
+ let currentCodeBlockStart = -1;
1564
+ for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
1565
+ const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
1566
+ if (lineMatch) {
1567
+ tempCodeFenceCount++;
1568
+ if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
1569
+ else if (currentCodeBlockStart !== -1) {
1570
+ codeBlockRanges.push({
1571
+ start: currentCodeBlockStart,
1572
+ end: i + lineMatch[0].length
1573
+ });
1574
+ currentCodeBlockStart = -1;
1575
+ }
1576
+ i += lineMatch[0].length - 1;
1577
+ }
1578
+ }
1579
+ for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
1580
+ let backslashCount = 0;
1581
+ for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
1582
+ if (backslashCount % 2 === 0) {
1583
+ for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
1584
+ let closingBackslashCount = 0;
1585
+ for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
1586
+ if (closingBackslashCount % 2 === 0) {
1587
+ inlineCodeRanges.push({
1588
+ start: i,
1589
+ end: j + 1
1590
+ });
1591
+ i = j;
1592
+ break;
1593
+ }
1594
+ }
1595
+ }
1596
+ }
1597
+ const isInCode = (pos) => {
1598
+ return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
1599
+ };
1600
+ for (let i = 0; i < chars.length; i++) {
1601
+ const char = chars[i];
1602
+ const nextChar = chars[i + 1];
1603
+ const prevChar = chars[i - 1];
1604
+ if (isInCode(i)) continue;
1605
+ if (char === "[") {
1606
+ let isCompleteLink = false;
1607
+ let bracketDepth = 1;
1608
+ let j = i + 1;
1609
+ while (j < chars.length && bracketDepth > 0) {
1610
+ if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
1611
+ if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
1612
+ j++;
1613
+ }
1614
+ if (bracketDepth === 0 && chars[j] === "(") {
1615
+ let parenDepth = 1;
1616
+ j++;
1617
+ while (j < chars.length && parenDepth > 0) {
1618
+ if (chars[j] === "(" && !isInCode(j)) parenDepth++;
1619
+ if (chars[j] === ")" && !isInCode(j)) parenDepth--;
1620
+ j++;
1621
+ }
1622
+ if (parenDepth === 0) {
1623
+ isCompleteLink = true;
1624
+ i = j - 1;
1625
+ continue;
1626
+ }
1627
+ }
1628
+ if (!isCompleteLink) {
1629
+ const existingIndex = openElements.findIndex((el) => el.type === "bracket");
1630
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1631
+ else openElements.push({
1632
+ type: "bracket",
1633
+ marker: "[",
1634
+ position: i
1635
+ });
1636
+ }
1637
+ } else if (char === "*" && nextChar === "*") {
1638
+ const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
1639
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1640
+ else openElements.push({
1641
+ type: "bold_star",
1642
+ marker: "**",
1643
+ position: i
1644
+ });
1645
+ i++;
1646
+ } else if (char === "_" && nextChar === "_") {
1647
+ const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
1648
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1649
+ else openElements.push({
1650
+ type: "bold_underscore",
1651
+ marker: "__",
1652
+ position: i
1653
+ });
1654
+ i++;
1655
+ } else if (char === "~" && nextChar === "~") {
1656
+ const existingIndex = openElements.findIndex((el) => el.type === "strike");
1657
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1658
+ else openElements.push({
1659
+ type: "strike",
1660
+ marker: "~~",
1661
+ position: i
1662
+ });
1663
+ i++;
1664
+ } else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
1665
+ const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
1666
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1667
+ else openElements.push({
1668
+ type: "italic_star",
1669
+ marker: "*",
1670
+ position: i
1671
+ });
1672
+ } else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
1673
+ const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
1674
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
1675
+ else openElements.push({
1676
+ type: "italic_underscore",
1677
+ marker: "_",
1678
+ position: i
1679
+ });
1680
+ }
1681
+ }
1682
+ let backtickCount = 0;
1683
+ for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
1684
+ if (backtickCount % 2 === 1) s += "`";
1685
+ openElements.sort((a, b) => b.position - a.position);
1686
+ const closers = openElements.map((el) => {
1687
+ switch (el.type) {
1688
+ case "bracket": return "]";
1689
+ case "bold_star": return "**";
1690
+ case "bold_underscore": return "__";
1691
+ case "strike": return "~~";
1692
+ case "italic_star": return "*";
1693
+ case "italic_underscore": return "_";
1694
+ default: return "";
1695
+ }
1696
+ });
1697
+ let result = s + closers.join("");
1698
+ const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
1699
+ const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
1700
+ const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
1701
+ let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
1702
+ if (shouldCloseParens) {
1703
+ const lastOpenParen = result.lastIndexOf("(");
1704
+ if (lastOpenParen !== -1) {
1705
+ if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
1706
+ }
1707
+ }
1708
+ if (shouldCloseParens) {
1709
+ const openParens = (result.match(/\(/g) || []).length;
1710
+ const closeParens = (result.match(/\)/g) || []).length;
1711
+ if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
1712
+ }
1713
+ return result;
2117
1714
  }
2118
- export {
2119
- AgentRegistry,
2120
- ContextStore,
2121
- CopilotKitCore,
2122
- CopilotKitCoreErrorCode,
2123
- CopilotKitCoreRuntimeConnectionStatus,
2124
- ProxiedCopilotRuntimeAgent,
2125
- RunHandler,
2126
- StateManager,
2127
- SuggestionEngine,
2128
- ToolCallStatus,
2129
- completePartialMarkdown
2130
- };
1715
+
1716
+ //#endregion
1717
+ export { AgentRegistry, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown };
2131
1718
  //# sourceMappingURL=index.mjs.map