@blocksdiy/react-common 1.39.0 → 1.40.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.
@@ -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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"}
@@ -313,9 +313,9 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
313
313
  // prop only feeds React context, but `agent.threadId` is what hits the
314
314
  // wire and the LangGraph checkpoint. `<CopilotChat>` does this for you;
315
315
  // we use the headless hook so we do it ourselves. Layout-effect timing
316
- // is required to beat the library's connect-on-mount effect.
317
- // Limitation: doesn't abort an in-flight run on thread-id swap — fine
318
- // because `currentThreadId` is effectively immutable today.
316
+ // is required to beat the library's connect-on-mount/on-swap effect.
317
+ // A swap doesn't abort an in-flight run — the connect effect's cleanup
318
+ // detaches it client-side, and the run completes server-side as usual.
319
319
  useIsomorphicLayoutEffect(() => {
320
320
  if (copilotAgent && currentThreadId) {
321
321
  copilotAgent.threadId = currentThreadId;
@@ -326,6 +326,64 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
326
326
  }, [copilotAgent, currentThreadId]);
327
327
  const [prompt, setPrompt] = useState("");
328
328
  const [attachments, setAttachments] = useState([]);
329
+ // Conversation identity. When a mounted chat is pointed at another conversation, the
330
+ // reconnect replay takes a round-trip — clear the previous transcript and composer
331
+ // immediately so the old conversation never lingers on screen (same visual contract as
332
+ // a remount). Deliberately NOT keyed on `initKey`: that also changes when the block
333
+ // configs finish loading, and clearing then would wipe a freshly replayed transcript.
334
+ const conversationKey = `${chatId ?? ""}|${currentThreadId ?? ""}`;
335
+ const prevConversationKeyRef = useRef(conversationKey);
336
+ useIsomorphicLayoutEffect(() => {
337
+ if (prevConversationKeyRef.current === conversationKey) {
338
+ return;
339
+ }
340
+ prevConversationKeyRef.current = conversationKey;
341
+ copilotAgent?.setMessages?.([]);
342
+ setPrompt("");
343
+ setAttachments([]);
344
+ // The clear above runs in the layout phase, but the previous conversation's run is
345
+ // detached in passive effects — and even past detach, events already buffered in the
346
+ // apply pipeline keep applying, each reassigning `agent.messages` WHOLESALE. One late
347
+ // chunk would resurrect the entire previous transcript (and re-arm its auto-executing
348
+ // tool-call follow-ups) under the new conversation's header. Detach here too and
349
+ // re-clear once the drain settles; the reconnect that follows replays on top of the
350
+ // (guaranteed-empty) mirror. On threadId switches the core's fresh-restore re-clears
351
+ // as well — harmless overlap — but on chatId-only switches this is the only re-clear.
352
+ const detachable = copilotAgent;
353
+ const drained = detachable?.detachActiveRun?.();
354
+ if (drained) {
355
+ const clearedForKey = conversationKey;
356
+ void drained.then(() => {
357
+ if (prevConversationKeyRef.current === clearedForKey) {
358
+ copilotAgent?.setMessages?.([]);
359
+ }
360
+ });
361
+ }
362
+ }, [conversationKey]);
363
+ // CopilotKit reconnects only when its threadId changes — but a conversation is the
364
+ // (chatId, threadId) PAIR, and rows written by surfaces that use the fixed default
365
+ // thread id differ only by chatId. On such a chatId-only switch the library's connect
366
+ // effect sees unchanged deps and does nothing, which would leave the (just cleared)
367
+ // transcript empty forever. Reconnect manually, replicating the core's fresh-restore
368
+ // steps: reset state and drop the replay cursor — cursors are keyed by threadId, so
369
+ // the shared id makes the previous conversation's cursor actively wrong here — then
370
+ // connect (the core detaches any in-flight run itself). The core reads `properties`
371
+ // after an await, so the new chatId is already synced by the time the request builds.
372
+ const prevConnectionRef = useRef({ chatId, threadId: currentThreadId });
373
+ useEffect(() => {
374
+ const previous = prevConnectionRef.current;
375
+ prevConnectionRef.current = { chatId, threadId: currentThreadId };
376
+ const chatIdChanged = previous.chatId !== chatId;
377
+ const threadIdChanged = previous.threadId !== currentThreadId;
378
+ if (!copilotAgent || !chatIdChanged || threadIdChanged) {
379
+ return;
380
+ }
381
+ copilotAgent.setState?.({});
382
+ copilotAgent.clearReplayCursor?.(currentThreadId);
383
+ // Same guard convention as the composer send path: a failed reconnect already
384
+ // surfaces through the availability state; the rejection carries no extra signal.
385
+ void copilotkit.connectAgent({ agent: copilotAgent }).catch(() => undefined);
386
+ }, [chatId, currentThreadId, copilotAgent, copilotkit]);
329
387
  const [isDraggingFiles, setIsDraggingFiles] = useState(false);
330
388
  const attachmentsEnabled = agentChat ? agentChat.disableAttachments !== true : false;
331
389
  const canSendMessage = Boolean(agentChatBlock && agentChat && agent && isConfigLoaded && isAgentReady && !isAgentRunning);
@@ -701,6 +759,18 @@ export const AgentChatRoot = ({ ...props
701
759
  ...(appId ? { "x-app-id": appId } : {}),
702
760
  }), [token, socketId, appId]);
