@blocksdiy/react-common 1.48.0 → 1.49.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,8 +2,10 @@ 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 ComposerMessageMeta } from "../utils/composer-message.js";
5
6
  import { type MessageRunIds, type RunStartedAt } from "../utils/message-run-ids.js";
6
7
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
8
+ export { type ComposerMessageMeta, FEEDBACK_MESSAGE_NAME, type FeedbackDraft, type FeedbackRate, feedbackComposerMeta, feedbackDraftOf, feedbackMessage, feedbackThreadId, isFeedbackMessage, isFeedbackTag, parseFeedbackContent, parseFeedbackTag, type ParsedFeedback, } from "../utils/composer-message.js";
7
9
  export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun, type MessageRunIds, type RunStartedAt, } from "../utils/message-run-ids.js";
8
10
  export { type Message, type AssistantMessage, type UserMessage } from "@ag-ui/client";
9
11
  export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
@@ -43,6 +45,7 @@ export interface Agent {
43
45
  voiceId?: string;
44
46
  harness?: string;
45
47
  }
48
+ export type OnUserMessageSent = (text: string, message: Omit<UserMessage, "id" | "role">) => void;
46
49
  export interface AgentChatContextValue {
47
50
  messages: Message[];
48
51
  attachments: Attachment[];
@@ -60,40 +63,14 @@ export interface AgentChatContextValue {
60
63
  role: "assistant" | "user";
61
64
  }[];
62
65
  messageById: Map<string, Message>;
63
- /**
64
- * The agent run (turn) that produced each message — the `agentRunId` the rows it wrote
65
- * carry. Replayed messages come attributed by the connect replay, live ones by the run
66
- * that streams them; messages from before run attribution have no entry. Optional so
67
- * contexts a host builds by hand (previews, stubs) need not state it; absent reads as
68
- * "no run known".
69
- */
70
66
  runIdByMessageId?: MessageRunIds;
71
- /**
72
- * When each run in `runIdByMessageId` started (epoch ms) — the time of a turn, which is
73
- * what a chat shows under a message. A live run is stamped as it starts; a replayed
74
- * one comes with the server's time. Runs from before run times have no entry.
75
- */
76
67
  runStartedAt?: RunStartedAt;
77
68
  toolMessages: ToolMessage[];
78
69
  renderToolCall: ReturnType<typeof useRenderToolCall>;
79
70
  sendMessage: (message: Omit<UserMessage, "id" | "role">) => Promise<void>;
80
71
  sendFromInputs: () => Promise<void>;
81
- /**
82
- * Replay this conversation's transcript from the server, in place.
83
- *
84
- * The same round-trip a fresh mount does — the connect endpoint reads the checkpoint and
85
- * answers with a MESSAGES_SNAPSHOT, which replaces the mirrored list. For turns that ran
86
- * SERVER-SIDE, which no client streamed and so no client has: without this they appear only
87
- * after a reload or a conversation switch.
88
- *
89
- * A no-op while a run is in flight: that run's own stream is the authoritative view of the
90
- * conversation, and replacing the list underneath it would fight the events still arriving.
91
- */
92
72
  reloadMessages: () => Promise<void>;
93
- /** Resumes a run parked on a server-side interrupt. Rejects if the resume fails. */
94
- /** Resolves false when a run was already in flight, so nothing was sent. */
95
73
  resolveInterrupt: (resume: unknown) => Promise<boolean>;
96
- /** Answers one parked card; resumes once every card of the turn is answered. */
97
74
  answerInterrupt: (answer: {
98
75
  toolCallId: string;
99
76
  answer: unknown;
@@ -106,6 +83,10 @@ export interface AgentChatContextValue {
106
83
  setAttachments: React.Dispatch<SetStateAction<Attachment[]>>;
107
84
  setIsDraggingFiles: React.Dispatch<SetStateAction<boolean>>;
108
85
  setCurrentThreadId: (currentThreadId: string) => void;
86
+ /** Arms the next send; cleared by send and conversation switch. */
87
+ composerMessageMeta?: ComposerMessageMeta | null;
88
+ setComposerMessageMeta?: (meta: ComposerMessageMeta | null) => void;
89
+ setRunningElsewhere?: (runId: string | null) => void;
109
90
  }
110
91
  export declare const AgentChatContext: import("react").Context<AgentChatContextValue | null>;
111
92
  export declare const useAgentChat: () => AgentChatContextValue;
@@ -147,9 +128,11 @@ export interface AgentChatRootProps {
147
128
  * Fires once a user send has been added to the conversation, with its text (empty
148
129
  * string for attachment-only sends) — the seam for ChatGPT-style optimistic thread
149
130
  * listing: hosts pair it with useAgentThreads' notifyThreadActivity. Covers sends
150
- * routed through `sendMessage`, not the auto-sent `initialPrompt`.
131
+ * routed through `sendMessage`, not the auto-sent `initialPrompt`. The second argument
132
+ * is the message as sent, for hosts that treat a protocol send (one carrying a `name`)
133
+ * differently from an ordinary turn.
151
134
  */
152
- onUserMessageSent?: (text: string) => void;
135
+ onUserMessageSent?: OnUserMessageSent;
153
136
  /**
154
137
  * Skip the agent-chat block's `initialPrompt` auto-send. For surfaces that mint a fresh
155
138
  * thread per conversation (an inbox's "New chat"): the auto-send fires once PER THREAD,
@@ -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,8 +6,10 @@ 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 { buildArmedMessageContent, userTextOfContent } from "../utils/composer-message.js";
9
10
  import { claimRunInput, EMPTY_MESSAGE_RUN_IDS, EMPTY_RUN_STARTED_AT, findMessageGroupElement, mergeEntries, MESSAGE_IDS_ATTRIBUTE, messageIdsOfRun, readMessageRunIdsEvent, readRunStartedAtEvent, } from "../utils/message-run-ids.js";
10
11
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
12
+ export { FEEDBACK_MESSAGE_NAME, feedbackComposerMeta, feedbackDraftOf, feedbackMessage, feedbackThreadId, isFeedbackMessage, isFeedbackTag, parseFeedbackContent, parseFeedbackTag, } from "../utils/composer-message.js";
11
13
  export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun, } from "../utils/message-run-ids.js";
12
14
  export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
13
15
  // Client-only `useLayoutEffect`, falls back to `useEffect` during SSR.
@@ -173,9 +175,9 @@ const uploadAttachments = async ({ attachments, appId, token, }) => {
173
175
  };
174
176
  }));
175
177
  };
176
- const hasSendableInput = (prompt, attachments) => {
177
- return prompt.trim().length > 0 || attachments.length > 0;
178
- };
178
+ // An armed send needs text: the composer is the comment path — a rating alone goes out as
179
+ // `feedbackMessage` — and an unrated marker on its own is an ordinary turn on the server.
180
+ const hasSendableInput = (prompt, attachments, meta) => prompt.trim().length > 0 || (!meta && attachments.length > 0);
179
181
  const isRecord = (value) => {
180
182
  return typeof value === "object" && value !== null;
181
183
  };
@@ -311,19 +313,10 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
311
313
  });
312
314
  return groups;
313
315
  }, [copilotMessages]);
314
- // Which run produced each message, and when it started (see utils/message-run-ids).
315
- // Replayed messages: the connect replay sends both as one CUSTOM event, and its word is
316
- // final — it overwrites what the session recorded. Live messages: RUN_STARTED names the
317
- // run (the server mints the id, so the one in the event, not the one we sent), times it,
318
- // and shows the transcript as it stood — the run's input is what sits after the last
319
- // reply. All of that is recorded with the FIRST message the run streams, and each
320
- // message it streams is its; first claim wins, as on the server. A run that streams
321
- // nothing leaves no trace: connect (a reconnect sees the whole transcript, and must not
322
- // adopt an old unanswered message), or a run that fails before its first token. Cleared
323
- // with the transcript on a swap.
324
316
  const [runIdByMessageId, setRunIdByMessageId] = useState(EMPTY_MESSAGE_RUN_IDS);
325
317
  const [runStartedAt, setRunStartedAt] = useState(EMPTY_RUN_STARTED_AT);
326
318
  const liveRunRef = useRef(null);
319
+ const ownRunIdsRef = useRef(new Set());
327
320
  useEffect(() => {
328
321
  if (!copilotAgent) {
329
322
  return;
@@ -349,10 +342,9 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
349
342
  const { unsubscribe } = copilotAgent.subscribe({
350
343
  onRunStartedEvent: ({ event, messages }) => {
351
344
  liveRunRef.current = { runId: event.runId, startedAt: event.timestamp ?? Date.now(), input: messages };
345
+ ownRunIdsRef.current.add(event.runId);
352
346
  },
353
347
  onTextMessageStartEvent: ({ event }) => claimLive(event.messageId),
354
- // A tool-call-only reply is created by its first tool call, under `parentMessageId`
355
- // when the server names one and the tool call's own id otherwise (the client's rule).
356
348
  onToolCallStartEvent: ({ event }) => claimLive(event.parentMessageId ?? event.toolCallId),
357
349
  onRunFinalized: () => {
358
350
  liveRunRef.current = null;
@@ -370,8 +362,6 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
370
362
  });
371
363
  return () => {
372
364
  unsubscribe();
373
- // A run in flight on the agent we leave finalizes without us; it must not claim
374
- // the next agent's messages.
375
365
  liveRunRef.current = null;
376
366
  };
377
367
  }, [copilotAgent]);
@@ -393,11 +383,13 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
393
383
  }, [copilotAgent, currentThreadId]);
394
384
  const [prompt, setPrompt] = useState("");
395
385
  const [attachments, setAttachments] = useState([]);
396
- // Conversation identity. When a mounted chat is pointed at another conversation, the
397
- // reconnect replay takes a round-trip — clear the previous transcript and composer
398
- // immediately so the old conversation never lingers on screen (same visual contract as
399
- // a remount). Deliberately NOT keyed on `initKey`: that also changes when the block
400
- // configs finish loading, and clearing then would wipe a freshly replayed transcript.
386
+ const [composerMessageMeta, setComposerMessageMeta] = useState(null);
387
+ // setRunningElsewhere: a run elsewhere reads as this chat's own; own runs match RUN_STARTED id; refused at send time via ref (upload awaits).
388
+ const [runningElsewhereRunId, setRunningElsewhere] = useState(null);
389
+ const [ownRunInFlight, setOwnRunInFlight] = useState(false);
390
+ const isRunningElsewhere = runningElsewhereRunId !== null && !ownRunInFlight && !ownRunIdsRef.current.has(runningElsewhereRunId);
391
+ const isRunningElsewhereRef = useRef(isRunningElsewhere);
392
+ isRunningElsewhereRef.current = isRunningElsewhere;
401
393
  const conversationKey = `${chatId ?? ""}|${currentThreadId ?? ""}`;
402
394
  const prevConversationKeyRef = useRef(conversationKey);
403
395
  useIsomorphicLayoutEffect(() => {
@@ -410,14 +402,8 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
410
402
  setRunStartedAt(EMPTY_RUN_STARTED_AT);
411
403
  setPrompt("");
412
404
  setAttachments([]);
413
- // The clear above runs in the layout phase, but the previous conversation's run is
414
- // detached in passive effects — and even past detach, events already buffered in the
415
- // apply pipeline keep applying, each reassigning `agent.messages` WHOLESALE. One late
416
- // chunk would resurrect the entire previous transcript (and re-arm its auto-executing
417
- // tool-call follow-ups) under the new conversation's header. Detach here too and
418
- // re-clear once the drain settles; the reconnect that follows replays on top of the
419
- // (guaranteed-empty) mirror. On threadId switches the core's fresh-restore re-clears
420
- // as well — harmless overlap — but on chatId-only switches this is the only re-clear.
405
+ setComposerMessageMeta(null);
406
+ setOwnRunInFlight(false);
421
407
  const detachable = copilotAgent;
422
408
  const drained = detachable?.detachActiveRun?.();
423
409
  if (drained) {
@@ -429,15 +415,6 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
429
415
  });
430
416
  }
431
417
  }, [conversationKey]);
432
- // CopilotKit reconnects only when its threadId changes — but a conversation is the
433
- // (chatId, threadId) PAIR, and rows written by surfaces that use the fixed default
434
- // thread id differ only by chatId. On such a chatId-only switch the library's connect
435
- // effect sees unchanged deps and does nothing, which would leave the (just cleared)
436
- // transcript empty forever. Reconnect manually, replicating the core's fresh-restore
437
- // steps: reset state and drop the replay cursor — cursors are keyed by threadId, so
438
- // the shared id makes the previous conversation's cursor actively wrong here — then
439
- // connect (the core detaches any in-flight run itself). The core reads `properties`
440
- // after an await, so the new chatId is already synced by the time the request builds.
441
418
  const prevConnectionRef = useRef({ chatId, threadId: currentThreadId });
442
419
  useEffect(() => {
443
420
  const previous = prevConnectionRef.current;
@@ -449,23 +426,16 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
449
426
  }
450
427
  copilotAgent.setState?.({});
451
428
  copilotAgent.clearReplayCursor?.(currentThreadId);
452
- // Same guard convention as the composer send path: a failed reconnect already
453
- // surfaces through the availability state; the rejection carries no extra signal.
454
429
  void copilotkit.connectAgent({ agent: copilotAgent }).catch(() => undefined);
455
430
  }, [chatId, currentThreadId, copilotAgent, copilotkit]);
456
431
  const [isDraggingFiles, setIsDraggingFiles] = useState(false);
457
432
  const attachmentsEnabled = agentChat ? agentChat.disableAttachments !== true : false;
458
- const canSendMessage = Boolean(agentChatBlock && agentChat && agent && isConfigLoaded && isAgentReady && !isAgentRunning);
433
+ const canSendMessage = Boolean(agentChatBlock && agentChat && agent && isConfigLoaded && isAgentReady && !isAgentRunning && !isRunningElsewhere);
459
434
  const isFetchingMessages = !isConfigLoaded || (!isAgentReady && copilotMessages.length === 0);
460
- // CopilotKit reports `isLoading` during connect/replay as well as real runs. Only expose
461
- // thinking once the bootstrap connect phase has completed — and that needs the readiness
462
- // latch, not just `isFetchingMessages`, which goes false as soon as ONE replayed message
463
- // exists: without `isAgentReady`, thinking leaks true for the tail of every replay, and
464
- // every load or thread switch flashes the typing dots under the transcript. Real runs are
465
- // unaffected — sending requires readiness (canSendMessage), so the latch is already set.
466
- const isThinking = isAgentRunning && !isFetchingMessages && isAgentReady;
435
+ const isThinking = (isAgentRunning || isRunningElsewhere) && !isFetchingMessages && isAgentReady;
467
436
  const runAgentWithRetry = useCallback(async (agentToRun, messageCountAtRunStart, forwardedProps) => {
468
- if (agentToRun.isRunning) {
437
+ // A run elsewhere is on this conversation's checkpoint too: ours would race it.
438
+ if (agentToRun.isRunning || isRunningElsewhereRef.current) {
469
439
  return false;
470
440
  }
471
441
  const runAgentAndThrowError = async () => {
@@ -488,8 +458,13 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
488
458
  unsubscribe();
489
459
  }
490
460
  };
461
+ // In flight until the run ends, whichever way (see `runningElsewhereRunId`) — unless
462
+ // the conversation switched under it, which resets this itself.
463
+ const ranOn = prevConversationKeyRef.current;
464
+ setOwnRunInFlight(true);
491
465
  try {
492
466
  await runAgentAndThrowError();
467
+ return true;
493
468
  }
494
469
  catch (error) {
495
470
  const hasAgentStartedResponding = agentToRun.messages.length > messageCountAtRunStart;
@@ -500,24 +475,19 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
500
475
  }
501
476
  throw error;
502
477
  }
503
- return true;
478
+ finally {
479
+ if (prevConversationKeyRef.current === ranOn) {
480
+ setOwnRunInFlight(false);
481
+ }
482
+ }
504
483
  }, [copilotkit]);
505
484
  const sendMessage = useCallback(async (message) => {
506
- if (!canSendMessage || !copilotAgent || copilotAgent.isRunning) {
485
+ if (!canSendMessage || !copilotAgent || copilotAgent.isRunning || isRunningElsewhereRef.current) {
507
486
  return;
508
487
  }
509
488
  copilotAgent.addMessage({ ...message, id: generateId(), role: "user" });
510
- // The send seam, fired once the message is IN the conversation, so hosts can react
511
- // to it (e.g. list the thread optimistically). Covers every send routed through
512
- // `sendMessage` — composer, empty-state heroes, user-generated chat components —
513
- // but deliberately NOT the auto-sent `initialPrompt` below, whose hidden variant is
514
- // a primer rather than something the user wrote.
515
489
  if (onUserMessageSent) {
516
- const { content } = message;
517
- const textPart = Array.isArray(content)
518
- ? content.find((part) => part.type === "text")
519
- : undefined;
520
- onUserMessageSent(typeof content === "string" ? content : (textPart?.text ?? ""));
490
+ onUserMessageSent(userTextOfContent(message.content), message);
521
491
  }
522
492
  await runAgentWithRetry(copilotAgent, copilotAgent.messages.length);
523
493
  }, [canSendMessage, copilotAgent, runAgentWithRetry, onUserMessageSent]);
@@ -525,14 +495,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
525
495
  if (!copilotAgent || copilotAgent.isRunning) {
526
496
  return;
527
497
  }
528
- // Replay cursors are keyed by threadId and record what has already been replayed, so a
529
- // stale one makes connect a no-op — exactly the case here, where the thread is unchanged
530
- // and only the server-side content moved. Messages are NOT cleared first: connect answers
531
- // with a full snapshot that replaces them, and clearing would blank the transcript for the
532
- // round-trip.
533
498
  copilotAgent.clearReplayCursor?.(currentThreadId);
534
- // Same guard convention as the composer send path: a failed reconnect already surfaces
535
- // through the availability state; the rejection carries no extra signal.
536
499
  await copilotkit.connectAgent({ agent: copilotAgent }).catch(() => undefined);
537
500
  }, [copilotAgent, copilotkit, currentThreadId]);
538
501
  // Not sourced from `useInterrupt`: that hook only hands `resolve` to its own
@@ -735,17 +698,44 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
735
698
  return contentArray;
736
699
  };
737
700
  const sendFromInputs = async () => {
738
- if (!canSendMessage || !hasSendableInput(prompt, attachments)) {
701
+ const currentMeta = composerMessageMeta;
702
+ if (!canSendMessage || !hasSendableInput(prompt, attachments, currentMeta)) {
739
703
  return;
740
704
  }
741
705
  const currentPrompt = prompt;
742
- const currentAttachments = attachments;
743
- const uploadedAttachments = await uploadAttachments({
744
- attachments: currentAttachments,
745
- appId,
746
- token,
747
- });
748
- const messageContent = buildMessageContentFromInput(currentPrompt, uploadedAttachments ?? []);
706
+ const composedOn = prevConversationKeyRef.current;
707
+ if (currentMeta) {
708
+ setComposerMessageMeta(null);
709
+ }
710
+ let uploadedAttachments;
711
+ try {
712
+ uploadedAttachments = await uploadAttachments({
713
+ attachments,
714
+ appId,
715
+ token,
716
+ });
717
+ }
718
+ catch (error) {
719
+ // Failed upload: re-arm unless the conversation switched.
720
+ if (currentMeta && prevConversationKeyRef.current === composedOn) {
721
+ setComposerMessageMeta((armed) => armed ?? currentMeta);
722
+ }
723
+ throw error;
724
+ }
725
+ // Post-upload: conversation switch → stop; run elsewhere → keep input and re-arm; failed upload handled above.
726
+ if (prevConversationKeyRef.current !== composedOn) {
727
+ return;
728
+ }
729
+ if (isRunningElsewhereRef.current || copilotAgent?.isRunning) {
730
+ if (currentMeta) {
731
+ setComposerMessageMeta((armed) => armed ?? currentMeta);
732
+ }
733
+ return;
734
+ }
735
+ const composed = buildMessageContentFromInput(currentPrompt, uploadedAttachments ?? []);
736
+ const messageContent = currentMeta
737
+ ? buildArmedMessageContent(currentMeta, composed)
738
+ : composed;
749
739
  setPrompt("");
750
740
  setAttachments([]);
751
741
  // Auto-skip any frontend user-choice tool call that's still waiting.
@@ -791,7 +781,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
791
781
  });
792
782
  }
793
783
  }
794
- await sendMessage({ content: messageContent }).catch(() => undefined);
784
+ await sendMessage(currentMeta?.name ? { content: messageContent, name: currentMeta.name } : { content: messageContent }).catch(() => undefined);
795
785
  };
796
786
  const addAttachments = (attachments) => {
797
787
  if (!attachmentsEnabled) {
@@ -841,6 +831,9 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, chatId, token, appId, com
841
831
  setAttachments: setChatAttachments,
842
832
  setIsDraggingFiles: setChatIsDraggingFiles,
843
833
  setCurrentThreadId,
834
+ composerMessageMeta,
835
+ setComposerMessageMeta,
836
+ setRunningElsewhere,
844
837
  isDraggingFiles,
845
838
  isFetchingMessages,
846
839
  isThinking,
@@ -1106,10 +1099,10 @@ export function AgentChatFetching({ asChild = false, render, ...props }) {
1106
1099
  return (_jsx(ComposeRender, { render: render, asChild: asChild, defaultTag: "div", "data-state": isFetchingMessages ? "open" : "closed", "data-slot": "agent-chat-fetching", ...props }));
1107
1100
  }
1108
1101
  export function AgentChatInput({ asChild = false, render, onChange, onKeyDown, onPaste, onDragOver, onDragLeave, onDrop, onSubmit, ...props }) {
1109
- const { setIsDraggingFiles, addAttachments, attachments, prompt, setPrompt, sendFromInputs, isThinking, isAgentReady, isFetchingMessages, agentChat, } = useAgentChat();
1102
+ const { setIsDraggingFiles, addAttachments, attachments, prompt, setPrompt, sendFromInputs, isThinking, isAgentReady, isFetchingMessages, agentChat, composerMessageMeta, } = useAgentChat();
1110
1103
  const attachmentsEnabled = agentChat ? agentChat.disableAttachments !== true : false;
1111
1104
  const isDisabled = props.disabled || isThinking || !isAgentReady || isFetchingMessages;
1112
- const isSubmitDisabled = isDisabled || !hasSendableInput(prompt, attachmentsEnabled ? attachments : []);
1105
+ const isSubmitDisabled = isDisabled || !hasSendableInput(prompt, attachmentsEnabled ? attachments : [], composerMessageMeta);
1113
1106
  const handleDragOver = useCallback((e) => {
1114
1107
  if (!attachmentsEnabled) {
1115
1108
  return;
@@ -1199,10 +1192,14 @@ export function AgentChatInput({ asChild = false, render, onChange, onKeyDown, o
1199
1192
  : onDrop, "data-slot": "agent-chat-input", ...props }));
1200
1193
  }
1201
1194
  export function AgentChatSendTrigger({ asChild = false, render, onClick, disabled, ...props }) {
1202
- const { attachments, prompt, isThinking, isAgentReady, isFetchingMessages, sendFromInputs,
1195
+ const { attachments, prompt, isThinking, isAgentReady, isFetchingMessages, sendFromInputs, composerMessageMeta,
1203
1196
  /* , stopGeneration */
1204
1197
  } = useAgentChat();
1205
- const isDisabled = Boolean(disabled || isThinking || !isAgentReady || isFetchingMessages || !hasSendableInput(prompt, attachments));
1198
+ const isDisabled = Boolean(disabled ||
1199
+ isThinking ||
1200
+ !isAgentReady ||
1201
+ isFetchingMessages ||
1202
+ !hasSendableInput(prompt, attachments, composerMessageMeta));
1206
1203
  return (_jsx(ComposeRender, { render: render, asChild: asChild, defaultTag: "button", onClick: (e) => {
1207
1204
  if (isDisabled) {
1208
1205
  e.preventDefault();
@@ -0,0 +1,32 @@
1
+ import { type ReactNode } from "react";
2
+ import type { AgentThreadItem } from "./agent-thread-live-update.js";
3
+ import { type AgentConversationChat, type AgentConversationRef, type UseAgentConversationResult } from "./use-agent-conversation.js";
4
+ import { type UseAgentThreadsOptions, type UseAgentThreadsResult } from "./use-agent-threads.js";
5
+ export type AgentThreadFilters = Pick<UseAgentThreadsOptions, "status" | "source">;
6
+ export interface AgentConversationContextValue {
7
+ agentId: string;
8
+ conversation: AgentConversationRef;
9
+ /** The new chat, nothing sent on it yet. */
10
+ isDraft: boolean;
11
+ /** The index under `filters`; its `renameThread` also keeps the open conversation's remembered title current. */
12
+ threads: UseAgentThreadsResult;
13
+ /** The open conversation's row: listed, else the last listed, else a stand-in (`isStandIn`). */
14
+ row: AgentThreadItem;
15
+ isStandIn: boolean;
16
+ filters: AgentThreadFilters;
17
+ setFilters: (filters: AgentThreadFilters) => void;
18
+ hasActiveFilters: boolean;
19
+ /** After this client sends on the conversation (the chat root's onUserMessageSent). */
20
+ notifyMessageSent: UseAgentConversationResult["notifyMessageSent"];
21
+ }
22
+ export interface AgentConversationProviderProps extends Pick<UseAgentThreadsOptions, "token" | "headers" | "baseUrl"> {
23
+ agentId: string;
24
+ conversation: AgentConversationRef;
25
+ isDraft: boolean;
26
+ /** The chat runtime's side of the bridge (react-common's useAgentChat). */
27
+ chat: AgentConversationChat;
28
+ children?: ReactNode;
29
+ }
30
+ export declare function AgentConversationProvider({ agentId, conversation, isDraft, chat, token, headers, baseUrl, children, }: AgentConversationProviderProps): import("react").JSX.Element;
31
+ export declare const useAgentConversationContext: () => AgentConversationContextValue;
32
+ //# sourceMappingURL=agent-conversation-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-conversation-context.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-conversation-context.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAiB,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAEzB,KAAK,0BAA0B,EAChC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAmB,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE/G,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,sBAAsB,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC;AAEnF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,OAAO,EAAE,qBAAqB,CAAC;IAC/B,gGAAgG;IAChG,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uFAAuF;IACvF,iBAAiB,EAAE,0BAA0B,CAAC,mBAAmB,CAAC,CAAC;CACpE;AAID,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACnH,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,IAAI,EAAE,qBAAqB,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,8BAA8B,+BA4BhC;AAED,eAAO,MAAM,2BAA2B,QAAO,6BAM9C,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // The headless Root of an agent conversation surface: one provider that owns the conversation
3
+ // index (useAgentThreads) under the surface's filters and the open conversation's bridge to the
4
+ // chat (useAgentConversation), for parts to read through useAgentConversationContext. The
5
+ // agent-layout registry item renders it; a custom UI over the same behaviour can too.
6
+ import { createContext, useContext, useState } from "react";
7
+ import { useAgentConversation, } from "./use-agent-conversation.js";
8
+ import { useAgentThreads } from "./use-agent-threads.js";
9
+ const AgentConversationContext = createContext(null);
10
+ export function AgentConversationProvider({ agentId, conversation, isDraft, chat, token, headers, baseUrl, children, }) {
11
+ const [filters, setFilters] = useState({});
12
+ const threads = useAgentThreads({ agentId, status: filters.status, source: filters.source, token, headers, baseUrl });
13
+ const { row, isStandIn, renameThread, notifyMessageSent } = useAgentConversation({
14
+ threads,
15
+ agentId,
16
+ conversation,
17
+ isDraft,
18
+ chat,
19
+ });
20
+ return (_jsx(AgentConversationContext.Provider, { value: {
21
+ agentId,
22
+ conversation,
23
+ isDraft,
24
+ threads: { ...threads, renameThread },
25
+ row,
26
+ isStandIn,
27
+ filters,
28
+ setFilters,
29
+ hasActiveFilters: Boolean(filters.status ?? filters.source),
30
+ notifyMessageSent,
31
+ }, children: children }));
32
+ }
33
+ export const useAgentConversationContext = () => {
34
+ const context = useContext(AgentConversationContext);
35
+ if (!context) {
36
+ throw new Error("useAgentConversationContext must be used within <AgentConversationProvider>.");
37
+ }
38
+ return context;
39
+ };
@@ -1,94 +1,65 @@
1
- export type AgentThreadStatus = "idle" | "interrupted" | "error";
2
- export type AgentThreadSource = "direct_chat" | "agent_call" | "send_message" | "feedback" | "unknown";
1
+ declare const THREAD_STATUSES: readonly ["idle", "interrupted", "waiting_on_agent", "busy", "error"];
2
+ export type AgentThreadStatus = (typeof THREAD_STATUSES)[number];
3
+ declare const THREAD_SOURCES: readonly ["direct_chat", "send_message", "feedback", "self_config_resume", "unknown"];
4
+ export type AgentThreadSource = (typeof THREAD_SOURCES)[number] | "agent_call";
3
5
  export interface AgentThreadItem {
4
6
  agentId: string | null;
5
- /** Never null — pass back verbatim to open the conversation. */
6
7
  chatId: string;
7
- /** Never null — pass back verbatim to open the conversation. */
8
8
  chatThreadId: string;
9
9
  source: AgentThreadSource;
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
13
  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
14
  fromSourceChatThreadId?: string | null;
26
- /** The message the feedback was about, when it was about one rather than the conversation. */
27
15
  fromSourceMessageId?: string | null;
28
- /** First seen by the index — NOT thread creation time. */
29
16
  firstSeenAt: string;
30
17
  lastActivityAt: string;
18
+ runningSince?: string | null;
19
+ runningRunId?: string | null;
31
20
  }
32
- /** The (chatId, chatThreadId) pair — the only stable identity of a thread row. */
33
21
  export declare const agentThreadKey: (thread: Pick<AgentThreadItem, "chatId" | "chatThreadId">) => string;
34
- /**
35
- * Whether a realtime payload's `thread` is a complete list-item row. The server
36
- * serializes the exact item shape into every event, so this normally passes; when
37
- * it doesn't (contract drift), the consumer falls back to the getOne endpoint.
38
- */
39
22
  export declare const isAgentThreadItem: (value: unknown) => value is AgentThreadItem;
40
- /**
41
- * Provisional row title from the prompt that started a conversation (ChatGPT-style):
42
- * one line, whitespace collapsed, capped like the server's generated titles. Null when
43
- * there's nothing usable (attachment-only sends) — the UI keeps its id-based fallback.
44
- */
45
23
  export declare const provisionalThreadTitle: (prompt: string | undefined) => string | null;
46
- /**
47
- * The optimistic row for a user send on `thread`, replacing `previous` (its current
48
- * optimistic entry, if any): the same identity, its recency bumped to `now`, and a title
49
- * that never regresses — the provisional title already shown, else the row's own, else
50
- * one from this prompt (null when the prompt has nothing usable).
51
- */
52
24
  export declare const optimisticThreadAfterSend: (thread: AgentThreadItem, previous: AgentThreadItem | undefined, prompt: string | undefined, now: string) => AgentThreadItem;
25
+ export type RemovedAgentThread = Pick<AgentThreadItem, "chatId" | "chatThreadId" | "runningRunId">;
26
+ export declare const removeAgentThread: (threads: AgentThreadItem[], optimistic: ReadonlyMap<string, AgentThreadItem>, removed: RemovedAgentThread) => {
27
+ threads: AgentThreadItem[];
28
+ optimistic: ReadonlyMap<string, AgentThreadItem>;
29
+ } | null;
53
30
  export interface AgentThreadLiveUpdateOptions {
54
- /** Active server-side filters — an updated row that stops matching leaves the list. */
55
31
  status?: AgentThreadStatus;
56
32
  source?: AgentThreadSource;
57
33
  chatId?: string;
58
- /** Active sort, mirroring the endpoint's defaults (lastActivity, desc). */
59
34
  sort?: "lastActivity" | "firstSeen";
60
35
  order?: "asc" | "desc";
61
- /** True when more pages exist server-side beyond the loaded window. */
62
36
  hasMore?: boolean;
63
37
  }
64
- /**
65
- * Merge one realtime thread update into a loaded list. Pure; returns the input array
66
- * untouched when the event is stale, filtered out, or out of the loaded window.
67
- *
68
- * - Out-of-order delivery can't regress a row: events older than the loaded row (by
69
- * lastActivityAt) are dropped — checked FIRST, so a stale event can't evict a
70
- * still-current row through the filter check below either. Renames keep
71
- * lastActivityAt, so equal passes.
72
- * - A row that stops matching the active filters is removed; a matching one is upserted
73
- * and the list re-sorted by the active sort (stable, so ties keep their server order).
74
- * - A NEW row sorting past every loaded row while more pages exist may belong beyond the
75
- * loaded window; it's skipped so the list stays contiguous with the pagination cursor
76
- * (unreachable under the default lastActivity-desc sort, where fresh activity sorts first).
77
- */
78
- /** Whether a row passes the list's active server-side filters. */
79
38
  export declare const matchesAgentThreadFilters: (item: AgentThreadItem, options?: AgentThreadLiveUpdateOptions) => boolean;
80
39
  export declare const applyAgentThreadUpdate: (threads: AgentThreadItem[], incoming: AgentThreadItem, options?: AgentThreadLiveUpdateOptions) => AgentThreadItem[];
81
- /**
82
- * Overlay optimistic rows (conversations the user just acted on, ChatGPT-style) onto the
83
- * loaded list. Each row goes through the same merge as a realtime event, so filters and
84
- * sorting apply — except that a server row still untitled borrows the optimistic
85
- * (prompt-derived) title until the generated one lands. Pure; returns `threads` untouched
86
- * when nothing changes.
87
- *
88
- * An entry steps aside once the loaded row has recorded MORE turns than it did: turnCount
89
- * is server-monotonic, so the handover can't be held off by a client clock running ahead
90
- * of the server (the entry's lastActivityAt is stamped locally, and the merge's staleness
91
- * guard compares it against server timestamps).
92
- */
40
+ /** Parked removal for an in-flight refresh walk (see reconcileWalkWithLive). */
41
+ export interface ParkedRemoval {
42
+ removed: RemovedAgentThread;
43
+ }
44
+ export declare const reconcileWalkWithLive: (items: AgentThreadItem[], live: ReadonlyMap<string, AgentThreadItem | ParkedRemoval>, options?: AgentThreadLiveUpdateOptions) => AgentThreadItem[];
93
45
  export declare const overlayOptimisticThreads: (threads: AgentThreadItem[], optimistic: ReadonlyMap<string, AgentThreadItem>, options?: AgentThreadLiveUpdateOptions) => AgentThreadItem[];
46
+ export declare const retireOptimisticThreadsTakenOver: (optimistic: ReadonlyMap<string, AgentThreadItem>, threads: AgentThreadItem[]) => ReadonlyMap<string, AgentThreadItem>;
47
+ /** The server's cap on a title a person sets (RENAME_TITLE_MAX_CHARS in wf-actions-py). */
48
+ export declare const RENAME_TITLE_MAX_CHARS = 255;
49
+ /** Conversation-index groups, in display order; a row's group follows its write-once `source`. */
50
+ export declare const AGENT_THREAD_GROUPS: readonly ["chats", "workflows", "feedback"];
51
+ export type AgentThreadGroup = (typeof AGENT_THREAD_GROUPS)[number];
52
+ /** Where a row files; a source this copy predates files under chats, so a row never renders nowhere. */
53
+ export declare const agentThreadGroup: (source: AgentThreadSource) => AgentThreadGroup;
54
+ export interface AgentThreadGroupRows {
55
+ group: AgentThreadGroup;
56
+ rows: AgentThreadItem[];
57
+ }
58
+ /** Rows by group in group order, each group in input order; empty groups dropped. */
59
+ export declare const groupAgentThreads: (threads: readonly AgentThreadItem[]) => AgentThreadGroupRows[];
60
+ /** A thread the agent opened to act on feedback — by `type`, or by `source` for rows from before the column. */
61
+ export declare const isFeedbackThread: (row: Pick<AgentThreadItem, "type" | "source">) => boolean;
62
+ /** The conversation a feedback thread was opened from, when `threads` lists it (same chat, the row's pointer). */
63
+ export declare const feedbackSourceThread: (row: AgentThreadItem, threads: readonly AgentThreadItem[]) => AgentThreadItem | undefined;
64
+ export {};
94
65
  //# sourceMappingURL=agent-thread-live-update.d.ts.map