@copilotkit/core 1.72.1-canary.sp-longthread-perf → 1.73.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.umd.js CHANGED
@@ -422,16 +422,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
422
422
  return (0, rxjs.defer)(async () => {
423
423
  try {
424
424
  var _this$config$fetch;
425
- const response = await ((_this$config$fetch = this.config.fetch) !== null && _this$config$fetch !== void 0 ? _this$config$fetch : globalFetch)(this.buildRuntimeUrl(mode), {
425
+ const requestFetch = (_this$config$fetch = this.config.fetch) !== null && _this$config$fetch !== void 0 ? _this$config$fetch : globalFetch;
426
+ const body = {
427
+ ...input,
428
+ ...mode === "connect" ? { lastSeenEventId: replayCursor === void 0 ? this.getReconnectCursor(input) : replayCursor } : {}
429
+ };
430
+ const single = this.config.transport === "single";
431
+ const response = await requestFetch(single ? this.config.runtimeUrl : this.buildRuntimeUrl(mode), {
426
432
  method: "POST",
433
+ redirect: "error",
427
434
  headers: {
428
435
  "Content-Type": "application/json",
429
436
  ...this.headers
430
437
  },
431
- body: JSON.stringify({
432
- ...input,
433
- ...mode === "connect" ? { lastSeenEventId: replayCursor === void 0 ? this.getReconnectCursor(input) : replayCursor } : {}
434
- }),
438
+ body: JSON.stringify(single ? {
439
+ method: `agent/${mode}`,
440
+ params: { agentId: this.config.agentId },
441
+ body
442
+ } : body),
435
443
  ...this.credentials ? { credentials: this.credentials } : {}
436
444
  });
437
445
  if (response.status === 204 && mode === "connect") return null;
@@ -672,6 +680,90 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
672
680
  return typeof error === "object" && error !== null && typeof error.runtimeInfoStatus === "number";
673
681
  }
674
682
 
683
+ //#endregion
684
+ //#region src/core/message-filter.ts
685
+ function toolCallIdsOf(message) {
686
+ const calls = message.toolCalls;
687
+ if (!Array.isArray(calls)) return [];
688
+ return calls.map((call) => call.id).filter((id) => Boolean(id));
689
+ }
690
+ function resultCallIdOf(message) {
691
+ if (message.role !== "tool") return void 0;
692
+ return message.toolCallId;
693
+ }
694
+ /**
695
+ * Repair the tool-call pairs a filter broke.
696
+ *
697
+ * Every provider rejects a half pair. A tool result whose call is gone reads as
698
+ * a reply to nothing, and an assistant tool call whose result is gone leaves
699
+ * the turn unanswered — the failure reporters hit on #1482 when a trimmed
700
+ * history landed mid-HITL and Anthropic answered "a tool result is expected".
701
+ * A filter written as `messages.slice(-1)` cannot know this, so the repair runs
702
+ * for every filter rather than being something each caller opts into.
703
+ *
704
+ * Both repairs restore, never discard, and both are anchored on the untrimmed
705
+ * thread:
706
+ *
707
+ * - A kept tool result whose assistant call was trimmed away gets that call put
708
+ * back in front of it. Dropping the result instead would be protocol-safe and
709
+ * semantically wrong: on a human-in-the-loop turn the result IS the new
710
+ * information, and a backend that already holds the call would be asked to
711
+ * resume with nothing.
712
+ * - A kept assistant call whose result was trimmed gets that result restored,
713
+ * placed directly after the call.
714
+ *
715
+ * Restoring a call pulls in every result for that call, not only the one the
716
+ * filter kept. Providers reject an assistant turn with a parallel tool call
717
+ * left unanswered, so a half-answered set is as invalid as a missing one.
718
+ *
719
+ * A call with no result anywhere in `full` is left alone. That is an open call
720
+ * (a pending frontend tool, an unanswered interrupt), not a broken pair. A
721
+ * result whose call is nowhere in `full` is left alone too: it was already
722
+ * unpaired before the filter ran, so it is not this function's to fix.
723
+ *
724
+ * The filter's own ordering is preserved. Restorations are the only insertions,
725
+ * and messages the filter synthesized (absent from `full`) pass through
726
+ * untouched.
727
+ */
728
+ function ɵrepairToolCallPairs(kept, full) {
729
+ const callIdToIssuer = /* @__PURE__ */ new Map();
730
+ const callIdToResult = /* @__PURE__ */ new Map();
731
+ for (const message of full) {
732
+ for (const callId of toolCallIdsOf(message)) callIdToIssuer.set(callId, message);
733
+ const resultCallId = resultCallIdOf(message);
734
+ if (resultCallId !== void 0) callIdToResult.set(resultCallId, message);
735
+ }
736
+ const repaired = [];
737
+ const emitted = /* @__PURE__ */ new Set();
738
+ const emit = (message) => {
739
+ if (emitted.has(message.id)) return;
740
+ emitted.add(message.id);
741
+ repaired.push(message);
742
+ };
743
+ /** Emit an assistant turn together with every result it is owed. */
744
+ const emitWithResults = (message) => {
745
+ emit(message);
746
+ for (const callId of toolCallIdsOf(message)) {
747
+ const result = callIdToResult.get(callId);
748
+ if (result) emit(result);
749
+ }
750
+ };
751
+ for (const message of kept) {
752
+ const resultCallId = resultCallIdOf(message);
753
+ if (resultCallId === void 0) {
754
+ emitWithResults(message);
755
+ continue;
756
+ }
757
+ const issuer = callIdToIssuer.get(resultCallId);
758
+ if (issuer) {
759
+ emitWithResults(issuer);
760
+ continue;
761
+ }
762
+ emit(message);
763
+ }
764
+ return repaired;
765
+ }
766
+
675
767
  //#endregion
676
768
  //#region \0@oxc-project+runtime@0.112.0/helpers/checkPrivateRedeclaration.js
677
769
  function _checkPrivateRedeclaration(e, t) {
@@ -773,6 +865,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
773
865
  _defineProperty(this, "_capabilities", void 0);
774
866
  _defineProperty(this, "delegate", void 0);
775
867
  _defineProperty(this, "runtimeInfoPromise", void 0);
868
+ _defineProperty(this, "_messageFilter", void 0);
869
+ _defineProperty(this, "activeRun", void 0);
776
870
  this.runtimeUrl = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl;
777
871
  this.runtimeEndpointUrl = config.runtimeUrl;
778
872
  this.credentials = config.credentials;
@@ -781,10 +875,48 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
781
875
  this.runtimeMode = (_config$runtimeMode = config.runtimeMode) !== null && _config$runtimeMode !== void 0 ? _config$runtimeMode : _copilotkit_shared.RUNTIME_MODE_SSE;
782
876
  this.intelligence = config.intelligence;
783
877
  this._capabilities = config.capabilities;
878
+ this._messageFilter = config.messageFilter;
784
879
  if (config.debug) this.debug = config.debug;
785
880
  if (this.transport === "single") this.singleEndpointUrl = this.runtimeEndpointUrl;
786
881
  }
787
882
  /**
883
+ * Adopt the runtime mode a fresh `/info` just reported.
884
+ *
885
+ * A live proxy outlives the runtime configuration that minted it: a
886
+ * redeploy, an env-var change or a rollback can flip `intelligence` → `sse`
887
+ * under a page that is already open. The registry preserves the proxy across
888
+ * that re-sync on purpose — it is backing an open conversation — so the new
889
+ * mode is pushed onto the instance here instead of replacing it.
890
+ *
891
+ * Without this the mode was decided once, at construction, and `run()` kept
892
+ * taking the delegate path against a runtime serving plain SSE, where
893
+ * `response.json()` on a `text/event-stream` body throws for the rest of the
894
+ * page's life. See #7130.
895
+ *
896
+ * A delegate built for the old mode is torn down: it speaks a protocol the
897
+ * runtime no longer serves, and it may be holding a websocket open. The
898
+ * memoized `/info` promise goes with it — it answered for the old
899
+ * configuration, so a later `ensureRuntimeConfiguration()` must re-ask
900
+ * rather than treat that answer as current.
901
+ *
902
+ * Only `wsUrl` is compared on the Intelligence metadata, because that is the
903
+ * one field the delegate bakes in at construction.
904
+ */
905
+ adoptRuntimeMode(runtimeMode, intelligence) {
906
+ var _this$intelligence;
907
+ const unchanged = this.runtimeMode === runtimeMode && ((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl) === (intelligence === null || intelligence === void 0 ? void 0 : intelligence.wsUrl);
908
+ this.runtimeMode = runtimeMode;
909
+ this.intelligence = intelligence;
910
+ if (unchanged) return;
911
+ this.runtimeInfoPromise = void 0;
912
+ const staleDelegate = this.delegate;
913
+ this.delegate = void 0;
914
+ if (staleDelegate) {
915
+ staleDelegate.abortRun();
916
+ this.detachActiveRun();
917
+ }
918
+ }
919
+ /**
788
920
  * The agent id used for outbound runtime requests — `runtimeAgentId` when
789
921
  * set (manually-registered proxy), otherwise `agentId` (registry id
790
922
  * matches runtime id). Subscriber bookkeeping keeps using `agentId`
@@ -803,6 +935,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
803
935
  get capabilities() {
804
936
  return this._capabilities;
805
937
  }
938
+ /**
939
+ * The filter applied to the outbound message list on every run.
940
+ *
941
+ * Registry-owned. `AgentRegistry` writes it whenever the core-level filter
942
+ * changes, so an agent discovered before the app configured one still picks
943
+ * it up — and so a value written here by hand is replaced on the registry's
944
+ * next sweep. Configure it through `CopilotKitCore` instead.
945
+ */
946
+ get messageFilter() {
947
+ return this._messageFilter;
948
+ }
949
+ set messageFilter(filter) {
950
+ this._messageFilter = filter;
951
+ }
806
952
  requestInit(input) {
807
953
  return {
808
954
  ...super.requestInit(input),
@@ -818,6 +964,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
818
964
  await super.detachActiveRun();
819
965
  }
820
966
  abortRun() {
967
+ var _this$activeRun;
821
968
  if (this.delegate) {
822
969
  this.syncDelegate(this.delegate);
823
970
  this.delegate.abortRun();
@@ -827,6 +974,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
827
974
  if (!this.agentId || !this.threadId) return;
828
975
  if (typeof fetch === "undefined") return;
829
976
  const routedId = this.routedAgentId();
977
+ const runId = ((_this$activeRun = this.activeRun) === null || _this$activeRun === void 0 ? void 0 : _this$activeRun.threadId) === this.threadId ? this.activeRun.runId : void 0;
830
978
  if (this.transport === "single") {
831
979
  if (!this.singleEndpointUrl) return;
832
980
  const headers = new Headers({
@@ -841,7 +989,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
841
989
  params: {
842
990
  agentId: routedId,
843
991
  threadId: this.threadId
844
- }
992
+ },
993
+ ...runId === void 0 ? {} : { body: { runId } }
845
994
  }),
846
995
  ...this.credentials ? { credentials: this.credentials } : {}
847
996
  }).catch((error) => {
@@ -860,6 +1009,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
860
1009
  "Content-Type": "application/json",
861
1010
  ...this.headers
862
1011
  },
1012
+ ...runId === void 0 ? {} : { body: JSON.stringify({ runId }) },
863
1013
  ...this.credentials ? { credentials: this.credentials } : {}
864
1014
  }).catch((error) => {
865
1015
  console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
@@ -926,7 +1076,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
926
1076
  intelligence: this.intelligence,
927
1077
  capabilities: this._capabilities,
928
1078
  debug: this.debug,
929
- fetch: this.fetch
1079
+ fetch: this.fetch,
1080
+ messageFilter: this._messageFilter
930
1081
  });
931
1082
  cloned.threadId = this.threadId;
932
1083
  cloned.setState(this.state);
@@ -1058,12 +1209,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1058
1209
  };
1059
1210
  }
1060
1211
  createIntelligenceDelegate() {
1061
- var _this$intelligence;
1212
+ var _this$intelligence2, _this$runtimeEndpoint3;
1062
1213
  const routedId = this.routedAgentId();
1063
- if (!this.runtimeUrl || !routedId || !((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl)) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
1214
+ if (!this.runtimeUrl || !routedId || !((_this$intelligence2 = this.intelligence) === null || _this$intelligence2 === void 0 ? void 0 : _this$intelligence2.wsUrl)) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
1215
+ const single = this.transport === "single";
1064
1216
  return new IntelligenceAgent({
1065
1217
  url: this.intelligence.wsUrl,
1066
- runtimeUrl: this.runtimeUrl,
1218
+ runtimeUrl: single ? (_this$runtimeEndpoint3 = this.runtimeEndpointUrl) !== null && _this$runtimeEndpoint3 !== void 0 ? _this$runtimeEndpoint3 : this.runtimeUrl : this.runtimeUrl,
1219
+ transport: single ? "single" : "rest",
1067
1220
  agentId: routedId,
1068
1221
  headers: { ...this.headers },
1069
1222
  credentials: this.credentials,
@@ -1081,10 +1234,60 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1081
1234
  }
1082
1235
  };
1083
1236
  _ProxiedCopilotRuntimeAgent = ProxiedCopilotRuntimeAgent;
1237
+ /**
1238
+ * Narrow the outbound payload with the configured message filter.
1239
+ *
1240
+ * **Called from the HTTP paths only, and that placement is the Intelligence
1241
+ * exemption.** An earlier revision applied the filter in
1242
+ * `prepareRunAgentInput`, which runs before the runtime mode is resolved:
1243
+ * with the default `"auto"` transport, or on a proxy still `"pending"` its
1244
+ * first `/info`, `run()` prepared the input, *then* resolved the mode, then
1245
+ * handed that already-filtered input to `#runViaDelegate` — so a managed
1246
+ * runtime received a truncated thread despite the exemption. Filtering here
1247
+ * makes that unreachable by construction: `#runViaHttp` and
1248
+ * `#connectViaHttp` are only entered once the mode is known not to be
1249
+ * Intelligence. Do not move this back up the call chain.
1250
+ *
1251
+ * The managed runtime is the store of record for the thread — the threads
1252
+ * drawer and the Slack transcript read from it — so a client-side truncation
1253
+ * there has a blast radius nobody asked for. Every reporter on #1482 is
1254
+ * self-hosted.
1255
+ *
1256
+ * `prepareRunAgentInput` has already deep-cloned the thread and stripped
1257
+ * `activity` messages by the time the input reaches here, so the filter
1258
+ * cannot reach the messages the UI renders no matter what it does with the
1259
+ * array it is handed. The filter gets a *second* deep clone on top of that,
1260
+ * because `input.messages` is also the repair baseline and the untrimmed
1261
+ * fallback: sharing the message objects let a filter that mutates a kept
1262
+ * message's `toolCallId` corrupt the baseline, and an orphaned tool result
1263
+ * then went out on the wire — a payload the provider rejects, which is
1264
+ * exactly the failure this whole mechanism exists to prevent.
1265
+ */
1266
+ function _applyMessageFilter(input) {
1267
+ const filter = this._messageFilter;
1268
+ if (!filter) return input;
1269
+ try {
1270
+ var _this$agentId;
1271
+ const kept = filter((0, _ag_ui_client.structuredClone_)(input.messages), { agentId: (_this$agentId = this.agentId) !== null && _this$agentId !== void 0 ? _this$agentId : "" });
1272
+ if (!Array.isArray(kept)) {
1273
+ console.warn("ProxiedCopilotRuntimeAgent: messageFilter returned a non-array value; sending the full message history instead.");
1274
+ return input;
1275
+ }
1276
+ return {
1277
+ ...input,
1278
+ messages: ɵrepairToolCallPairs(kept, input.messages)
1279
+ };
1280
+ } catch (error) {
1281
+ console.warn("ProxiedCopilotRuntimeAgent: messageFilter failed; sending the full message history instead.", error);
1282
+ return input;
1283
+ }
1284
+ }
1084
1285
  function _connectViaDelegate(input) {
1085
1286
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
1086
1287
  }
1087
- function _connectViaHttp(input) {
1288
+ function _connectViaHttp(unfiltered) {
1289
+ const input = _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _applyMessageFilter).call(this, unfiltered);
1290
+ this.activeRun = void 0;
1088
1291
  const routedId = this.routedAgentId();
1089
1292
  if (this.transport === "single") {
1090
1293
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
@@ -1098,13 +1301,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1098
1301
  function _runViaDelegate(input) {
1099
1302
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
1100
1303
  }
1101
- function _runViaHttp(input) {
1304
+ function _runViaHttp(unfiltered) {
1305
+ const input = _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _applyMessageFilter).call(this, unfiltered);
1306
+ const activeRun = {
1307
+ threadId: input.threadId,
1308
+ runId: input.runId
1309
+ };
1310
+ const trackActiveRun = (source) => {
1311
+ this.activeRun = activeRun;
1312
+ return source.pipe((0, rxjs_operators.finalize)(() => {
1313
+ if (this.activeRun === activeRun) this.activeRun = void 0;
1314
+ }));
1315
+ };
1102
1316
  if (this.transport === "single") {
1103
1317
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
1104
1318
  const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.routedAgentId() });
1105
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(() => this.fetch(this.singleEndpointUrl, requestInit))));
1319
+ return trackActiveRun(withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(() => this.fetch(this.singleEndpointUrl, requestInit)))));
1106
1320
  }
1107
- return withAbortErrorHandling(_superPropGet(_ProxiedCopilotRuntimeAgent.prototype, "run", this, 2)([input]));
1321
+ return trackActiveRun(withAbortErrorHandling(_superPropGet(_ProxiedCopilotRuntimeAgent.prototype, "run", this, 2)([input])));
1108
1322
  }
1109
1323
 
1110
1324
  //#endregion
@@ -1343,6 +1557,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1343
1557
  this.localAgents = this.assignAgentIds(agents);
1344
1558
  this.applyHeadersToAgents(this.localAgents);
1345
1559
  this.applyCredentialsToAgents(this.localAgents);
1560
+ this.applyMessageFilterToAgents(this.localAgents);
1346
1561
  this.applyRuntimeFetchToAgents(this.localAgents);
1347
1562
  this._agents = this.localAgents;
1348
1563
  }
