@blocksdiy/react-common 1.43.1 → 1.45.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.
@@ -2,7 +2,9 @@ import { type Message, ToolMessage, type UserMessage } from "@ag-ui/client";
2
2
  import { useRenderToolCall } from "@copilotkit/react-core/v2";
3
3
  import { ReactNode, SetStateAction } from "react";
4
4
  import { type RenderProp } from "../utils/compose-render.js";
5
+ import { type MessageRunIds } from "../utils/message-run-ids.js";
5
6
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
7
+ export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun, type MessageRunIds } from "../utils/message-run-ids.js";
6
8
  export { type Message, type AssistantMessage, type UserMessage } from "@ag-ui/client";
7
9
  export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
8
10
  export interface Attachment {
@@ -58,10 +60,29 @@ export interface AgentChatContextValue {
58
60
  role: "assistant" | "user";
59
61
  }[];
60
62
  messageById: Map<string, Message>;
63
+ /**
64
+ * The agent run (turn) that produced each replayed message — the `agentRunId` the rows
65
+ * it wrote carry. Filled from the connect replay; messages from before run attribution
66
+ * (and live-streamed ones) have no entry. Optional so contexts a host builds by hand
67
+ * (previews, stubs) need not state it; absent reads as "no run known".
68
+ */
69
+ runIdByMessageId?: MessageRunIds;
61
70
  toolMessages: ToolMessage[];
62
71
  renderToolCall: ReturnType<typeof useRenderToolCall>;
63
72
  sendMessage: (message: Omit<UserMessage, "id" | "role">) => Promise<void>;
64
73
  sendFromInputs: () => Promise<void>;
74
+ /**
75
+ * Replay this conversation's transcript from the server, in place.
76
+ *
77
+ * The same round-trip a fresh mount does — the connect endpoint reads the checkpoint and
78
+ * answers with a MESSAGES_SNAPSHOT, which replaces the mirrored list. For turns that ran
79
+ * SERVER-SIDE, which no client streamed and so no client has: without this they appear only
80
+ * after a reload or a conversation switch.
81
+ *
82
+ * A no-op while a run is in flight: that run's own stream is the authoritative view of the
83
+ * conversation, and replacing the list underneath it would fight the events still arriving.
84
+ */
85
+ reloadMessages: () => Promise<void>;
65
86
  /** Resumes a run parked on a server-side interrupt. Rejects if the resume fails. */
66
87
  /** Resolves false when a run was already in flight, so nothing was sent. */
67
88
  resolveInterrupt: (resume: unknown) => Promise<boolean>;
@@ -151,8 +172,29 @@ export interface AgentChatMessageGroupProps {
151
172
  export declare function AgentChatMessageGroup({ messageGroup, ...props }: React.ComponentProps<"div"> & AgentChatMessageGroupProps): import("react").JSX.Element;
152
173
  export interface AgentChatMessagesProps {
153
174
  scrollAreaClassName?: string;
154
- }
155
- export declare function AgentChatMessages({ scrollAreaClassName, ...props }: React.ComponentProps<"div"> & AgentChatMessagesProps): import("react").JSX.Element;
175
+ /**
176
+ * An agent run (turn) to open the conversation at — the `agentRunId` a row the agent
177
+ * wrote carries. Once the transcript has replayed, the first message group of that run
178
+ * is scrolled into view and the run's messages are marked highlighted for
179
+ * `focusHighlightMs` (read it with `useAgentChatRunFocus`). Happens once per
180
+ * conversation; a no-op when the run is not in this conversation (an older thread,
181
+ * another conversation's run).
182
+ */
183
+ focusRunId?: string;
184
+ /** How long a focused run stays highlighted; defaults to 2400ms. */
185
+ focusHighlightMs?: number;
186
+ }
187
+ export interface AgentChatRunFocusValue {
188
+ /** The run being focused (the `focusRunId` passed to AgentChatMessages), if any. */
189
+ runId?: string;
190
+ /** Ids of the messages that run produced, in transcript order. */
191
+ messageIds: ReadonlySet<string>;
192
+ /** True for a moment after the run is scrolled into view — drive the highlight off it. */
193
+ isHighlighted: boolean;
194
+ }
195
+ /** The run focus of the enclosing AgentChatMessages (see its `focusRunId`). */
196
+ export declare const useAgentChatRunFocus: () => AgentChatRunFocusValue;
197
+ export declare function AgentChatMessages({ scrollAreaClassName, focusRunId, focusHighlightMs, ...props }: React.ComponentProps<"div"> & AgentChatMessagesProps): import("react").JSX.Element;
156
198
  export interface AgentChatThinkingProps {
157
199
  asChild?: boolean;
158
200
  render?: RenderProp;
@@ -1 +1 @@
1
- {"version":3,"file":"new-agent-chat.d.ts","sourceRoot":"","sources":["../../src/components/new-agent-chat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"new-agent-chat.d.ts","sourceRoot":"","sources":["../../src/components/new-agent-chat.tsx"],"names":[],"mappings":"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"}
@@ -6,7 +6,9 @@ import { useCopilotKit, useRenderToolCall } from "@copilotkit/react-core/v2";
6
6
  import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
7
7
  import { useStickToBottom } from "use-stick-to-bottom";
8
8
  import { ComposeRender } from "../utils/compose-render.js";
9
+ import { EMPTY_MESSAGE_RUN_IDS, findMessageGroupElement, mergeMessageRunIds, MESSAGE_IDS_ATTRIBUTE, messageIdsOfRun, readMessageRunIdsEvent, } from "../utils/message-run-ids.js";
9
10
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
11
+ export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun } from "../utils/message-run-ids.js";
10
12
  export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
11
13
  // Client-only `useLayoutEffect`, falls back to `useEffect` during SSR.
12
14
  // Needed so the `agent.threadId` mirror commits before CopilotKit's
@@ -309,6 +311,23 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
309
311
  });
310
312
  return groups;
311
313
  }, [copilotMessages]);
