@copilotkit/core 1.69.0 → 1.69.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.cjs CHANGED
@@ -1999,6 +1999,30 @@ const SUGGEST_TOOL = {
1999
1999
  }
2000
2000
  };
2001
2001
 
2002
+ //#endregion
2003
+ //#region src/core/tool-result-content.ts
2004
+ /**
2005
+ * Single authority for the forwarded-to-client sentinel used by StateManager
2006
+ * and RunHandler.
2007
+ */
2008
+ const FORWARDED_TO_CLIENT = "Forwarded to client";
2009
+ function normalizeToolResultContent(content) {
2010
+ if (typeof content === "string") return content.trim();
2011
+ if (Array.isArray(content)) {
2012
+ const text = content.flatMap((part) => {
2013
+ if (typeof part === "string") return [part];
2014
+ if (part && typeof part === "object" && "text" in part && typeof part.text === "string") return [part.text];
2015
+ return [];
2016
+ }).join("").trim();
2017
+ return text.length > 0 ? text : null;
2018
+ }
2019
+ if (content && typeof content === "object" && "text" in content && typeof content.text === "string") return content.text.trim();
2020
+ return null;
2021
+ }
2022
+ function isForwardedToClientPlaceholder(content) {
2023
+ return normalizeToolResultContent(content) === FORWARDED_TO_CLIENT;
2024
+ }
2025
+
2002
2026
  //#endregion
2003
2027
  //#region src/core/run-handler.ts
2004
2028
  /**
@@ -2182,8 +2206,8 @@ var RunHandler = class {
2182
2206
  * Connect an agent (establish initial connection)
2183
2207
  */
