@blocksdiy/react-common 1.64.0 → 1.66.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.
@@ -5,10 +5,12 @@ import { type ApprovalCardView, type ApprovalDecision } from "../utils/agui-inte
5
5
  import { type RenderProp } from "../utils/compose-render.js";
6
6
  import { type ComposerMessageMeta } from "../utils/composer-message.js";
7
7
  import { type MessageRunIds, type RunStartedAt } from "../utils/message-run-ids.js";
8
+ import { type ScheduledTrigger } from "../utils/scheduled-trigger.js";
8
9
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
9
10
  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";
10
11
  export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun, type MessageRunIds, type RunStartedAt, } from "../utils/message-run-ids.js";
11
12
  export { type ApprovalCardView, type ApprovalDecision, toolStepVisibleBelowCards } from "../utils/agui-interrupts.js";
13
+ export { type ScheduledTrigger } from "../utils/scheduled-trigger.js";
12
14
  export { type Message, type AssistantMessage, type UserMessage } from "@ag-ui/client";
13
15
  export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
14
16
  export interface Attachment {
@@ -73,6 +75,12 @@ export interface AgentChatContextValue {
73
75
  role: "assistant" | "user";
74
76
  }[];
75
77
  messageById: Map<string, Message>;
78
+ /**
79
+ * The reminder or schedule that started a turn, keyed by the turn's first message id. A
80
+ * message group starts at each one, so a group whose first message is here draws the line.
81
+ * Optional: a context a host builds by hand may omit it.
82
+ */
83
+ scheduledTriggerByMessageId?: ReadonlyMap<string, ScheduledTrigger>;
76
84
  runIdByMessageId?: MessageRunIds;
77
85
  runStartedAt?: RunStartedAt;
78
86
  toolMessages: ToolMessage[];
@@ -99,6 +107,11 @@ export interface AgentChatContextValue {
99
107
  /** A tool step's title: the tool's display name when the server stamped one, else its name, in words. */
100
108
  toolTitleFor?: (toolCallId: string, toolName: string) => string;
101
109
  stopGeneration: () => void;
110
+ /**
111
+ * A running reply Stop applies to: this tab's own, or a followed one a chat started (never a
112
+ * workflow's or a reminder's), and only with the live turn stream on.
113
+ */
114
+ canStop?: boolean;
102
115
  addAttachments: (attachments: Attachment[]) => void;
103
116
  removeAttachment: (url: string) => void;
104
117
  clearAttachments: () => void;
@@ -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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"}
@@ -12,7 +12,9 @@ import { answerRouteOf, approvalCardsForToolCall, buildResumeEntries, cancelledR
12
12
  import { ComposeRender } from "../utils/compose-render.js";
13
13
  import { buildArmedMessageContent, userTextOfContent } from "../utils/composer-message.js";
14
14
  import { forwardedLegacyChatId, pinnedLegacyChatThreadId } from "../utils/legacy-chat-thread-id.js";
15
+ import { buildStopEnvelope, canStop, isThreadBusyError, liveAfterTerminal, readLiveTurnEvent, shouldConnectForRun, shouldReconnectAfterStream, stopRunIdOf, streamRunIdOf, } from "../utils/live-turn.js";
15
16
  import { claimRunInput, EMPTY_MESSAGE_RUN_IDS, EMPTY_RUN_STARTED_AT, findMessageGroupElement, mergeEntries, MESSAGE_IDS_ATTRIBUTE, messageIdsOfRun, readMessageRunIdsEvent, readRunStartedAtEvent, } from "../utils/message-run-ids.js";
17
+ import { scheduledTriggersByMessageId } from "../utils/scheduled-trigger.js";
16
18
  export { useTextGrowthAnimating } from "../hooks/text-growth-animation.js";
17
19
  export { FEEDBACK_MESSAGE_NAME, feedbackComposerMeta, feedbackDraftOf, feedbackMessage, feedbackThreadId, isFeedbackMessage, isFeedbackTag, parseFeedbackContent, parseFeedbackTag, } from "../utils/composer-message.js";
18
20
  export { MESSAGE_RUN_IDS_EVENT_NAME, messageIdsOfRun, } from "../utils/message-run-ids.js";
@@ -247,24 +249,6 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
247
249
  token ?? "",
248
250
  appId ?? "",
249
251
  ].join("|");
250
- // Readiness latch. CopilotKit's `isAvailable` deadlocks false when a replayed
251
- // transcript ends with an unanswered frontend HITL tool call — see
252
- // `isConnectParkedOnPendingToolCall`. So also treat "parked but loaded" as
253
- // ready, and latch it: once ready we stay ready for the session, otherwise
254
- // typing past the question (which empties the pending set) would re-lock the
255
- // composer while `isAvailable` is still parked-false. Keyed to `initKey` so a
256
- // swap resets readiness. We skip promotion on the render the key changes on,
257
- // because `isCopilotAgentAvailable`/`copilotMessages` still hold the previous
258
- // session's values until CopilotKit's connect effect runs post-commit.
259
- const agentReadyLatchRef = useRef({ key: initKey, ready: false });
260
- const initKeyChanged = agentReadyLatchRef.current.key !== initKey;
261
- if (initKeyChanged) {
262
- agentReadyLatchRef.current = { key: initKey, ready: false };
263
- }
264
- if (!initKeyChanged && (isCopilotAgentAvailable || isConnectParkedOnPendingToolCall(copilotMessages))) {
265
- agentReadyLatchRef.current.ready = true;
266
- }
267
- const isAgentReady = agentReadyLatchRef.current.ready;
268
252
  const { copilotkit } = useCopilotKit();
269
253
  const renderToolCall = useRenderToolCall();
270
254
  const messageById = useMemo(() => {
@@ -277,6 +261,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
277
261
  const toolMessages = useMemo(() => {
278
262
  return copilotMessages.filter((message) => message.role === "tool");
279
263
  }, [copilotMessages]);
264
+ const scheduledTriggerByMessageId = useMemo(() => scheduledTriggersByMessageId(copilotMessages), [copilotMessages]);
280
265
  const messageGroups = useMemo(() => {
281
266
  const groups = [];
282
267
  copilotMessages.forEach((message) => {
@@ -284,7 +269,9 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
284
269
  return;
285
270
  }
286
271
  const lastGroup = groups[groups.length - 1];
287
- if (!lastGroup || lastGroup.role !== message.role) {
272
+ // A reminder's reply starts its own group even right after the agent's last message, so
273
+ // its trigger line sits above it and not inside the earlier reply.
274
+ if (!lastGroup || lastGroup.role !== message.role || scheduledTriggerByMessageId.has(message.id)) {
288
275
  groups.push({ role: message.role, messageIds: [message.id] });
289
276
  }
290
277
  else {
@@ -292,11 +279,63 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
292
279
  }
293
280
  });
294
281
  return groups;
295
- }, [copilotMessages]);
282
+ }, [copilotMessages, scheduledTriggerByMessageId]);
296
283
  const [runIdByMessageId, setRunIdByMessageId] = useState(EMPTY_MESSAGE_RUN_IDS);
297
284
  const [runStartedAt, setRunStartedAt] = useState(EMPTY_RUN_STARTED_AT);
298
285
  const liveRunRef = useRef(null);
299
286
  const ownRunIdsRef = useRef(new Set());
287
+ // The live turn stream (flag on): what the connect said about the thread's active turn. A
288
+ // flag-off server sends no such event, so `liveTurn` stays null and every branch stays off.
289
+ const [liveTurn, setLiveTurn] = useState(null);
290
+ const liveTurnRef = useRef(null);
291
+ liveTurnRef.current = liveTurn;
292
+ // Readiness latch. CopilotKit's `isAvailable` deadlocks false when a replayed
293
+ // transcript ends with an unanswered frontend HITL tool call — see
294
+ // `isConnectParkedOnPendingToolCall`. So also treat "parked but loaded" as
295
+ // ready, and latch it: once ready we stay ready for the session, otherwise
296
+ // typing past the question (which empties the pending set) would re-lock the
297
+ // composer while `isAvailable` is still parked-false. Keyed to `initKey` so a
298
+ // swap resets readiness. We skip promotion on the render the key changes on,
299
+ // because `isCopilotAgentAvailable`/`copilotMessages` still hold the previous
300
+ // session's values until CopilotKit's connect effect runs post-commit.
301
+ // A tab that joined a running turn is ready too: its connect streams until the turn ends, so
302
+ // `isAvailable` stays false while the tab already shows the reply and may stop it.
303
+ const agentReadyLatchRef = useRef({ key: initKey, ready: false });
304
+ const initKeyChanged = agentReadyLatchRef.current.key !== initKey;
305
+ if (initKeyChanged) {
306
+ agentReadyLatchRef.current = { key: initKey, ready: false };
307
+ }
308
+ if (!initKeyChanged &&
309
+ (isCopilotAgentAvailable || isConnectParkedOnPendingToolCall(copilotMessages) || Boolean(liveTurn?.runId))) {
310
+ agentReadyLatchRef.current.ready = true;
311
+ }
312
+ const isAgentReady = agentReadyLatchRef.current.ready;
313
+ const ownRunInFlightRef = useRef(false);
314
+ // The run each stream last started (a connect's own history run first, then the followed
315
+ // turn's), and the runs a RUN_FINISHED / RUN_ERROR closed.
316
+ const streamRunIdRef = useRef(null);
317
+ const terminalRunIdsRef = useRef(new Set());
318
+ // Whether the stream now ending delivered its RUN_STARTED: a request that failed outright did not.
319
+ const streamStartedRef = useRef(false);
320
+ const connectInFlightRef = useRef(false);
321
+ const lastConnectedForRunIdRef = useRef(null);
322
+ const threadBusyRefusedRef = useRef(false);
323
+ // One connect to watch the thread's running turn; `runId` is the run it answers for.
324
+ const followRunningTurn = useCallback((runId) => {
325
+ if (!copilotAgent || connectInFlightRef.current) {
326
+ return;
327
+ }
328
+ connectInFlightRef.current = true;
329
+ if (runId) {
330
+ lastConnectedForRunIdRef.current = runId;
331
+ }
332
+ void copilotkit
333
+ .connectAgent({ agent: copilotAgent })
334
+ .catch(() => undefined)
335
+ .finally(() => {
336
+ connectInFlightRef.current = false;
337
+ });
338
+ }, [copilotAgent, copilotkit]);
300
339
  // Paired once, when the pause arrives: while the next run streams, a sub-agent's own
301
340
  // calls arrive as the parent's and would re-pair the request with them -- a second
302
341
  // card on the parent's call.
@@ -324,6 +363,20 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
324
363
  if (!copilotAgent) {
325
364
  return;
326
365
  }
366
+ const threadOfStream = () => copilotAgent.threadId;
367
+ const endRun = (runId) => {
368
+ if (!runId) {
369
+ return;
370
+ }
371
+ terminalRunIdsRef.current.add(runId);
372
+ const live = liveTurnRef.current;
373
+ if (live?.runId === runId) {
374
+ // Answered for: the row still names it until the settle arrives, so no doorbell.
375
+ lastConnectedForRunIdRef.current = runId;
376
+ liveTurnRef.current = liveAfterTerminal(live, runId);
377
+ setLiveTurn(liveTurnRef.current);
378
+ }
379
+ };
327
380
  const claimLive = (messageId) => {
328
381
  const run = liveRunRef.current;
329
382
  if (!run) {
@@ -346,7 +399,11 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
346
399
  onRunStartedEvent: ({ event, messages }) => {
347
400
  liveRunRef.current = { runId: event.runId, startedAt: event.timestamp ?? Date.now(), input: messages };
348
401
  ownRunIdsRef.current.add(event.runId);
402
+ streamRunIdRef.current = event.runId;
403
+ streamStartedRef.current = true;
349
404
  },
405
+ onRunFinishedEvent: ({ event }) => endRun(event.runId),
406
+ onRunErrorEvent: () => endRun(streamRunIdRef.current),
350
407
  onTextMessageStartEvent: ({ event }) => claimLive(event.messageId),
351
408
  onToolCallStartEvent: ({ event }) => claimLive(event.parentMessageId ?? event.toolCallId),
352
409
  onRunFinalized: () => {
@@ -354,8 +411,36 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
354
411
  // The agent's own field, which @ag-ui/client has set on RUN_FINISHED by now (pinned
355
412
  // in agui-interrupts.spec) -- live runs and connects alike; a RUN_ERROR leaves it.
356
413
  setInterruptRequests(requestsOf(openInterruptsOf(copilotAgent), copilotAgent.messages));
414
+ // A stream that closed with no terminal event for the turn it showed (the 400 s
415
+ // self-close, a restart, a drop): watch the turn again.
416
+ const streamStarted = streamStartedRef.current;
417
+ streamStartedRef.current = false;
418
+ const streamRunId = streamRunIdOf({
419
+ ownRunInFlight: ownRunInFlightRef.current,
420
+ lastStartedRunId: streamRunIdRef.current,
421
+ live: liveTurnRef.current,
422
+ });
423
+ streamRunIdRef.current = null;
424
+ if (shouldReconnectAfterStream({
425
+ liveEnabled: liveTurnRef.current?.enabled === true,
426
+ streamRunId,
427
+ sawTerminalFor: terminalRunIdsRef.current,
428
+ streamStarted,
429
+ })) {
430
+ const threadId = threadOfStream();
431
+ setTimeout(() => {
432
+ if (threadOfStream() === threadId && !copilotAgent.isRunning) {
433
+ followRunningTurn(streamRunId);
434
+ }
435
+ }, 0);
436
+ }
357
437
  },
358
438
  onCustomEvent: ({ event }) => {
439
+ const live = readLiveTurnEvent(event);
440
+ if (live) {
441
+ liveTurnRef.current = live;
442
+ setLiveTurn(live);
443
+ }
359
444
  const runIds = readMessageRunIdsEvent(event);
360
445
  if (runIds) {
361
446
  setRunIdByMessageId((previous) => mergeEntries(previous, runIds));
@@ -370,14 +455,15 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
370
455
  unsubscribe();
371
456
  liveRunRef.current = null;
372
457
  };
373
- }, [copilotAgent]);
458
+ }, [copilotAgent, followRunningTurn]);
374
459
  // Mirror `currentThreadId` onto the agent instance — the `<CopilotKit>`
375
460
  // prop only feeds React context, but `agent.threadId` is what hits the
376
461
  // wire and the LangGraph checkpoint. `<CopilotChat>` does this for you;
377
462
  // we use the headless hook so we do it ourselves. Layout-effect timing
378
463
  // is required to beat the library's connect-on-mount/on-swap effect.
379
- // A swap doesn't abort an in-flight run — the connect effect's cleanup
380
- // detaches it client-side, and the run completes server-side as usual.
464
+ // A swap never stops a run: the connect effect's cleanup only detaches this client's
465
+ // reader. With the live turn stream on, the turn keeps going on the server and a later
466
+ // connect watches it again; with it off, the run still completes server-side as before.
381
467
  useIsomorphicLayoutEffect(() => {
382
468
  if (copilotAgent && currentThreadId) {
383
469
  copilotAgent.threadId = currentThreadId;
@@ -395,6 +481,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
395
481
  const isRunningElsewhere = runningElsewhereRunId !== null && !ownRunInFlight && !ownRunIdsRef.current.has(runningElsewhereRunId);
396
482
  const isRunningElsewhereRef = useRef(isRunningElsewhere);
397
483
  isRunningElsewhereRef.current = isRunningElsewhere;
484
+ ownRunInFlightRef.current = ownRunInFlight;
398
485
  const conversationKey = currentThreadId ?? "";
399
486
  const prevConversationKeyRef = useRef(conversationKey);
400
487
  useIsomorphicLayoutEffect(() => {
@@ -410,6 +497,11 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
410
497
  setComposerMessageMeta(null);
411
498
  resetInterrupts();
412
499
  setOwnRunInFlight(false);
500
+ setLiveTurn(null);
501
+ streamRunIdRef.current = null;
502
+ terminalRunIdsRef.current.clear();
503
+ lastConnectedForRunIdRef.current = null;
504
+ connectInFlightRef.current = false;
413
505
  const detachable = copilotAgent;
414
506
  const drained = detachable?.detachActiveRun?.();
415
507
  if (drained) {
@@ -426,6 +518,20 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
426
518
  const canSendMessage = Boolean(agentChatBlock && agentChat && agent && isConfigLoaded && isAgentReady && !isAgentRunning && !isRunningElsewhere);
427
519
  const isFetchingMessages = !isConfigLoaded || (!isAgentReady && copilotMessages.length === 0);
428
520
  const isThinking = (isAgentRunning || isRunningElsewhere) && !isFetchingMessages && isAgentReady;
521
+ // Doorbell: the row names a run this tab neither started nor follows, so connect and
522
+ // stream it live (replaces thinking until the end, then a reload).
523
+ useEffect(() => {
524
+ if (shouldConnectForRun({
525
+ liveEnabled: liveTurn?.enabled === true,
526
+ runningRunId: runningElsewhereRunId,
527
+ followingRunId: liveTurn?.runId ?? null,
528
+ lastConnectedForRunId: lastConnectedForRunIdRef.current,
529
+ ownRunIds: ownRunIdsRef.current,
530
+ connectInFlight: isAgentRunning || ownRunInFlight || connectInFlightRef.current,
531
+ })) {
532
+ followRunningTurn(runningElsewhereRunId);
533
+ }
534
+ }, [liveTurn, runningElsewhereRunId, isAgentRunning, ownRunInFlight, followRunningTurn]);
429
535
  const runAgentWithRetry = useCallback(async (agentToRun, messageCountAtRunStart, forwardedProps, resume, withoutSend = false) => {
430
536
  // A run elsewhere is on this conversation's checkpoint too: ours would race it.
431
537
  if (agentToRun.isRunning || isRunningElsewhereRef.current) {
@@ -436,14 +542,21 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
436
542
  setOwnRunsWithoutSend((count) => count + 1);
437
543
  }
438
544
  let finished = false;
545
+ threadBusyRefusedRef.current = false;
439
546
  const runAgentAndThrowError = async () => {
440
547
  let runEventError;
441
548
  const { unsubscribe } = agentToRun.subscribe({
442
549
  onRunFailed: (event) => {
443
550
  runEventError = event;
444
551
  },
445
- onRunErrorEvent: (event) => {
446
- runEventError = event;
552
+ onRunErrorEvent: (params) => {
553
+ // A refused send on a busy thread is not a failure: the sender puts its text back.
554
+ const { event } = params;
555
+ if (isThreadBusyError(event)) {
556
+ threadBusyRefusedRef.current = true;
557
+ return;
558
+ }
559
+ runEventError = params;
447
560
  },
448
561
  onRunFinishedEvent: () => {
449
562
  finished = true;
@@ -499,14 +612,15 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
499
612
  reconnected = true;
500
613
  }
501
614
  }
502
- // A reconnected run did not take effect as sent: callers must not record it as done.
503
- return !reconnected;
615
+ // A reconnected or refused run did not take effect as sent: callers must not record it as done.
616
+ return !reconnected && !threadBusyRefusedRef.current;
504
617
  }, [copilotkit, currentThreadId, resetInterrupts, readChatContext]);
505
618
  const sendMessage = useCallback(async (message) => {
506
619
  if (!canSendMessage || !copilotAgent || copilotAgent.isRunning || isRunningElsewhereRef.current) {
507
620
  return;
508
621
  }
509
- copilotAgent.addMessage({ ...message, id: generateId(), role: "user" });
622
+ const sentMessageId = generateId();
623
+ copilotAgent.addMessage({ ...message, id: sentMessageId, role: "user" });
510
624
  if (onUserMessageSent) {
511
625
  onUserMessageSent(userTextOfContent(message.content), message);
512
626
  }
@@ -520,6 +634,13 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
520
634
  const interrupts = openInterruptsOf(copilotAgent);
521
635
  if (interrupts.length === 0) {
522
636
  await runAgentWithRetry(copilotAgent, copilotAgent.messages.length);
637
+ if (threadBusyRefusedRef.current) {
638
+ // Refused: a turn is already running on the thread. Give the text back and watch it.
639
+ threadBusyRefusedRef.current = false;
640
+ copilotAgent.setMessages?.(copilotAgent.messages.filter((existing) => existing.id !== sentMessageId));
641
+ setPrompt(userTextOfContent(message.content));
642
+ followRunningTurn(null);
643
+ }
523
644
  return;
524
645
  }
525
646
  const requests = requestsOf(interrupts, copilotAgent.messages);
@@ -542,7 +663,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
542
663
  }
543
664
  setInterruptAnswers(EMPTY_ANSWERS);
544
665
  }
545
- }, [canSendMessage, copilotAgent, runAgentWithRetry, onUserMessageSent]);
666
+ }, [canSendMessage, copilotAgent, runAgentWithRetry, onUserMessageSent, followRunningTurn]);
546
667
  const reloadMessages = useCallback(async () => {
547
668
  if (!copilotAgent || copilotAgent.isRunning) {
548
669
  return;
@@ -665,10 +786,39 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
665
786
  throw new Error("answerInterrupt: a run was already in flight; answer not sent");
666
787
  }
667
788
  }, [copilotAgent, runAgentWithRetry, submitInterruptAnswers]);
789
+ const stoppable = canStop({ ownRunInFlight, following: liveTurn });
790
+ // The run body's thread fields, from the same values a run sends, to the runtime URL with
791
+ // the headers CopilotKit uses. Fire and forget: a failed stop request is only logged.
792
+ const postStopEnvelope = useCallback(() => {
793
+ const runId = stopRunIdOf({ ownRunInFlight, lastStartedRunId: streamRunIdRef.current, live: liveTurn });
794
+ if (!copilotAgent?.threadId || !runId || !copilotkit.runtimeUrl) {
795
+ return;
796
+ }
797
+ const envelope = buildStopEnvelope({
798
+ threadId: copilotAgent.threadId,
799
+ runId,
800
+ forwardedProps: { ...copilotkit.properties, chatContext: readChatContext() },
801
+ });
802
+ fetch(copilotkit.runtimeUrl, {
803
+ method: "POST",
804
+ headers: { ...copilotkit.headers, "Content-Type": "application/json" },
805
+ body: JSON.stringify(envelope),
806
+ ...(copilotkit.credentials ? { credentials: copilotkit.credentials } : {}),
807
+ }).catch((error) => {
808
+ console.warn("agent stop request failed", error);
809
+ });
810
+ }, [copilotAgent, copilotkit, liveTurn, ownRunInFlight, readChatContext]);
668
811
  const stopGeneration = useCallback(() => {
812
+ if (liveTurn?.enabled) {
813
+ if (!stoppable) {
814
+ return;
815
+ }
816
+ // Closing the stream no longer stops a turn: ask the server, before the reader goes.
817
+ postStopEnvelope();
818
+ }
669
819
  copilotStopGeneration();
670
820
  copilotAgent?.abortRun?.();
671
- }, [copilotAgent, copilotStopGeneration]);
821
+ }, [copilotAgent, copilotStopGeneration, liveTurn, stoppable, postStopEnvelope]);
672
822
  const initKeyRef = useRef(null);
673
823
  // Guard against re-firing the initial prompt across re-renders of the
674
824
  // post-connect effect. Reset whenever the init key changes (thread
@@ -925,6 +1075,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
925
1075
  messageGroups,
926
1076
  renderToolCall,
927
1077
  messageById,
1078
+ scheduledTriggerByMessageId,
928
1079
  runIdByMessageId,
929
1080
  runStartedAt,
930
1081
  toolMessages,
@@ -939,6 +1090,7 @@ const ChatInitializer = ({ agentBlock, agentChatBlock, token, appId, components,
939
1090
  approvalCardsFor,
940
1091
  toolTitleFor,
941
1092
  stopGeneration,
1093
+ canStop: stoppable,
942
1094
  addAttachments,
943
1095
  removeAttachment,
944
1096
  clearAttachments,
@@ -1377,26 +1529,28 @@ export function AgentChatInput({ asChild = false, render, onChange, onKeyDown, o
1377
1529
  : onDrop, "data-slot": "agent-chat-input", ...props }));
1378
1530
  }
1379
1531
  export function AgentChatSendTrigger({ asChild = false, render, onClick, disabled, ...props }) {
1380
- const { attachments, prompt, isThinking, isAgentReady, isFetchingMessages, sendFromInputs, composerMessageMeta,
1381
- /* , stopGeneration */
1382
- } = useAgentChat();
1532
+ const { attachments, prompt, isThinking, isAgentReady, isFetchingMessages, sendFromInputs, composerMessageMeta, stopGeneration, canStop, } = useAgentChat();
1533
+ // While a reply Stop applies to runs, the send button stops it instead.
1534
+ const stops = isThinking && canStop === true;
1383
1535
  const isDisabled = Boolean(disabled ||
1384
- isThinking ||
1385
- !isAgentReady ||
1386
- isFetchingMessages ||
1387
- !hasSendableInput(prompt, attachments, composerMessageMeta));
1536
+ (!stops &&
1537
+ (isThinking ||
1538
+ !isAgentReady ||
1539
+ isFetchingMessages ||
1540
+ !hasSendableInput(prompt, attachments, composerMessageMeta))));
1388
1541
  return (_jsx(ComposeRender, { render: render, asChild: asChild, defaultTag: "button", onClick: (e) => {
1389
1542
  if (isDisabled) {
1390
1543
  e.preventDefault();
1391
1544
  return;
1392
1545
  }
1393
- // if (isThinking) {
1394
- // stopGeneration();
1395
- // } else {
1396
- sendFromInputs();
1397
- // }
1546
+ if (stops) {
1547
+ stopGeneration();
1548
+ }
1549
+ else {
1550
+ sendFromInputs();
1551
+ }
1398
1552
  onClick?.(e);
1399
- }, disabled: isDisabled, "data-slot": "agent-chat-send-trigger", ...props }));
1553
+ }, disabled: isDisabled, "data-slot": "agent-chat-send-trigger", "data-state": stops ? "stop" : "send", ...props }));
1400
1554
  }