@@ -1435,6 +1650,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1435
1650
  };
1436
1651
  this.applyHeadersToAgents(this._agents);
1437
1652
  this.applyCredentialsToAgents(this._agents);
1653
+ this.applyMessageFilterToAgents(this._agents);
1438
1654
  this.applyRuntimeFetchToAgents(this._agents);
1439
1655
  this.notifyAgentsChanged();
1440
1656
  }
@@ -1488,7 +1704,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1488
1704
  credentials: friends.credentials,
1489
1705
  runtimeMode: this._runtimeUrl ? this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected ? this._runtimeMode : "pending" : _copilotkit_shared.RUNTIME_MODE_SSE,
1490
1706
  intelligence: this._intelligence,
1491
- debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0
1707
+ debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0,
1708
+ messageFilter: friends.messageFilter
1492
1709
  });
1493
1710
  this.applyHeadersToAgent(agent);
1494
1711
  this.applyRuntimeFetchToAgent(agent);
@@ -1557,6 +1774,48 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1557
1774
  this.applyCredentialsToAgent(agent);
1558
1775
  });
1559
1776
  }
1777
+ /**
1778
+ * Carry the mode a fresh `/info` reported onto a proxy this re-sync kept.
1779
+ *
1780
+ * `canReuseRuntimeAgent` deliberately ignores the mode: a preserved proxy is
1781
+ * backing an open conversation, and replacing the instance to change one
1782
+ * field would drop it. The mode is therefore pushed onto the survivor here,
1783
+ * the same way headers and credentials are. Without it the mode was fixed at
1784
+ * construction, so a runtime that flipped `intelligence` → `sse` under an
1785
+ * open page left every later run on the delegate path. See #7130.
1786
+ */
1787
+ applyRuntimeModeToAgent(agent, runtimeInfo) {
1788
+ if (agent instanceof ProxiedCopilotRuntimeAgent) {
1789
+ var _runtimeInfo$mode;
1790
+ agent.adoptRuntimeMode((_runtimeInfo$mode = runtimeInfo.mode) !== null && _runtimeInfo$mode !== void 0 ? _runtimeInfo$mode : _copilotkit_shared.RUNTIME_MODE_SSE, runtimeInfo.intelligence);
1791
+ }
1792
+ }
1793
+ /**
1794
+ * Apply the core's message filter to an agent.
1795
+ *
1796
+ * The test is the class, not which bucket the agent is registered in: every
1797
+ * `ProxiedCopilotRuntimeAgent` gets the core filter, whether it came from
1798
+ * `/info` or from `registerProxiedAgent` (which files its proxy under
1799
+ * `localAgents`). Agents of any other class are left untouched — an
1800
+ * `AbstractAgent` the app built has no such hook, and its owner already has
1801
+ * the AG-UI middleware seam.
1802
+ *
1803
+ * This is the sole writer of `agent.messageFilter` in normal operation. The
1804
+ * public setter exists for the registry and for tests; a value written
1805
+ * directly onto an agent is replaced the next time the registry sweeps, the
1806
+ * same way per-agent credentials are.
1807
+ */
1808
+ applyMessageFilterToAgent(agent) {
1809
+ if (agent instanceof ProxiedCopilotRuntimeAgent) agent.messageFilter = this.core.messageFilter;
1810
+ }
1811
+ /**
1812
+ * Apply the core's message filter to all agents
1813
+ */
1814
+ applyMessageFilterToAgents(agents) {
1815
+ Object.values(agents).forEach((agent) => {
1816
+ this.applyMessageFilterToAgent(agent);
1817
+ });
1818
+ }
1560
1819
  createRuntimeFetch() {
1561
1820
  if (!this.runtimeFetch) this.runtimeFetch = (async (input, init) => {
1562
1821
  const meta = () => runtimeRequestMeta(init);
@@ -1952,7 +2211,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1952
2211
  if (existing instanceof ProxiedCopilotRuntimeAgent && this.canReuseRuntimeAgent(existing, runtimeUrl, this._runtimeTransport)) {
1953
2212
  this.applyHeadersToAgent(existing);
1954
2213
  this.applyCredentialsToAgent(existing);
2214
+ this.applyMessageFilterToAgent(existing);
1955
2215
  this.applyRuntimeFetchToAgent(existing);
2216
+ this.applyRuntimeModeToAgent(existing, runtimeInfoResponse);
1956
2217
  return [id, existing];
1957
2218
  }
1958
2219
  const agent = new ProxiedCopilotRuntimeAgent({
@@ -1964,7 +2225,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1964
2225
  runtimeMode: (_runtimeInfoResponse$ = runtimeInfoResponse.mode) !== null && _runtimeInfoResponse$ !== void 0 ? _runtimeInfoResponse$ : _copilotkit_shared.RUNTIME_MODE_SSE,
1965
2226
  intelligence: runtimeInfoResponse.intelligence,
1966
2227
  capabilities,
1967
- debug: rawDebug ? (0, _copilotkit_shared.resolveDebugConfig)(rawDebug) : void 0
2228
+ debug: rawDebug ? (0, _copilotkit_shared.resolveDebugConfig)(rawDebug) : void 0,
2229
+ messageFilter: this.core.messageFilter
1968
2230
  });
1969
2231
  this.applyHeadersToAgent(agent);
1970
2232
  this.applyRuntimeFetchToAgent(agent);
@@ -2371,7 +2633,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2371
2633
  credentials
2372
2634
  }) } : {}
