@copilotkit/core 1.57.0 → 1.57.1-canary.1778272612
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 +183 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +174 -84
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +173 -83
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +183 -52
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +172 -59
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -255,10 +255,22 @@ var IntelligenceAgent = class IntelligenceAgent extends _ag_ui_client.AbstractAg
|
|
|
255
255
|
* Reconnect to an existing thread by fetching websocket credentials and
|
|
256
256
|
* joining the realtime thread channel.
|
|
257
257
|
*/
|
|
258
|
+
/**
|
|
259
|
+
* Reconnect to an existing thread by fetching websocket credentials
|
|
260
|
+
* and joining the realtime thread channel.
|
|
261
|
+
*
|
|
262
|
+
* Note: this method does NOT clear the replay cursor. Whether to
|
|
263
|
+
* request a full historical replay vs. resume from
|
|
264
|
+
* `lastSeenEventId` is a decision the caller (typically
|
|
265
|
+
* `RunHandler.connectAgent`) makes by calling
|
|
266
|
+
* {@link clearReconnectCursor} ahead of time on a fresh thread
|
|
267
|
+
* restore. Same-thread churn re-connects preserve the cursor so the
|
|
268
|
+
* gateway only streams events past it instead of replaying the
|
|
269
|
+
* entire history every time the chat re-opens a socket.
|
|
270
|
+
*/
|
|
258
271
|
connect(input) {
|
|
259
272
|
this.threadId = input.threadId;
|
|
260
273
|
this.canonicalRunId = null;
|
|
261
|
-
this.clearReconnectCursor(input.threadId);
|
|
262
274
|
return (0, rxjs.defer)(() => this.requestJoinCredentials$("connect", input)).pipe((0, rxjs.switchMap)((credentials) => {
|
|
263
275
|
if (credentials === null) return rxjs.EMPTY;
|
|
264
276
|
const canonicalInput = this.applyCanonicalRunIdentity(input, credentials, { fallbackToInputRunId: false });
|
|
@@ -440,6 +452,14 @@ var IntelligenceAgent = class IntelligenceAgent extends _ag_ui_client.AbstractAg
|
|
|
440
452
|
getReconnectCursor(input) {
|
|
441
453
|
return this.getLastSeenEventId(input.threadId);
|
|
442
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Drop the cached `lastSeenEventId` cursor for `threadId` so the
|
|
457
|
+
* next connect to that topic asks the gateway for a full historical
|
|
458
|
+
* replay (rather than resuming). Public because
|
|
459
|
+
* `RunHandler.connectAgent` calls it on a detected thread switch
|
|
460
|
+
* to rebuild local state from scratch, and skips it on same-thread
|
|
461
|
+
* churn so the gateway can resume.
|
|
462
|
+
*/
|
|
443
463
|
clearReconnectCursor(threadId) {
|
|
444
464
|
this.sharedState.lastSeenEventIds.delete(threadId);
|
|
445
465
|
}
|
|
@@ -502,6 +522,7 @@ function withAbortErrorHandling(observable) {
|
|
|
502
522
|
var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui_client.HttpAgent {
|
|
503
523
|
runtimeUrl;
|
|
504
524
|
credentials;
|
|
525
|
+
runtimeAgentId;
|
|
505
526
|
transport;
|
|
506
527
|
singleEndpointUrl;
|
|
507
528
|
runtimeMode;
|
|
@@ -512,7 +533,8 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
512
533
|
constructor(config) {
|
|
513
534
|
const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
|
|
514
535
|
const transport = config.transport ?? "auto";
|
|
515
|
-
const
|
|
536
|
+
const routedId = config.runtimeAgentId ?? config.agentId ?? "";
|
|
537
|
+
const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;
|
|
516
538
|
if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
|
|
517
539
|
super({
|
|
518
540
|
...config,
|
|
@@ -520,6 +542,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
520
542
|
});
|
|
521
543
|
this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;
|
|
522
544
|
this.credentials = config.credentials;
|
|
545
|
+
this.runtimeAgentId = config.runtimeAgentId;
|
|
523
546
|
this.transport = transport;
|
|
524
547
|
this.runtimeMode = config.runtimeMode ?? _copilotkit_shared.RUNTIME_MODE_SSE;
|
|
525
548
|
this.intelligence = config.intelligence;
|
|
@@ -527,6 +550,21 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
527
550
|
if (config.debug) this.debug = config.debug;
|
|
528
551
|
if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
|
|
529
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* The agent id used for outbound runtime requests — `runtimeAgentId` when
|
|
555
|
+
* set (manually-registered proxy), otherwise `agentId` (registry id
|
|
556
|
+
* matches runtime id). Subscriber bookkeeping keeps using `agentId`
|
|
557
|
+
* directly.
|
|
558
|
+
*
|
|
559
|
+
* Throws when both are unset: a proxy reaching an HTTP path with no
|
|
560
|
+
* routable id is a bug, and a missing id would otherwise produce a
|
|
561
|
+
* malformed `/agent//run` or `/agent/undefined/connect` URL silently.
|
|
562
|
+
*/
|
|
563
|
+
routedAgentId() {
|
|
564
|
+
const id = this.runtimeAgentId ?? this.agentId;
|
|
565
|
+
if (!id) throw new Error("ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or runtimeAgentId.");
|
|
566
|
+
return id;
|
|
567
|
+
}
|
|
530
568
|
get capabilities() {
|
|
531
569
|
return this._capabilities;
|
|
532
570
|
}
|
|
@@ -546,6 +584,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
546
584
|
}
|
|
547
585
|
if (!this.agentId || !this.threadId) return;
|
|
548
586
|
if (typeof fetch === "undefined") return;
|
|
587
|
+
const routedId = this.routedAgentId();
|
|
549
588
|
if (this.transport === "single") {
|
|
550
589
|
if (!this.singleEndpointUrl) return;
|
|
551
590
|
const headers = new Headers({
|
|
@@ -558,7 +597,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
558
597
|
body: JSON.stringify({
|
|
559
598
|
method: "agent/stop",
|
|
560
599
|
params: {
|
|
561
|
-
agentId:
|
|
600
|
+
agentId: routedId,
|
|
562
601
|
threadId: this.threadId
|
|
563
602
|
}
|
|
564
603
|
}),
|
|
@@ -569,7 +608,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
569
608
|
return;
|
|
570
609
|
}
|
|
571
610
|
if (!this.runtimeUrl) return;
|
|
572
|
-
const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(
|
|
611
|
+
const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;
|
|
573
612
|
const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
|
|
574
613
|
const base = new URL(this.runtimeUrl, origin);
|
|
575
614
|
const stopUrl = new URL(stopPath, base);
|
|
@@ -633,12 +672,13 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
633
672
|
return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
|
|
634
673
|
}
|
|
635
674
|
#connectViaHttp(input) {
|
|
675
|
+
const routedId = this.routedAgentId();
|
|
636
676
|
if (this.transport === "single") {
|
|
637
677
|
if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
|
|
638
|
-
const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId:
|
|
678
|
+
const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: routedId });
|
|
639
679
|
return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
|
|
640
680
|
}
|
|
641
|
-
return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${
|
|
681
|
+
return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${routedId}/connect`, this.requestInit(input))));
|
|
642
682
|
}
|
|
643
683
|
#runViaDelegate(input) {
|
|
644
684
|
return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
|
|
@@ -646,7 +686,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
646
686
|
#runViaHttp(input) {
|
|
647
687
|
if (this.transport === "single") {
|
|
648
688
|
if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
|
|
649
|
-
const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.
|
|
689
|
+
const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.routedAgentId() });
|
|
650
690
|
return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
|
|
651
691
|
}
|
|
652
692
|
return withAbortErrorHandling(super.run(input));
|
|
@@ -655,6 +695,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
655
695
|
const cloned = new ProxiedCopilotRuntimeAgent({
|
|
656
696
|
runtimeUrl: this.runtimeUrl,
|
|
657
697
|
agentId: this.agentId,
|
|
698
|
+
runtimeAgentId: this.runtimeAgentId,
|
|
658
699
|
description: this.description,
|
|
659
700
|
headers: { ...this.headers },
|
|
660
701
|
credentials: this.credentials,
|
|
@@ -673,6 +714,22 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
673
714
|
}
|
|
674
715
|
return cloned;
|
|
675
716
|
}
|
|
717
|
+
/**
|
|
718
|
+
* Drop the delegate's cached `lastSeenEventId` for this thread so
|
|
719
|
+
* the next connect requests a full historical replay from the
|
|
720
|
+
* gateway. Used by `RunHandler.connectAgent` on a detected thread
|
|
721
|
+
* switch (the chat moved between threads, so its local
|
|
722
|
+
* messages/state are about to be cleared and need rebuilding from
|
|
723
|
+
* the gateway). Skipped on same-thread churn re-connects so the
|
|
724
|
+
* gateway can resume from the cursor instead.
|
|
725
|
+
*
|
|
726
|
+
* No-op for non-Intelligence runtime modes — the HTTP transport
|
|
727
|
+
* doesn't replay.
|
|
728
|
+
*/
|
|
729
|
+
clearReplayCursor(threadId) {
|
|
730
|
+
if (this.runtimeMode !== _copilotkit_shared.RUNTIME_MODE_INTELLIGENCE) return;
|
|
731
|
+
this.delegate?.clearReconnectCursor?.(threadId);
|
|
732
|
+
}
|
|
676
733
|
async resolveDelegate() {
|
|
677
734
|
await this.ensureRuntimeMode();
|
|
678
735
|
if (!this.delegate) {
|
|
@@ -763,17 +820,18 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
|
|
|
763
820
|
};
|
|
764
821
|
}
|
|
765
822
|
createIntelligenceDelegate() {
|
|
766
|
-
|
|
823
|
+
const routedId = this.routedAgentId();
|
|
824
|
+
if (!this.runtimeUrl || !routedId || !this.intelligence?.wsUrl) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
|
|
767
825
|
return new IntelligenceAgent({
|
|
768
826
|
url: this.intelligence.wsUrl,
|
|
769
827
|
runtimeUrl: this.runtimeUrl,
|
|
770
|
-
agentId:
|
|
828
|
+
agentId: routedId,
|
|
771
829
|
headers: { ...this.headers },
|
|
772
830
|
credentials: this.credentials
|
|
773
831
|
});
|
|
774
832
|
}
|
|
775
833
|
syncDelegate(delegate) {
|
|
776
|
-
delegate.agentId = this.
|
|
834
|
+
delegate.agentId = this.routedAgentId();
|
|
777
835
|
delegate.description = this.description;
|
|
778
836
|
delegate.threadId = this.threadId;
|
|
779
837
|
delegate.setMessages(this.messages);
|
|
@@ -907,6 +965,52 @@ var AgentRegistry = class {
|
|
|
907
965
|
this.notifyAgentsChanged();
|
|
908
966
|
}
|
|
909
967
|
/**
|
|
968
|
+
* Register a proxied agent that routes outbound runtime requests to an
|
|
969
|
+
* existing runtime agent (`runtimeAgentId`) while exposing a distinct local
|
|
970
|
+
* registry id (`agentId`). Throws if `agentId` is already taken by either a
|
|
971
|
+
* local or runtime-discovered agent.
|
|
972
|
+
*
|
|
973
|
+
* Use this to mount multiple frontend agents against a single runtime
|
|
974
|
+
* agent (e.g. a chat-1 / chat-2 pair both proxying to "default") without
|
|
975
|
+
* implicit per-thread cloning. The returned `unregister` removes the proxy
|
|
976
|
+
* from the registry and emits `onAgentsChanged`.
|
|
977
|
+
*/
|
|
978
|
+
registerProxiedAgent({ agentId, runtimeAgentId }) {
|
|
979
|
+
if (Object.prototype.hasOwnProperty.call(this._agents, agentId)) throw new Error(`CopilotKitCore.registerProxiedAgent: agentId "${agentId}" is already registered. Pick a different agentId, or unregister the existing agent first.`);
|
|
980
|
+
const friends = this.core;
|
|
981
|
+
const debug = friends.debug;
|
|
982
|
+
const agent = new ProxiedCopilotRuntimeAgent({
|
|
983
|
+
runtimeUrl: this._runtimeUrl,
|
|
984
|
+
agentId,
|
|
985
|
+
runtimeAgentId,
|
|
986
|
+
transport: this._runtimeTransport,
|
|
987
|
+
credentials: friends.credentials,
|
|
988
|
+
runtimeMode: this._runtimeUrl ? this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected ? this._runtimeMode : "pending" : _copilotkit_shared.RUNTIME_MODE_SSE,
|
|
989
|
+
intelligence: this._intelligence,
|
|
990
|
+
debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0
|
|
991
|
+
});
|
|
992
|
+
this.applyHeadersToAgent(agent);
|
|
993
|
+
this.localAgents[agentId] = agent;
|
|
994
|
+
this._agents = {
|
|
995
|
+
...this.localAgents,
|
|
996
|
+
...this.remoteAgents
|
|
997
|
+
};
|
|
998
|
+
this.notifyAgentsChanged();
|
|
999
|
+
return {
|
|
1000
|
+
agent,
|
|
1001
|
+
unregister: () => {
|
|
1002
|
+
if (this.localAgents[agentId] === agent) {
|
|
1003
|
+
delete this.localAgents[agentId];
|
|
1004
|
+
this._agents = {
|
|
1005
|
+
...this.localAgents,
|
|
1006
|
+
...this.remoteAgents
|
|
1007
|
+
};
|
|
1008
|
+
this.notifyAgentsChanged();
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
910
1014
|
* Get an agent by ID
|
|
911
1015
|
*/
|
|
912
1016
|
getAgent(id) {
|
|
@@ -1186,16 +1290,10 @@ var SuggestionEngine = class {
|
|
|
1186
1290
|
/**
|
|
1187
1291
|
* Reload suggestions for a specific agent
|
|
1188
1292
|
* This triggers generation of new suggestions based on current configs
|
|
1189
|
-
*
|
|
1190
|
-
* @param agentId - The consumer agent ID
|
|
1191
|
-
* @param consumerAgent - Optional: the specific agent instance whose messages should be used
|
|
1192
|
-
* for availability filtering and context. When running with per-thread clones, the thread
|
|
1193
|
-
* clone holds the conversation messages; passing it here ensures dynamic suggestions fire
|
|
1194
|
-
* after the first message even though the registry agent has an empty message list.
|
|
1195
1293
|
*/
|
|
1196
|
-
reloadSuggestions(agentId
|
|
1294
|
+
reloadSuggestions(agentId) {
|
|
1197
1295
|
this.clearSuggestions(agentId);
|
|
1198
|
-
const agent =
|
|
1296
|
+
const agent = this.core.getAgent(agentId);
|
|
1199
1297
|
const messageCount = agent?.messages?.length ?? 0;
|
|
1200
1298
|
let hasAnySuggestions = false;
|
|
1201
1299
|
for (const config of Object.values(this._suggestionsConfig)) {
|
|
@@ -1208,7 +1306,7 @@ var SuggestionEngine = class {
|
|
|
1208
1306
|
hasAnySuggestions = true;
|
|
1209
1307
|
this.notifySuggestionsStartedLoading(agentId);
|
|
1210
1308
|
}
|
|
1211
|
-
this.generateSuggestions(suggestionId, config, agentId
|
|
1309
|
+
this.generateSuggestions(suggestionId, config, agentId);
|
|
1212
1310
|
} else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
|
|
1213
1311
|
}
|
|
1214
1312
|
}
|
|
@@ -1236,12 +1334,12 @@ var SuggestionEngine = class {
|
|
|
1236
1334
|
/**
|
|
1237
1335
|
* Generate suggestions using a provider agent
|
|
1238
1336
|
*/
|
|
1239
|
-
async generateSuggestions(suggestionId, config, consumerAgentId
|
|
1337
|
+
async generateSuggestions(suggestionId, config, consumerAgentId) {
|
|
1240
1338
|
let agent = void 0;
|
|
1241
1339
|
try {
|
|
1242
1340
|
const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
|
|
1243
1341
|
if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
|
|
1244
|
-
const suggestionsConsumerAgent =
|
|
1342
|
+
const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
|
|
1245
1343
|
if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
|
|
1246
1344
|
agent = suggestionsProviderAgent.clone();
|
|
1247
1345
|
agent.threadId = suggestionId;
|
|
@@ -1469,6 +1567,23 @@ var RunHandler = class {
|
|
|
1469
1567
|
* `processAgentResult`.
|
|
1470
1568
|
*/
|
|
1471
1569
|
_runDepth = 0;
|
|
1570
|
+
/**
|
|
1571
|
+
* Tracks the threadId of the most recent `connectAgent` call so we
|
|
1572
|
+
* can distinguish a fresh thread restore (different threadId than
|
|
1573
|
+
* last time — chat is rebuilding state from scratch, must clear
|
|
1574
|
+
* messages/state and ask the gateway for a full replay) from a
|
|
1575
|
+
* same-thread churn re-connect (effect-dep churn or transient
|
|
1576
|
+
* disconnect — local messages/state are still meaningful, must
|
|
1577
|
+
* preserve them and let the gateway resume from
|
|
1578
|
+
* `lastSeenEventId`).
|
|
1579
|
+
*
|
|
1580
|
+
* Tyler's bug fired because every `connectAgent` was treated as a
|
|
1581
|
+
* fresh restore, which forced the gateway to replay the full
|
|
1582
|
+
* thread history on every churn re-connect and amplified the
|
|
1583
|
+
* downstream churn into duplicate `cpki_event_id` rows in the
|
|
1584
|
+
* inspector and intermittent "Message not found" toasts.
|
|
1585
|
+
*/
|
|
1586
|
+
_lastConnectedThreadId = null;
|
|
1472
1587
|
constructor(core) {
|
|
1473
1588
|
this.core = core;
|
|
1474
1589
|
}
|
|
@@ -1542,14 +1657,17 @@ var RunHandler = class {
|
|
|
1542
1657
|
*/
|
|
1543
1658
|
async connectAgent({ agent }) {
|
|
1544
1659
|
try {
|
|
1660
|
+
const incomingThreadId = agent.threadId ?? null;
|
|
1661
|
+
const isFreshRestore = incomingThreadId !== this._lastConnectedThreadId;
|
|
1662
|
+
this._lastConnectedThreadId = incomingThreadId;
|
|
1545
1663
|
await agent.detachActiveRun();
|
|
1546
|
-
|
|
1547
|
-
|
|
1664
|
+
if (isFreshRestore) {
|
|
1665
|
+
agent.setMessages([]);
|
|
1666
|
+
agent.setState({});
|
|
1667
|
+
const proxied = agent;
|
|
1668
|
+
if (incomingThreadId && typeof proxied.clearReplayCursor === "function") proxied.clearReplayCursor(incomingThreadId);
|
|
1669
|
+
}
|
|
1548
1670
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
|
|
1549
|
-
await this._internal.notifySubscribers((subscriber) => subscriber.onAgentRunStarted?.({
|
|
1550
|
-
copilotkit: this.core,
|
|
1551
|
-
agent
|
|
1552
|
-
}), "Subscriber onAgentRunStarted error:");
|
|
1553
1671
|
const runAgentResult = await agent.connectAgent({
|
|
1554
1672
|
forwardedProps: this._internal.properties,
|
|
1555
1673
|
tools: this.buildFrontendTools(agent.agentId),
|
|
@@ -1580,11 +1698,6 @@ var RunHandler = class {
|
|
|
1580
1698
|
if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
|
|
1581
1699
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
|
|
1582
1700
|
if (agent.detachActiveRun) await agent.detachActiveRun();
|
|
1583
|
-
this._internal.subscribeAgentToStateManager(agent);
|
|
1584
|
-
await this._internal.notifySubscribers((subscriber) => subscriber.onAgentRunStarted?.({
|
|
1585
|
-
copilotkit: this.core,
|
|
1586
|
-
agent
|
|
1587
|
-
}), "Subscriber onAgentRunStarted error:");
|
|
1588
1701
|
const isTopLevel = this._runDepth === 0;
|
|
1589
1702
|
let originalAbortRun;
|
|
1590
1703
|
if (isTopLevel) {
|
|
@@ -1655,7 +1768,7 @@ var RunHandler = class {
|
|
|
1655
1768
|
await this._internal.waitForPendingFrameworkUpdates();
|
|
1656
1769
|
return await this.runAgent({ agent });
|
|
1657
1770
|
}
|
|
1658
|
-
this._internal.suggestionEngine.reloadSuggestions(agentId
|
|
1771
|
+
this._internal.suggestionEngine.reloadSuggestions(agentId);
|
|
1659
1772
|
return runAgentResult;
|
|
1660
1773
|
}
|
|
1661
1774
|
/**
|
|
@@ -2067,21 +2180,14 @@ var StateManager = class {
|
|
|
2067
2180
|
initialize() {}
|
|
2068
2181
|
/**
|
|
2069
2182
|
* Subscribe to an agent's events to track state and messages.
|
|
2070
|
-
*
|
|
2071
|
-
* Registry agents (subscribed via `onAgentsChanged`) use the bare `agentId`
|
|
2072
|
-
* key so that `unsubscribeFromAgent(agentId)` can remove them when they
|
|
2073
|
-
* are replaced. Per-thread clones (subscribed via `subscribeAgentToStateManager`)
|
|
2074
|
-
* pass `{ isClone: true }` to use a composite `agentId:threadId` key, keeping
|
|
2075
|
-
* their subscription independent of the registry agent's.
|
|
2076
2183
|
*/
|
|
2077
|
-
subscribeToAgent(agent
|
|
2184
|
+
subscribeToAgent(agent) {
|
|
2078
2185
|
if (!agent.agentId) return;
|
|
2079
2186
|
const agentId = agent.agentId;
|
|
2080
|
-
const
|
|
2081
|
-
const existingUnsubscribe = this.agentSubscriptions.get(subscriptionKey);
|
|
2187
|
+
const existingUnsubscribe = this.agentSubscriptions.get(agentId);
|
|
2082
2188
|
if (existingUnsubscribe) {
|
|
2083
2189
|
existingUnsubscribe();
|
|
2084
|
-
this.agentSubscriptions.delete(
|
|
2190
|
+
this.agentSubscriptions.delete(agentId);
|
|
2085
2191
|
}
|
|
2086
2192
|
let revoked = false;
|
|
2087
2193
|
let subRunId;
|
|
@@ -2125,16 +2231,13 @@ var StateManager = class {
|
|
|
2125
2231
|
this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
|
|
2126
2232
|
}
|
|
2127
2233
|
});
|
|
2128
|
-
this.agentSubscriptions.set(
|
|
2234
|
+
this.agentSubscriptions.set(agentId, () => {
|
|
2129
2235
|
revoked = true;
|
|
2130
2236
|
unsubscribe();
|
|
2131
2237
|
});
|
|
2132
2238
|
}
|
|
2133
2239
|
/**
|
|
2134
|
-
* Unsubscribe
|
|
2135
|
-
* Per-thread clone subscriptions use composite `agentId:threadId` keys and
|
|
2136
|
-
* are replaced (not removed) by subsequent subscribeToAgent(agent, { isClone: true })
|
|
2137
|
-
* calls for the same (agentId, threadId) pair.
|
|
2240
|
+
* Unsubscribe an agent's subscription.
|
|
2138
2241
|
*/
|
|
2139
2242
|
unsubscribeFromAgent(agentId) {
|
|
2140
2243
|
const unsubscribe = this.agentSubscriptions.get(agentId);
|
|
@@ -2419,7 +2522,16 @@ var CopilotKitCore = class {
|
|
|
2419
2522
|
if (agent.agentId) this.stateManager.subscribeToAgent(agent);
|
|
2420
2523
|
});
|
|
2421
2524
|
const currentAgentIds = new Set(Object.keys(agents));
|
|
2422
|
-
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId))
|
|
2525
|
+
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
|
|
2526
|
+
this.threadStoreRegistry.unregister(agentId);
|
|
2527
|
+
} catch (err) {
|
|
2528
|
+
console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
|
|
2529
|
+
}
|
|
2530
|
+
for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
|
|
2531
|
+
this.stateManager.unsubscribeFromAgent(agentId);
|
|
2532
|
+
} catch (err) {
|
|
2533
|
+
console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
2534
|
+
}
|
|
2423
2535
|
this.previousAgentIds = currentAgentIds;
|
|
2424
2536
|
} });
|
|
2425
2537
|
}
|
|
@@ -2582,6 +2694,28 @@ var CopilotKitCore = class {
|
|
|
2582
2694
|
removeAgent__unsafe_dev_only(id) {
|
|
2583
2695
|
this.agentRegistry.removeAgent__unsafe_dev_only(id);
|
|
2584
2696
|
}
|
|
2697
|
+
/**
|
|
2698
|
+
* Register a proxied agent against an existing runtime agent. The proxy is
|
|
2699
|
+
* exposed under `agentId` (local registry id) and routes outbound runtime
|
|
2700
|
+
* requests to `runtimeAgentId`. Throws if `agentId` is already taken.
|
|
2701
|
+
*
|
|
2702
|
+
* Returns the minted proxy and an `unregister` handle for cleanup.
|
|
2703
|
+
*
|
|
2704
|
+
* Use this to mount multiple frontend agents against a single runtime
|
|
2705
|
+
* agent (e.g. one per chat window) without implicit per-thread cloning.
|
|
2706
|
+
*
|
|
2707
|
+
* @example
|
|
2708
|
+
* const { agent, unregister } = copilotkit.registerProxiedAgent({
|
|
2709
|
+
* agentId: "chat-1",
|
|
2710
|
+
* runtimeAgentId: "default",
|
|
2711
|
+
* });
|
|
2712
|
+
* // ... <CopilotChat agentId="chat-1" />
|
|
2713
|
+
* // on cleanup:
|
|
2714
|
+
* unregister();
|
|
2715
|
+
*/
|
|
2716
|
+
registerProxiedAgent(params) {
|
|
2717
|
+
return this.agentRegistry.registerProxiedAgent(params);
|
|
2718
|
+
}
|
|
2585
2719
|
getAgent(id) {
|
|
2586
2720
|
return this.agentRegistry.getAgent(id);
|
|
2587
2721
|
}
|
|
@@ -2815,9 +2949,6 @@ var CopilotKitCore = class {
|
|
|
2815
2949
|
getRunIdsForThread(agentId, threadId) {
|
|
2816
2950
|
return this.stateManager.getRunIdsForThread(agentId, threadId);
|
|
2817
2951
|
}
|
|
2818
|
-
subscribeAgentToStateManager(agent) {
|
|
2819
|
-
this.stateManager.subscribeToAgent(agent, { isClone: true });
|
|
2820
|
-
}
|
|
2821
2952
|
/**
|
|
2822
2953
|
* Internal method used by RunHandler to build frontend tools
|
|
2823
2954
|
*/
|