1401
1555
  export function AgentChatAttachmentTrigger({ asChild = false, render, onClick, disabled, accept, multiple = true, ...props }) {
1402
1556
  const { isThinking, isAgentReady, isFetchingMessages, addAttachments, agentChat } = useAgentChat();
@@ -1,6 +1,6 @@
1
1
  declare const THREAD_STATUSES: readonly ["idle", "interrupted", "waiting_on_agent", "busy", "error"];
2
2
  export type AgentThreadStatus = (typeof THREAD_STATUSES)[number];
3
- declare const THREAD_SOURCES: readonly ["direct_chat", "send_message", "feedback", "self_config_resume", "unknown"];
3
+ declare const THREAD_SOURCES: readonly ["direct_chat", "send_message", "feedback", "self_config_resume", "scheduled_reminder", "unknown"];
4
4
  export type AgentThreadSource = (typeof THREAD_SOURCES)[number] | "agent_call";
5
5
  export interface AgentThreadItem {
6
6
  agentId: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,14 @@
1
1
  // Wire types and pure merge logic for the agent-threads index; dependency-free for tests.
2
2
  const THREAD_STATUSES = ["idle", "interrupted", "waiting_on_agent", "busy", "error"];
3
- const THREAD_SOURCES = ["direct_chat", "send_message", "feedback", "self_config_resume", "unknown"];
3
+ const THREAD_SOURCES = [
4
+ "direct_chat",
5
+ "send_message",
6
+ "feedback",
7
+ "self_config_resume",
8
+ // A thread a fired reminder or schedule started (wf-actions-py scheduled_reminder_runner.py).
9
+ "scheduled_reminder",
10
+ "unknown",
11
+ ];
4
12
  /** A thread's identity within its agent: the thread id alone. */
5
13
  export const agentThreadKey = (thread) => thread.chatThreadId;
6
14
  export const isAgentThreadItem = (value) => {
@@ -134,6 +142,7 @@ export const AGENT_THREAD_GROUPS = ["chats", "workflows", "feedback"];
134
142
  const GROUP_OF_SOURCE = {
135
143
  direct_chat: "chats",
136
144
  self_config_resume: "chats",
145
+ scheduled_reminder: "chats",
137
146
  unknown: "chats",
138
147
  send_message: "workflows",
139
148
  feedback: "feedback",
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The chat's side of the live turn stream.
3
+ *
4
+ * With the server flag on, every `agent/connect` opens with one CUSTOM event,
5
+ * `blocks.live_turn`, and then streams the thread's active turn live in the same response.
6
+ * With the flag off the server sends none of this, so `liveEnabled` stays false and every
7
+ * decision below answers "do nothing".
8
+ */
9
+ export declare const LIVE_TURN_EVENT_NAME = "blocks.live_turn";
10
+ /** The RUN_ERROR code of a send refused because a turn is already running on the thread. */
11
+ export declare const THREAD_BUSY_ERROR_CODE = "thread_busy";
12
+ export type LiveTurnInfo = {
13
+ enabled: boolean;
14
+ runId?: string;
15
+ startedBy?: "chat" | "server";
16
+ };
17
+ /** The payload of the connect's live-turn CUSTOM event, or null for any other event. */
18
+ export declare const readLiveTurnEvent: (event: {
19
+ type: string;
20
+ name?: string;
21
+ value?: unknown;
22
+ }) => LiveTurnInfo | null;
23
+ /**
24
+ * Whether the thread row's running run (the doorbell) calls for a connect to watch it:
25
+ * one this tab neither follows nor started, that no connect has answered for yet.
26
+ */
27
+ export declare const shouldConnectForRun: (args: {
28
+ liveEnabled: boolean;
29
+ runningRunId: string | null;
30
+ followingRunId: string | null;
31
+ lastConnectedForRunId: string | null;
32
+ ownRunIds: ReadonlySet<string>;
33
+ connectInFlight: boolean;
34
+ }) => boolean;
35
+ /**
36
+ * Whether a run or connect stream that just ended should be followed by one more connect: it
37
+ * showed a running turn (this tab's send, or one the server named) and ended with no terminal
38
+ * event for it -- the 400 s self-close, a pod restart, a dropped network. A connect for a turn
39
+ * that has finished meanwhile names none, so it is not followed again. A stream that never
40
+ * started (the server unreachable) is not retried, or an outage would loop.
41
+ */
42
+ export declare const shouldReconnectAfterStream: (args: {
43
+ liveEnabled: boolean;
44
+ streamRunId: string | null;
45
+ sawTerminalFor: ReadonlySet<string>;
46
+ streamStarted: boolean;
47
+ }) => boolean;
48
+ /**
49
+ * Stop is for this tab's own run, or a followed turn a chat started (never workflow, reminder,
50
+ * ...), and only with the live turn stream on: only then does the server stop the turn itself.
51
+ */
52
+ export declare const canStop: (args: {
53
+ ownRunInFlight: boolean;
54
+ following: LiveTurnInfo | null;
55
+ }) => boolean;
56
+ export declare const isThreadBusyError: (event: {
57
+ type: string;
58
+ code?: string;
59
+ }) => boolean;
60
+ /** The `agent/stop` request: the run body's thread fields only, none of its content. */
61
+ export declare const buildStopEnvelope: (runBody: Record<string, unknown>) => {
62
+ method: "agent/stop";
63
+ body: Record<string, unknown>;
64
+ };
65
+ /**
66
+ * The run a stream that just ended is judged by. A tab's own send streams under its own run
67
+ * id; a connect body carries its own id for the history replay (RUN_STARTED/RUN_FINISHED),
68
+ * followed by the live turn's events, so a followed stream is judged by the live turn's id.
69
+ */
70
+ export declare const streamRunIdOf: (args: {
71
+ ownRunInFlight: boolean;
72
+ lastStartedRunId: string | null;
73
+ live: LiveTurnInfo | null;
74
+ }) => string | null;
75
+ /** The run a stop is for: the tab's own run, else the followed turn (never a connect's id). */
76
+ export declare const stopRunIdOf: (args: {
77
+ ownRunInFlight: boolean;
78
+ lastStartedRunId: string | null;
79
+ live: LiveTurnInfo | null;
80
+ }) => string | null;
81
+ /** After a terminal event for `runId`: a followed turn that just ended is no longer followed. */
82
+ export declare const liveAfterTerminal: (live: LiveTurnInfo | null, runId: string | null) => LiveTurnInfo | null;
83
+ //# sourceMappingURL=live-turn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-turn.d.ts","sourceRoot":"","sources":["../../src/utils/live-turn.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,4FAA4F;AAC5F,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAC;AAK/F,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAAI,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAAG,YAAY,GAAG,IAU1G,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM;IACxC,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;CAC1B,KAAG,OAMoC,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,MAAM;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,aAAa,EAAE,OAAO,CAAC;CACxB,KAAG,OAC+G,CAAC;AAEpH;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM;IAAE,cAAc,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,KAAG,OACM,CAAC;AAEnG,eAAO,MAAM,iBAAiB,GAAI,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,OACN,CAAC;AAEtE,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAWtD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM;IAClC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3B,KAAG,MAAM,GAAG,IAAkF,CAAC;AAEhG,+FAA+F;AAC/F,eAAO,MAAM,WAAW,GAAI,MAAM;IAChC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3B,KAAG,MAAM,GAAG,IAC2F,CAAC;AAEzG,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,GAAI,MAAM,YAAY,GAAG,IAAI,EAAE,OAAO,MAAM,GAAG,IAAI,KAAG,YAAY,GAAG,IAChB,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The chat's side of the live turn stream.
3
+ *
4
+ * With the server flag on, every `agent/connect` opens with one CUSTOM event,
5
+ * `blocks.live_turn`, and then streams the thread's active turn live in the same response.
6
+ * With the flag off the server sends none of this, so `liveEnabled` stays false and every
7
+ * decision below answers "do nothing".
8
+ */
9
+ export const LIVE_TURN_EVENT_NAME = "blocks.live_turn";
10
+ /** The RUN_ERROR code of a send refused because a turn is already running on the thread. */
11
+ export const THREAD_BUSY_ERROR_CODE = "thread_busy";
12
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
13
+ /** The payload of the connect's live-turn CUSTOM event, or null for any other event. */
14
+ export const readLiveTurnEvent = (event) => {
15
+ if (event.type !== "CUSTOM" || event.name !== LIVE_TURN_EVENT_NAME || !isRecord(event.value)) {
16
+ return null;
17
+ }
18
+ const { enabled, runId, startedBy } = event.value;
19
+ return {
20
+ enabled: enabled === true,
21
+ ...(typeof runId === "string" && runId !== "" ? { runId } : {}),
22
+ ...(startedBy === "chat" || startedBy === "server" ? { startedBy } : {}),
23
+ };
24
+ };
25
+ /**
26
+ * Whether the thread row's running run (the doorbell) calls for a connect to watch it:
27
+ * one this tab neither follows nor started, that no connect has answered for yet.
28
+ */
29
+ export const shouldConnectForRun = (args) => args.liveEnabled &&
30
+ args.runningRunId !== null &&
31
+ !args.connectInFlight &&
32
+ args.runningRunId !== args.followingRunId &&
33
+ args.runningRunId !== args.lastConnectedForRunId &&
34
+ !args.ownRunIds.has(args.runningRunId);
35
+ /**
36
+ * Whether a run or connect stream that just ended should be followed by one more connect: it
37
+ * showed a running turn (this tab's send, or one the server named) and ended with no terminal
38
+ * event for it -- the 400 s self-close, a pod restart, a dropped network. A connect for a turn
39
+ * that has finished meanwhile names none, so it is not followed again. A stream that never
40
+ * started (the server unreachable) is not retried, or an outage would loop.
41
+ */
42
+ export const shouldReconnectAfterStream = (args) => args.liveEnabled && args.streamStarted && args.streamRunId !== null && !args.sawTerminalFor.has(args.streamRunId);
43
+ /**
44
+ * Stop is for this tab's own run, or a followed turn a chat started (never workflow, reminder,
45
+ * ...), and only with the live turn stream on: only then does the server stop the turn itself.
46
+ */
47
+ export const canStop = (args) => args.following?.enabled === true && (args.ownRunInFlight || args.following.startedBy === "chat");
48
+ export const isThreadBusyError = (event) => event.type === "RUN_ERROR" && event.code === THREAD_BUSY_ERROR_CODE;
49
+ /** The `agent/stop` request: the run body's thread fields only, none of its content. */
50
+ export const buildStopEnvelope = (runBody) => ({
51
+ method: "agent/stop",
52
+ body: {
53
+ threadId: runBody.threadId,
54
+ runId: runBody.runId,
55
+ forwardedProps: isRecord(runBody.forwardedProps) ? runBody.forwardedProps : {},
56
+ messages: [],
57
+ tools: [],
58
+ context: [],
59
+ state: {},
60
+ },
61
+ });
62
+ /**
63
+ * The run a stream that just ended is judged by. A tab's own send streams under its own run
64
+ * id; a connect body carries its own id for the history replay (RUN_STARTED/RUN_FINISHED),
65
+ * followed by the live turn's events, so a followed stream is judged by the live turn's id.
66
+ */
67
+ export const streamRunIdOf = (args) => (args.ownRunInFlight ? args.lastStartedRunId : (args.live?.runId ?? null));
68
+ /** The run a stop is for: the tab's own run, else the followed turn (never a connect's id). */
69
+ export const stopRunIdOf = (args) => args.ownRunInFlight ? (args.lastStartedRunId ?? args.live?.runId ?? null) : (args.live?.runId ?? null);
70
+ /** After a terminal event for `runId`: a followed turn that just ended is no longer followed. */
71
+ export const liveAfterTerminal = (live, runId) => live && runId !== null && live.runId === runId ? { enabled: live.enabled } : live;
@@ -0,0 +1,18 @@
1
+ export interface ScheduledTrigger {
2
+ /** "reminder": one the agent set in chat. "schedule": one the app's builder created. */
3
+ kind: "reminder" | "schedule";
4
+ /** Absent on a fire from before the line existed. */
5
+ title?: string;
6
+ recurring?: boolean;
7
+ }
8
+ interface MessageLike {
9
+ id?: string;
10
+ role?: string;
11
+ metadata?: unknown;
12
+ }
13
+ /** The trigger stamped on a message, or null when it carries none. */
14
+ export declare function scheduledTriggerOf(message: MessageLike): ScheduledTrigger | null;
15
+ /** Each stamped message's trigger, by message id: a message group starting there draws the line. */
16
+ export declare function scheduledTriggersByMessageId(messages: readonly MessageLike[]): ReadonlyMap<string, ScheduledTrigger>;
17
+ export {};
18
+ //# sourceMappingURL=scheduled-trigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled-trigger.d.ts","sourceRoot":"","sources":["../../src/utils/scheduled-trigger.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,gBAAgB;IAC/B,wFAAwF;IACxF,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAKD,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,gBAAgB,GAAG,IAAI,CAgBhF;AAED,oGAAoG;AACpG,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CASpH"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The line a chat draws above a turn a fired reminder (or app schedule) started.
3
+ *
4
+ * The run's prompt is hidden, so the agent's reply would read as if the agent spoke on its own.
5
+ * Chat load stamps the fire's details on that reply, `metadata["blocks.scheduledTrigger"]` on the
6
+ * agent's first message of the turn (wf-actions-py `scheduled_trigger.py`); this reads it. Never
7
+ * parse the prompt's text: it is for the model, not data.
8
+ */
9
+ const SCHEDULED_TRIGGER_METADATA_KEY = "blocks.scheduledTrigger";
10
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
11
+ /** The trigger stamped on a message, or null when it carries none. */
12
+ export function scheduledTriggerOf(message) {
13
+ if (message.role !== "assistant" || !isRecord(message.metadata)) {
14
+ return null;
15
+ }
16
+ const stamp = message.metadata[SCHEDULED_TRIGGER_METADATA_KEY];
17
+ if (!isRecord(stamp)) {
18
+ return null;
19
+ }
20
+ const trigger = { kind: stamp.kind === "schedule" ? "schedule" : "reminder" };
21
+ if (typeof stamp.title === "string" && stamp.title) {
22
+ trigger.title = stamp.title;
23
+ }
24
+ if (typeof stamp.recurring === "boolean") {
25
+ trigger.recurring = stamp.recurring;
26
+ }
27
+ return trigger;
28
+ }
29
+ /** Each stamped message's trigger, by message id: a message group starting there draws the line. */
30
+ export function scheduledTriggersByMessageId(messages) {
31
+ const byMessageId = new Map();
32
+ for (const message of messages) {
33
+ const trigger = message.id ? scheduledTriggerOf(message) : null;
34
+ if (trigger && message.id) {
35
+ byMessageId.set(message.id, trigger);
36
+ }
37
+ }
38
+ return byMessageId;
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/react-common",
3
- "version": "1.64.0",
3
+ "version": "1.66.0",
4
4
  "type": "module",
5
5
  "description": "React common",
6
6
  "keywords": [],