2373
2635
  });
2374
- } else suggestionAgent = suggestionsProviderAgent.clone();
2636
+ } else {
2637
+ suggestionAgent = suggestionsProviderAgent.clone();
2638
+ if (suggestionAgent instanceof ProxiedCopilotRuntimeAgent) suggestionAgent.messageFilter = void 0;
2639
+ }
2375
2640
  suggestionAgent.threadId = suggestionId;
2376
2641
  suggestionAgent.setMessages(seededMessages);
2377
2642
  suggestionAgent.setState(seededState);
@@ -2755,6 +3020,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2755
3020
  //#endregion
2756
3021
  //#region src/core/run-handler.ts
2757
3022
  /**
3023
+ * Live approvals cancelled by stopping their own run, keyed by the handler's
3024
+ * signal. The value reports whether that stop is still current: no reconnect
3025
+ * has started and the thread is unchanged, so nothing will restore the call.
3026
+ *
3027
+ * Kept here rather than in `AbortSignal.reason`: React Native's global
3028
+ * `AbortController` is the `abort-controller@3` polyfill, whose `abort()`
3029
+ * takes no reason and whose signals never expose one.
3030
+ */
3031
+ const liveHITLStops = /* @__PURE__ */ new WeakMap();
3032
+ function discardAbortedResult(signal, discardOnAbort, errorMessage) {
3033
+ var _liveHITLStops$get;
3034
+ return !!(discardOnAbort && (signal === null || signal === void 0 ? void 0 : signal.aborted) && !(((_liveHITLStops$get = liveHITLStops.get(signal)) === null || _liveHITLStops$get === void 0 ? void 0 : _liveHITLStops$get()) && errorMessage));
3035
+ }
3036
+ /**
2758
3037
  * Absolute safety cap on the depth of recursive follow-up runs triggered by
2759
3038
  * `processAgentResult`. Without this, any scenario that keeps
2760
3039
  * `needsFollowUp = true` (e.g. the LLM repeatedly calling the same tool, a
@@ -2793,15 +3072,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2793
3072
  _defineProperty(this, "_lastConnectedThreadIdsByAgent", /* @__PURE__ */ new Map());