703
761
  const [currentThreadId, setCurrentThreadId] = useState(() => defaultThreadId ?? (noPersistency ? crypto.randomUUID() : DEFAULT_CHAT_THREAD_ID));
762
+ // Follow later `defaultThreadId` changes — a mounted chat can be pointed at another
763
+ // conversation (the agent inbox switches threads without remounting). Adjusted during
764
+ // render (the React derived-state pattern) so children commit with the new thread and
765
+ // the new chatId prop atomically; the headless connect effect keys on the configuration
766
+ // threadId and replays the new transcript. Static-prop consumers never hit this branch.
767
+ const [prevDefaultThreadId, setPrevDefaultThreadId] = useState(defaultThreadId);
768
+ if (defaultThreadId !== prevDefaultThreadId) {
769
+ setPrevDefaultThreadId(defaultThreadId);
770
+ if (defaultThreadId && defaultThreadId !== currentThreadId) {
771
+ setCurrentThreadId(defaultThreadId);
772
+ }
773
+ }
704
774
  const blocksApiService = useMemo(() => new BlocksApiService({ token }), [token]);
705
775
  const [agentChatBlock, setAgentChatBlock] = useState(null);
706
776
  const [agentBlock, setAgentBlock] = useState(null);
@@ -0,0 +1,86 @@
1
+ export type AgentThreadStatus = "idle" | "interrupted" | "error";
2
+ export type AgentThreadSource = "direct_chat" | "agent_call" | "send_message" | "unknown";
3
+ export interface AgentThreadItem {
4
+ agentId: string | null;
5
+ /** Never null — pass back verbatim to open the conversation. */
6
+ chatId: string;
7
+ /** Never null — pass back verbatim to open the conversation. */
8
+ chatThreadId: string;
9
+ source: AgentThreadSource;
10
+ status: AgentThreadStatus;
11
+ title: string | null;
12
+ turnCount: number;
13
+ /** First seen by the index — NOT thread creation time. */
14
+ firstSeenAt: string;
15
+ lastActivityAt: string;
16
+ }
17
+ export interface AgentThreadsPage {
18
+ items: AgentThreadItem[];
19
+ nextCursor: string | null;
20
+ }
21
+ export interface UseAgentThreadsOptions {
22
+ agentId: string;
23
+ status?: AgentThreadStatus;
24
+ source?: AgentThreadSource;
25
+ chatId?: string;
26
+ limit?: number;
27
+ sort?: "lastActivity" | "firstSeen";
28
+ order?: "asc" | "desc";
29
+ /** Platform host override; defaults to getApiHost() (same convention as the agent chat). */
30
+ baseUrl?: string;
31
+ /** Bearer token for callers that don't share the platform session cookie. */
32
+ token?: string;
33
+ /** Extra request headers, merged over the defaults. */
34
+ headers?: Record<string, string>;
35
+ }
36
+ export interface UseAgentThreadsResult {
37
+ threads: AgentThreadItem[];
38
+ /**
39
+ * The thread the consumer is currently viewing — never null. When nothing is
40
+ * selected the hook auto-generates a draft with a fresh (chatId, chatThreadId)
41
+ * pair the chat surface can use verbatim; once the draft's first turn is indexed
42
+ * and the list refreshes, this resolves to that real row (same key) seamlessly.
43
+ * For selected threads it prefers the LIST's row for the same identity — so
44
+ * status/turnCount stay fresh after a refresh — falling back to the last set
45
+ * item when the row isn't in the loaded pages, so selection never vanishes.
46
+ */
47
+ currentThread: AgentThreadItem;
48
+ /** True while currentThread is an auto-generated draft not yet in the index. */
49
+ isDraftThread: boolean;
50
+ /** Move between threads; null mints a fresh draft ("new chat"). Resets when agentId changes. */
51
+ setCurrentThread: (thread: AgentThreadItem | null) => void;
52
+ /** First page (or refresh) in flight. */
53
+ isLoading: boolean;
54
+ /** A cursor page is being appended. */
55
+ isLoadingMore: boolean;
56
+ error: Error | null;
57
+ hasMore: boolean;
58
+ loadMore: () => Promise<void>;
59
+ refresh: () => Promise<void>;
60
+ }
61
+ /** The (chatId, chatThreadId) pair — the only stable identity of a thread row. */
62
+ export declare const agentThreadKey: (thread: Pick<AgentThreadItem, "chatId" | "chatThreadId">) => string;
63
+ /**
64
+ * The platform inbox's fixed chatId for an agent: one shared value per agent block, so
65
+ * index rows are recognizable as "direct chats with this agent on the platform" at a
66
+ * glance (and filterable via the endpoint's chatId param). Conversations under it are
67
+ * distinguished by their unique chatThreadId.
68
+ */
69
+ export declare const AGENT_INBOX_CHAT_PREFIX = "agent-inbox-";
70
+ export declare const agentInboxChatId: (agentId: string) => string;
71
+ /**
72
+ * Short human label for a row with no generated title yet: the half of the identity
73
+ * pair that varies for the row. Inbox rows share one fixed chatId (above) and vary by
74
+ * thread id; rows from other surfaces (published-app chats) are the reverse. One-sided
75
+ * writers (agent calls) index a "_" placeholder for the missing half — fall back to
76
+ * the real half rather than labeling every such row "_".
77
+ */
78
+ export declare const agentThreadShortLabel: (thread: Pick<AgentThreadItem, "chatId" | "chatThreadId">) => string;
79
+ /**
80
+ * Headless agent-threads index: fetches an agent's conversation threads from the platform
81
+ * endpoint with keyset-cursor pagination. Data only — pair it with whatever list UI the host
82
+ * app uses (the platform's ThreadList, a boilerplate app's own components, ...).
83
+ */
84
+ export declare const useAgentThreads: (options: UseAgentThreadsOptions) => UseAgentThreadsResult;
85
+ export default useAgentThreads;
86
+ //# sourceMappingURL=use-agent-threads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-agent-threads.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-threads.ts"],"names":[],"mappings":"AASA,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,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,cAAc,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B;;;;;;;;OAQG;IACH,aAAa,EAAE,eAAe,CAAC;IAC/B,gFAAgF;IAChF,aAAa,EAAE,OAAO,CAAC;IACvB,gGAAgG;IAChG,gBAAgB,EAAE,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,cAAc,CAAC,KAAG,MAC9C,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,MAAgD,CAAC;AAEpG;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,cAAc,CAAC,KAAG,MAIhG,CAAC;AA8DF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,qBAsPjE,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,308 @@
1
+ import { getApiHost } from "@blocksdiy/blocks-client-api/envService";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ /** The (chatId, chatThreadId) pair — the only stable identity of a thread row. */
4
+ export const agentThreadKey = (thread) => `${thread.chatId}::${thread.chatThreadId}`;
5
+ /**
6
+ * The platform inbox's fixed chatId for an agent: one shared value per agent block, so
7
+ * index rows are recognizable as "direct chats with this agent on the platform" at a
8
+ * glance (and filterable via the endpoint's chatId param). Conversations under it are
9
+ * distinguished by their unique chatThreadId.
10
+ */
11
+ export const AGENT_INBOX_CHAT_PREFIX = "agent-inbox-";
12
+ export const agentInboxChatId = (agentId) => `${AGENT_INBOX_CHAT_PREFIX}${agentId}`;
13
+ /**
14
+ * Short human label for a row with no generated title yet: the half of the identity
15
+ * pair that varies for the row. Inbox rows share one fixed chatId (above) and vary by
16
+ * thread id; rows from other surfaces (published-app chats) are the reverse. One-sided
17
+ * writers (agent calls) index a "_" placeholder for the missing half — fall back to
18
+ * the real half rather than labeling every such row "_".
19
+ */
20
+ export const agentThreadShortLabel = (thread) => {
21
+ const varying = thread.chatId.startsWith(AGENT_INBOX_CHAT_PREFIX) ? thread.chatThreadId : thread.chatId;
22
+ const other = varying === thread.chatId ? thread.chatThreadId : thread.chatId;
23
+ return (varying === "_" ? other : varying).slice(0, 8);
24
+ };
25
+ const buildQuery = (filters, cursor) => {
26
+ const params = new URLSearchParams();
27
+ if (filters.status) {
28
+ params.set("status", filters.status);
29
+ }
30
+ if (filters.source) {
31
+ params.set("source", filters.source);
32
+ }
33
+ if (filters.chatId) {
34
+ params.set("chatId", filters.chatId);
35
+ }
36
+ if (filters.limit) {
37
+ params.set("limit", String(filters.limit));
38
+ }
39
+ if (filters.sort) {
40
+ params.set("sort", filters.sort);
41
+ }
42
+ if (filters.order) {
43
+ params.set("order", filters.order);
44
+ }
45
+ if (cursor) {
46
+ params.set("cursor", cursor);
47
+ }
48
+ const query = params.toString();
49
+ return query ? `?${query}` : "";
50
+ };
51
+ const appendPage = (existing, page) => {
52
+ const seen = new Set(existing.map(agentThreadKey));
53
+ return [...existing, ...page.filter((thread) => !seen.has(agentThreadKey(thread)))];
54
+ };
55
+ /**
56
+ * A not-yet-indexed conversation. chatId is ALWAYS the agent's static inbox id (the
57
+ * surface marker — identical for every inbox conversation with this agent); only the
58
+ * thread id makes each conversation unique, and it must be a UUID — CopilotKit
59
+ * replaces non-UUID thread ids per load, which breaks history. Sharing the chatId
60
+ * also means inbox thread switches are pure thread-id changes, the chat stack's
61
+ * native reconnect path.
62
+ */
63
+ const makeDraftThread = (agentId) => {
64
+ const now = new Date().toISOString();
65
+ return {
66
+ agentId: agentId || null,
67
+ chatId: agentInboxChatId(agentId),
68
+ chatThreadId: crypto.randomUUID(),
69
+ source: "direct_chat",
70
+ status: "idle",
71
+ title: null,
72
+ turnCount: 0,
73
+ firstSeenAt: now,
74
+ lastActivityAt: now,
75
+ };
76
+ };
77
+ /**
78
+ * Headless agent-threads index: fetches an agent's conversation threads from the platform
79
+ * endpoint with keyset-cursor pagination. Data only — pair it with whatever list UI the host
80
+ * app uses (the platform's ThreadList, a boilerplate app's own components, ...).
81
+ */
82
+ export const useAgentThreads = (options) => {
83
+ const { agentId, status, source, chatId, limit, sort, order, baseUrl } = options;
84
+ const [threads, setThreads] = useState([]);
85
+ // Mirror of `threads` for reads outside render (a refresh needs the loaded count without
86
+ // re-closing over state). Every write goes through applyThreads so the two can't diverge;
87
+ // reads are race-free because writers are serialized (loadMore awaits any in-flight
88
+ // refresh, and every write re-checks the request sequence first).
89
+ const threadsRef = useRef([]);
90
+ const applyThreads = useCallback((items) => {
91
+ threadsRef.current = items;
92
+ setThreads(items);
93
+ }, []);
94
+ const [nextCursor, setNextCursor] = useState(null);
95
+ // Cursor mirror, same contract as threadsRef: loadMore reads it after awaiting an
96
+ // in-flight refresh, when its render-time closure value is stale by definition.
97
+ const nextCursorRef = useRef(null);
98
+ const applyCursor = useCallback((cursor) => {
99
+ nextCursorRef.current = cursor;
100
+ setNextCursor(cursor);
101
+ }, []);
102
+ // Starts true (when a fetch is coming): the first-page effect only runs AFTER the mount
103
+ // paint, so initializing false would flash the "no threads" empty state for a frame.
104
+ const [isLoading, setIsLoading] = useState(Boolean(agentId));
105
+ const [isLoadingMore, setIsLoadingMore] = useState(false);
106
+ const [error, setError] = useState(null);
107
+ const [selectedThread, setSelectedThread] = useState(null);
108
+ const [draftThread, setDraftThread] = useState(() => makeDraftThread(agentId));
109
+ const setCurrentThread = useCallback((thread) => {
110
+ // Null means "new chat": mint a fresh draft so each one is its own conversation.
111
+ if (!thread) {
112
+ setDraftThread(makeDraftThread(agentId));
113
+ }
114
+ setSelectedThread(thread);
115
+ }, [agentId]);
116
+ // Selection follows the agent, not the query: filter changes keep it (the fallback in
117
+ // `currentThread` covers rows the new filter drops), but another agent's thread — or
118
+ // draft — is meaningless here. Guarded by the previous id so the mount render keeps the
119
+ // initial draft (regenerating it would remount a consumer's keyed chat surface for nothing).
120
+ const prevAgentIdRef = useRef(agentId);
121
+ useEffect(() => {
122
+ if (prevAgentIdRef.current === agentId) {
123
+ return;
124
+ }
125
+ prevAgentIdRef.current = agentId;
126
+ setSelectedThread(null);
127
+ setDraftThread(makeDraftThread(agentId));
128
+ }, [agentId]);
129
+ // Rows are rewritten server-side every turn, so after a refresh the stored item is stale;
130
+ // prefer the list's row with the same identity, keep the stored one if it's not loaded.
131
+ // The draft goes through the same lookup: once its first turn is indexed, the real row
132
+ // wins under the same key — the draft has materialized, without changing identity.
133
+ const currentThread = useMemo(() => {
134
+ const stored = selectedThread ?? draftThread;
135
+ const storedKey = agentThreadKey(stored);
136
+ return threads.find((thread) => agentThreadKey(thread) === storedKey) ?? stored;
137
+ }, [threads, selectedThread, draftThread]);
138
+ const isDraftThread = !selectedThread && currentThread === draftThread;
139
+ // Once the draft's first turn is indexed, its row IS the conversation — adopt it as the
140
+ // selection. Otherwise a later filter change (which blanks the list before refetching)
141
+ // would flip `isDraftThread` back to true for a conversation that has turns, and the
142
+ // consumer's draft-only presentation ("New chat" header, empty-state slot) with it.
143
+ useEffect(() => {
144
+ if (selectedThread) {
145
+ return;
146
+ }
147
+ const draftKey = agentThreadKey(draftThread);
148
+ const materialized = threads.find((thread) => agentThreadKey(thread) === draftKey);
149
+ if (materialized) {
150
+ setSelectedThread(materialized);
151
+ }
152
+ }, [threads, selectedThread, draftThread]);
153
+ // Auth material is read at request time via refs so an inline `headers` object literal
154
+ // doesn't churn the effect below into a refetch loop.
155
+ const authRef = useRef({ token: options.token, headers: options.headers });
156
+ authRef.current = { token: options.token, headers: options.headers };
157
+ // Every state-writing path checks it still owns the latest request before touching state,
158
+ // so a stale response (filter switched mid-flight, unmount) can never clobber a newer one.
159
+ const requestSeqRef = useRef(0);
160
+ const fetchPage = useCallback(async (cursor) => {
161
+ const { token, headers } = authRef.current;
162
+ const base = baseUrl ?? getApiHost();
163
+ const response = await fetch(`${base}/agent-threads/${encodeURIComponent(agentId)}${buildQuery({ status, source, chatId, limit, sort, order }, cursor)}`, {
164
+ headers: {
165
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
166
+ ...headers,
167
+ },
168
+ });
169
+ if (!response.ok) {
170
+ throw new Error(`Agent threads request failed with status ${response.status}`);
171
+ }
172
+ return (await response.json());
173
+ }, [agentId, status, source, chatId, limit, sort, order, baseUrl]);
174
+ // The in-flight refresh, if any, so loadMore can wait it out instead of dropping the
175
+ // gesture (a click on "Load more" often arrives right behind the window-focus refresh
176
+ // the same gesture triggered).
177
+ const refreshPromiseRef = useRef(null);
178
+ const loadFirstPage = useCallback(() => {
179
+ if (!agentId) {
180
+ // Nothing will fetch — make sure the optimistic initial `true` (or a fetch
181
+ // superseded by agentId turning falsy) can't leave the loading flag latched on.
182
+ setIsLoading(false);
183
+ return Promise.resolve();
184
+ }
185
+ const requestSeq = ++requestSeqRef.current;
186
+ setIsLoading(true);
187
+ setError(null);
188
+ const run = (async () => {
189
+ try {
190
+ // A refresh re-covers every page the user has already loaded — one request in the
191
+ // common one-page case (the query-change effect blanks the list first, so filter
192
+ // switches also fetch a single page). The alternatives both break pagination:
193
+ // replacing with page one collapses the list back to page one on every focus
194
+ // refresh, and splicing page one over the old tail either rewinds the cursor
195
+ // ("Load more" then refetches known rows and looks dead) or keeps the old cursor
196
+ // and permanently skips rows that arrived beyond page one while the user was away.
197
+ // Walking the cursor keeps the list contiguous from the top, in server order,
198
+ // with the cursor pointing past everything shown.
199
+ const loadedCount = threadsRef.current.length;
200
+ let items = [];
201
+ let cursor = null;
202
+ do {
203
+ const page = await fetchPage(cursor);
204
+ if (requestSeqRef.current !== requestSeq) {
205
+ return;
206
+ }
207
+ if (page.items.length === 0) {
208
+ // Defensive: an empty page must terminate the walk even with a non-null cursor.
209
+ cursor = null;
210
+ break;
211
+ }
212
+ items = appendPage(items, page.items);
213
+ if (page.nextCursor === cursor) {
214
+ // Defensive: dedupe can hold items.length under loadedCount, so a
215
+ // non-advancing cursor must terminate too or the walk loops unbounded.
216
+ cursor = null;
217
+ break;
218
+ }
219
+ cursor = page.nextCursor;
220
+ } while (cursor !== null && items.length < loadedCount);
221
+ applyThreads(items);
222
+ applyCursor(cursor);
223
+ }
224
+ catch (fetchError) {
225
+ if (requestSeqRef.current !== requestSeq) {
226
+ return;
227
+ }
228
+ setError(fetchError instanceof Error ? fetchError : new Error(String(fetchError)));
229
+ }
230
+ finally {
231
+ if (requestSeqRef.current === requestSeq) {
232
+ setIsLoading(false);
233
+ }
234
+ }
235
+ })();
236
+ refreshPromiseRef.current = run;
237
+ return run;
238
+ }, [agentId, fetchPage, applyThreads, applyCursor]);
239
+ // Ref-guarded rather than state-guarded: after the awaited refresh below, the closure's
240
+ // state flags are stale by definition — and a ref also makes double-clicks race-free.
241
+ const loadMoreInFlightRef = useRef(false);
242
+ const loadMore = useCallback(async () => {
243
+ if (!agentId || loadMoreInFlightRef.current) {
244
+ return;
245
+ }
246
+ loadMoreInFlightRef.current = true;
247
+ setIsLoadingMore(true);
248
+ // Captured BEFORE the wait below: this closure's fetchPage belongs to the render the
249
+ // click landed on, so anything that supersedes the list while we sit behind the
250
+ // refresh (a query change, a newer refresh) must invalidate this gesture too.
251
+ const requestSeq = requestSeqRef.current;
252
+ try {
253
+ // A refresh may be in flight — typically fired by the very window-focus that
254
+ // preceded this click. Wait it out instead of silently swallowing the gesture;
255
+ // the cursor ref then points past everything the refresh walk re-covered.
256
+ if (refreshPromiseRef.current) {
257
+ await refreshPromiseRef.current;
258
+ }
259
+ if (requestSeqRef.current !== requestSeq) {
260
+ return;
261
+ }
262
+ const cursor = nextCursorRef.current;
263
+ if (cursor === null) {
264
+ return;
265
+ }
266
+ const page = await fetchPage(cursor);
267
+ if (requestSeqRef.current !== requestSeq) {
268
+ return;
269
+ }
270
+ applyThreads(appendPage(threadsRef.current, page.items));
271
+ applyCursor(page.nextCursor);
272
+ }
273
+ catch (fetchError) {
274
+ if (requestSeqRef.current !== requestSeq) {
275
+ return;
276
+ }
277
+ setError(fetchError instanceof Error ? fetchError : new Error(String(fetchError)));
278
+ }
279
+ finally {
280
+ // Unconditional: even when a refresh superseded this request the flags must clear
281
+ // or pagination locks up.
282
+ loadMoreInFlightRef.current = false;
283
+ setIsLoadingMore(false);
284
+ }
285
+ }, [agentId, fetchPage, applyThreads, applyCursor]);
286
+ useEffect(() => {
287
+ applyThreads([]);
288
+ applyCursor(null);
289
+ void loadFirstPage();
290
+ return () => {
291
+ // Invalidate in-flight requests on unmount / query change.
292
+ requestSeqRef.current += 1;
293
+ };
294
+ }, [loadFirstPage, applyThreads, applyCursor]);
295
+ return {
296
+ threads,
297
+ currentThread,
298
+ isDraftThread,
299
+ setCurrentThread,
300
+ isLoading,
301
+ isLoadingMore,
302
+ error,
303
+ hasMore: nextCursor !== null,
304
+ loadMore,
305
+ refresh: loadFirstPage,
306
+ };
307
+ };
308
+ export default useAgentThreads;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./hooks/use-agent-threads.js";
1
2
  export * from "./hooks/use-ai-stream-chunks.js";
2
3
  export * from "./components/agent-chat.js";
3
4
  export * from "./iframe-communication/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./hooks/use-agent-threads.js";
1
2
  export * from "./hooks/use-ai-stream-chunks.js";
2
3
  export * from "./components/agent-chat.js";
3
4
  export * from "./iframe-communication/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/react-common",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "type": "module",
5
5
  "description": "React common",
6
6
  "keywords": [],
@@ -11,6 +11,7 @@
11
11
  "exports": {
12
12
  ".": "./dist/index.js",
13
13
  "./useAiStreamChunks": "./dist/hooks/use-ai-stream-chunks.js",
14
+ "./agent-threads": "./dist/hooks/use-agent-threads.js",
14
15
  "./agent-chat": "./dist/components/agent-chat.js",
15
16
  "./new-agent-chat": "./dist/components/new-agent-chat.js",
16
17
  "./iframe-communication": "./dist/iframe-communication/index.js"