314
+ // Which run produced each replayed message: the connect replay sends it as a CUSTOM
315
+ // event (see utils/message-run-ids). Cleared with the transcript on a conversation swap.
316
+ const [runIdByMessageId, setRunIdByMessageId] = useState(EMPTY_MESSAGE_RUN_IDS);
317
+ useEffect(() => {
318
+ if (!copilotAgent) {
319
+ return;
320
+ }
321
+ const { unsubscribe } = copilotAgent.subscribe({
322
+ onCustomEvent: ({ event }) => {
323
+ const runIds = readMessageRunIdsEvent(event);
324
+ if (runIds) {
325
+ setRunIdByMessageId((previous) => mergeMessageRunIds(previous, runIds));
326
+ }
327
+ },
328
+ });
329
+ return unsubscribe;
330
+ }, [copilotAgent]);
312
331
  const interruptAnswersRef = useRef(new Map());
313
332
  // Mirror `currentThreadId` onto the agent instance — the `<CopilotKit>`
314
333
  // prop only feeds React context, but `agent.threadId` is what hits the
@@ -340,6 +359,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
340
359
  }
341
360
  prevConversationKeyRef.current = conversationKey;
342
361
  copilotAgent?.setMessages?.([]);
362
+ setRunIdByMessageId(EMPTY_MESSAGE_RUN_IDS);
343
363
  setPrompt("");
344
364
  setAttachments([]);
345
365
  // The clear above runs in the layout phase, but the previous conversation's run is
@@ -453,6 +473,20 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
453
473
  }
454
474
  await runAgentWithRetry(copilotAgent, copilotAgent.messages.length);
455
475
  }, [canSendMessage, copilotAgent, runAgentWithRetry, onUserMessageSent]);
476
+ const reloadMessages = useCallback(async () => {
477
+ if (!copilotAgent || copilotAgent.isRunning) {
478
+ return;
479
+ }
480
+ // Replay cursors are keyed by threadId and record what has already been replayed, so a
481
+ // stale one makes connect a no-op — exactly the case here, where the thread is unchanged
482
+ // and only the server-side content moved. Messages are NOT cleared first: connect answers
483
+ // with a full snapshot that replaces them, and clearing would blank the transcript for the
484
+ // round-trip.
485
+ copilotAgent.clearReplayCursor?.(currentThreadId);
486
+ // Same guard convention as the composer send path: a failed reconnect already surfaces
487
+ // through the availability state; the rejection carries no extra signal.
488
+ await copilotkit.connectAgent({ agent: copilotAgent }).catch(() => undefined);
489
+ }, [copilotAgent, copilotkit, currentThreadId]);
456
490
  // Not sourced from `useInterrupt`: that hook only hands `resolve` to its own
457
491
  // `render`, which it skips whenever nothing is pending — so after a reload there
458
492
  // is no way to obtain it. `runAgentWithRetry`'s `isRunning` guard makes a
