@copilotkitnext/core 0.0.8 → 0.0.9-alpha.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.js CHANGED
@@ -21,7 +21,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  CopilotKitCore: () => CopilotKitCore,
24
- CopilotKitHttpAgent: () => CopilotKitHttpAgent,
24
+ CopilotKitCoreErrorCode: () => CopilotKitCoreErrorCode,
25
+ CopilotKitCoreRuntimeConnectionStatus: () => CopilotKitCoreRuntimeConnectionStatus,
26
+ ProxiedCopilotRuntimeAgent: () => ProxiedCopilotRuntimeAgent,
25
27
  ToolCallStatus: () => ToolCallStatus,
26
28
  completePartialMarkdown: () => completePartialMarkdown
27
29
  });
@@ -29,12 +31,11 @@ module.exports = __toCommonJS(index_exports);
29
31
 
30
32
  // src/core.ts
31
33
  var import_shared = require("@copilotkitnext/shared");
32
- var import_shared2 = require("@copilotkitnext/shared");
34
+ var import_client2 = require("@ag-ui/client");
33
35
 
34
36
  // src/agent.ts
35
37
  var import_client = require("@ag-ui/client");
36
- var CopilotKitHttpAgent = class extends import_client.HttpAgent {
37
- isCopilotKitAgent = true;
38
+ var ProxiedCopilotRuntimeAgent = class extends import_client.HttpAgent {
38
39
  runtimeUrl;
39
40
  constructor(config) {
40
41
  super({
@@ -43,144 +44,387 @@ var CopilotKitHttpAgent = class extends import_client.HttpAgent {
43
44
  });
44
45
  this.runtimeUrl = config.runtimeUrl;
45
46
  }
46
- run(input) {
47
- const url = input.forwardedProps.__copilotkitConnect === true ? `${this.runtimeUrl}/agent/${this.agentId}/connect` : this.url;
48
- const httpEvents = (0, import_client.runHttpRequest)(url, this.requestInit(input));
47
+ connect(input) {
48
+ const httpEvents = (0, import_client.runHttpRequest)(
49
+ `${this.runtimeUrl}/agent/${this.agentId}/connect`,
50
+ this.requestInit(input)
51
+ );
49
52
  return (0, import_client.transformHttpEventStream)(httpEvents);
50
53
  }
51
54
  };
52
55
 
53
56
  // src/core.ts
57
+ var import_zod_to_json_schema = require("zod-to-json-schema");
58
+ var CopilotKitCoreErrorCode = /* @__PURE__ */ ((CopilotKitCoreErrorCode2) => {
59
+ CopilotKitCoreErrorCode2["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
60
+ CopilotKitCoreErrorCode2["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
61
+ CopilotKitCoreErrorCode2["AGENT_RUN_FAILED"] = "agent_run_failed";
62
+ CopilotKitCoreErrorCode2["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
63
+ CopilotKitCoreErrorCode2["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
64
+ CopilotKitCoreErrorCode2["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
65
+ CopilotKitCoreErrorCode2["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
66
+ return CopilotKitCoreErrorCode2;
67
+ })(CopilotKitCoreErrorCode || {});
68
+ var CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ ((CopilotKitCoreRuntimeConnectionStatus2) => {
69
+ CopilotKitCoreRuntimeConnectionStatus2["Disconnected"] = "disconnected";
70
+ CopilotKitCoreRuntimeConnectionStatus2["Connected"] = "connected";
71
+ CopilotKitCoreRuntimeConnectionStatus2["Connecting"] = "connecting";
72
+ CopilotKitCoreRuntimeConnectionStatus2["Error"] = "error";
73
+ return CopilotKitCoreRuntimeConnectionStatus2;
74
+ })(CopilotKitCoreRuntimeConnectionStatus || {});
54
75
  var CopilotKitCore = class {
55
- runtimeUrl;
56
- didLoadRuntime = false;
57
- context = {};
58
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
- tools = {};
60
- agents = {};
61
76
  headers;
62
77
  properties;
63
- version;
78
+ _context = {};
79
+ _agents = {};
80
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
+ _tools = [];
64
82
  localAgents = {};
65
83
  remoteAgents = {};
66
84
  subscribers = /* @__PURE__ */ new Set();
85
+ _runtimeUrl;
86
+ _runtimeVersion;
87
+ _runtimeConnectionStatus = "disconnected" /* Disconnected */;
67
88
  constructor({
68
89
  runtimeUrl,
69
90
  headers = {},
70
91
  properties = {},
71
92
  agents = {},
72
- tools = {}
93
+ tools = []
73
94
  }) {
74
95
  this.headers = headers;
75
96
  this.properties = properties;
76
- this.localAgents = agents;
77
- this.agents = this.localAgents;
78
- this.tools = tools;
97
+ this.localAgents = this.assignAgentIds(agents);
98
+ this._agents = this.localAgents;
99
+ this._tools = tools;
79
100
  this.setRuntimeUrl(runtimeUrl);
80
101
  }
81
- async getRuntimeInfo() {
82
- const response = await fetch(`${this.runtimeUrl}/info`, {
83
- headers: this.headers
102
+ assignAgentIds(agents) {
103
+ Object.entries(agents).forEach(([id, agent]) => {
104
+ if (agent && !agent.agentId) {
105
+ agent.agentId = id;
106
+ }
84
107
  });
85
- const {
86
- version,
87
- ...runtimeInfo
88
- } = await response.json();
89
- const agents = Object.fromEntries(
90
- Object.entries(runtimeInfo.agents).map(([id, { description }]) => {
91
- const agent = new CopilotKitHttpAgent({
92
- runtimeUrl: this.runtimeUrl,
93
- agentId: id,
94
- description
95
- });
96
- return [id, agent];
108
+ return agents;
109
+ }
110
+ async notifySubscribers(handler, errorMessage) {
111
+ await Promise.all(
112
+ Array.from(this.subscribers).map(async (subscriber) => {
113
+ try {
114
+ await handler(subscriber);
115
+ } catch (error) {
116
+ import_shared.logger.error(errorMessage, error);
117
+ }
97
118
  })
98
119
  );
99
- return { agents, version };
100
- }
101
- async fetchRemoteAgents() {
102
- if (this.runtimeUrl) {
103
- this.getRuntimeInfo().then(({ agents, version }) => {
104
- this.remoteAgents = agents;
105
- this.agents = { ...this.localAgents, ...this.remoteAgents };
106
- this.didLoadRuntime = true;
107
- this.version = version;
108
- this.subscribers.forEach(async (subscriber) => {
109
- try {
110
- await subscriber.onRuntimeLoaded?.({ copilotkit: this });
111
- } catch (error) {
112
- import_shared2.logger.error(
113
- "Error in CopilotKitCore subscriber (onRuntimeLoaded):",
114
- error
115
- );
116
- }
117
- });
118
- }).catch((error) => {
119
- this.subscribers.forEach(async (subscriber) => {
120
- try {
121
- await subscriber.onRuntimeLoadError?.({ copilotkit: this });
122
- } catch (error2) {
123
- import_shared2.logger.error(
124
- "Error in CopilotKitCore subscriber (onRuntimeLoadError):",
125
- error2
126
- );
127
- }
128
- });
129
- import_shared2.logger.warn(`Failed to load runtime info: ${error.message}`);
120
+ }
121
+ async emitError({
122
+ error,
123
+ code,
124
+ context = {}
125
+ }) {
126
+ await this.notifySubscribers(
127
+ (subscriber) => subscriber.onError?.({
128
+ copilotkit: this,
129
+ error,
130
+ code,
131
+ context
132
+ }),
133
+ "Subscriber onError error:"
134
+ );
135
+ }
136
+ resolveAgentId(agent, providedAgentId) {
137
+ if (providedAgentId) {
138
+ return providedAgentId;
139
+ }
140
+ if (agent.agentId) {
141
+ return agent.agentId;
142
+ }
143
+ const found = Object.entries(this._agents).find(([, storedAgent]) => {
144
+ return storedAgent === agent;
145
+ });
146
+ if (found) {
147
+ agent.agentId = found[0];
148
+ return found[0];
149
+ }
150
+ agent.agentId = import_shared.DEFAULT_AGENT_ID;
151
+ return import_shared.DEFAULT_AGENT_ID;
152
+ }
153
+ /**
154
+ * Snapshot accessors
155
+ */
156
+ get context() {
157
+ return this._context;
158
+ }
159
+ get agents() {
160
+ return this._agents;
161
+ }
162
+ get tools() {
163
+ return this._tools;
164
+ }
165
+ get runtimeUrl() {
166
+ return this._runtimeUrl;
167
+ }
168
+ setRuntimeUrl(runtimeUrl) {
169
+ const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
170
+ if (this._runtimeUrl === normalizedRuntimeUrl) {
171
+ return;
172
+ }
173
+ this._runtimeUrl = normalizedRuntimeUrl;
174
+ void this.updateRuntimeConnection();
175
+ }
176
+ get runtimeVersion() {
177
+ return this._runtimeVersion;
178
+ }
179
+ get runtimeConnectionStatus() {
180
+ return this._runtimeConnectionStatus;
181
+ }
182
+ /**
183
+ * Runtime connection
184
+ */
185
+ async updateRuntimeConnection() {
186
+ if (!this.runtimeUrl) {
187
+ this._runtimeConnectionStatus = "disconnected" /* Disconnected */;
188
+ this._runtimeVersion = void 0;
189
+ this.remoteAgents = {};
190
+ this._agents = this.localAgents;
191
+ await this.notifySubscribers(
192
+ (subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
193
+ copilotkit: this,
194
+ status: "disconnected" /* Disconnected */
195
+ }),
196
+ "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):"
197
+ );
198
+ await this.notifySubscribers(
199
+ (subscriber) => subscriber.onAgentsChanged?.({
200
+ copilotkit: this,
201
+ agents: this._agents
202
+ }),
203
+ "Subscriber onAgentsChanged error:"
204
+ );
205
+ return;
206
+ }
207
+ this._runtimeConnectionStatus = "connecting" /* Connecting */;
208
+ await this.notifySubscribers(
209
+ (subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
210
+ copilotkit: this,
211
+ status: "connecting" /* Connecting */
212
+ }),
213
+ "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):"
214
+ );
215
+ try {
216
+ const response = await fetch(`${this.runtimeUrl}/info`, {
217
+ headers: this.headers
218
+ });
219
+ const {
220
+ version,
221
+ ...runtimeInfo
222
+ } = await response.json();
223
+ const agents = Object.fromEntries(
224
+ Object.entries(runtimeInfo.agents).map(([id, { description }]) => {
225
+ const agent = new ProxiedCopilotRuntimeAgent({
226
+ runtimeUrl: this.runtimeUrl,
227
+ agentId: id,
228
+ description
229
+ });
230
+ return [id, agent];
231
+ })
232
+ );
233
+ this.remoteAgents = agents;
234
+ this._agents = { ...this.localAgents, ...this.remoteAgents };
235
+ this._runtimeConnectionStatus = "connected" /* Connected */;
236
+ this._runtimeVersion = version;
237
+ await this.notifySubscribers(
238
+ (subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
239
+ copilotkit: this,
240
+ status: "connected" /* Connected */
241
+ }),
242
+ "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):"
243
+ );
244
+ await this.notifySubscribers(
245
+ (subscriber) => subscriber.onAgentsChanged?.({
246
+ copilotkit: this,
247
+ agents: this._agents
248
+ }),
249
+ "Subscriber onAgentsChanged error:"
250
+ );
251
+ } catch (error) {
252
+ this._runtimeConnectionStatus = "error" /* Error */;
253
+ this._runtimeVersion = void 0;
254
+ this.remoteAgents = {};
255
+ this._agents = this.localAgents;
256
+ await this.notifySubscribers(
257
+ (subscriber) => subscriber.onRuntimeConnectionStatusChanged?.({
258
+ copilotkit: this,
259
+ status: "error" /* Error */
260
+ }),
261
+ "Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):"
262
+ );
263
+ await this.notifySubscribers(
264
+ (subscriber) => subscriber.onAgentsChanged?.({
265
+ copilotkit: this,
266
+ agents: this._agents
267
+ }),
268
+ "Subscriber onAgentsChanged error:"
269
+ );
270
+ const message = error instanceof Error ? error.message : JSON.stringify(error);
271
+ import_shared.logger.warn(
272
+ `Failed to load runtime info (${this.runtimeUrl}/info): ${message}`
273
+ );
274
+ const runtimeError = error instanceof Error ? error : new Error(String(error));
275
+ await this.emitError({
276
+ error: runtimeError,
277
+ code: "runtime_info_fetch_failed" /* RUNTIME_INFO_FETCH_FAILED */,
278
+ context: {
279
+ runtimeUrl: this.runtimeUrl
280
+ }
130
281
  });
131
282
  }
132
283
  }
284
+ /**
285
+ * Configuration updates
286
+ */
287
+ setHeaders(headers) {
288
+ this.headers = headers;
289
+ void this.notifySubscribers(
290
+ (subscriber) => subscriber.onHeadersChanged?.({
291
+ copilotkit: this,
292
+ headers: this.headers
293
+ }),
294
+ "Subscriber onHeadersChanged error:"
295
+ );
296
+ }
297
+ setProperties(properties) {
298
+ this.properties = properties;
299
+ void this.notifySubscribers(
300
+ (subscriber) => subscriber.onPropertiesChanged?.({
301
+ copilotkit: this,
302
+ properties: this.properties
303
+ }),
304
+ "Subscriber onPropertiesChanged error:"
305
+ );
306
+ }
133
307
  setAgents(agents) {
134
- this.localAgents = agents;
135
- this.agents = { ...this.localAgents, ...this.remoteAgents };
308
+ this.localAgents = this.assignAgentIds(agents);
309
+ this._agents = { ...this.localAgents, ...this.remoteAgents };
310
+ void this.notifySubscribers(
311
+ (subscriber) => subscriber.onAgentsChanged?.({
312
+ copilotkit: this,
313
+ agents: this._agents
314
+ }),
315
+ "Subscriber onAgentsChanged error:"
316
+ );
136
317
  }
137
318
  addAgent({ id, agent }) {
138
319
  this.localAgents[id] = agent;
139
- this.agents = { ...this.localAgents, ...this.remoteAgents };
320
+ if (!agent.agentId) {
321
+ agent.agentId = id;
322
+ }
323
+ this._agents = { ...this.localAgents, ...this.remoteAgents };
324
+ void this.notifySubscribers(
325
+ (subscriber) => subscriber.onAgentsChanged?.({
326
+ copilotkit: this,
327
+ agents: this._agents
328
+ }),
329
+ "Subscriber onAgentsChanged error:"
330
+ );
140
331
  }
141
332
  removeAgent(id) {
142
333
  delete this.localAgents[id];
143
- this.agents = { ...this.localAgents, ...this.remoteAgents };
334
+ this._agents = { ...this.localAgents, ...this.remoteAgents };
335
+ void this.notifySubscribers(
336
+ (subscriber) => subscriber.onAgentsChanged?.({
337
+ copilotkit: this,
338
+ agents: this._agents
339
+ }),
340
+ "Subscriber onAgentsChanged error:"
341
+ );
144
342
  }
145
343
  getAgent(id) {
146
- if (id in this.agents) {
147
- return this.agents[id];
344
+ if (id in this._agents) {
345
+ return this._agents[id];
346
+ }
347
+ if (this.runtimeUrl !== void 0 && (this.runtimeConnectionStatus === "disconnected" /* Disconnected */ || this.runtimeConnectionStatus === "connecting" /* Connecting */)) {
348
+ return void 0;
148
349
  } else {
149
- if (!this.didLoadRuntime) {
150
- return void 0;
151
- } else {
152
- throw new Error(`Agent ${id} not found`);
153
- }
350
+ console.warn(`Agent ${id} not found`);
351
+ return void 0;
154
352
  }
155
353
  }
354
+ /**
355
+ * Context management
356
+ */
156
357
  addContext({ description, value }) {
157
358
  const id = (0, import_shared.randomUUID)();
158
- this.context[id] = { description, value };
359
+ this._context[id] = { description, value };
360
+ void this.notifySubscribers(
361
+ (subscriber) => subscriber.onContextChanged?.({
362
+ copilotkit: this,
363
+ context: this._context
364
+ }),
365
+ "Subscriber onContextChanged error:"
366
+ );
159
367
  return id;
160
368
  }
161
369
  removeContext(id) {
162
- delete this.context[id];
163
- }
164
- setRuntimeUrl(runtimeUrl) {
165
- this.runtimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
166
- this.fetchRemoteAgents();
370
+ delete this._context[id];
371
+ void this.notifySubscribers(
372
+ (subscriber) => subscriber.onContextChanged?.({
373
+ copilotkit: this,
374
+ context: this._context
375
+ }),
376
+ "Subscriber onContextChanged error:"
377
+ );
167
378
  }
379
+ /**
380
+ * Tool management
381
+ */
168
382
  addTool(tool) {
169
- if (tool.name in this.tools) {
170
- import_shared2.logger.warn(`Tool already exists: '${tool.name}', skipping.`);
383
+ const existingToolIndex = this._tools.findIndex(
384
+ (t) => t.name === tool.name && t.agentId === tool.agentId
385
+ );
386
+ if (existingToolIndex !== -1) {
387
+ import_shared.logger.warn(
388
+ `Tool already exists: '${tool.name}' for agent '${tool.agentId || "global"}', skipping.`
389
+ );
171
390
  return;
172
391
  }
173
- this.tools[tool.name] = tool;
392
+ this._tools.push(tool);
174
393
  }
175
- removeTool(id) {
176
- delete this.tools[id];
394
+ removeTool(id, agentId) {
395
+ this._tools = this._tools.filter((tool) => {
396
+ if (agentId !== void 0) {
397
+ return !(tool.name === id && tool.agentId === agentId);
398
+ }
399
+ return !(tool.name === id && !tool.agentId);
400
+ });
177
401
  }
178
- setHeaders(headers) {
179
- this.headers = headers;
402
+ /**
403
+ * Get a tool by name and optionally by agentId.
404
+ * If agentId is provided, it will first look for an agent-specific tool,
405
+ * then fall back to a global tool with the same name.
406
+ */
407
+ getTool(params) {
408
+ const { toolName, agentId } = params;
409
+ if (agentId) {
410
+ const agentTool = this._tools.find(
411
+ (tool) => tool.name === toolName && tool.agentId === agentId
412
+ );
413
+ if (agentTool) {
414
+ return agentTool;
415
+ }
416
+ }
417
+ return this._tools.find((tool) => tool.name === toolName && !tool.agentId);
180
418
  }
181
- setProperties(properties) {
182
- this.properties = properties;
419
+ /**
420
+ * Set all tools at once. Replaces existing tools.
421
+ */
422
+ setTools(tools) {
423
+ this._tools = [...tools];
183
424
  }
425
+ /**
426
+ * Subscription lifecycle
427
+ */
184
428
  subscribe(subscriber) {
185
429
  this.subscribers.add(subscriber);
186
430
  return () => {
@@ -190,19 +434,83 @@ var CopilotKitCore = class {
190
434
  unsubscribe(subscriber) {
191
435
  this.subscribers.delete(subscriber);
192
436
  }
193
- // TODO: AG-UI needs to expose the runAgent result type
437
+ /**
438
+ * Agent connectivity
439
+ */
440
+ async connectAgent({
441
+ agent,
442
+ agentId
443
+ }) {
444
+ try {
445
+ if (agent instanceof import_client2.HttpAgent) {
446
+ agent.headers = { ...this.headers };
447
+ }
448
+ const runAgentResult = await agent.connectAgent(
449
+ {
450
+ forwardedProps: this.properties,
451
+ tools: this.buildFrontendTools(agentId)
452
+ },
453
+ this.createAgentErrorSubscriber(agent, agentId)
454
+ );
455
+ return this.processAgentResult({ runAgentResult, agent, agentId });
456
+ } catch (error) {
457
+ const connectError = error instanceof Error ? error : new Error(String(error));
458
+ const context = {};
459
+ if (agentId ?? agent.agentId) {
460
+ context.agentId = agentId ?? agent.agentId;
461
+ }
462
+ await this.emitError({
463
+ error: connectError,
464
+ code: "agent_connect_failed" /* AGENT_CONNECT_FAILED */,
465
+ context
466
+ });
467
+ throw error;
468
+ }
469
+ }
194
470
  async runAgent({
195
471
  agent,
196
472
  withMessages,
197
473
  agentId
198
474
  }) {
475
+ if (agent instanceof import_client2.HttpAgent) {
476
+ agent.headers = { ...this.headers };
477
+ }
199
478
  if (withMessages) {
200
479
  agent.addMessages(withMessages);
201
480
  }
202
- const runAgentResult = await agent.runAgent({
203
- forwardedProps: this.properties
204
- });
481
+ try {
482
+ const runAgentResult = await agent.runAgent(
483
+ {
484
+ forwardedProps: this.properties,
485
+ tools: this.buildFrontendTools(agentId)
486
+ },
487
+ this.createAgentErrorSubscriber(agent, agentId)
488
+ );
489
+ return this.processAgentResult({ runAgentResult, agent, agentId });
490
+ } catch (error) {
491
+ const runError = error instanceof Error ? error : new Error(String(error));
492
+ const context = {};
493
+ if (agentId ?? agent.agentId) {
494
+ context.agentId = agentId ?? agent.agentId;
495
+ }
496
+ if (withMessages) {
497
+ context.messageCount = withMessages.length;
498
+ }
499
+ await this.emitError({
500
+ error: runError,
501
+ code: "agent_run_failed" /* AGENT_RUN_FAILED */,
502
+ context
503
+ });
504
+ throw error;
505
+ }
506
+ }
507
+ async processAgentResult({
508
+ runAgentResult,
509
+ agent,
510
+ agentId
511
+ }) {
205
512
  const { newMessages } = runAgentResult;
513
+ const effectiveAgentId = this.resolveAgentId(agent, agentId);
206
514
  let needsFollowUp = false;
207
515
  for (const message of newMessages) {
208
516
  if (message.role === "assistant") {
@@ -210,76 +518,214 @@ var CopilotKitCore = class {
210
518
  if (newMessages.findIndex(
211
519
  (m) => m.role === "tool" && m.toolCallId === toolCall.id
212
520
  ) === -1) {
213
- if (toolCall.function.name in this.tools) {
214
- const tool = this.tools[toolCall.function.name];
521
+ const tool = this.getTool({
522
+ toolName: toolCall.function.name,
523
+ agentId
524
+ });
525
+ if (tool) {
215
526
  if (tool?.agentId && tool.agentId !== agentId) {
216
527
  continue;
217
528
  }
218
529
  let toolCallResult = "";
530
+ let errorMessage;
531
+ let isArgumentError = false;
219
532
  if (tool?.handler) {
220
- const args = JSON.parse(toolCall.function.arguments);
533
+ let parsedArgs;
221
534
  try {
222
- const result = await tool.handler(args);
223
- if (result === void 0 || result === null) {
224
- toolCallResult = "";
225
- } else if (typeof result === "string") {
226
- toolCallResult = result;
227
- } else {
228
- toolCallResult = JSON.stringify(result);
229
- }
535
+ parsedArgs = JSON.parse(toolCall.function.arguments);
230
536
  } catch (error) {
231
- toolCallResult = `Error: ${error instanceof Error ? error.message : String(error)}`;
537
+ const parseError = error instanceof Error ? error : new Error(String(error));
538
+ errorMessage = parseError.message;
539
+ isArgumentError = true;
540
+ await this.emitError({
541
+ error: parseError,
542
+ code: "tool_argument_parse_failed" /* TOOL_ARGUMENT_PARSE_FAILED */,
543
+ context: {
544
+ agentId: effectiveAgentId,
545
+ toolCallId: toolCall.id,
546
+ toolName: toolCall.function.name,
547
+ rawArguments: toolCall.function.arguments,
548
+ toolType: "specific",
549
+ messageId: message.id
550
+ }
551
+ });
552
+ }
553
+ await this.notifySubscribers(
554
+ (subscriber) => subscriber.onToolExecutionStart?.({
555
+ copilotkit: this,
556
+ toolCallId: toolCall.id,
557
+ agentId: effectiveAgentId,
558
+ toolName: toolCall.function.name,
559
+ args: parsedArgs
560
+ }),
561
+ "Subscriber onToolExecutionStart error:"
562
+ );
563
+ if (!errorMessage) {
564
+ try {
565
+ const result = await tool.handler(parsedArgs);
566
+ if (result === void 0 || result === null) {
567
+ toolCallResult = "";
568
+ } else if (typeof result === "string") {
569
+ toolCallResult = result;
570
+ } else {
571
+ toolCallResult = JSON.stringify(result);
572
+ }
573
+ } catch (error) {
574
+ const handlerError = error instanceof Error ? error : new Error(String(error));
575
+ errorMessage = handlerError.message;
576
+ await this.emitError({
577
+ error: handlerError,
578
+ code: "tool_handler_failed" /* TOOL_HANDLER_FAILED */,
579
+ context: {
580
+ agentId: effectiveAgentId,
581
+ toolCallId: toolCall.id,
582
+ toolName: toolCall.function.name,
583
+ parsedArgs,
584
+ toolType: "specific",
585
+ messageId: message.id
586
+ }
587
+ });
588
+ }
589
+ }
590
+ if (errorMessage) {
591
+ toolCallResult = `Error: ${errorMessage}`;
592
+ }
593
+ await this.notifySubscribers(
594
+ (subscriber) => subscriber.onToolExecutionEnd?.({
595
+ copilotkit: this,
596
+ toolCallId: toolCall.id,
597
+ agentId: effectiveAgentId,
598
+ toolName: toolCall.function.name,
599
+ result: errorMessage ? "" : toolCallResult,
600
+ error: errorMessage
601
+ }),
602
+ "Subscriber onToolExecutionEnd error:"
603
+ );
604
+ if (isArgumentError) {
605
+ throw new Error(errorMessage ?? "Tool execution failed");
232
606
  }
233
607
  }
234
- const messageIndex = agent.messages.findIndex(
235
- (m) => m.id === message.id
236
- );
237
- const toolMessage = {
238
- id: (0, import_shared.randomUUID)(),
239
- role: "tool",
240
- toolCallId: toolCall.id,
241
- content: toolCallResult
242
- };
243
- agent.messages.splice(messageIndex + 1, 0, toolMessage);
244
- if (tool?.followUp !== false) {
245
- needsFollowUp = true;
246
- }
247
- } else if ("*" in this.tools) {
248
- const wildcardTool = this.tools["*"];
249
- if (wildcardTool?.agentId && wildcardTool.agentId !== agentId) {
250
- continue;
251
- }
252
- let toolCallResult = "";
253
- if (wildcardTool?.handler) {
254
- const wildcardArgs = {
255
- toolName: toolCall.function.name,
256
- args: JSON.parse(toolCall.function.arguments)
608
+ if (!errorMessage || !isArgumentError) {
609
+ const messageIndex = agent.messages.findIndex(
610
+ (m) => m.id === message.id
611
+ );
612
+ const toolMessage = {
613
+ id: (0, import_shared.randomUUID)(),
614
+ role: "tool",
615
+ toolCallId: toolCall.id,
616
+ content: toolCallResult
257
617
  };
258
- try {
259
- const result = await wildcardTool.handler(wildcardArgs);
260
- if (result === void 0 || result === null) {
261
- toolCallResult = "";
262
- } else if (typeof result === "string") {
263
- toolCallResult = result;
264
- } else {
265
- toolCallResult = JSON.stringify(result);
266
- }
267
- } catch (error) {
268
- toolCallResult = `Error: ${error instanceof Error ? error.message : String(error)}`;
618
+ agent.messages.splice(messageIndex + 1, 0, toolMessage);
619
+ if (!errorMessage && tool?.followUp !== false) {
620
+ needsFollowUp = true;
269
621
  }
270
622
  }
271
- const messageIndex = agent.messages.findIndex(
272
- (m) => m.id === message.id
273
- );
274
- const toolMessage = {
275
- id: (0, import_shared.randomUUID)(),
276
- role: "tool",
277
- toolCallId: toolCall.id,
278
- content: toolCallResult
279
- };
280
- agent.messages.splice(messageIndex + 1, 0, toolMessage);
281
- if (wildcardTool?.followUp !== false) {
282
- needsFollowUp = true;
623
+ } else {
624
+ const wildcardTool = this.getTool({ toolName: "*", agentId });
625
+ if (wildcardTool) {
626
+ if (wildcardTool?.agentId && wildcardTool.agentId !== agentId) {
627
+ continue;
628
+ }
629
+ let toolCallResult = "";
630
+ let errorMessage;
631
+ let isArgumentError = false;
632
+ if (wildcardTool?.handler) {
633
+ let parsedArgs;
634
+ try {
635
+ parsedArgs = JSON.parse(toolCall.function.arguments);
636
+ } catch (error) {
637
+ const parseError = error instanceof Error ? error : new Error(String(error));
638
+ errorMessage = parseError.message;
639
+ isArgumentError = true;
640
+ await this.emitError({
641
+ error: parseError,
642
+ code: "tool_argument_parse_failed" /* TOOL_ARGUMENT_PARSE_FAILED */,
643
+ context: {
644
+ agentId: effectiveAgentId,
645
+ toolCallId: toolCall.id,
646
+ toolName: toolCall.function.name,
647
+ rawArguments: toolCall.function.arguments,
648
+ toolType: "wildcard",
649
+ messageId: message.id
650
+ }
651
+ });
652
+ }
653
+ const wildcardArgs = {
654
+ toolName: toolCall.function.name,
655
+ args: parsedArgs
656
+ };
657
+ await this.notifySubscribers(
658
+ (subscriber) => subscriber.onToolExecutionStart?.({
659
+ copilotkit: this,
660
+ toolCallId: toolCall.id,
661
+ agentId: effectiveAgentId,
662
+ toolName: toolCall.function.name,
663
+ args: wildcardArgs
664
+ }),
665
+ "Subscriber onToolExecutionStart error:"
666
+ );
667
+ if (!errorMessage) {
668
+ try {
669
+ const result = await wildcardTool.handler(
670
+ wildcardArgs
671
+ );
672
+ if (result === void 0 || result === null) {
673
+ toolCallResult = "";
674
+ } else if (typeof result === "string") {
675
+ toolCallResult = result;
676
+ } else {
677
+ toolCallResult = JSON.stringify(result);
678
+ }
679
+ } catch (error) {
680
+ const handlerError = error instanceof Error ? error : new Error(String(error));
681
+ errorMessage = handlerError.message;
682
+ await this.emitError({
683
+ error: handlerError,
684
+ code: "tool_handler_failed" /* TOOL_HANDLER_FAILED */,
685
+ context: {
686
+ agentId: effectiveAgentId,
687
+ toolCallId: toolCall.id,
688
+ toolName: toolCall.function.name,
689
+ parsedArgs: wildcardArgs,
690
+ toolType: "wildcard",
691
+ messageId: message.id
692
+ }
693
+ });
694
+ }
695
+ }
696
+ if (errorMessage) {
697
+ toolCallResult = `Error: ${errorMessage}`;
698
+ }
699
+ await this.notifySubscribers(
700
+ (subscriber) => subscriber.onToolExecutionEnd?.({
701
+ copilotkit: this,
702
+ toolCallId: toolCall.id,
703
+ agentId: effectiveAgentId,
704
+ toolName: toolCall.function.name,
705
+ result: errorMessage ? "" : toolCallResult,
706
+ error: errorMessage
707
+ }),
708
+ "Subscriber onToolExecutionEnd error:"
709
+ );
710
+ if (isArgumentError) {
711
+ throw new Error(errorMessage ?? "Tool execution failed");
712
+ }
713
+ }
714
+ if (!errorMessage || !isArgumentError) {
715
+ const messageIndex = agent.messages.findIndex(
716
+ (m) => m.id === message.id
717
+ );
718
+ const toolMessage = {
719
+ id: (0, import_shared.randomUUID)(),
720
+ role: "tool",
721
+ toolCallId: toolCall.id,
722
+ content: toolCallResult
723
+ };
724
+ agent.messages.splice(messageIndex + 1, 0, toolMessage);
725
+ if (!errorMessage && wildcardTool?.followUp !== false) {
726
+ needsFollowUp = true;
727
+ }
728
+ }
283
729
  }
284
730
  }
285
731
  }
@@ -291,7 +737,82 @@ var CopilotKitCore = class {
291
737
  }
292
738
  return runAgentResult;
293
739
  }
740
+ buildFrontendTools(agentId) {
741
+ return this._tools.filter((tool) => !tool.agentId || tool.agentId === agentId).map((tool) => ({
742
+ name: tool.name,
743
+ description: tool.description ?? "",
744
+ parameters: createToolSchema(tool)
745
+ }));
746
+ }
747
+ createAgentErrorSubscriber(agent, agentId) {
748
+ const emitAgentError = async (error, code, extraContext = {}) => {
749
+ const context = { ...extraContext };
750
+ if (agentId ?? agent.agentId) {
751
+ context.agentId = agentId ?? agent.agentId;
752
+ }
753
+ await this.emitError({
754
+ error,
755
+ code,
756
+ context
757
+ });
758
+ };
759
+ return {
760
+ onRunFailed: async ({ error }) => {
761
+ await emitAgentError(
762
+ error,
763
+ "agent_run_failed_event" /* AGENT_RUN_FAILED_EVENT */,
764
+ {
765
+ source: "onRunFailed"
766
+ }
767
+ );
768
+ },
769
+ onRunErrorEvent: async ({ event }) => {
770
+ const eventError = event?.rawEvent instanceof Error ? event.rawEvent : event?.rawEvent?.error instanceof Error ? event.rawEvent.error : void 0;
771
+ const errorMessage = typeof event?.rawEvent?.error === "string" ? event.rawEvent.error : event?.message ?? "Agent run error";
772
+ const rawError = eventError ?? new Error(errorMessage);
773
+ if (event?.code && !rawError.code) {
774
+ rawError.code = event.code;
775
+ }
776
+ await emitAgentError(
777
+ rawError,
778
+ "agent_run_error_event" /* AGENT_RUN_ERROR_EVENT */,
779
+ {
780
+ source: "onRunErrorEvent",
781
+ event,
782
+ runtimeErrorCode: event?.code
783
+ }
784
+ );
785
+ }
786
+ };
787
+ }
294
788
  };
789
+ var EMPTY_TOOL_SCHEMA = {
790
+ type: "object",
791
+ properties: {},
792
+ additionalProperties: false
793
+ };
794
+ function createToolSchema(tool) {
795
+ if (!tool.parameters) {
796
+ return EMPTY_TOOL_SCHEMA;
797
+ }
798
+ const rawSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(tool.parameters, {
799
+ $refStrategy: "none"
800
+ });
801
+ if (!rawSchema || typeof rawSchema !== "object") {
802
+ return { ...EMPTY_TOOL_SCHEMA };
803
+ }
804
+ const { $schema, ...schema } = rawSchema;
805
+ if (typeof schema.type !== "string") {
806
+ schema.type = "object";
807
+ }
808
+ if (typeof schema.properties !== "object" || schema.properties === null) {
809
+ schema.properties = {};
810
+ }
811
+ if (schema.additionalProperties === void 0) {
812
+ schema.additionalProperties = false;
813
+ }
814
+ return schema;
815
+ }
295
816
 
296
817
  // src/types.ts
297
818
  var ToolCallStatus = /* @__PURE__ */ ((ToolCallStatus2) => {
@@ -519,7 +1040,9 @@ ${indent}${fence}`;
519
1040
  // Annotate the CommonJS export names for ESM import in node:
520
1041
  0 && (module.exports = {
521
1042
  CopilotKitCore,
522
- CopilotKitHttpAgent,
1043
+ CopilotKitCoreErrorCode,
1044
+ CopilotKitCoreRuntimeConnectionStatus,
1045
+ ProxiedCopilotRuntimeAgent,
523
1046
  ToolCallStatus,
524
1047
  completePartialMarkdown
525
1048
  });