@copilotkit/runtime 1.55.0-next.7 → 1.55.0-next.8
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/CHANGELOG.md +12 -0
- package/dist/agent/index.cjs +184 -173
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +184 -173
- package/dist/agent/index.mjs.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/package.json +2 -2
- package/src/agent/__tests__/basic-agent.test.ts +455 -5
- package/src/agent/__tests__/test-helpers.ts +27 -12
- package/src/agent/index.ts +44 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @copilotkit/runtime
|
|
2
2
|
|
|
3
|
+
## 1.55.0-next.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8aafcbe: fix(agent): harden BuiltInAgent reasoning lifecycle
|
|
8
|
+
- Skip empty reasoning deltas (violates @ag-ui/core schema)
|
|
9
|
+
- Auto-close reasoning lifecycle when SDK omits reasoning-end (on consecutive-start, phase transitions, abort, error, and fallback paths)
|
|
10
|
+
- Make reasoning-end idempotent to prevent duplicate close events when auto-close already fired
|
|
11
|
+
- Regenerate reasoningMessageId for consecutive reasoning blocks when SDK provides no id
|
|
12
|
+
- Close reasoning in outer catch block so exceptions mid-reasoning emit proper lifecycle events
|
|
13
|
+
- @copilotkit/shared@1.55.0-next.8
|
|
14
|
+
|
|
3
15
|
## 1.55.0-next.7
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/agent/index.cjs
CHANGED
|
@@ -320,6 +320,23 @@ This is state from the application that you can edit by calling AGUISendStateSna
|
|
|
320
320
|
const abortController = new AbortController();
|
|
321
321
|
this.abortController = abortController;
|
|
322
322
|
let terminalEventEmitted = false;
|
|
323
|
+
let messageId = (0, crypto.randomUUID)();
|
|
324
|
+
let reasoningMessageId = (0, crypto.randomUUID)();
|
|
325
|
+
let isInReasoning = false;
|
|
326
|
+
const closeReasoningIfOpen = () => {
|
|
327
|
+
if (!isInReasoning) return;
|
|
328
|
+
isInReasoning = false;
|
|
329
|
+
const reasoningMsgEnd = {
|
|
330
|
+
type: _ag_ui_client.EventType.REASONING_MESSAGE_END,
|
|
331
|
+
messageId: reasoningMessageId
|
|
332
|
+
};
|
|
333
|
+
subscriber.next(reasoningMsgEnd);
|
|
334
|
+
const reasoningEnd = {
|
|
335
|
+
type: _ag_ui_client.EventType.REASONING_END,
|
|
336
|
+
messageId: reasoningMessageId
|
|
337
|
+
};
|
|
338
|
+
subscriber.next(reasoningEnd);
|
|
339
|
+
};
|
|
323
340
|
try {
|
|
324
341
|
streamTextParams.tools = {
|
|
325
342
|
...streamTextParams.tools,
|
|
@@ -377,8 +394,6 @@ This is state from the application that you can edit by calling AGUISendStateSna
|
|
|
377
394
|
...streamTextParams,
|
|
378
395
|
abortSignal: abortController.signal
|
|
379
396
|
});
|
|
380
|
-
let messageId = (0, crypto.randomUUID)();
|
|
381
|
-
let reasoningMessageId = (0, crypto.randomUUID)();
|
|
382
397
|
const toolCallStates = /* @__PURE__ */ new Map();
|
|
383
398
|
const ensureToolCallState = (toolCallId) => {
|
|
384
399
|
let state = toolCallStates.get(toolCallId);
|
|
@@ -392,194 +407,189 @@ This is state from the application that you can edit by calling AGUISendStateSna
|
|
|
392
407
|
}
|
|
393
408
|
return state;
|
|
394
409
|
};
|
|
395
|
-
for await (const part of response.fullStream)
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
terminalEventEmitted = true;
|
|
404
|
-
subscriber.complete();
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
407
|
-
case "reasoning-start": {
|
|
408
|
-
const providedId = "id" in part ? part.id : void 0;
|
|
409
|
-
if (providedId && providedId !== "0") reasoningMessageId = providedId;
|
|
410
|
-
const reasoningStartEvent = {
|
|
411
|
-
type: _ag_ui_client.EventType.REASONING_START,
|
|
412
|
-
messageId: reasoningMessageId
|
|
413
|
-
};
|
|
414
|
-
subscriber.next(reasoningStartEvent);
|
|
415
|
-
const reasoningMessageStart = {
|
|
416
|
-
type: _ag_ui_client.EventType.REASONING_MESSAGE_START,
|
|
417
|
-
messageId: reasoningMessageId,
|
|
418
|
-
role: "reasoning"
|
|
419
|
-
};
|
|
420
|
-
subscriber.next(reasoningMessageStart);
|
|
421
|
-
break;
|
|
422
|
-
}
|
|
423
|
-
case "reasoning-delta": {
|
|
424
|
-
const reasoningDeltaEvent = {
|
|
425
|
-
type: _ag_ui_client.EventType.REASONING_MESSAGE_CONTENT,
|
|
426
|
-
messageId: reasoningMessageId,
|
|
427
|
-
delta: ("text" in part ? part.text : part.delta) ?? ""
|
|
428
|
-
};
|
|
429
|
-
subscriber.next(reasoningDeltaEvent);
|
|
430
|
-
break;
|
|
431
|
-
}
|
|
432
|
-
case "reasoning-end": {
|
|
433
|
-
const reasoningMessageEnd = {
|
|
434
|
-
type: _ag_ui_client.EventType.REASONING_MESSAGE_END,
|
|
435
|
-
messageId: reasoningMessageId
|
|
436
|
-
};
|
|
437
|
-
subscriber.next(reasoningMessageEnd);
|
|
438
|
-
const reasoningEndEvent = {
|
|
439
|
-
type: _ag_ui_client.EventType.REASONING_END,
|
|
440
|
-
messageId: reasoningMessageId
|
|
441
|
-
};
|
|
442
|
-
subscriber.next(reasoningEndEvent);
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
case "tool-input-start": {
|
|
446
|
-
const toolCallId = part.id;
|
|
447
|
-
const state = ensureToolCallState(toolCallId);
|
|
448
|
-
state.toolName = part.toolName;
|
|
449
|
-
if (!state.started) {
|
|
450
|
-
state.started = true;
|
|
451
|
-
const startEvent = {
|
|
452
|
-
type: _ag_ui_client.EventType.TOOL_CALL_START,
|
|
453
|
-
parentMessageId: messageId,
|
|
454
|
-
toolCallId,
|
|
455
|
-
toolCallName: part.toolName
|
|
410
|
+
for await (const part of response.fullStream) {
|
|
411
|
+
if (part.type !== "reasoning-delta") closeReasoningIfOpen();
|
|
412
|
+
switch (part.type) {
|
|
413
|
+
case "abort": {
|
|
414
|
+
const abortEndEvent = {
|
|
415
|
+
type: _ag_ui_client.EventType.RUN_FINISHED,
|
|
416
|
+
threadId: input.threadId,
|
|
417
|
+
runId: input.runId
|
|
456
418
|
};
|
|
457
|
-
subscriber.next(
|
|
419
|
+
subscriber.next(abortEndEvent);
|
|
420
|
+
terminalEventEmitted = true;
|
|
421
|
+
subscriber.complete();
|
|
422
|
+
break;
|
|
458
423
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
role: "assistant",
|
|
484
|
-
messageId,
|
|
485
|
-
delta: textDelta
|
|
486
|
-
};
|
|
487
|
-
subscriber.next(textEvent);
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
490
|
-
case "tool-call": {
|
|
491
|
-
const toolCallId = part.toolCallId;
|
|
492
|
-
const state = ensureToolCallState(toolCallId);
|
|
493
|
-
state.toolName = part.toolName ?? state.toolName;
|
|
494
|
-
if (!state.started) {
|
|
495
|
-
state.started = true;
|
|
496
|
-
const startEvent = {
|
|
497
|
-
type: _ag_ui_client.EventType.TOOL_CALL_START,
|
|
498
|
-
parentMessageId: messageId,
|
|
499
|
-
toolCallId,
|
|
500
|
-
toolCallName: part.toolName
|
|
424
|
+
case "reasoning-start": {
|
|
425
|
+
const providedId = "id" in part ? part.id : void 0;
|
|
426
|
+
reasoningMessageId = providedId && providedId !== "0" ? providedId : (0, crypto.randomUUID)();
|
|
427
|
+
const reasoningStartEvent = {
|
|
428
|
+
type: _ag_ui_client.EventType.REASONING_START,
|
|
429
|
+
messageId: reasoningMessageId
|
|
430
|
+
};
|
|
431
|
+
subscriber.next(reasoningStartEvent);
|
|
432
|
+
const reasoningMessageStart = {
|
|
433
|
+
type: _ag_ui_client.EventType.REASONING_MESSAGE_START,
|
|
434
|
+
messageId: reasoningMessageId,
|
|
435
|
+
role: "reasoning"
|
|
436
|
+
};
|
|
437
|
+
subscriber.next(reasoningMessageStart);
|
|
438
|
+
isInReasoning = true;
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
case "reasoning-delta": {
|
|
442
|
+
const delta = part.text ?? "";
|
|
443
|
+
if (!delta) break;
|
|
444
|
+
const reasoningDeltaEvent = {
|
|
445
|
+
type: _ag_ui_client.EventType.REASONING_MESSAGE_CONTENT,
|
|
446
|
+
messageId: reasoningMessageId,
|
|
447
|
+
delta
|
|
501
448
|
};
|
|
502
|
-
subscriber.next(
|
|
449
|
+
subscriber.next(reasoningDeltaEvent);
|
|
450
|
+
break;
|
|
503
451
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
452
|
+
case "reasoning-end": break;
|
|
453
|
+
case "tool-input-start": {
|
|
454
|
+
const toolCallId = part.id;
|
|
455
|
+
const state = ensureToolCallState(toolCallId);
|
|
456
|
+
state.toolName = part.toolName;
|
|
457
|
+
if (!state.started) {
|
|
458
|
+
state.started = true;
|
|
459
|
+
const startEvent = {
|
|
460
|
+
type: _ag_ui_client.EventType.TOOL_CALL_START,
|
|
461
|
+
parentMessageId: messageId,
|
|
462
|
+
toolCallId,
|
|
463
|
+
toolCallName: part.toolName
|
|
464
|
+
};
|
|
465
|
+
subscriber.next(startEvent);
|
|
511
466
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
case "tool-input-delta": {
|
|
470
|
+
const toolCallId = part.id;
|
|
471
|
+
const state = ensureToolCallState(toolCallId);
|
|
472
|
+
state.hasArgsDelta = true;
|
|
473
|
+
const argsEvent = {
|
|
474
|
+
type: _ag_ui_client.EventType.TOOL_CALL_ARGS,
|
|
475
|
+
toolCallId,
|
|
476
|
+
delta: part.delta
|
|
477
|
+
};
|
|
478
|
+
subscriber.next(argsEvent);
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
case "tool-input-end": break;
|
|
482
|
+
case "text-start": {
|
|
483
|
+
const providedId = "id" in part ? part.id : void 0;
|
|
484
|
+
messageId = providedId && providedId !== "0" ? providedId : (0, crypto.randomUUID)();
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case "text-delta": {
|
|
488
|
+
const textDelta = "text" in part ? part.text : "";
|
|
489
|
+
const textEvent = {
|
|
490
|
+
type: _ag_ui_client.EventType.TEXT_MESSAGE_CHUNK,
|
|
491
|
+
role: "assistant",
|
|
492
|
+
messageId,
|
|
493
|
+
delta: textDelta
|
|
494
|
+
};
|
|
495
|
+
subscriber.next(textEvent);
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
case "tool-call": {
|
|
499
|
+
const toolCallId = part.toolCallId;
|
|
500
|
+
const state = ensureToolCallState(toolCallId);
|
|
501
|
+
state.toolName = part.toolName ?? state.toolName;
|
|
502
|
+
if (!state.started) {
|
|
503
|
+
state.started = true;
|
|
504
|
+
const startEvent = {
|
|
505
|
+
type: _ag_ui_client.EventType.TOOL_CALL_START,
|
|
506
|
+
parentMessageId: messageId,
|
|
515
507
|
toolCallId,
|
|
516
|
-
|
|
508
|
+
toolCallName: part.toolName
|
|
517
509
|
};
|
|
518
|
-
subscriber.next(
|
|
519
|
-
state.hasArgsDelta = true;
|
|
510
|
+
subscriber.next(startEvent);
|
|
520
511
|
}
|
|
512
|
+
if (!state.hasArgsDelta && "input" in part && part.input !== void 0) {
|
|
513
|
+
let serializedInput = "";
|
|
514
|
+
if (typeof part.input === "string") serializedInput = part.input;
|
|
515
|
+
else try {
|
|
516
|
+
serializedInput = JSON.stringify(part.input);
|
|
517
|
+
} catch {
|
|
518
|
+
serializedInput = String(part.input);
|
|
519
|
+
}
|
|
520
|
+
if (serializedInput.length > 0) {
|
|
521
|
+
const argsEvent = {
|
|
522
|
+
type: _ag_ui_client.EventType.TOOL_CALL_ARGS,
|
|
523
|
+
toolCallId,
|
|
524
|
+
delta: serializedInput
|
|
525
|
+
};
|
|
526
|
+
subscriber.next(argsEvent);
|
|
527
|
+
state.hasArgsDelta = true;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (!state.ended) {
|
|
531
|
+
state.ended = true;
|
|
532
|
+
const endEvent = {
|
|
533
|
+
type: _ag_ui_client.EventType.TOOL_CALL_END,
|
|
534
|
+
toolCallId
|
|
535
|
+
};
|
|
536
|
+
subscriber.next(endEvent);
|
|
537
|
+
}
|
|
538
|
+
break;
|
|
521
539
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
540
|
+
case "tool-result": {
|
|
541
|
+
const toolResult = "output" in part ? part.output : null;
|
|
542
|
+
const toolName = "toolName" in part ? part.toolName : "";
|
|
543
|
+
toolCallStates.delete(part.toolCallId);
|
|
544
|
+
if (toolName === "AGUISendStateSnapshot" && toolResult && typeof toolResult === "object") {
|
|
545
|
+
const stateSnapshotEvent = {
|
|
546
|
+
type: _ag_ui_client.EventType.STATE_SNAPSHOT,
|
|
547
|
+
snapshot: toolResult.snapshot
|
|
548
|
+
};
|
|
549
|
+
subscriber.next(stateSnapshotEvent);
|
|
550
|
+
} else if (toolName === "AGUISendStateDelta" && toolResult && typeof toolResult === "object") {
|
|
551
|
+
const stateDeltaEvent = {
|
|
552
|
+
type: _ag_ui_client.EventType.STATE_DELTA,
|
|
553
|
+
delta: toolResult.delta
|
|
554
|
+
};
|
|
555
|
+
subscriber.next(stateDeltaEvent);
|
|
556
|
+
}
|
|
557
|
+
const resultEvent = {
|
|
558
|
+
type: _ag_ui_client.EventType.TOOL_CALL_RESULT,
|
|
559
|
+
role: "tool",
|
|
560
|
+
messageId: (0, crypto.randomUUID)(),
|
|
561
|
+
toolCallId: part.toolCallId,
|
|
562
|
+
content: JSON.stringify(toolResult)
|
|
527
563
|
};
|
|
528
|
-
subscriber.next(
|
|
564
|
+
subscriber.next(resultEvent);
|
|
565
|
+
break;
|
|
529
566
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
toolCallStates.delete(part.toolCallId);
|
|
536
|
-
if (toolName === "AGUISendStateSnapshot" && toolResult && typeof toolResult === "object") {
|
|
537
|
-
const stateSnapshotEvent = {
|
|
538
|
-
type: _ag_ui_client.EventType.STATE_SNAPSHOT,
|
|
539
|
-
snapshot: toolResult.snapshot
|
|
567
|
+
case "finish": {
|
|
568
|
+
const finishedEvent = {
|
|
569
|
+
type: _ag_ui_client.EventType.RUN_FINISHED,
|
|
570
|
+
threadId: input.threadId,
|
|
571
|
+
runId: input.runId
|
|
540
572
|
};
|
|
541
|
-
subscriber.next(
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
573
|
+
subscriber.next(finishedEvent);
|
|
574
|
+
terminalEventEmitted = true;
|
|
575
|
+
subscriber.complete();
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
case "error": {
|
|
579
|
+
if (abortController.signal.aborted) break;
|
|
580
|
+
const runErrorEvent = {
|
|
581
|
+
type: _ag_ui_client.EventType.RUN_ERROR,
|
|
582
|
+
message: part.error + ""
|
|
546
583
|
};
|
|
547
|
-
subscriber.next(
|
|
584
|
+
subscriber.next(runErrorEvent);
|
|
585
|
+
terminalEventEmitted = true;
|
|
586
|
+
subscriber.error(part.error);
|
|
587
|
+
break;
|
|
548
588
|
}
|
|
549
|
-
const resultEvent = {
|
|
550
|
-
type: _ag_ui_client.EventType.TOOL_CALL_RESULT,
|
|
551
|
-
role: "tool",
|
|
552
|
-
messageId: (0, crypto.randomUUID)(),
|
|
553
|
-
toolCallId: part.toolCallId,
|
|
554
|
-
content: JSON.stringify(toolResult)
|
|
555
|
-
};
|
|
556
|
-
subscriber.next(resultEvent);
|
|
557
|
-
break;
|
|
558
|
-
}
|
|
559
|
-
case "finish": {
|
|
560
|
-
const finishedEvent = {
|
|
561
|
-
type: _ag_ui_client.EventType.RUN_FINISHED,
|
|
562
|
-
threadId: input.threadId,
|
|
563
|
-
runId: input.runId
|
|
564
|
-
};
|
|
565
|
-
subscriber.next(finishedEvent);
|
|
566
|
-
terminalEventEmitted = true;
|
|
567
|
-
subscriber.complete();
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
case "error": {
|
|
571
|
-
if (abortController.signal.aborted) break;
|
|
572
|
-
const runErrorEvent = {
|
|
573
|
-
type: _ag_ui_client.EventType.RUN_ERROR,
|
|
574
|
-
message: part.error + ""
|
|
575
|
-
};
|
|
576
|
-
subscriber.next(runErrorEvent);
|
|
577
|
-
terminalEventEmitted = true;
|
|
578
|
-
subscriber.error(part.error);
|
|
579
|
-
break;
|
|
580
589
|
}
|
|
581
590
|
}
|
|
582
591
|
if (!terminalEventEmitted) {
|
|
592
|
+
closeReasoningIfOpen();
|
|
583
593
|
if (abortController.signal.aborted) {} else {
|
|
584
594
|
const finishedEvent = {
|
|
585
595
|
type: _ag_ui_client.EventType.RUN_FINISHED,
|
|
@@ -592,6 +602,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
|
|
|
592
602
|
subscriber.complete();
|
|
593
603
|
}
|
|
594
604
|
} catch (error) {
|
|
605
|
+
closeReasoningIfOpen();
|
|
595
606
|
if (abortController.signal.aborted) subscriber.complete();
|
|
596
607
|
else {
|
|
597
608
|
const runErrorEvent = {
|