@@ -741,11 +775,13 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
741
775
  messageGroups,
742
776
  renderToolCall,
743
777
  messageById,
778
+ runIdByMessageId,
744
779
  toolMessages,
745
780
  prompt,
746
781
  attachments,
747
782
  sendMessage,
748
783
  sendFromInputs,
784
+ reloadMessages,
749
785
  resolveInterrupt,
750
786
  answerInterrupt,
751
787
  stopGeneration,
@@ -925,16 +961,26 @@ export function AgentChatMessage({ message, index, ...props }) {
925
961
  return _jsx("div", { "data-message-index": index, "data-message-role": message.role, ...props });
926
962
  }
927
963
  export function AgentChatMessageGroup({ messageGroup, ...props }) {
928
- return (_jsx("div", { "data-slot": "agent-chat-message-group", "data-message-group": messageGroup.role, "data-message-group-role": messageGroup.role, ...props }));
964
+ return (_jsx("div", { "data-slot": "agent-chat-message-group", "data-message-group": messageGroup.role, "data-message-group-role": messageGroup.role, [MESSAGE_IDS_ATTRIBUTE]: messageGroup.messageIds.join(" "), ...props }));
929
965
  }
930
- export function AgentChatMessages({ scrollAreaClassName, ...props }) {
931
- const { messages } = useAgentChat();
966
+ const NO_RUN_FOCUS = { messageIds: new Set(), isHighlighted: false };
967
+ const AgentChatRunFocusContext = createContext(NO_RUN_FOCUS);
968
+ /** The run focus of the enclosing AgentChatMessages (see its `focusRunId`). */
969
+ export const useAgentChatRunFocus = () => useContext(AgentChatRunFocusContext);
970
+ const DEFAULT_FOCUS_HIGHLIGHT_MS = 2400;
971
+ export function AgentChatMessages({ scrollAreaClassName, focusRunId, focusHighlightMs = DEFAULT_FOCUS_HIGHLIGHT_MS, ...props }) {
972
+ const { messages, runIdByMessageId = EMPTY_MESSAGE_RUN_IDS, isFetchingMessages, currentThreadId } = useAgentChat();
932
973
  const userMessageCount = messages.filter((message) => message.role === "user" && message.name !== HIDDEN_INITIAL_PROMPT_MESSAGE_NAME).length;
933
974
  const previousUserMessageCountRef = useRef(userMessageCount);
934
- const { scrollRef, contentRef, scrollToBottom } = useStickToBottom({
975
+ const { scrollRef, contentRef, scrollToBottom, stopScroll } = useStickToBottom({
935
976
  resize: "smooth",
936
977
  initial: { damping: 1, stiffness: 1 },
937
978
  });
979
+ const contentElementRef = useRef(null);
980
+ const setContentRef = useCallback((element) => {
981
+ contentElementRef.current = element;
982
+ contentRef(element);
983
+ }, [contentRef]);
938
984
  useEffect(() => {
939
985
  if (userMessageCount > previousUserMessageCountRef.current) {
940
986
  void scrollToBottom({
@@ -944,12 +990,48 @@ export function AgentChatMessages({ scrollAreaClassName, ...props }) {
944
990
  }
945
991
  previousUserMessageCountRef.current = userMessageCount;
946
992
  }, [scrollToBottom, userMessageCount]);
947
- return (_jsx("div", { ref: scrollRef, className: scrollAreaClassName, style: {
948
- height: "100%",
949
- width: "100%",
950
- overflow: "auto",
951
- scrollbarGutter: "stable both-edges",
952
- }, children: _jsx("div", { ref: contentRef, "data-slot": "agent-chat-messages", ...props }) }));
993
+ const runMessageIds = useMemo(() => messageIdsOfRun(messages, runIdByMessageId, focusRunId), [messages, runIdByMessageId, focusRunId]);
994
+ const [isHighlighted, setIsHighlighted] = useState(false);
995
+ const focusedKeyRef = useRef(null);
996
+ // Declared after the stick-to-bottom effect above on purpose: the replay that lands the
997
+ // run also bumps the user-message count, and this effect has to run second so its
998
+ // `stopScroll` cancels that scroll-to-bottom instead of being overridden by it.
999
+ useEffect(() => {
1000
+ const firstMessageId = runMessageIds[0];
1001
+ if (!focusRunId || isFetchingMessages || !firstMessageId) {
1002
+ return;
1003
+ }
1004
+ const focusKey = `${currentThreadId ?? ""}|${focusRunId}`;
1005
+ if (focusedKeyRef.current === focusKey) {
1006
+ return;
1007
+ }
1008
+ focusedKeyRef.current = focusKey;
1009
+ // Leave the bottom lock, or the next resize (a replayed group fading in, a markdown
1010
+ // block laying out) pulls the transcript back down past the run.
1011
+ stopScroll();
1012
+ requestAnimationFrame(() => {
1013
+ const reduceMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
1014
+ findMessageGroupElement(contentElementRef.current, firstMessageId)?.scrollIntoView({
1015
+ block: "start",
1016
+ behavior: reduceMotion ? "auto" : "smooth",
1017
+ });
1018
+ setIsHighlighted(true);
1019
+ });
1020
+ }, [focusRunId, isFetchingMessages, runMessageIds, currentThreadId, stopScroll]);
1021
+ useEffect(() => {
1022
+ if (!isHighlighted) {
1023
+ return;
1024
+ }
1025
+ const timeoutId = window.setTimeout(() => setIsHighlighted(false), focusHighlightMs);
1026
+ return () => window.clearTimeout(timeoutId);
1027
+ }, [isHighlighted, focusHighlightMs]);
1028
+ const runFocus = useMemo(() => (focusRunId ? { runId: focusRunId, messageIds: new Set(runMessageIds), isHighlighted } : NO_RUN_FOCUS), [focusRunId, runMessageIds, isHighlighted]);
1029
+ return (_jsx(AgentChatRunFocusContext.Provider, { value: runFocus, children: _jsx("div", { ref: scrollRef, className: scrollAreaClassName, style: {
1030
+ height: "100%",
1031
+ width: "100%",
1032
+ overflow: "auto",
1033
+ scrollbarGutter: "stable both-edges",
1034
+ }, children: _jsx("div", { ref: setContentRef, "data-slot": "agent-chat-messages", ...props }) }) }));
953
1035
  }
954
1036
  export function AgentChatThinking({ asChild = false, render, ...props }) {
955
1037
  const { isThinking } = useAgentChat();
@@ -1,5 +1,5 @@
1
1
  export type AgentThreadStatus = "idle" | "interrupted" | "error";
2
- export type AgentThreadSource = "direct_chat" | "agent_call" | "send_message" | "unknown";
2
+ export type AgentThreadSource = "direct_chat" | "agent_call" | "send_message" | "feedback" | "unknown";
3
3
  export interface AgentThreadItem {
4
4
  agentId: string | null;
5
5
  /** Never null — pass back verbatim to open the conversation. */
@@ -10,6 +10,21 @@ export interface AgentThreadItem {
10
10
  status: AgentThreadStatus;
11
11
  title: string | null;
12
12
  turnCount: number;
13
+ /**
14
+ * What KIND of conversation this is — `"feedback"` for a thread opened by a feedback send,
15
+ * absent/null for an ordinary chat. Optional in the type, not on the wire: a server that
16
+ * predates it sends nothing, and `undefined` must read as "an ordinary chat", not as a
17
+ * missing field to work around.
18
+ */
19
+ type?: string | null;
20
+ /**
21
+ * For a thread spawned from another conversation: that conversation's `chatThreadId` — pass
22
+ * it back verbatim to open the source, exactly like `chatThreadId` itself. Null when the
23
+ * source predates this field; a UI must then say where the thread came from without linking.
24
+ */
25
+ fromSourceChatThreadId?: string | null;
26
+ /** The message the feedback was about, when it was about one rather than the conversation. */
27
+ fromSourceMessageId?: string | null;
13
28
  /** First seen by the index — NOT thread creation time. */
14
29
  firstSeenAt: string;
15
30
  lastActivityAt: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,CAAC;AAEjE,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,YAAY,GAAG,cAAc,GAAG,SAAS,CAAC;AAE1F,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,cAAc,CAAC,KAAG,MAC9C,CAAC;AAK7C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,eAiB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,QAAQ,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,IAQ5E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACpC,QAAQ,eAAe,EACvB,UAAU,eAAe,GAAG,SAAS,EACrC,QAAQ,MAAM,GAAG,SAAS,EAC1B,KAAK,MAAM,KACV,eAID,CAAC;AAEH,MAAM,WAAW,4BAA4B;IAC3C,uFAAuF;IACvF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,cAAc,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAOD;;;;;;;;;;;;;GAaG;AACH,kEAAkE;AAClE,eAAO,MAAM,yBAAyB,GAAI,MAAM,eAAe,EAAE,UAAS,4BAAiC,KAAG,OAGzD,CAAC;AAEtD,eAAO,MAAM,sBAAsB,GACjC,SAAS,eAAe,EAAE,EAC1B,UAAU,eAAe,EACzB,UAAS,4BAAiC,KACzC,eAAe,EAqBjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS,eAAe,EAAE,EAC1B,YAAY,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAChD,UAAS,4BAAiC,KACzC,eAAe,EAkBjB,CAAC"}
1
+ {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,CAAC;AAEjE,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,CAAC;AAEvG,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,8FAA8F;IAC9F,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,cAAc,CAAC,KAAG,MAC9C,CAAC;AAW7C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,eAiB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,QAAQ,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,IAQ5E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACpC,QAAQ,eAAe,EACvB,UAAU,eAAe,GAAG,SAAS,EACrC,QAAQ,MAAM,GAAG,SAAS,EAC1B,KAAK,MAAM,KACV,eAID,CAAC;AAEH,MAAM,WAAW,4BAA4B;IAC3C,uFAAuF;IACvF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,cAAc,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAOD;;;;;;;;;;;;;GAaG;AACH,kEAAkE;AAClE,eAAO,MAAM,yBAAyB,GAAI,MAAM,eAAe,EAAE,UAAS,4BAAiC,KAAG,OAGzD,CAAC;AAEtD,eAAO,MAAM,sBAAsB,GACjC,SAAS,eAAe,EAAE,EAC1B,UAAU,eAAe,EACzB,UAAS,4BAAiC,KACzC,eAAe,EAqBjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS,eAAe,EAAE,EAC1B,YAAY,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAChD,UAAS,4BAAiC,KACzC,eAAe,EAkBjB,CAAC"}
@@ -4,7 +4,13 @@
4
4
  /** The (chatId, chatThreadId) pair — the only stable identity of a thread row. */
5
5
  export const agentThreadKey = (thread) => `${thread.chatId}::${thread.chatThreadId}`;
6
6
  const THREAD_STATUSES = ["idle", "interrupted", "error"];
7
- const THREAD_SOURCES = ["direct_chat", "agent_call", "send_message", "unknown"];
7
+ const THREAD_SOURCES = [
8
+ "direct_chat",
9
+ "agent_call",
10
+ "send_message",
11
+ "feedback",
12
+ "unknown",
13
+ ];
8
14
  /**
9
15
  * Whether a realtime payload's `thread` is a complete list-item row. The server
10
16
  * serializes the exact item shape into every event, so this normally passes; when
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Which agent run (turn) produced each message of a conversation.
3
+ *
4
+ * A row an app agent writes records the run that wrote it (`agentRunId`). On
5
+ * `agent/connect` the server replays the transcript and then sends one AG-UI CUSTOM
6
+ * event, `blocks.message_run_ids`, carrying `{ runIds: { [messageId]: runId } }` for
7
+ * the replayed messages it can attribute (older messages have none). The run id
8
+ * rides in an event rather than on the messages because the AG-UI client validates
9
+ * snapshot messages against a strict schema that drops unknown fields.
10
+ */
11
+ export declare const MESSAGE_RUN_IDS_EVENT_NAME = "blocks.message_run_ids";
12
+ export type MessageRunIds = ReadonlyMap<string, string>;
13
+ export declare const EMPTY_MESSAGE_RUN_IDS: MessageRunIds;
14
+ /** The `{ messageId: runId }` payload of a run-ids CUSTOM event, or null for any other event. */
15
+ export declare const readMessageRunIdsEvent: (event: unknown) => Record<string, string> | null;
16
+ /** `previous` plus `incoming`; returns `previous` itself when nothing changes (no re-render). */
17
+ export declare const mergeMessageRunIds: (previous: MessageRunIds, incoming: Record<string, string>) => MessageRunIds;
18
+ /** Ids of the messages `runId` produced, in transcript order (empty when the run isn't in it). */
19
+ export declare const messageIdsOfRun: (messages: readonly {
20
+ id: string;
21
+ }[], runIds: MessageRunIds, runId: string | undefined) => string[];
22
+ /** The attribute a message group carries so a run's first message can be found in the DOM. */
23
+ export declare const MESSAGE_IDS_ATTRIBUTE = "data-message-ids";
24
+ /** The rendered message group containing `messageId` inside `root`, if any. */
25
+ export declare const findMessageGroupElement: (root: ParentNode | null, messageId: string) => HTMLElement | null;
26
+ //# sourceMappingURL=message-run-ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-run-ids.d.ts","sourceRoot":"","sources":["../../src/utils/message-run-ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AAEnE,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,qBAAqB,EAAE,aAAyB,CAAC;AAK9D,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAehF,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,kBAAkB,GAAI,UAAU,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,aAU9F,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,eAAe,GAC1B,UAAU,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EACnC,QAAQ,aAAa,EACrB,OAAO,MAAM,GAAG,SAAS,KACxB,MAAM,EAKR,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,GAAI,MAAM,UAAU,GAAG,IAAI,EAAE,WAAW,MAAM,KAAG,WAAW,GAAG,IAYlG,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Which agent run (turn) produced each message of a conversation.
3
+ *
4
+ * A row an app agent writes records the run that wrote it (`agentRunId`). On
5
+ * `agent/connect` the server replays the transcript and then sends one AG-UI CUSTOM
6
+ * event, `blocks.message_run_ids`, carrying `{ runIds: { [messageId]: runId } }` for
7
+ * the replayed messages it can attribute (older messages have none). The run id
8
+ * rides in an event rather than on the messages because the AG-UI client validates
9
+ * snapshot messages against a strict schema that drops unknown fields.
10
+ */
11
+ export const MESSAGE_RUN_IDS_EVENT_NAME = "blocks.message_run_ids";
12
+ export const EMPTY_MESSAGE_RUN_IDS = new Map();
13
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
14
+ /** The `{ messageId: runId }` payload of a run-ids CUSTOM event, or null for any other event. */
15
+ export const readMessageRunIdsEvent = (event) => {
16
+ if (!isRecord(event) || event.name !== MESSAGE_RUN_IDS_EVENT_NAME || !isRecord(event.value)) {
17
+ return null;
18
+ }
19
+ const runIds = event.value.runIds;
20
+ if (!isRecord(runIds)) {
21
+ return null;
22
+ }
23
+ const out = {};
24
+ for (const [messageId, runId] of Object.entries(runIds)) {
25
+ if (messageId && typeof runId === "string" && runId) {
26
+ out[messageId] = runId;
27
+ }
28
+ }
29
+ return out;
30
+ };
31
+ /** `previous` plus `incoming`; returns `previous` itself when nothing changes (no re-render). */
32
+ export const mergeMessageRunIds = (previous, incoming) => {
33
+ let next = null;
34
+ for (const [messageId, runId] of Object.entries(incoming)) {
35
+ if (previous.get(messageId) === runId) {
36
+ continue;
37
+ }
38
+ next ??= new Map(previous);
39
+ next.set(messageId, runId);
40
+ }
41
+ return next ?? previous;
42
+ };
43
+ /** Ids of the messages `runId` produced, in transcript order (empty when the run isn't in it). */
44
+ export const messageIdsOfRun = (messages, runIds, runId) => {
45
+ if (!runId) {
46
+ return [];
47
+ }
48
+ return messages.filter((message) => runIds.get(message.id) === runId).map((message) => message.id);
49
+ };
50
+ /** The attribute a message group carries so a run's first message can be found in the DOM. */
51
+ export const MESSAGE_IDS_ATTRIBUTE = "data-message-ids";
52
+ /** The rendered message group containing `messageId` inside `root`, if any. */
53
+ export const findMessageGroupElement = (root, messageId) => {
54
+ if (!root) {
55
+ return null;
56
+ }
57
+ const groups = root.querySelectorAll(`[${MESSAGE_IDS_ATTRIBUTE}]`);
58
+ for (const group of Array.from(groups)) {
59
+ const ids = (group.getAttribute(MESSAGE_IDS_ATTRIBUTE) ?? "").split(" ");
60
+ if (ids.includes(messageId)) {
61
+ return group;
62
+ }
63
+ }
64
+ return null;
65
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/react-common",
3
- "version": "1.43.1",
3
+ "version": "1.45.0",
4
4
  "type": "module",
5
5
  "description": "React common",
6
6
  "keywords": [],
@@ -39,7 +39,7 @@
39
39
  "penpal": "^8.0.0",
40
40
  "react": "^19.2.8",
41
41
  "use-stick-to-bottom": "1.1.4",
42
- "@blocksdiy/blocks-client-api": "1.22.0"
42
+ "@blocksdiy/blocks-client-api": "1.23.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/react": "^19.2.18",