2794
3073
  _defineProperty(this, "_anonymousAgentIds", /* @__PURE__ */ new WeakMap());
2795
3074
  _defineProperty(this, "_nextAnonymousAgentId", 0);
3075
+ _defineProperty(this, "_executingToolCalls", /* @__PURE__ */ new WeakMap());
3076
+ _defineProperty(this, "_connectionGenerations", /* @__PURE__ */ new WeakMap());
3077
+ _defineProperty(this, "_interactionAbortControllers", /* @__PURE__ */ new WeakMap());
2796
3078
  }
2797
3079
  /**
2798
3080
  * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal
2799
3081
  * that in-flight tool handlers should stop and `processAgentResult` should
2800
3082
  * not start a follow-up run.
2801
3083
  */
2802
- abortCurrentRun() {
3084
+ abortCurrentRun(agent) {
2803
3085
  var _this$_runAbortContro;
2804
3086
  (_this$_runAbortContro = this._runAbortController) === null || _this$_runAbortContro === void 0 || _this$_runAbortContro.abort();
3087
+ const replay = this._interactionAbortControllers.get(agent);
3088
+ if (replay) {
3089
+ for (const controller of replay.controllers) controller.abort();
3090
+ this._interactionAbortControllers.delete(agent);
3091
+ this._executingToolCalls.delete(agent);
3092
+ }
2805
3093
  }
2806
3094
  /**
2807
3095
  * Typed access to CopilotKitCore's internal ("friend") methods.
@@ -2958,9 +3246,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2958
3246
  */
2959
3247
  async connectAgent({ agent }) {
2960
3248
  var _agent$threadId;
3249
+ this._connectionGenerations.set(agent, {});
2961
3250
  const incomingThreadId = (_agent$threadId = agent.threadId) !== null && _agent$threadId !== void 0 ? _agent$threadId : null;
3251
+ const previousReplay = this._interactionAbortControllers.get(agent);
3252
+ if (previousReplay && previousReplay.threadId !== incomingThreadId) {
3253
+ for (const controller of previousReplay.controllers) controller.abort();
3254
+ this._interactionAbortControllers.delete(agent);
3255
+ this._executingToolCalls.delete(agent);
3256
+ }
2962
3257
  try {
2963
- var _this$_lastConnectedT;
3258
+ var _this$_lastConnectedT, _agent$threadId2, _this$_interactionAbo;
2964
3259
  const restoreKey = this.getConnectRestoreKey(agent);
2965
3260
  const isFreshRestore = incomingThreadId !== ((_this$_lastConnectedT = this._lastConnectedThreadIdsByAgent.get(restoreKey)) !== null && _this$_lastConnectedT !== void 0 ? _this$_lastConnectedT : null);
2966
3261
  this._lastConnectedThreadIdsByAgent.set(restoreKey, incomingThreadId);
@@ -2987,11 +3282,33 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2987
3282
  tools: this.buildFrontendTools(agent.agentId),
2988
3283
  context: this._internal.getContextForAgent(agent.agentId)
2989
3284
  }, this.createAgentErrorSubscriber(agent));
2990
- return this.processAgentResult({
3285
+ if (((_agent$threadId2 = agent.threadId) !== null && _agent$threadId2 !== void 0 ? _agent$threadId2 : null) !== incomingThreadId) return runAgentResult;
3286
+ const controller = new AbortController();
3287
+ const replay = (_this$_interactionAbo = this._interactionAbortControllers.get(agent)) !== null && _this$_interactionAbo !== void 0 ? _this$_interactionAbo : {
3288
+ threadId: incomingThreadId,
3289
+ controllers: /* @__PURE__ */ new Set()
3290
+ };
3291
+ replay.controllers.add(controller);
3292
+ this._interactionAbortControllers.set(agent, replay);
3293
+ this.processAgentResult({
2991
3294
  runAgentResult,
2992
3295
  agent,
2993
- executeFrontendTools: false
3296
+ toolExecutionMode: "human-in-the-loop",
3297
+ signal: controller.signal
3298
+ }).catch(async (error) => {
3299
+ await this._internal.emitError({
3300
+ error: error instanceof Error ? error : new Error(String(error)),
3301
+ code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
3302
+ context: {
3303
+ agentId: agent.agentId,
3304
+ threadId: incomingThreadId
3305
+ }
3306
+ });
3307
+ }).finally(() => {
3308
+ replay.controllers.delete(controller);
3309
+ if (replay.controllers.size === 0 && this._interactionAbortControllers.get(agent) === replay) this._interactionAbortControllers.delete(agent);
2994
3310
  });
3311
+ return runAgentResult;
2995
3312
  } catch (error) {
2996
3313
  const connectError = error instanceof Error ? error : new Error(String(error));
2997
3314
  if (!isAbortError$1(connectError)) {
@@ -3096,46 +3413,92 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3096
3413
  /**
3097
3414
  * Process agent result and execute tools
3098
3415
  */
3099
- async processAgentResult({ runAgentResult, agent, runId, executeFrontendTools = true }) {
3416
+ async processAgentResult({ runAgentResult, agent, runId, toolExecutionMode = "all", signal = (() => {
3100
3417
  var _this$_runAbortContro2;
3418
+ return (_this$_runAbortContro2 = this._runAbortController) === null || _this$_runAbortContro2 === void 0 ? void 0 : _this$_runAbortContro2.signal;
3419
+ })() }) {
3420
+ var _this$_executingToolC;
3101
3421
  const { newMessages } = runAgentResult;
3102
3422
  const agentId = agent.agentId;
3103
3423
  let needsFollowUp = false;
3104
- if (executeFrontendTools) {
3105
- for (const message of newMessages) if (message.role === "assistant") for (const toolCall of message.toolCalls || []) {
3106
- const tool = this.getTool({
3107
- toolName: toolCall.function.name,
3424
+ const threadId = agent.threadId;
3425
+ const executing = (_this$_executingToolC = this._executingToolCalls.get(agent)) !== null && _this$_executingToolC !== void 0 ? _this$_executingToolC : /* @__PURE__ */ new Set();
3426
+ this._executingToolCalls.set(agent, executing);
3427
+ if (toolExecutionMode === "human-in-the-loop" && agent.messages.some((message) => {
3428
+ var _message$toolCalls;
3429
+ return message.role === "assistant" && ((_message$toolCalls = message.toolCalls) === null || _message$toolCalls === void 0 ? void 0 : _message$toolCalls.some((call) => executing.has(JSON.stringify([threadId, call.id])) && !agent.messages.some((result) => result.role === "tool" && result.toolCallId === call.id && !this.isFrontendPlaceholderResult(result))));
3430
+ })) return runAgentResult;
3431
+ const messagesToProcess = toolExecutionMode === "human-in-the-loop" ? [...agent.messages] : newMessages;
3432
+ for (const message of messagesToProcess) if (message.role === "assistant") for (const toolCall of message.toolCalls || []) {
3433
+ var _agent$messages$find;
3434
+ const tool = this.getTool({
3435
+ toolName: toolCall.function.name,
3436
+ agentId: agent.agentId
3437
+ });
3438
+ let wildcardTool;
3439
+ const getWildcardTool = () => {
3440
+ if (tool || wildcardTool) return wildcardTool;
3441
+ wildcardTool = this.getTool({
3442
+ toolName: WILDCARD_TOOL_NAME,
3108
3443
  agentId: agent.agentId
3109
3444
  });
3110
- let wildcardTool;
3111
- const getWildcardTool = () => {
3112
- if (tool || wildcardTool) return wildcardTool;
3113
- wildcardTool = this.getTool({
3114
- toolName: WILDCARD_TOOL_NAME,
3115
- agentId: agent.agentId
3116
- });
3117
- return wildcardTool;
3445
+ return wildcardTool;
3446
+ };
3447
+ const executableTool = tool !== null && tool !== void 0 ? tool : getWildcardTool();
3448
+ if (toolExecutionMode === "human-in-the-loop" && ((executableTool === null || executableTool === void 0 ? void 0 : executableTool.type) !== "human-in-the-loop" || !executableTool.handler)) continue;
3449
+ const executionKey = JSON.stringify([threadId, toolCall.id]);
3450
+ if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || agent.threadId !== threadId || executing.has(executionKey)) continue;
3451
+ const existingResultIndex = newMessages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id);
3452
+ let existingResult = (_agent$messages$find = agent.messages.find((m) => m.role === "tool" && m.toolCallId === toolCall.id)) !== null && _agent$messages$find !== void 0 ? _agent$messages$find : newMessages[existingResultIndex];
3453
+ if (existingResult && (executableTool === null || executableTool === void 0 ? void 0 : executableTool.handler) && this.isFrontendPlaceholderResult(existingResult)) {
3454
+ if (existingResultIndex !== -1) newMessages.splice(existingResultIndex, 1);
3455
+ existingResult = void 0;
3456
+ const agentMsgIdx = agent.messages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id);
3457
+ if (agentMsgIdx !== -1) agent.messages.splice(agentMsgIdx, 1);
3458
+ }
3459
+ if (!existingResult) {
3460
+ var _this$_interactionAbo2, _interactionControlle;
3461
+ executing.add(executionKey);
3462
+ const interactionController = toolExecutionMode === "all" && (executableTool === null || executableTool === void 0 ? void 0 : executableTool.type) === "human-in-the-loop" ? new AbortController() : void 0;
3463
+ const interactions = (_this$_interactionAbo2 = this._interactionAbortControllers.get(agent)) !== null && _this$_interactionAbo2 !== void 0 ? _this$_interactionAbo2 : {
3464
+ threadId: threadId !== null && threadId !== void 0 ? threadId : null,
3465
+ controllers: /* @__PURE__ */ new Set()
3118
3466
  };
3119
- let existingResultIndex = newMessages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id);
3120
- const existingResult = existingResultIndex === -1 ? void 0 : newMessages[existingResultIndex];
3121
- const executableTool = tool !== null && tool !== void 0 ? tool : getWildcardTool();
3122
- if (existingResult && (executableTool === null || executableTool === void 0 ? void 0 : executableTool.handler) && this.isFrontendPlaceholderResult(existingResult)) {
3123
- newMessages.splice(existingResultIndex, 1);
3124
- existingResultIndex = -1;
3125
- const agentMsgIdx = agent.messages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id);
3126
- if (agentMsgIdx !== -1) agent.messages.splice(agentMsgIdx, 1);
3467
+ const abortInteraction = () => {
3468
+ if (!interactionController) return;
3469
+ const connectionGeneration = this._connectionGenerations.get(agent);
3470
+ liveHITLStops.set(interactionController.signal, () => this._connectionGenerations.get(agent) === connectionGeneration && agent.threadId === threadId);
3471
+ interactionController.abort();
3472
+ };
3473
+ if (interactionController) {
3474
+ interactions.controllers.add(interactionController);
3475
+ this._interactionAbortControllers.set(agent, interactions);
3476
+ signal === null || signal === void 0 || signal.addEventListener("abort", abortInteraction, { once: true });
3477
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) abortInteraction();
3127
3478
  }
3128
- if (existingResultIndex === -1) if (tool) {
3129
- if (await this.executeSpecificTool(tool, toolCall, message, agent, agentId)) needsFollowUp = true;
3130
- } else {
3131
- const fallbackTool = getWildcardTool();
3132
- if (fallbackTool) {
3133
- if (await this.executeWildcardTool(fallbackTool, toolCall, message, agent, agentId)) needsFollowUp = true;
3479
+ const executionSignal = (_interactionControlle = interactionController === null || interactionController === void 0 ? void 0 : interactionController.signal) !== null && _interactionControlle !== void 0 ? _interactionControlle : signal;
3480
+ const discardOnAbort = toolExecutionMode === "human-in-the-loop" || !!interactionController;
3481
+ try {
3482
+ if (tool) {
3483
+ if (await this.executeSpecificTool(tool, toolCall, message, agent, agentId, executionSignal, discardOnAbort)) needsFollowUp = true;
3484
+ } else {
3485
+ const fallbackTool = getWildcardTool();
3486
+ if (fallbackTool) {
3487
+ if (await this.executeWildcardTool(fallbackTool, toolCall, message, agent, agentId, executionSignal, discardOnAbort)) needsFollowUp = true;
3488
+ }
3489
+ }
3490
+ } finally {
3491
+ executing.delete(executionKey);
3492
+ if (interactionController) {
3493
+ signal === null || signal === void 0 || signal.removeEventListener("abort", abortInteraction);
3494
+ interactions.controllers.delete(interactionController);
3495
+ if (interactions.controllers.size === 0 && this._interactionAbortControllers.get(agent) === interactions) this._interactionAbortControllers.delete(agent);
3134
3496
  }
3135
3497
  }
3498
+ if (interactionController === null || interactionController === void 0 ? void 0 : interactionController.signal.aborted) return runAgentResult;
3136
3499
  }
3137
3500
  }
3138
- if (needsFollowUp && !((_this$_runAbortContro2 = this._runAbortController) === null || _this$_runAbortContro2 === void 0 ? void 0 : _this$_runAbortContro2.signal.aborted)) if (this._runDepth >= MAX_FOLLOW_UP_DEPTH) _copilotkit_shared.logger.warn(`[CopilotKit] Follow-up depth limit (${MAX_FOLLOW_UP_DEPTH}) reached for agent "${agentId}". Stopping recursive follow-up runs to prevent an infinite loop. This usually indicates a tool that keeps requesting a follow-up (e.g. the LLM repeatedly calling the same tool). Consider setting "followUp: false" on the offending tool.`);
3501
+ if (needsFollowUp && agent.threadId === threadId && !(signal === null || signal === void 0 ? void 0 : signal.aborted)) if (this._runDepth >= MAX_FOLLOW_UP_DEPTH) _copilotkit_shared.logger.warn(`[CopilotKit] Follow-up depth limit (${MAX_FOLLOW_UP_DEPTH}) reached for agent "${agentId}". Stopping recursive follow-up runs to prevent an infinite loop. This usually indicates a tool that keeps requesting a follow-up (e.g. the LLM repeatedly calling the same tool). Consider setting "followUp: false" on the offending tool.`);
3139
3502
  else {
3140
3503
  await this._internal.waitForPendingFrameworkUpdates();
3141
3504
  const continuationHandoff = this._internal.stateManager.markNextRunAsContinuation(agent, runId);
@@ -3155,7 +3518,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3155
3518
  * Handles arg parsing, subscriber notifications, handler invocation, result stringification,
3156
3519
  * and error handling.
3157
3520
  */
3158
- async executeToolHandler({ tool, toolCall, agent, agentId, handlerArgs, toolType, messageId }) {
3521
+ async executeToolHandler({ tool, toolCall, agent, agentId, handlerArgs, toolType, messageId, signal = (() => {
3522
+ var _this$_runAbortContro3;
3523
+ return (_this$_runAbortContro3 = this._runAbortController) === null || _this$_runAbortContro3 === void 0 ? void 0 : _this$_runAbortContro3.signal;
3524
+ })(), discardOnAbort = false }) {
3159
3525
  let toolCallResult = "";
3160
3526
  let errorMessage;
3161
3527
  let isArgumentError = false;
@@ -3190,11 +3556,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3190
3556
  });
3191
3557
  }, "Subscriber onToolExecutionStart error:");
3192
3558
  if (!errorMessage) try {
3193
- var _this$_runAbortContro3;
3194
3559
  const result = await tool.handler(parsedArgs, {
3195
3560
  toolCall,
3196
3561
  agent,
3197
- signal: (_this$_runAbortContro3 = this._runAbortController) === null || _this$_runAbortContro3 === void 0 ? void 0 : _this$_runAbortContro3.signal
3562
+ signal
3198
3563
  });
3199
3564
  if (result === void 0 || result === null) toolCallResult = "";
3200
3565
  else if (typeof result === "string") toolCallResult = result;
@@ -3202,7 +3567,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3202
3567
  } catch (error) {
3203
3568
  const handlerError = error instanceof Error ? error : new Error(String(error));
3204
3569
  errorMessage = handlerError.message;
3205
- await this._internal.emitError({
3570
+ if (!discardAbortedResult(signal, discardOnAbort, errorMessage)) await this._internal.emitError({
3206
3571
  error: handlerError,
3207
3572
  code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
3208
3573
  context: {
@@ -3236,7 +3601,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3236
3601
  /**
3237
3602
  * Execute a specific tool
3238
3603
  */
3239
- async executeSpecificTool(tool, toolCall, message, agent, agentId) {
3604
+ async executeSpecificTool(tool, toolCall, message, agent, agentId, signal, discardOnAbort = false) {
3605
+ const threadId = agent.threadId;
3240
3606
  if ((tool === null || tool === void 0 ? void 0 : tool.agentId) && tool.agentId !== agent.agentId) return false;
3241
3607
  let handlerResult = {
3242
3608
  result: "",
@@ -3250,12 +3616,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3250
3616
  agentId,
3251
3617
  handlerArgs: toolCall.function.arguments,
3252
3618
  toolType: "specific",
3253
- messageId: message.id
3619
+ messageId: message.id,
3620
+ signal,
3621
+ discardOnAbort
3254
3622
  });
3255
3623
  {
3256
3624
  var _agent$messages$inser;
3257
3625
  const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
3258
- if (messageIndex === -1) return false;
3626
+ if (discardAbortedResult(signal, discardOnAbort, handlerResult.error) || agent.threadId !== threadId || messageIndex === -1 || agent.messages.some((m) => m.role === "tool" && m.toolCallId === toolCall.id && !this.isFrontendPlaceholderResult(m))) return false;
3259
3627
  let insertAt = messageIndex + 1;
3260
3628
  while (insertAt < agent.messages.length && ((_agent$messages$inser = agent.messages[insertAt]) === null || _agent$messages$inser === void 0 ? void 0 : _agent$messages$inser.role) === "tool") insertAt++;
3261
3629
  const toolMessage = {
@@ -3275,7 +3643,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3275
3643
  * specific tools, so this method keeps its own arg-wrapping logic rather than
3276
3644
  * delegating to `executeToolHandler`.
3277
3645
  */
3278
- async executeWildcardTool(wildcardTool, toolCall, message, agent, agentId) {
3646
+ async executeWildcardTool(wildcardTool, toolCall, message, agent, agentId, signal, discardOnAbort = false) {
3647
+ const threadId = agent.threadId;
3279
3648
  if ((wildcardTool === null || wildcardTool === void 0 ? void 0 : wildcardTool.agentId) && wildcardTool.agentId !== agent.agentId) return false;
3280
3649
  let toolCallResult = "";
3281
3650
  let errorMessage;
@@ -3316,7 +3685,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3316
3685
  if (!errorMessage) try {
3317
3686
  const result = await wildcardTool.handler(wildcardArgs, {
3318
3687
  toolCall,
3319
- agent
3688
+ agent,
3689
+ signal
3320
3690
  });
3321
3691
  if (result === void 0 || result === null) toolCallResult = "";
3322
3692
  else if (typeof result === "string") toolCallResult = result;
@@ -3324,7 +3694,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3324
3694
  } catch (error) {
3325
3695
  const handlerError = error instanceof Error ? error : new Error(String(error));
3326
3696
  errorMessage = handlerError.message;
3327
- await this._internal.emitError({
3697
+ if (!discardAbortedResult(signal, discardOnAbort, errorMessage)) await this._internal.emitError({
3328
3698
  error: handlerError,
3329
3699
  code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
3330
3700
  context: {
@@ -3353,7 +3723,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3353
3723
  {
3354
3724
  var _agent$messages$inser2;
3355
3725
  const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
3356
- if (messageIndex === -1) return false;
3726
+ if (discardAbortedResult(signal, discardOnAbort, errorMessage) || agent.threadId !== threadId || messageIndex === -1 || agent.messages.some((m) => m.role === "tool" && m.toolCallId === toolCall.id && !this.isFrontendPlaceholderResult(m))) return false;
3357
3727
  let insertAt = messageIndex + 1;
3358
3728
  while (insertAt < agent.messages.length && ((_agent$messages$inser2 = agent.messages[insertAt]) === null || _agent$messages$inser2 === void 0 ? void 0 : _agent$messages$inser2.role) === "tool") insertAt++;
3359
3729
  const toolMessage = {
@@ -5188,9 +5558,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5188
5558
  return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
5189
5559
  }
5190
5560
  var CopilotKitCore = class {
5191
- constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
5561
+ constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, messageFilter, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
5192
5562
  _defineProperty(this, "_headers", void 0);
5193
5563
  _defineProperty(this, "_credentials", void 0);
5564
+ _defineProperty(this, "_messageFilter", void 0);
5194
5565
  _defineProperty(this, "_properties", void 0);
5195
5566
  _defineProperty(this, "_defaultThrottleMs", void 0);
5196
5567
  _defineProperty(this, "_debug", void 0);
@@ -5205,6 +5576,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5205
5576
  _defineProperty(this, "previousAgentIds", /* @__PURE__ */ new Set());
5206
5577
  this._headers = normalizeHeaders(headers);
5207
5578
  this._credentials = credentials;
5579
+ this._messageFilter = messageFilter;
5208
5580
  this._properties = properties;
5209
5581
  this._debug = debug;
5210
5582
  this.agentRegistry = new AgentRegistry(this);
@@ -5327,6 +5699,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5327
5699
  get credentials() {
5328
5700
  return this._credentials;
5329
5701
  }
5702
+ get messageFilter() {
5703
+ return this._messageFilter;
5704
+ }
5330
5705
  get properties() {
5331
5706
  return this._properties;
5332
5707
  }
@@ -5475,6 +5850,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5475
5850
  this.agentRegistry.applyCredentialsToAgents(this.agentRegistry.agents);
5476
5851
  this.agentRegistry.handleCredentialsChanged();
5477
5852
  }
5853
+ /**
5854
+ * Replace the message filter applied to every runtime agent.
5855
+ *
5856
+ * Applies to agents already discovered as well as ones discovered later, so
5857
+ * a filter set before `/info` lands is not lost. Pass `undefined` to go back
5858
+ * to sending the full thread.
5859
+ */
5860
+ setMessageFilter(messageFilter) {
5861
+ this._messageFilter = messageFilter;
5862
+ this.agentRegistry.applyMessageFilterToAgents(this.agentRegistry.agents);
5863
+ }
5478
5864
  setProperties(properties) {
5479
5865
  this._properties = properties;
5480
5866
  this.notifySubscribers((subscriber) => {
@@ -5834,7 +6220,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5834
6220
  return this.runHandler.connectAgent(params);
5835
6221
  }
5836
6222
  stopAgent(params) {
5837
- this.runHandler.abortCurrentRun();
6223
+ this.runHandler.abortCurrentRun(params.agent);
5838
6224
  params.agent.abortRun();
5839
6225
  }
5840
6226
  async runAgent(params) {