2184
2208
  async connectAgent({ agent }) {
2209
+ const incomingThreadId = agent.threadId ?? null;
2185
2210
  try {
2186
- const incomingThreadId = agent.threadId ?? null;
2187
2211
  const restoreKey = this.getConnectRestoreKey(agent);
2188
2212
  const isFreshRestore = incomingThreadId !== (this._lastConnectedThreadIdsByAgent.get(restoreKey) ?? null);
2189
2213
  this._lastConnectedThreadIdsByAgent.set(restoreKey, incomingThreadId);
@@ -2217,6 +2241,7 @@ var RunHandler = class {
2217
2241
  if (!(connectError.name === "AbortError" || connectError.message === "Fetch is aborted" || connectError.message === "signal is aborted without reason" || connectError.message === "component unmounted")) {
2218
2242
  const context = {};
2219
2243
  if (agent.agentId) context.agentId = agent.agentId;
2244
+ if (incomingThreadId) context.threadId = incomingThreadId;
2220
2245
  await this._internal.emitError({
2221
2246
  error: connectError,
2222
2247
  code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
@@ -2363,21 +2388,7 @@ var RunHandler = class {
2363
2388
  return runAgentResult;
2364
2389
  }
2365
2390
  isFrontendPlaceholderResult(message) {
2366
- if (message.role !== "tool") return false;
2367
- return this.normalizeToolResultContent(message.content) === "Forwarded to client";
2368
- }
2369
- normalizeToolResultContent(content) {
2370
- if (typeof content === "string") return content.trim();
2371
- if (Array.isArray(content)) {
2372
- const text = content.flatMap((part) => {
2373
- if (typeof part === "string") return [part];
2374
- if (part && typeof part === "object" && "text" in part && typeof part.text === "string") return [part.text];
2375
- return [];
2376
- }).join("").trim();
2377
- return text.length > 0 ? text : null;
2378
- }
2379
- if (content && typeof content === "object" && "text" in content && typeof content.text === "string") return content.text.trim();
2380
- return null;
2391
+ return message.role === "tool" && isForwardedToClientPlaceholder(message.content);
2381
2392
  }
2382
2393
  /**
2383
2394
  * Shared handler execution logic used by executeSpecificTool, executeWildcardTool, and runTool.
@@ -2850,6 +2861,61 @@ var StateManager = class {
2850
2861
  let revoked = false;
2851
2862
  let subRunId;
2852
2863
  let runFinished = false;
2864
+ const pendingResults = /* @__PURE__ */ new WeakMap();
2865
+ const reconcilePendingResults = (historyMessages, input) => {
2866
+ const events = pendingResults.get(input);
2867
+ if (!events) return void 0;
2868
+ const messages = [...historyMessages];
2869
+ let changed = false;
2870
+ for (const event of events.values()) {
2871
+ const ownerIndex = messages.findIndex((message) => message.role === "assistant" && message.toolCalls?.some((toolCall) => toolCall.id === event.toolCallId));
2872
+ if (ownerIndex < 0) continue;
2873
+ const matchingIndexes = messages.reduce((indexes, message, index) => {
2874
+ if (message.role === "tool" && message.toolCallId === event.toolCallId) indexes.push(index);
2875
+ return indexes;
2876
+ }, []);
2877
+ const realIndex = matchingIndexes.find((index) => !isForwardedToClientPlaceholder(messages[index]?.content));
2878
+ if (realIndex !== void 0) {
2879
+ for (const duplicateIndex of matchingIndexes.filter((candidateIndex) => candidateIndex !== realIndex).sort((a, b) => b - a)) {
2880
+ messages.splice(duplicateIndex, 1);
2881
+ changed = true;
2882
+ }
2883
+ continue;
2884
+ }
2885
+ const placeholderIndex = matchingIndexes.find((index) => isForwardedToClientPlaceholder(messages[index]?.content));
2886
+ if (placeholderIndex !== void 0) {
2887
+ if (isForwardedToClientPlaceholder(event.content)) {
2888
+ for (const duplicateIndex of matchingIndexes.slice(1).sort((a, b) => b - a)) {
2889
+ messages.splice(duplicateIndex, 1);
2890
+ changed = true;
2891
+ }
2892
+ continue;
2893
+ }
2894
+ messages[placeholderIndex] = {
2895
+ ...messages[placeholderIndex],
2896
+ id: event.messageId,
2897
+ content: event.content
2898
+ };
2899
+ changed = true;
2900
+ for (const duplicateIndex of matchingIndexes.filter((candidateIndex) => candidateIndex !== placeholderIndex && isForwardedToClientPlaceholder(messages[candidateIndex]?.content)).sort((a, b) => b - a)) messages.splice(duplicateIndex, 1);
2901
+ continue;
2902
+ }
2903
+ const result = {
2904
+ id: event.messageId,
2905
+ role: "tool",
2906
+ toolCallId: event.toolCallId,
2907
+ content: event.content
2908
+ };
2909
+ let insertIndex = ownerIndex + 1;
2910
+ while (messages[insertIndex]?.role === "tool") insertIndex++;
2911
+ messages.splice(insertIndex, 0, result);
2912
+ changed = true;
2913
+ }
2914
+ return changed ? { messages } : void 0;
2915
+ };
2916
+ const clearPendingResults = (input) => {
2917
+ pendingResults.delete(input);
2918
+ };
2853
2919
  const effectiveInput = (input) => ({
2854
2920
  ...input,
2855
2921
  runId: subRunId ?? input.runId
@@ -2865,15 +2931,39 @@ var StateManager = class {
2865
2931
  runFinished = false;
2866
2932
  this.handleRunStarted(agent, effectiveInput(input), state);
2867
2933
  },
2868
- onRunFinishedEvent: ({ input, state }) => {
2934
+ onRunFinishedEvent: ({ input, state, messages }) => {
2869
2935
  if (revoked) return;
2870
2936
  runFinished = true;
2871
- this.handleRunFinished(agent, effectiveInput(input), state);
2937
+ const effective = effectiveInput(input);
2938
+ const mutation = reconcilePendingResults(messages, input);
2939
+ clearPendingResults(input);
2940
+ this.handleRunFinished(agent, effective, state);
2941
+ return mutation;
2872
2942
  },
2873
- onRunErrorEvent: ({ input, state }) => {
2943
+ onRunErrorEvent: ({ input, state, messages }) => {
2874
2944
  if (revoked) return;
2875
2945
  runFinished = true;
2876
- this.handleRunFinished(agent, effectiveInput(input), state);
2946
+ const effective = effectiveInput(input);
2947
+ const mutation = reconcilePendingResults(messages, input);
2948
+ this.handleRunFinished(agent, effective, state);
2949
+ return mutation;
2950
+ },
2951
+ onRunFailed: ({ input, messages }) => {
2952
+ if (revoked) return;
2953
+ return reconcilePendingResults(messages, input);
2954
+ },
2955
+ onRunFinalized: ({ input }) => {
2956
+ if (revoked) return;
2957
+ clearPendingResults(input);
2958
+ },
2959
+ onToolCallResultEvent: ({ event, input }) => {
2960
+ if (revoked) return;
2961
+ let events = pendingResults.get(input);
2962
+ if (!events) {
2963
+ events = /* @__PURE__ */ new Map();
2964
+ pendingResults.set(input, events);
2965
+ }
2966
+ events.set(event.toolCallId, event);
2877
2967
  },
2878
2968
  onStateSnapshotEvent: ({ event, input, state }) => {
2879
2969
  if (revoked) return;
@@ -3012,7 +3102,7 @@ var StateManager = class {
3012
3102
  /**
3013
3103
  * Handle messages snapshot event
3014
3104
  */
3015
- handleMessagesSnapshot(agent, event, input, messages) {
3105
+ handleMessagesSnapshot(agent, event, input, _messages) {
3016
3106
  if (!agent.agentId) return;
3017
3107
  const { threadId, runId } = input;
3018
3108
  for (const message of event.messages) if (this.getRunIdForMessage(agent.agentId, threadId, message.id) === void 0) this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
@@ -4935,6 +5025,67 @@ var CopilotKitCore = class {
4935
5025
  async waitForPendingFrameworkUpdates() {}
4936
5026
  };
4937
5027
 
5028
+ //#endregion
5029
+ //#region src/core/inspect-inject.ts
5030
+ const REMINT_ID_KEYS = [
5031
+ "messageId",
5032
+ "parentMessageId",
5033
+ "toolCallId",
5034
+ "runId"
5035
+ ];
5036
+ function newInspectorId() {
5037
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
5038
+ return `cpk-inject-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
5039
+ }
5040
+ function remintInspectorEventIds(events) {
5041
+ const mapped = /* @__PURE__ */ new Map();
5042
+ const idFor = (value) => {
5043
+ const existing = mapped.get(value);
5044
+ if (existing) return existing;
5045
+ const next = newInspectorId();
5046
+ mapped.set(value, next);
5047
+ return next;
5048
+ };
5049
+ return events.map((event) => {
5050
+ const copy = { ...event };
5051
+ for (const key of REMINT_ID_KEYS) {
5052
+ const value = copy[key];
5053
+ if (typeof value === "string" && value.length > 0) copy[key] = idFor(value);
5054
+ }
5055
+ return copy;
5056
+ });
5057
+ }
5058
+ /**
5059
+ * Inspector-only helper. Apply AG-UI events to a live agent through the
5060
+ * same runAgent path a real agent uses, so chat and frontend-tool handlers
5061
+ * update. Not a documented product API.
5062
+ */
5063
+ async function ɵinjectInspectorEvents(params) {
5064
+ const { core, agent, events } = params;
5065
+ if (agent.isRunning) throw new Error("The agent is running. Wait for the current run to end.");
5066
+ if (events.length === 0) throw new Error("Snippet JSON must be an array of events.");
5067
+ const before = new Set(agent.messages.map((message) => message.id));
5068
+ const originalRun = agent.run;
5069
+ const runEvents = remintInspectorEventIds(events);
5070
+ agent.run = (_input) => (0, rxjs.from)(runEvents);
5071
+ try {
5072
+ await core.runAgent({ agent });
5073
+ } finally {
5074
+ agent.run = originalRun;
5075
+ }
5076
+ return { messageIds: agent.messages.filter((message) => !before.has(message.id)).map((message) => message.id) };
5077
+ }
5078
+ /**
5079
+ * Remove messages created by the last Inspector inject. Does not undo
5080
+ * frontend-tool handler side effects.
5081
+ */
5082
+ function ɵresetInspectorInject(params) {
5083
+ const drop = new Set(params.messageIds);
5084
+ if (drop.size === 0) return;
5085
+ const next = params.agent.messages.filter((message) => !drop.has(message.id));
5086
+ params.agent.setMessages(next);
5087
+ }
5088
+
4938
5089
  //#endregion
4939
5090
  //#region src/types.ts
4940
5091
  /**
@@ -5979,6 +6130,101 @@ var ɵInterruptState = class {
5979
6130
  }
5980
6131
  };
5981
6132
 
6133
+ //#endregion
6134
+ //#region src/inspector-thread-bridge.ts
6135
+ const INSPECTOR_THREAD_BRIDGE_PLUGIN_ID = "cpk-inspector-thread";
6136
+ const EVENT_PREFIX = `copilotkit:${INSPECTOR_THREAD_BRIDGE_PLUGIN_ID}`;
6137
+ function eventName(suffix) {
6138
+ return `${EVENT_PREFIX}:${suffix}`;
6139
+ }
6140
+ function getEventTarget() {
6141
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") return window;
6142
+ if (typeof EventTarget === "undefined") return null;
6143
+ const sharedGlobal = globalThis;
6144
+ sharedGlobal.__COPILOTKIT_INSPECTOR_THREAD_EVENT_TARGET__ ??= new EventTarget();
6145
+ return sharedGlobal.__COPILOTKIT_INSPECTOR_THREAD_EVENT_TARGET__;
6146
+ }
6147
+ function createDetailEvent(name, detail) {
6148
+ if (typeof CustomEvent !== "undefined") return new CustomEvent(name, { detail });
6149
+ const event = new Event(name);
6150
+ Object.defineProperty(event, "detail", { value: detail });
6151
+ return event;
6152
+ }
6153
+ function detailFromEvent(event) {
6154
+ return event.detail;
6155
+ }
6156
+ /** The Inspector thread bridge is development-only. */
6157
+ function isInspectorThreadBridgeEnabled() {
6158
+ return process.env.NODE_ENV !== "production";
6159
+ }
6160
+ function createInspectorThreadRequestId() {
6161
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
6162
+ return `inspector-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6163
+ }
6164
+ function dispatch(suffix, payload) {
6165
+ if (!isInspectorThreadBridgeEnabled()) return;
6166
+ const target = getEventTarget();
6167
+ if (!target) return;
6168
+ target.dispatchEvent(createDetailEvent(eventName(suffix), payload));
6169
+ }
6170
+ function on$1(suffix, handler) {
6171
+ if (!isInspectorThreadBridgeEnabled()) return () => void 0;
6172
+ const target = getEventTarget();
6173
+ if (!target) return () => void 0;
6174
+ const listener = (event) => {
6175
+ handler(detailFromEvent(event));
6176
+ };
6177
+ const name = eventName(suffix);
6178
+ target.addEventListener(name, listener);
6179
+ return () => target.removeEventListener(name, listener);
6180
+ }
6181
+ /**
6182
+ * Ask the first mounted official chat for the matching agent to load a thread.
6183
+ * Returns false when no chat claims the request synchronously.
6184
+ */
6185
+ function emitInspectorViewThread(payload) {
6186
+ if (!isInspectorThreadBridgeEnabled()) return false;
6187
+ const target = getEventTarget();
6188
+ if (!target) return false;
6189
+ const detail = {
6190
+ payload,
6191
+ claimed: false
6192
+ };
6193
+ target.dispatchEvent(createDetailEvent(eventName("view-thread"), detail));
6194
+ return detail.claimed;
6195
+ }
6196
+ function emitInspectorStopViewing(payload) {
6197
+ dispatch("stop-viewing", payload);
6198
+ }
6199
+ function emitInspectorActiveThread(payload) {
6200
+ dispatch("active-thread", payload);
6201
+ }
6202
+ function emitInspectorViewThreadResult(payload) {
6203
+ dispatch("view-thread-result", payload);
6204
+ }
6205
+ function onInspectorViewThread(handler) {
6206
+ if (!isInspectorThreadBridgeEnabled()) return () => void 0;
6207
+ const target = getEventTarget();
6208
+ if (!target) return () => void 0;
6209
+ const listener = (event) => {
6210
+ const detail = detailFromEvent(event);
6211
+ if (detail.claimed) return;
6212
+ detail.claimed = handler(detail.payload);
6213
+ };
6214
+ const name = eventName("view-thread");
6215
+ target.addEventListener(name, listener);
6216
+ return () => target.removeEventListener(name, listener);
6217
+ }
6218
+ function onInspectorStopViewing(handler) {
6219
+ return on$1("stop-viewing", handler);
6220
+ }
6221
+ function onInspectorActiveThread(handler) {
6222
+ return on$1("active-thread", handler);
6223
+ }
6224
+ function onInspectorViewThreadResult(handler) {
6225
+ return on$1("view-thread-result", handler);
6226
+ }
6227
+
5982
6228
  //#endregion
5983
6229
  exports.AgentRegistry = AgentRegistry;
5984
6230
  exports.AgentThreadLockedError = AgentThreadLockedError;
@@ -5986,6 +6232,7 @@ exports.ContextStore = ContextStore;
5986
6232
  exports.CopilotKitCore = CopilotKitCore;
5987
6233
  exports.CopilotKitCoreErrorCode = CopilotKitCoreErrorCode;
5988
6234
  exports.CopilotKitCoreRuntimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus;
6235
+ exports.INSPECTOR_THREAD_BRIDGE_PLUGIN_ID = INSPECTOR_THREAD_BRIDGE_PLUGIN_ID;
5989
6236
  exports.IntelligenceAgent = IntelligenceAgent;
5990
6237
  exports.MEMORY_ERROR_REGISTRY = MEMORY_ERROR_REGISTRY;
5991
6238
  exports.MemoryError = MemoryError;
@@ -5997,15 +6244,25 @@ exports.ToolCallStatus = ToolCallStatus;
5997
6244
  exports.completePartialMarkdown = completePartialMarkdown;
5998
6245
  exports.createActionGroup = createActionGroup;
5999
6246
  exports.createEffect = createEffect;
6247
+ exports.createInspectorThreadRequestId = createInspectorThreadRequestId;
6000
6248
  exports.createReducer = createReducer;
6001
6249
  exports.createSelector = createSelector;
6002
6250
  exports.createStore = createStore;
6251
+ exports.emitInspectorActiveThread = emitInspectorActiveThread;
6252
+ exports.emitInspectorStopViewing = emitInspectorStopViewing;
6253
+ exports.emitInspectorViewThread = emitInspectorViewThread;
6254
+ exports.emitInspectorViewThreadResult = emitInspectorViewThreadResult;
6003
6255
  exports.empty = empty;
6004
6256
  exports.ensureObjectArgs = ensureObjectArgs;
6005
6257
  exports.isAbortError = isAbortError;
6258
+ exports.isInspectorThreadBridgeEnabled = isInspectorThreadBridgeEnabled;
6006
6259
  exports.isRunCompletionAware = isRunCompletionAware;
6007
6260
  exports.ofType = ofType;
6008
6261
  exports.on = on;
6262
+ exports.onInspectorActiveThread = onInspectorActiveThread;
6263
+ exports.onInspectorStopViewing = onInspectorStopViewing;
6264
+ exports.onInspectorViewThread = onInspectorViewThread;
6265
+ exports.onInspectorViewThreadResult = onInspectorViewThreadResult;
6009
6266
  exports.parseToolArguments = parseToolArguments;
6010
6267
  exports.props = props;
6011
6268
  exports.select = select;
@@ -6015,6 +6272,7 @@ exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
6015
6272
  exports.ɵcreateMemoryStore = createMemoryStore;
6016
6273
  exports.ɵcreateThreadSelectors = ɵcreateThreadSelectors;
6017
6274
  exports.ɵcreateThreadStore = createThreadStore;
6275
+ exports.ɵinjectInspectorEvents = ɵinjectInspectorEvents;
6018
6276
  exports.ɵisCopilotKitFeature = ɵisCopilotKitFeature;
6019
6277
  exports.ɵisRetryableMemoryStatus = isRetryableStatus;
6020
6278
  exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
@@ -6029,6 +6287,7 @@ exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
6029
6287
  exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
6030
6288
  exports.ɵphoenixChannel$ = ɵphoenixChannel$;
6031
6289
  exports.ɵphoenixSocket$ = ɵphoenixSocket$;
6290
+ exports.ɵresetInspectorInject = ɵresetInspectorInject;
6032
6291
  exports.ɵselectFetchMoreError = ɵselectFetchMoreError;
6033
6292
  exports.ɵselectHasNextPage = ɵselectHasNextPage;
6034
6293
  exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;