@copilotkit/core 1.75.0 → 1.75.2
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.cjs +100 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +18 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +101 -29
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +106 -29
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { Throttler } from "@tanstack/pacer";
|
|
|
2
2
|
import { AGUIConnectNotImplementedError, AbstractAgent, EventType, HttpAgent, buildResumeArray, isInterruptExpired, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
|
|
3
3
|
import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, parseInspectorMetadataV1, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
|
|
4
4
|
import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, combineLatest, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, observeOn, of, switchMap, throwError } from "rxjs";
|
|
5
|
-
import { catchError, concatWith, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn as observeOn$1, scan, share, shareReplay, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
|
|
5
|
+
import { catchError, concatWith, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn as observeOn$1, scan, share, shareReplay, startWith, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
|
|
6
6
|
import { Socket } from "phoenix";
|
|
7
7
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
8
8
|
|
|
@@ -24,20 +24,23 @@ import { zodToJsonSchema } from "zod-to-json-schema";
|
|
|
24
24
|
*
|
|
25
25
|
* `transformChunks` is still applied — message reassembly is needed either way.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* Connection-local replay hooks track the phase before applying events. An
|
|
28
|
+
* explicitly live RUN_ERROR clears busy without closing the connection;
|
|
29
|
+
* historical errors remain data. Connections without hooks retain the existing
|
|
30
|
+
* completion behavior. Subscriber, detach, and result contracts are preserved.
|
|
30
31
|
*
|
|
31
32
|
* TODO: Remove this in favour of the base implementation once AG-UI's
|
|
32
33
|
* AbstractAgent supports opting out of `verifyEvents` for transports whose
|
|
33
|
-
* connection life-cycle isn't a single run
|
|
34
|
+
* connection life-cycle isn't a single run AND preserves the connection-local
|
|
35
|
+
* replay lifecycle and running-state behavior below. Skipping verification alone
|
|
36
|
+
* is insufficient. As of `@ag-ui/client@0.0.57`
|
|
34
37
|
* `connectAgent(parameters?, subscriber?)` takes no such option.
|
|
35
38
|
*
|
|
36
39
|
* @param agent - The agent whose `connect()` stream should be consumed.
|
|
37
40
|
* @param parameters - Run parameters, forwarded to `prepareRunAgentInput`.
|
|
38
41
|
* @param subscriber - Optional one-shot subscriber for this connect call.
|
|
39
42
|
*/
|
|
40
|
-
async function ɵconnectWithoutEventVerification(agent, parameters, subscriber) {
|
|
43
|
+
async function ɵconnectWithoutEventVerification(agent, parameters, subscriber, connect) {
|
|
41
44
|
const self = agent;
|
|
42
45
|
try {
|
|
43
46
|
agent.isRunning = true;
|
|
@@ -45,10 +48,20 @@ async function ɵconnectWithoutEventVerification(agent, parameters, subscriber)
|
|
|
45
48
|
const input = self.prepareRunAgentInput(parameters);
|
|
46
49
|
let result;
|
|
47
50
|
const previousMessageIds = new Set(agent.messages.map((m) => m.id));
|
|
51
|
+
let isReplaying = true;
|
|
52
|
+
const liveErrors = /* @__PURE__ */ new WeakSet();
|
|
48
53
|
const subscribers = [
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
{
|
|
55
|
+
onRunStartedEvent: () => {
|
|
56
|
+
agent.isRunning = true;
|
|
57
|
+
},
|
|
58
|
+
onRunErrorEvent: ({ event }) => {
|
|
59
|
+
if (liveErrors.has(event)) agent.isRunning = false;
|
|
60
|
+
},
|
|
61
|
+
onRunFinishedEvent: (event) => {
|
|
62
|
+
if (event.outcome === "success") result = event.result;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
52
65
|
...agent.subscribers,
|
|
53
66
|
subscriber ?? {}
|
|
54
67
|
];
|
|
@@ -58,7 +71,18 @@ async function ɵconnectWithoutEventVerification(agent, parameters, subscriber)
|
|
|
58
71
|
self.activeRunCompletionPromise = new Promise((resolve) => {
|
|
59
72
|
resolveCompletion = resolve;
|
|
60
73
|
});
|
|
61
|
-
const
|
|
74
|
+
const lifecycle = {
|
|
75
|
+
onReplayStarted: () => {
|
|
76
|
+
isReplaying = true;
|
|
77
|
+
agent.isRunning = true;
|
|
78
|
+
},
|
|
79
|
+
onReplayFinished: () => {
|
|
80
|
+
isReplaying = false;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const source$ = defer(() => connect ? connect(input, lifecycle) : self.connect(input)).pipe(tap((event) => {
|
|
84
|
+
if (!isReplaying && event.type === EventType.RUN_ERROR) liveErrors.add(event);
|
|
85
|
+
}), transformChunks(self.debugLogger), takeUntil(self.activeRunDetach$));
|
|
62
86
|
const applied$ = self.apply(input, source$, subscribers);
|
|
63
87
|
await lastValueFrom(self.processApplyEvents(input, applied$, subscribers).pipe(catchError((error) => {
|
|
64
88
|
agent.isRunning = false;
|
|
@@ -209,6 +233,7 @@ const REPLAY_FAILED_EVENT = "replay_failed";
|
|
|
209
233
|
const STREAM_IDLE_EVENT = "stream_idle";
|
|
210
234
|
const STOP_RUN_EVENT = "stop_run";
|
|
211
235
|
const CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS = 100;
|
|
236
|
+
const CONNECT_IDLE_WARNING_MS = 3e4;
|
|
212
237
|
const MAX_UNOPENED_CREDENTIAL_REFRESHES = 2;
|
|
213
238
|
var AgentThreadLockedError = class extends Error {
|
|
214
239
|
constructor(threadId) {
|
|
@@ -296,7 +321,7 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
296
321
|
...parameters,
|
|
297
322
|
runId: this.canonicalRunId
|
|
298
323
|
};
|
|
299
|
-
return ɵconnectWithoutEventVerification(this, effectiveParameters, subscriber);
|
|
324
|
+
return ɵconnectWithoutEventVerification(this, effectiveParameters, subscriber, (input, lifecycle) => this.connect(input, lifecycle));
|
|
300
325
|
}
|
|
301
326
|
abortRun() {
|
|
302
327
|
if (this.activeChannel && this.canonicalRunId) {
|
|
@@ -345,17 +370,22 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
345
370
|
* gateway only streams events past it instead of replaying the
|
|
346
371
|
* entire history every time the chat re-opens a socket.
|
|
347
372
|
*/
|
|
348
|
-
connect(input) {
|
|
373
|
+
connect(input, lifecycle) {
|
|
349
374
|
this.threadId = input.threadId;
|
|
350
375
|
this.canonicalRunId = null;
|
|
351
376
|
const replayCursor = this.getReconnectCursor(input);
|
|
352
377
|
return defer(() => this.requestJoinCredentials$("connect", input, replayCursor)).pipe(switchMap((credentials) => {
|
|
353
|
-
if (credentials === null)
|
|
378
|
+
if (credentials === null) {
|
|
379
|
+
lifecycle?.onReplayStarted?.();
|
|
380
|
+
lifecycle?.onReplayFinished?.();
|
|
381
|
+
return EMPTY;
|
|
382
|
+
}
|
|
354
383
|
const canonicalInput = this.applyCanonicalRunIdentity(input, credentials, { fallbackToInputRunId: false });
|
|
355
384
|
return this.observeThread$(canonicalInput, credentials, {
|
|
356
385
|
completeOnRunError: false,
|
|
357
386
|
streamMode: "connect",
|
|
358
|
-
replayCursor
|
|
387
|
+
replayCursor,
|
|
388
|
+
lifecycle
|
|
359
389
|
});
|
|
360
390
|
}));
|
|
361
391
|
}
|
|
@@ -455,8 +485,24 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
455
485
|
}
|
|
456
486
|
observeThreadSession$(input, credentials, options) {
|
|
457
487
|
return defer(() => {
|
|
488
|
+
options.lifecycle?.onReplayStarted?.();
|
|
458
489
|
let ownSocket = null;
|
|
459
490
|
let ownChannel = null;
|
|
491
|
+
let replayFinished = false;
|
|
492
|
+
let warnedAboutIdle = false;
|
|
493
|
+
let idleWarning;
|
|
494
|
+
const clearIdleWarning = () => {
|
|
495
|
+
clearTimeout(idleWarning);
|
|
496
|
+
idleWarning = void 0;
|
|
497
|
+
};
|
|
498
|
+
const scheduleIdleWarning = () => {
|
|
499
|
+
clearIdleWarning();
|
|
500
|
+
if (options.streamMode !== "connect" || !replayFinished || warnedAboutIdle) return;
|
|
501
|
+
idleWarning = setTimeout(() => {
|
|
502
|
+
warnedAboutIdle = true;
|
|
503
|
+
this.debugLogger?.lifecycle("INTELLIGENCE", "No progress or stream_idle for 30 seconds after replay_complete; the run may still be active or its status unavailable.", { threadId: input.threadId });
|
|
504
|
+
}, CONNECT_IDLE_WARNING_MS);
|
|
505
|
+
};
|
|
460
506
|
const socket$ = ɵphoenixSocket$({
|
|
461
507
|
url: credentials.realtime.clientUrl,
|
|
462
508
|
options: {
|
|
@@ -490,6 +536,7 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
490
536
|
let latestObservedReplayCursor = null;
|
|
491
537
|
const threadEvents$ = this.observeThreadEvents$(input.threadId, channel$, options).pipe(tap((payload) => {
|
|
492
538
|
latestObservedReplayCursor = this.readEventId(payload) ?? latestObservedReplayCursor;
|
|
539
|
+
scheduleIdleWarning();
|
|
493
540
|
}), share());
|
|
494
541
|
const controlCursor = {
|
|
495
542
|
applied: null,
|
|
@@ -498,18 +545,33 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
498
545
|
const replayFailed$ = channel$.pipe(switchMap$1(({ channel }) => this.observeChannelEvent$(channel, REPLAY_FAILED_EVENT)), tap(() => {
|
|
499
546
|
controlCursor.replayFailed = true;
|
|
500
547
|
}));
|
|
501
|
-
const replayComplete$ = this.observeControlEvent$(input.threadId, channel$, REPLAY_COMPLETE_EVENT, controlCursor).pipe(
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
548
|
+
const replayComplete$ = this.observeControlEvent$(input.threadId, channel$, REPLAY_COMPLETE_EVENT, controlCursor).pipe(tap(() => {
|
|
549
|
+
replayFinished = true;
|
|
550
|
+
scheduleIdleWarning();
|
|
551
|
+
options.lifecycle?.onReplayFinished?.();
|
|
552
|
+
}), share());
|
|
553
|
+
const streamIdle$ = this.observeControlEvent$(input.threadId, channel$, STREAM_IDLE_EVENT, controlCursor).pipe(share());
|
|
554
|
+
const replayRestart$ = merge(this.observeControlEvent$(input.threadId, channel$, "phx_error", controlCursor), ɵobservePhoenixSocketSignals$(socket$).pipe(filter((signal) => signal.type === "error"))).pipe(tap(() => {
|
|
555
|
+
replayFinished = false;
|
|
556
|
+
warnedAboutIdle = false;
|
|
557
|
+
clearIdleWarning();
|
|
558
|
+
options.lifecycle?.onReplayStarted?.();
|
|
559
|
+
}), share());
|
|
560
|
+
const streamIdleCompletion$ = options.streamMode === "connect" ? replayRestart$.pipe(startWith(null), switchMap(() => merge(combineLatest([replayComplete$.pipe(take(1)), streamIdle$.pipe(take(1))]), streamIdle$.pipe(take(1), filter((payload) => this.canFallbackCompleteConnect(payload, reconnectCursor, latestObservedReplayCursor)), delay(CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS), tap(() => {
|
|
561
|
+
this.debugLogger?.lifecycle("INTELLIGENCE", "Completing connection on stream_idle fallback without replay_complete.", {
|
|
562
|
+
threadId: input.threadId,
|
|
563
|
+
fallbackMs: CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS
|
|
564
|
+
});
|
|
565
|
+
})))), take(1), shareReplay({
|
|
506
566
|
bufferSize: 1,
|
|
507
567
|
refCount: true
|
|
508
|
-
}));
|
|
509
|
-
const streamIdleCompletion$ = options.streamMode === "connect" ? merge(combineLatest([replayComplete$.pipe(take(1)), streamIdle$.pipe(take(1))]), streamIdle$.pipe(take(1), filter((payload) => this.canFallbackCompleteConnect(payload, reconnectCursor, latestObservedReplayCursor)), delay(CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS))).pipe(take(1)) : EMPTY;
|
|
568
|
+
})) : EMPTY;
|
|
510
569
|
const threadCompleted$ = threadEvents$.pipe(ignoreElements(), endWith(null), take(1));
|
|
511
570
|
const terminal$ = merge(threadCompleted$, streamIdleCompletion$);
|
|
512
|
-
return merge(this.joinThreadChannel$(channel$), this.observeSocketHealth$(socket$, options.onSocketOpen).pipe(takeUntil(terminal$)), threadEvents$.pipe(takeUntil(streamIdleCompletion$)),
|
|
571
|
+
return merge(replayFailed$.pipe(ignoreElements(), takeUntil(terminal$)), replayComplete$.pipe(ignoreElements(), takeUntil(terminal$)), this.joinThreadChannel$(channel$), this.observeSocketHealth$(socket$, options.onSocketOpen).pipe(takeUntil(terminal$)), threadEvents$.pipe(takeUntil(streamIdleCompletion$)), streamIdleCompletion$.pipe(ignoreElements(), takeUntil(threadCompleted$))).pipe(finalize(() => {
|
|
572
|
+
clearIdleWarning();
|
|
573
|
+
this.cleanupOwned(ownChannel, ownSocket);
|
|
574
|
+
}));
|
|
513
575
|
});
|
|
514
576
|
}
|
|
515
577
|
joinThreadChannel$(channel$) {
|
|
@@ -991,7 +1053,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
|
|
|
991
1053
|
});
|
|
992
1054
|
}
|
|
993
1055
|
async connectAgent(parameters, subscriber) {
|
|
994
|
-
if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return ɵconnectWithoutEventVerification(this, parameters, subscriber);
|
|
1056
|
+
if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return ɵconnectWithoutEventVerification(this, parameters, subscriber, (input, lifecycle) => this.connect(input, lifecycle));
|
|
995
1057
|
if (this.delegate) await this.delegate.detachActiveRun();
|
|
996
1058
|
await this.resolveDelegate();
|
|
997
1059
|
const delegate = this.delegate;
|
|
@@ -1012,7 +1074,10 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
|
|
|
1012
1074
|
this.isRunning = false;
|
|
1013
1075
|
},
|
|
1014
1076
|
onRunErrorEvent: () => {
|
|
1015
|
-
this.isRunning =
|
|
1077
|
+
this.isRunning = delegate.isRunning;
|
|
1078
|
+
},
|
|
1079
|
+
onRunStartedEvent: () => {
|
|
1080
|
+
this.isRunning = delegate.isRunning;
|
|
1016
1081
|
}
|
|
1017
1082
|
});
|
|
1018
1083
|
const forwardedSubs = this.subscribers.map((s) => delegate.subscribe(s));
|
|
@@ -1027,9 +1092,9 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
|
|
|
1027
1092
|
for (const sub of forwardedSubs) sub.unsubscribe();
|
|
1028
1093
|
}
|
|
1029
1094
|
}
|
|
1030
|
-
connect(input) {
|
|
1031
|
-
if (this.runtimeMode === "pending" || this.transport === "auto" && this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return defer(() => from(this.ensureRuntimeConfiguration())).pipe(switchMap$1(() => this.connect(input)));
|
|
1032
|
-
if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) return this.#connectViaDelegate(input);
|
|
1095
|
+
connect(input, lifecycle) {
|
|
1096
|
+
if (this.runtimeMode === "pending" || this.transport === "auto" && this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return defer(() => from(this.ensureRuntimeConfiguration())).pipe(switchMap$1(() => this.connect(input, lifecycle)));
|
|
1097
|
+
if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) return this.#connectViaDelegate(input, lifecycle);
|
|
1033
1098
|
return this.#connectViaHttp(input);
|
|
1034
1099
|
}
|
|
1035
1100
|
run(input) {
|
|
@@ -1037,8 +1102,8 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
|
|
|
1037
1102
|
if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) return this.#runViaDelegate(input);
|
|
1038
1103
|
return this.#runViaHttp(input);
|
|
1039
1104
|
}
|
|
1040
|
-
#connectViaDelegate(input) {
|
|
1041
|
-
return defer(() => from(this.resolveDelegate())).pipe(switchMap$1((delegate) => withAbortErrorHandling(delegate.connect(input))));
|
|
1105
|
+
#connectViaDelegate(input, lifecycle) {
|
|
1106
|
+
return defer(() => from(this.resolveDelegate())).pipe(switchMap$1((delegate) => withAbortErrorHandling(delegate.connect(input, lifecycle))));
|
|
1042
1107
|
}
|
|
1043
1108
|
#connectViaHttp(unfiltered) {
|
|
1044
1109
|
const input = this.#applyMessageFilter(unfiltered);
|
|
@@ -1232,6 +1297,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
|
|
|
1232
1297
|
delegate.agentId = this.routedAgentId();
|
|
1233
1298
|
delegate.description = this.description;
|
|
1234
1299
|
delegate.threadId = this.threadId;
|
|
1300
|
+
delegate.debugLogger = this.debugLogger;
|
|
1235
1301
|
delegate.setMessages(this.messages);
|
|
1236
1302
|
delegate.setState(this.state);
|
|
1237
1303
|
if (hasHeaders(delegate)) delegate.headers = { ...this.headers };
|
|
@@ -5403,6 +5469,7 @@ const ALLOWED_KEYS = new Set([
|
|
|
5403
5469
|
"onMessagesChanged",
|
|
5404
5470
|
"onStateChanged",
|
|
5405
5471
|
"onRunInitialized",
|
|
5472
|
+
"onRunStartedEvent",
|
|
5406
5473
|
"onRunFinalized",
|
|
5407
5474
|
"onRunFailed",
|
|
5408
5475
|
"onRunErrorEvent"
|
|
@@ -6004,6 +6071,10 @@ var CopilotKitCore = class {
|
|
|
6004
6071
|
const fn = sub.onRunInitialized;
|
|
6005
6072
|
guarded.onRunInitialized = (params) => safeCall("onRunInitialized", fn, params);
|
|
6006
6073
|
}
|
|
6074
|
+
if (sub.onRunStartedEvent) {
|
|
6075
|
+
const fn = sub.onRunStartedEvent;
|
|
6076
|
+
guarded.onRunStartedEvent = (params) => safeCall("onRunStartedEvent", fn, params);
|
|
6077
|
+
}
|
|
6007
6078
|
if (sub.onRunFinalized) {
|
|
6008
6079
|
const fn = sub.onRunFinalized;
|
|
6009
6080
|
guarded.onRunFinalized = (params) => safeCall("onRunFinalized", fn, params);
|
|
@@ -6055,6 +6126,7 @@ var CopilotKitCore = class {
|
|
|
6055
6126
|
});
|
|
6056
6127
|
const lifecycleOnly = {};
|
|
6057
6128
|
if (subscriber.onRunInitialized) lifecycleOnly.onRunInitialized = subscriber.onRunInitialized;
|
|
6129
|
+
if (subscriber.onRunStartedEvent) lifecycleOnly.onRunStartedEvent = subscriber.onRunStartedEvent;
|
|
6058
6130
|
if (subscriber.onRunFinalized) lifecycleOnly.onRunFinalized = subscriber.onRunFinalized;
|
|
6059
6131
|
if (subscriber.onRunFailed) lifecycleOnly.onRunFailed = subscriber.onRunFailed;
|
|
6060
6132
|
if (subscriber.onRunErrorEvent) lifecycleOnly.onRunErrorEvent = subscriber.onRunErrorEvent;
|