@copilotkit/core 1.68.3 → 1.69.0

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
@@ -2803,6 +2803,7 @@ const isContinuation = (input) => input.resume !== void 0 || Object.prototype.ha
2803
2803
  var StateManager = class {
2804
2804
  stateByRun = /* @__PURE__ */ new Map();
2805
2805
  messageToRun = /* @__PURE__ */ new Map();
2806
+ rawEventByMessage = /* @__PURE__ */ new Map();
2806
2807
  activeRun = /* @__PURE__ */ new Map();
2807
2808
  agentSubscriptions = /* @__PURE__ */ new Map();
2808
2809
  pendingContinuations = /* @__PURE__ */ new WeakMap();
@@ -2854,12 +2855,13 @@ var StateManager = class {
2854
2855
  runId: subRunId ?? input.runId
2855
2856
  });
2856
2857
  const { unsubscribe } = agent.subscribe({
2857
- onRunStartedEvent: ({ input, state }) => {
2858
+ onRunStartedEvent: ({ event, input, state }) => {
2858
2859
  if (revoked) return;
2859
2860
  const internalContinuation = [...this.pendingContinuations.get(agent) ?? []].find((pending) => pending.expectedInput === input);
2860
2861
  internalContinuation?.cancel();
2861
- if (runFinished && input.runId === subRunId && !internalContinuation && !isContinuation(input)) subRunId = (0, _ag_ui_client.randomUUID)();
2862
- else subRunId = internalContinuation?.expectedRunId ?? input.runId;
2862
+ if (internalContinuation) subRunId = internalContinuation.expectedRunId ?? event.runId ?? input.runId;
2863
+ else if (runFinished && input.runId === subRunId && !isContinuation(input) && (event.runId == null || event.runId === subRunId)) subRunId = (0, _ag_ui_client.randomUUID)();
2864
+ else subRunId = event.runId || input.runId;
2863
2865
  runFinished = false;
2864
2866
  this.handleRunStarted(agent, effectiveInput(input), state);
2865
2867
  },
@@ -2881,13 +2883,22 @@ var StateManager = class {
2881
2883
  if (revoked) return;
2882
2884
  this.handleStateDelta(agent, event, effectiveInput(input), state);
2883
2885
  },
2886
+ onTextMessageStartEvent: ({ event, input }) => {
2887
+ if (revoked) return;
2888
+ this.handleTextMessageStart(agent, event, effectiveInput(input));
2889
+ },
2884
2890
  onMessagesSnapshotEvent: ({ event, input, messages }) => {
2885
2891
  if (revoked) return;
2886
2892
  this.handleMessagesSnapshot(agent, event, effectiveInput(input), messages);
2893
+ this.pruneRawEvents(agent.agentId, input.threadId, event.messages, effectiveInput(input));
2887
2894
  },
2888
2895
  onNewMessage: ({ message, input }) => {
2889
2896
  if (revoked) return;
2890
2897
  this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
2898
+ },
2899
+ onMessagesChanged: ({ messages, input }) => {
2900
+ if (revoked) return;
2901
+ if (!input) this.pruneRawEvents(agent.agentId, agent.threadId, messages);
2891
2902
  }
2892
2903
  });
2893
2904
  this.agentSubscriptions.set(agentId, () => {
@@ -2905,6 +2916,7 @@ var StateManager = class {
2905
2916
  unsubscribe();
2906
2917
  this.agentSubscriptions.delete(agentId);
2907
2918
  }
2919
+ this.rawEventByMessage.delete(agentId);
2908
2920
  }
2909
2921
  /**
2910
2922
  * Get state for a specific run
@@ -2922,6 +2934,13 @@ var StateManager = class {
2922
2934
  return this.messageToRun.get(agentId)?.get(threadId)?.get(messageId);
2923
2935
  }
2924
2936
  /**
2937
+ * Get direct text-start metadata associated with a message.
2938
+ */
2939
+ getRawEventForMessage(agentId, threadId, messageId) {
2940
+ const rawEvent = this.rawEventByMessage.get(agentId)?.get(threadId)?.get(messageId);
2941
+ return rawEvent === void 0 ? void 0 : (0, _ag_ui_client.structuredClone_)(rawEvent);
2942
+ }
2943
+ /**
2925
2944
  * Get all states for an agent's thread
2926
2945
  */
2927
2946
  getStatesForThread(agentId, threadId) {
@@ -2973,12 +2992,30 @@ var StateManager = class {
2973
2992
  this.saveState(agent.agentId, threadId, runId, state);
2974
2993
  }
2975
2994
  /**
2995
+ * Capture only defined metadata from a normalized direct text-start event.
2996
+ */
2997
+ handleTextMessageStart(agent, event, input) {
2998
+ if (!agent.agentId) return;
2999
+ const { threadId } = input;
3000
+ if (event.rawEvent === void 0) {
3001
+ const threadEvents = this.rawEventByMessage.get(agent.agentId)?.get(threadId);
3002
+ threadEvents?.delete(event.messageId);
3003
+ if (threadEvents?.size === 0) this.rawEventByMessage.get(agent.agentId)?.delete(threadId);
3004
+ if (this.rawEventByMessage.get(agent.agentId)?.size === 0) this.rawEventByMessage.delete(agent.agentId);
3005
+ return;
3006
+ }
3007
+ if (!this.rawEventByMessage.has(agent.agentId)) this.rawEventByMessage.set(agent.agentId, /* @__PURE__ */ new Map());
3008
+ const agentEvents = this.rawEventByMessage.get(agent.agentId);
3009
+ if (!agentEvents.has(threadId)) agentEvents.set(threadId, /* @__PURE__ */ new Map());
3010
+ agentEvents.get(threadId).set(event.messageId, event.rawEvent);
3011
+ }
3012
+ /**
2976
3013
  * Handle messages snapshot event
2977
3014
  */
2978
3015
  handleMessagesSnapshot(agent, event, input, messages) {
2979
3016
  if (!agent.agentId) return;
2980
3017
  const { threadId, runId } = input;
2981
- for (const message of event.messages) this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
3018
+ for (const message of event.messages) if (this.getRunIdForMessage(agent.agentId, threadId, message.id) === void 0) this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
2982
3019
  }
2983
3020
  /**
2984
3021
  * Handle new message event
@@ -3012,12 +3049,23 @@ var StateManager = class {
3012
3049
  if (!agentMessages.has(threadId)) agentMessages.set(threadId, /* @__PURE__ */ new Map());
3013
3050
  agentMessages.get(threadId).set(messageId, runId);
3014
3051
  }
3052
+ pruneRawEvents(agentId, fallbackThreadId, messages, input) {
3053
+ const threadId = input?.threadId ?? fallbackThreadId;
3054
+ if (!threadId) return;
3055
+ const threadEvents = this.rawEventByMessage.get(agentId)?.get(threadId);
3056
+ if (!threadEvents) return;
3057
+ const messageIds = new Set(messages.map((message) => message.id));
3058
+ for (const messageId of threadEvents.keys()) if (!messageIds.has(messageId)) threadEvents.delete(messageId);
3059
+ if (threadEvents.size === 0) this.rawEventByMessage.get(agentId)?.delete(threadId);
3060
+ if (this.rawEventByMessage.get(agentId)?.size === 0) this.rawEventByMessage.delete(agentId);
3061
+ }
3015
3062
  /**
3016
3063
  * Clear all state for an agent
3017
3064
  */
3018
3065
  clearAgentState(agentId) {
3019
3066
  this.stateByRun.delete(agentId);
3020
3067
  this.messageToRun.delete(agentId);
3068
+ this.rawEventByMessage.delete(agentId);
3021
3069
  }
3022
3070
  /**
3023
3071
  * Clear all state for a thread
@@ -3025,6 +3073,7 @@ var StateManager = class {
3025
3073
  clearThreadState(agentId, threadId) {
3026
3074
  this.stateByRun.get(agentId)?.delete(threadId);
3027
3075
  this.messageToRun.get(agentId)?.delete(threadId);
3076
+ this.rawEventByMessage.get(agentId)?.delete(threadId);
3028
3077
  }
3029
3078
  };
3030
3079
 
@@ -4854,6 +4903,9 @@ var CopilotKitCore = class {
4854
4903
  getRunIdForMessage(agentId, threadId, messageId) {
4855
4904
  return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
4856
4905
  }
4906
+ getRawEventForMessage(agentId, threadId, messageId) {
4907
+ return this.stateManager.getRawEventForMessage(agentId, threadId, messageId);
4908
+ }
4857
4909
  getRunIdsForThread(agentId, threadId) {
4858
4910
  return this.stateManager.getRunIdsForThread(agentId, threadId);
4859
4911
  }
@@ -5138,6 +5190,16 @@ function optionalString(value) {
5138
5190
  return typeof value === "string" && value.length > 0 ? value : void 0;
5139
5191
  }
5140
5192
  /**
5193
+ * REST `/threads` is agent-scoped. The Phoenix `user_meta` channel is not.
5194
+ * Drop live upserts that belong to a different agent, or one Inspector
5195
+ * `all-agents` flatten shows the same thread twice until a hard refresh.
5196
+ */
5197
+ function threadMetadataTargetsAgent(payload, agentId) {
5198
+ if (!agentId || payload.operation === "deleted") return true;
5199
+ const threadAgentId = optionalString(payload.thread.agentId);
5200
+ return !threadAgentId || threadAgentId === agentId;
5201
+ }
5202
+ /**
5141
5203
  * Converts gateway run-activity payloads into the internal TypeScript shape.
5142
5204
  */
5143
5205
  function normalizeThreadRunActivityNotification(payload) {
@@ -5563,7 +5625,7 @@ function createThreadStore(environment) {
5563
5625
  }))), ɵobservePhoenixJoinOutcome$(channel$).pipe((0, rxjs_operators.filter)((outcome) => outcome.type !== "joined"), (0, rxjs_operators.map)((outcome) => outcome.type === "timeout" ? threadSocketEvents.joinTimedOut({ sessionId: action.sessionId }) : threadSocketEvents.joinFailed({ sessionId: action.sessionId })))).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$)));
5564
5626
  });
5565
5627
  }))),
5566
- createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => action.sessionId === state.sessionId), (0, rxjs_operators.map)(([action, state]) => {
5628
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => action.sessionId === state.sessionId && threadMetadataTargetsAgent(action.payload, state.context?.agentId)), (0, rxjs_operators.map)(([action, state]) => {
5567
5629
  if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
5568
5630
  sessionId: action.sessionId,
5569
5631
  threadId: action.payload.deleted.id