@agents24/chat-react 0.5.36 → 0.5.38

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.
Files changed (42) hide show
  1. package/README.md +31 -1
  2. package/compatibility.json +5 -5
  3. package/dist/{chunk-INO5DSSJ.js → chunk-DWDHK4FZ.js} +3 -4
  4. package/dist/chunk-DWDHK4FZ.js.map +1 -0
  5. package/dist/generated/delegation-types.d.ts +3 -2
  6. package/dist/generated/run-usage.d.ts +11 -0
  7. package/dist/registry/agents24-chat.json +13 -13
  8. package/dist/runtime/index.cjs +25 -9
  9. package/dist/runtime/index.cjs.map +1 -1
  10. package/dist/runtime/index.js +24 -7
  11. package/dist/runtime/index.js.map +1 -1
  12. package/dist/runtime/input-contract.d.ts +1 -1
  13. package/dist/runtime/use-agent-chat-hitl.d.ts +2 -2
  14. package/dist/runtime/use-agent-chat-runtime.d.ts +4 -6
  15. package/dist/scaffold/app.d.ts +2 -2
  16. package/dist/scaffold/components/chat/chat-composer.d.ts +2 -1
  17. package/dist/scaffold/components/chat/chat-message.d.ts +2 -2
  18. package/dist/scaffold/components/chat/message-parts.d.ts +2 -2
  19. package/dist/scaffold/index.cjs +17 -13
  20. package/dist/scaffold/index.cjs.map +1 -1
  21. package/dist/scaffold/index.js +11 -7
  22. package/dist/scaffold/index.js.map +1 -1
  23. package/dist/styles.css +7 -0
  24. package/dist/ui/agent-chat-composer.d.ts +9 -1
  25. package/dist/ui/agent-chat-message.d.ts +6 -2
  26. package/dist/ui/agent-response-timeline.d.ts +11 -3
  27. package/dist/ui/ask-user-interaction.d.ts +5 -1
  28. package/dist/ui/hitl-submission-status.d.ts +22 -0
  29. package/dist/ui/index.cjs +540 -340
  30. package/dist/ui/index.cjs.map +1 -1
  31. package/dist/ui/index.d.ts +1 -0
  32. package/dist/ui/index.js +536 -338
  33. package/dist/ui/index.js.map +1 -1
  34. package/dist/ui/use-agent-chat-composer.d.ts +28 -3
  35. package/dist/ui/use-audio-recorder.d.ts +15 -2
  36. package/package.json +3 -3
  37. package/scaffold/src/app.tsx +2 -1
  38. package/scaffold/src/components/chat/chat-composer.tsx +5 -3
  39. package/scaffold/src/components/chat/chat-message.tsx +3 -3
  40. package/scaffold/src/components/chat/chat-shell.tsx +2 -1
  41. package/scaffold/src/components/chat/message-parts.tsx +6 -6
  42. package/dist/chunk-INO5DSSJ.js.map +0 -1
package/dist/ui/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  canonicalInputMimeType,
8
8
  inputMimeTypes,
9
9
  validateAgentChatSubmission
10
- } from "../chunk-INO5DSSJ.js";
10
+ } from "../chunk-DWDHK4FZ.js";
11
11
 
12
12
  // src/ui/agent-chat-composer.tsx
13
13
  import * as React6 from "react";
@@ -801,47 +801,69 @@ function useChatComposerFocus({ textareaRef, disabled, focusKey, restoredDraft,
801
801
 
802
802
  // src/ui/use-audio-recorder.ts
803
803
  import * as React3 from "react";
804
+ import { normalizeAttachmentMimeType as normalizeAttachmentMimeType2 } from "@agents24/client";
804
805
  var RECORDING_CANDIDATES = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4"];
805
806
  function useAudioRecorder(onRecorded, options = {}) {
806
807
  const recorderRef = React3.useRef(null);
807
808
  const streamRef = React3.useRef(null);
809
+ const operationRef = React3.useRef(null);
808
810
  const pendingRef = React3.useRef(false);
809
- const generationRef = React3.useRef(0);
810
- const onRecordedRef = React3.useRef(onRecorded);
811
- const onStreamChangeRef = React3.useRef(options.onStreamChange);
812
- React3.useEffect(() => {
813
- onRecordedRef.current = onRecorded;
814
- onStreamChangeRef.current = options.onStreamChange;
811
+ const callbacksRef = React3.useRef({ onRecorded, onStreamChange: options.onStreamChange, acceptedMimeTypes: options.acceptedMimeTypes });
812
+ React3.useLayoutEffect(() => {
813
+ callbacksRef.current = { onRecorded, onStreamChange: options.onStreamChange, acceptedMimeTypes: options.acceptedMimeTypes };
815
814
  });
816
815
  const [isRecording, setIsRecording] = React3.useState(false);
816
+ const [isStarting, setIsStarting] = React3.useState(false);
817
+ const [isProcessing, setIsProcessing] = React3.useState(false);
817
818
  const [error, setError] = React3.useState(null);
818
819
  const release = React3.useCallback(() => {
819
820
  streamRef.current?.getTracks().forEach((track) => track.stop());
820
821
  streamRef.current = null;
821
822
  recorderRef.current = null;
822
- onStreamChangeRef.current?.(null);
823
+ callbacksRef.current.onStreamChange?.(null);
823
824
  }, []);
825
+ const discard = React3.useCallback(() => {
826
+ operationRef.current?.controller.abort();
827
+ operationRef.current = null;
828
+ pendingRef.current = false;
829
+ const recorder = recorderRef.current;
830
+ if (recorder) {
831
+ recorder.onstop = null;
832
+ recorder.onerror = null;
833
+ recorder.ondataavailable = null;
834
+ if (recorder.state !== "inactive") recorder.stop();
835
+ }
836
+ release();
837
+ }, [release]);
838
+ const cancel = React3.useCallback(() => {
839
+ discard();
840
+ setIsStarting(false);
841
+ setIsRecording(false);
842
+ setIsProcessing(false);
843
+ setError(null);
844
+ }, [discard]);
824
845
  const stop = React3.useCallback(() => {
825
846
  const recorder = recorderRef.current;
826
847
  if (recorder && recorder.state !== "inactive") recorder.stop();
827
848
  }, []);
828
- const start = React3.useCallback(async () => {
829
- if (pendingRef.current || recorderRef.current) return;
849
+ const isCapturing = React3.useCallback(() => pendingRef.current || recorderRef.current !== null, []);
850
+ const start = React3.useCallback(async (startOptions = {}) => {
851
+ if (operationRef.current) return;
830
852
  setError(null);
831
853
  if (!navigator.mediaDevices?.getUserMedia || typeof MediaRecorder === "undefined") {
832
854
  setError("Audio recording is not supported in this browser.");
833
855
  return;
834
856
  }
857
+ const controller = new AbortController();
858
+ const operation = { operationId: startOptions.operationId ?? crypto.randomUUID(), signal: controller.signal, controller };
859
+ operationRef.current = operation;
835
860
  pendingRef.current = true;
836
- const generation = generationRef.current;
861
+ setIsStarting(true);
837
862
  try {
838
- const mimeType = RECORDING_CANDIDATES.find((candidate) => MediaRecorder.isTypeSupported(candidate));
839
- if (!mimeType) {
840
- setError("Audio recording is not supported in this browser.");
841
- return;
842
- }
863
+ const mimeType = RECORDING_CANDIDATES.find((candidate) => MediaRecorder.isTypeSupported(candidate) && (callbacksRef.current.acceptedMimeTypes === void 0 || callbacksRef.current.acceptedMimeTypes.includes(normalizeAttachmentMimeType2(candidate))));
864
+ if (!mimeType) throw new Error("unsupported");
843
865
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
844
- if (generation !== generationRef.current) {
866
+ if (operation.signal.aborted) {
845
867
  stream.getTracks().forEach((track) => track.stop());
846
868
  return;
847
869
  }
@@ -853,48 +875,54 @@ function useAudioRecorder(onRecorded, options = {}) {
853
875
  if (event.data.size) chunks.push(event.data);
854
876
  };
855
877
  recorder.onstop = () => {
856
- if (generation !== generationRef.current) return;
878
+ if (operation.signal.aborted) return;
857
879
  const actualType = recorder.mimeType || mimeType;
858
- const extension = actualType.startsWith("audio/mp4") ? "m4a" : "webm";
859
- try {
860
- onRecordedRef.current(new File([new Blob(chunks, { type: actualType })], `recording-${Date.now()}.${extension}`, { type: actualType }));
861
- } finally {
862
- release();
863
- setIsRecording(false);
880
+ const accepted = callbacksRef.current.acceptedMimeTypes;
881
+ if (accepted !== void 0 && !accepted.includes(normalizeAttachmentMimeType2(actualType))) {
882
+ cancel();
883
+ setError("This Agent does not accept the recorded audio format.");
884
+ return;
864
885
  }
865
- };
866
- recorder.onerror = () => {
867
- recorder.onstop = null;
868
- if (recorder.state !== "inactive") recorder.stop();
886
+ const extension = actualType.startsWith("audio/mp4") ? "m4a" : "webm";
887
+ const file = new File(chunks, `recording-${Date.now()}.${extension}`, { type: actualType });
869
888
  release();
870
889
  setIsRecording(false);
890
+ setIsProcessing(true);
891
+ void Promise.resolve().then(() => {
892
+ if (!operation.signal.aborted) return callbacksRef.current.onRecorded(file, operation);
893
+ }).catch(() => {
894
+ if (!operation.signal.aborted) setError("Recording processing failed.");
895
+ }).finally(() => {
896
+ if (operationRef.current === operation) {
897
+ operationRef.current = null;
898
+ setIsProcessing(false);
899
+ }
900
+ });
901
+ };
902
+ recorder.onerror = () => {
903
+ cancel();
871
904
  setError("Audio recording failed. Try again.");
872
905
  };
873
906
  recorder.start();
874
907
  setIsRecording(true);
875
- onStreamChangeRef.current?.(stream);
908
+ callbacksRef.current.onStreamChange?.(stream);
876
909
  } catch {
877
- if (generation === generationRef.current) {
878
- release();
879
- setIsRecording(false);
880
- setError("Microphone access is unavailable.");
910
+ if (!operation.signal.aborted) {
911
+ cancel();
912
+ setError("Microphone access or audio recording is unavailable.");
881
913
  }
882
914
  } finally {
883
- if (generation === generationRef.current) pendingRef.current = false;
884
- }
885
- }, [release]);
886
- React3.useEffect(() => () => {
887
- generationRef.current += 1;
888
- pendingRef.current = false;
889
- const recorder = recorderRef.current;
890
- if (recorder) {
891
- recorder.onstop = null;
892
- recorder.onerror = null;
893
- if (recorder.state !== "inactive") recorder.stop();
915
+ if (!operation.signal.aborted) {
916
+ pendingRef.current = false;
917
+ setIsStarting(false);
918
+ }
894
919
  }
895
- release();
896
- }, [release]);
897
- return { error, isRecording, start, stop };
920
+ }, [cancel, discard, release]);
921
+ React3.useLayoutEffect(() => {
922
+ cancel();
923
+ return discard;
924
+ }, [options.scopeKey, cancel, discard]);
925
+ return { error, isRecording, isStarting, isProcessing, isCapturing, start, stop, cancel };
898
926
  }
899
927
 
900
928
  // src/ui/use-agent-chat-composer.ts
@@ -906,16 +934,47 @@ function useAgentChatComposer(options) {
906
934
  const localTextareaRef = React4.useRef(null);
907
935
  const textareaRef = options.textareaRef ?? localTextareaRef;
908
936
  const filesRef = React4.useRef(files);
909
- const inFlightFilesRef = React4.useRef([]);
937
+ const inFlightFilesRef = React4.useRef(/* @__PURE__ */ new Map());
910
938
  const revisionRef = React4.useRef(0);
911
939
  const submittingRef = React4.useRef(false);
912
- React4.useEffect(() => {
913
- filesRef.current = files;
914
- }, [files]);
940
+ const generationRef = React4.useRef(0);
941
+ const mountedRef = React4.useRef(true);
942
+ const textRef = React4.useRef(text);
943
+ const scope = React4.useMemo(() => ({ active: false }), [options.scopeKey]);
944
+ const [textInteraction, setTextInteraction] = React4.useState(null);
945
+ const handledTextInteractionRef = React4.useRef(textInteraction);
946
+ React4.useLayoutEffect(() => {
947
+ scope.active = true;
948
+ mountedRef.current = true;
949
+ submittingRef.current = false;
950
+ setIsSubmitting(false);
951
+ return () => {
952
+ scope.active = false;
953
+ mountedRef.current = false;
954
+ generationRef.current += 1;
955
+ };
956
+ }, [scope]);
957
+ React4.useLayoutEffect(() => {
958
+ if (handledTextInteractionRef.current === textInteraction) return;
959
+ handledTextInteractionRef.current = textInteraction;
960
+ if (!textInteraction || textInteraction.scope !== scope || !scope.active || textInteraction.revision !== revisionRef.current || options.disabled) return;
961
+ const textarea = textareaRef.current;
962
+ if (!textarea) return;
963
+ if (textInteraction.options.focus) textarea.focus({ preventScroll: true });
964
+ const selection = textInteraction.options.selection;
965
+ if (selection) {
966
+ const clamp = (offset) => Math.max(0, Math.min(textRef.current.length, offset));
967
+ textarea.setSelectionRange(clamp(selection.start), clamp(selection.end), selection.direction);
968
+ }
969
+ }, [textInteraction, scope, textareaRef, options.disabled]);
915
970
  React4.useEffect(() => () => {
916
971
  revokeAgentChatComposerFiles(filesRef.current);
917
- revokeAgentChatComposerFiles(inFlightFilesRef.current);
972
+ revokeAgentChatComposerFiles([...inFlightFilesRef.current.values()].flat());
918
973
  }, []);
974
+ const revokeUnownedFiles = (candidates) => {
975
+ const retained = new Set([...filesRef.current, ...[...inFlightFilesRef.current.values()].flat()].map((file) => file.url));
976
+ revokeAgentChatComposerFiles(candidates.filter((file) => !retained.has(file.url)));
977
+ };
919
978
  const focusComposer = useChatComposerFocus({
920
979
  textareaRef,
921
980
  disabled: Boolean(options.disabled),
@@ -923,60 +982,94 @@ function useAgentChatComposer(options) {
923
982
  restoredDraft: options.restoredDraft,
924
983
  onRestore: (draft) => {
925
984
  revisionRef.current += 1;
926
- revokeAgentChatComposerFiles(filesRef.current);
985
+ const previousFiles = filesRef.current;
986
+ textRef.current = draft.text;
987
+ filesRef.current = draft.files;
988
+ revokeUnownedFiles(previousFiles);
927
989
  setTextState(draft.text);
928
990
  setFiles(draft.files);
929
991
  }
930
992
  });
931
993
  const attachmentMimeTypes = inputMimeTypes(options.inputContract);
932
- const setText = (value) => {
933
- revisionRef.current += 1;
994
+ const setText = React4.useCallback((value, interaction = {}) => {
995
+ if (!scope.active) return false;
996
+ const revision = ++revisionRef.current;
997
+ textRef.current = value;
934
998
  setTextState(value);
935
- };
999
+ setTextInteraction({ scope, revision, options: interaction });
1000
+ return true;
1001
+ }, [scope]);
936
1002
  const addFiles = (selected) => {
937
1003
  const accepted = selected.filter((file) => attachmentMimeTypes.includes(canonicalInputMimeType(file.type, file.name)));
938
1004
  revisionRef.current += 1;
939
- const additions = accepted.map(createAgentChatComposerFile);
940
- setFiles((current) => [...current, ...additions]);
1005
+ const additions = selected.map(createAgentChatComposerFile);
1006
+ filesRef.current = [...filesRef.current, ...additions];
1007
+ setFiles(filesRef.current);
941
1008
  setAttachmentError(accepted.length === selected.length ? null : "One or more selected file types are not supported by this Agent.");
942
1009
  };
943
1010
  const removeFile = (id) => {
944
1011
  revisionRef.current += 1;
945
1012
  const removed = filesRef.current.find((file) => file.id === id);
946
- if (removed) revokeAgentChatComposerFiles([removed]);
947
- setFiles((current) => current.filter((file) => file.id !== id));
1013
+ filesRef.current = filesRef.current.filter((file) => file.id !== id);
1014
+ if (removed) revokeUnownedFiles([removed]);
1015
+ setFiles(filesRef.current);
948
1016
  };
949
- const recorder = useAudioRecorder((file) => addFiles([file]), { onStreamChange: options.onRecordingStreamChange });
1017
+ const recorder = useAudioRecorder(
1018
+ (file, context) => options.onRecordingComplete ? options.onRecordingComplete(file, context) : addFiles([file]),
1019
+ {
1020
+ onStreamChange: options.onRecordingStreamChange,
1021
+ scopeKey: options.scopeKey,
1022
+ acceptedMimeTypes: options.onRecordingComplete ? void 0 : options.inputContract?.modalities.audio.allowed_mime_types ?? []
1023
+ }
1024
+ );
950
1025
  const validationError = options.inputContract ? validateAgentChatSubmission(
951
1026
  options.inputContract,
952
1027
  text,
953
1028
  files.map((file) => ({ data: file.source || new Uint8Array(), mediaType: file.mediaType, name: file.filename, byteSize: file.byteSize }))
954
1029
  ) : null;
955
- const canSubmit = Boolean(text.trim() || files.length) && !options.disabled && !options.isCancelling && !isSubmitting && !recorder.isRecording && !validationError;
956
- const submit = async () => {
957
- if (!canSubmit || submittingRef.current) return;
958
- const value = text;
959
- const selectedFiles = files;
1030
+ const canSubmit = Boolean(text.trim() || files.length) && !options.disabled && !options.isCancelling && !isSubmitting && !recorder.isRecording && !recorder.isStarting && !recorder.isProcessing && !validationError;
1031
+ const submit = async (submission) => {
1032
+ const value = submission?.text ?? textRef.current;
1033
+ const selectedFiles = submission?.files ?? filesRef.current;
1034
+ const suppliedError = options.inputContract ? validateAgentChatSubmission(
1035
+ options.inputContract,
1036
+ value,
1037
+ selectedFiles.map((file) => ({ data: file.source || new Uint8Array(), mediaType: file.mediaType, name: file.filename, byteSize: file.byteSize }))
1038
+ ) : null;
1039
+ if (!mountedRef.current || !value.trim() && !selectedFiles.length || options.disabled || options.isCancelling || submittingRef.current || recorder.isCapturing() || !submission && recorder.isProcessing || suppliedError) return false;
1040
+ const generation = generationRef.current;
960
1041
  const clearedRevision = ++revisionRef.current;
961
1042
  submittingRef.current = true;
962
1043
  setIsSubmitting(true);
963
- inFlightFilesRef.current = selectedFiles;
1044
+ const selectedUrls = new Set(selectedFiles.map((file) => file.url));
1045
+ const replacedFiles = filesRef.current.filter((file) => !selectedUrls.has(file.url));
1046
+ const submissionId = /* @__PURE__ */ Symbol();
1047
+ inFlightFilesRef.current.set(submissionId, selectedFiles);
1048
+ textRef.current = "";
1049
+ filesRef.current = [];
1050
+ revokeUnownedFiles(replacedFiles);
964
1051
  setTextState("");
965
1052
  setFiles([]);
966
1053
  focusComposer();
967
1054
  try {
968
1055
  await options.onSubmit(value, selectedFiles);
969
- revokeAgentChatComposerFiles(selectedFiles);
1056
+ return true;
970
1057
  } catch {
971
- if (revisionRef.current === clearedRevision) {
1058
+ if (mountedRef.current && generationRef.current === generation && revisionRef.current === clearedRevision) {
972
1059
  revisionRef.current += 1;
1060
+ textRef.current = value;
1061
+ filesRef.current = selectedFiles;
973
1062
  setTextState(value);
974
1063
  setFiles(selectedFiles);
975
- } else revokeAgentChatComposerFiles(selectedFiles);
1064
+ }
1065
+ return false;
976
1066
  } finally {
977
- inFlightFilesRef.current = [];
978
- submittingRef.current = false;
979
- setIsSubmitting(false);
1067
+ inFlightFilesRef.current.delete(submissionId);
1068
+ revokeUnownedFiles(selectedFiles);
1069
+ if (mountedRef.current && generationRef.current === generation) {
1070
+ submittingRef.current = false;
1071
+ setIsSubmitting(false);
1072
+ }
980
1073
  }
981
1074
  };
982
1075
  return {
@@ -993,6 +1086,7 @@ function useAgentChatComposer(options) {
993
1086
  attachmentMimeTypes,
994
1087
  validationError,
995
1088
  recorder,
1089
+ isProcessing: recorder.isProcessing,
996
1090
  recordingAllowed: options.recordingEnabled ?? options.inputContract?.modalities.audio.recording_enabled ?? false,
997
1091
  fileAccept: attachmentFileAccept(attachmentMimeTypes),
998
1092
  onKeyDown: (event) => {
@@ -1117,6 +1211,7 @@ function formatFileCount(files) {
1117
1211
  var pillButtonClass = "inline-flex size-8 shrink-0 items-center justify-center gap-2 rounded-lg border-0 bg-muted text-sm text-muted-foreground shadow-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50";
1118
1212
  var submitButtonClass = "inline-flex size-9 shrink-0 items-center justify-center gap-2 rounded-lg border-0 bg-primary text-sm text-primary-foreground shadow-none transition-[background-color,color,opacity,transform] duration-200 hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50";
1119
1213
  function AgentChatComposer({
1214
+ ref,
1120
1215
  inputContract,
1121
1216
  recordingEnabled,
1122
1217
  contextWindow,
@@ -1126,6 +1221,7 @@ function AgentChatComposer({
1126
1221
  disabled = false,
1127
1222
  forceExpanded = false,
1128
1223
  focusKey,
1224
+ scopeKey,
1129
1225
  inputToolbarContent,
1130
1226
  isRunning = false,
1131
1227
  isCancelling = false,
@@ -1144,12 +1240,14 @@ function AgentChatComposer({
1144
1240
  disabled,
1145
1241
  isRunning,
1146
1242
  isCancelling,
1243
+ scopeKey,
1147
1244
  focusKey,
1148
1245
  restoredDraft,
1149
1246
  textareaRef: localTextareaRef,
1150
1247
  onSubmit: (text2, files2) => onSubmit({ text: text2.trim(), files: files2, attachmentIds: files2.flatMap((file) => file.id ? [file.id] : []) })
1151
1248
  });
1152
1249
  const { text, files, setText, isSubmitting, canSubmit, action, submit } = composer;
1250
+ React6.useImperativeHandle(ref, () => ({ setText }), [setText]);
1153
1251
  const isExpanded = forceExpanded || text.includes("\n") || text.length > 62;
1154
1252
  const setTextareaRef = React6.useCallback(
1155
1253
  (node) => {
@@ -1625,14 +1723,71 @@ function AgentChatDefaultActions({
1625
1723
  }
1626
1724
 
1627
1725
  // src/ui/agent-chat-message.tsx
1628
- import * as React16 from "react";
1726
+ import * as React17 from "react";
1629
1727
  import { ChevronDown as ChevronDown3, ChevronUp } from "lucide-react";
1630
1728
 
1729
+ // src/ui/hitl-submission-status.tsx
1730
+ import * as React9 from "react";
1731
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1732
+ var defaultHitlSubmissionLabels = {
1733
+ submitting: "Submitting\u2026",
1734
+ checking: "Checking submission\u2026",
1735
+ uncertain: "Submission could not be confirmed.",
1736
+ retry: "Retry submission",
1737
+ accepted: "Accepted; agent continuing",
1738
+ approved: "Approved; agent continuing",
1739
+ rejected: "Rejected"
1740
+ };
1741
+ function isHitlSubmissionCompact(state) {
1742
+ return ["submitting", "resuming", "checking", "uncertain", "accepted"].includes(state?.status || "");
1743
+ }
1744
+ function HitlSubmissionStatus({ state, labels: overrides, onPaint }) {
1745
+ const labels = { ...defaultHitlSubmissionLabels, ...overrides };
1746
+ const started = React9.useRef(performance.now());
1747
+ const ref = React9.useRef(null);
1748
+ const paintCallback = React9.useRef(onPaint);
1749
+ paintCallback.current = onPaint;
1750
+ React9.useEffect(() => {
1751
+ const frame = requestAnimationFrame(() => paintCallback.current?.(performance.now() - started.current));
1752
+ return () => cancelAnimationFrame(frame);
1753
+ }, []);
1754
+ React9.useEffect(() => {
1755
+ ref.current?.focus({ preventScroll: true });
1756
+ }, []);
1757
+ const text = state.status === "checking" ? labels.checking : state.status === "uncertain" ? labels.uncertain : state.status === "accepted" ? state.action === "approve" ? labels.approved : state.action === "reject" ? labels.rejected : labels.accepted : labels.submitting;
1758
+ return /* @__PURE__ */ jsxs5(
1759
+ "div",
1760
+ {
1761
+ ref,
1762
+ tabIndex: -1,
1763
+ role: "status",
1764
+ "aria-live": "polite",
1765
+ "aria-atomic": "true",
1766
+ "data-hitl-submission": state.status,
1767
+ className: "a24-hitl-submission flex items-center gap-2 py-1 text-start text-sm text-muted-foreground outline-none",
1768
+ children: [
1769
+ /* @__PURE__ */ jsx7("span", { children: text }),
1770
+ state.status === "uncertain" && state.retry && /* @__PURE__ */ jsx7(
1771
+ "button",
1772
+ {
1773
+ type: "button",
1774
+ className: "rounded px-2 py-1 text-foreground underline underline-offset-2",
1775
+ onClick: () => {
1776
+ void state.retry?.().catch(() => void 0);
1777
+ },
1778
+ children: labels.retry
1779
+ }
1780
+ )
1781
+ ]
1782
+ }
1783
+ );
1784
+ }
1785
+
1631
1786
  // src/ui/agent-response-timeline.tsx
1632
- import * as React15 from "react";
1787
+ import * as React16 from "react";
1633
1788
 
1634
1789
  // src/ui/ask-user-interaction.tsx
1635
- import * as React9 from "react";
1790
+ import * as React10 from "react";
1636
1791
  import {
1637
1792
  ChevronDown,
1638
1793
  ChevronLeft,
@@ -1694,7 +1849,7 @@ function askUserAnswersFromDrafts(questions, drafts) {
1694
1849
  }
1695
1850
 
1696
1851
  // src/ui/ask-user-interaction.tsx
1697
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1852
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1698
1853
  function resolvedAnswerText(question, answer) {
1699
1854
  if (!answer) return ["No response recorded"];
1700
1855
  const labels = answer.selectedOptionIds.flatMap((optionId) => {
@@ -1708,7 +1863,7 @@ function ResolvedQuestions({
1708
1863
  buttonRef,
1709
1864
  part
1710
1865
  }) {
1711
- const [open, setOpen] = React9.useState(false);
1866
+ const [open, setOpen] = React10.useState(false);
1712
1867
  const count = part.questions.length;
1713
1868
  const answers = new Map(
1714
1869
  (part.resolution?.answers || []).map((answer) => [
@@ -1716,8 +1871,8 @@ function ResolvedQuestions({
1716
1871
  answer
1717
1872
  ])
1718
1873
  );
1719
- return /* @__PURE__ */ jsxs5("div", { className: "a24-ask-user a24-ask-user--resolved w-full", children: [
1720
- /* @__PURE__ */ jsxs5(
1874
+ return /* @__PURE__ */ jsxs6("div", { className: "a24-ask-user a24-ask-user--resolved w-full", children: [
1875
+ /* @__PURE__ */ jsxs6(
1721
1876
  "button",
1722
1877
  {
1723
1878
  "aria-expanded": open,
@@ -1726,13 +1881,13 @@ function ResolvedQuestions({
1726
1881
  ref: buttonRef,
1727
1882
  type: "button",
1728
1883
  children: [
1729
- /* @__PURE__ */ jsxs5("span", { children: [
1884
+ /* @__PURE__ */ jsxs6("span", { children: [
1730
1885
  "Asked ",
1731
1886
  count,
1732
1887
  " question",
1733
1888
  count === 1 ? "" : "s"
1734
1889
  ] }),
1735
- open ? /* @__PURE__ */ jsx7(ChevronDown, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ jsx7(
1890
+ open ? /* @__PURE__ */ jsx8(ChevronDown, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ jsx8(
1736
1891
  ChevronRight,
1737
1892
  {
1738
1893
  "aria-hidden": "true",
@@ -1742,12 +1897,12 @@ function ResolvedQuestions({
1742
1897
  ]
1743
1898
  }
1744
1899
  ),
1745
- open ? /* @__PURE__ */ jsx7("div", { className: "mt-2 space-y-3 ps-4", children: part.questions.map((question) => /* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
1746
- /* @__PURE__ */ jsx7("div", { className: "text-sm font-medium text-foreground", children: question.question }),
1747
- /* @__PURE__ */ jsx7("div", { className: "mt-1 space-y-1 text-sm text-muted-foreground", children: resolvedAnswerText(
1900
+ open ? /* @__PURE__ */ jsx8("div", { className: "mt-2 space-y-3 ps-4", children: part.questions.map((question) => /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1901
+ /* @__PURE__ */ jsx8("div", { className: "text-sm font-medium text-foreground", children: question.question }),
1902
+ /* @__PURE__ */ jsx8("div", { className: "mt-1 space-y-1 text-sm text-muted-foreground", children: resolvedAnswerText(
1748
1903
  question,
1749
1904
  answers.get(question.id)
1750
- ).map((value, index) => /* @__PURE__ */ jsx7(
1905
+ ).map((value, index) => /* @__PURE__ */ jsx8(
1751
1906
  "div",
1752
1907
  {
1753
1908
  className: "whitespace-pre-wrap break-words",
@@ -1760,40 +1915,50 @@ function ResolvedQuestions({
1760
1915
  }
1761
1916
  function AskUserInteraction({
1762
1917
  error,
1918
+ submission,
1919
+ submissionLabels,
1920
+ onSubmissionPaint,
1763
1921
  isBusy = false,
1764
1922
  onSubmit,
1765
1923
  part
1766
1924
  }) {
1767
1925
  const questions = part.questions;
1768
- const [step, setStep] = React9.useState(0);
1769
- const [drafts, setDrafts] = React9.useState(
1926
+ const [step, setStep] = React10.useState(0);
1927
+ const [drafts, setDrafts] = React10.useState(
1770
1928
  () => emptyAskUserDrafts(questions)
1771
1929
  );
1772
- const headingRef = React9.useRef(null);
1773
- const questionsRef = React9.useRef(questions);
1774
- const resolvedButtonRef = React9.useRef(null);
1775
- const wasResolvedRef = React9.useRef(part.status !== "pending");
1930
+ const otherRef = React10.useRef(null);
1931
+ const headingRef = React10.useRef(null);
1932
+ const questionsRef = React10.useRef(questions);
1933
+ const resolvedButtonRef = React10.useRef(null);
1934
+ const wasResolvedRef = React10.useRef(part.status !== "pending");
1776
1935
  questionsRef.current = questions;
1777
- React9.useEffect(() => {
1936
+ React10.useEffect(() => {
1778
1937
  setStep(0);
1779
1938
  setDrafts(emptyAskUserDrafts(questionsRef.current));
1780
1939
  }, [part.interruptId]);
1781
- React9.useEffect(() => {
1940
+ React10.useEffect(() => {
1782
1941
  headingRef.current?.focus();
1783
1942
  }, [step]);
1784
- React9.useEffect(() => {
1943
+ React10.useEffect(() => {
1785
1944
  const isResolved = part.status !== "pending";
1786
1945
  if (isResolved && !wasResolvedRef.current) {
1787
1946
  resolvedButtonRef.current?.focus();
1788
1947
  }
1789
1948
  wasResolvedRef.current = isResolved;
1790
1949
  }, [part.status]);
1950
+ React10.useEffect(() => {
1951
+ if (submission?.status === "error") (otherRef.current?.value ? otherRef.current : headingRef.current)?.focus();
1952
+ }, [submission?.status]);
1953
+ if (part.status === "pending" && isHitlSubmissionCompact(submission)) {
1954
+ return /* @__PURE__ */ jsx8(HitlSubmissionStatus, { state: submission, labels: submissionLabels, onPaint: onSubmissionPaint });
1955
+ }
1791
1956
  if (part.status !== "pending") {
1792
- return /* @__PURE__ */ jsx7(ResolvedQuestions, { buttonRef: resolvedButtonRef, part });
1957
+ return /* @__PURE__ */ jsx8(ResolvedQuestions, { buttonRef: resolvedButtonRef, part });
1793
1958
  }
1794
1959
  const question = questions[step];
1795
1960
  if (!question) {
1796
- return /* @__PURE__ */ jsx7("div", { className: "text-sm text-destructive", role: "alert", children: "This question request is unavailable." });
1961
+ return /* @__PURE__ */ jsx8("div", { className: "text-sm text-destructive", role: "alert", children: "This question request is unavailable." });
1797
1962
  }
1798
1963
  const draft = drafts[question.id] || {
1799
1964
  customText: "",
@@ -1827,9 +1992,9 @@ function AskUserInteraction({
1827
1992
  })
1828
1993
  );
1829
1994
  };
1830
- return /* @__PURE__ */ jsxs5("div", { className: "a24-ask-user space-y-3 rounded-xl border border-border/50 bg-background p-4 shadow-sm", children: [
1831
- /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-start justify-between gap-4", children: [
1832
- /* @__PURE__ */ jsx7(
1995
+ return /* @__PURE__ */ jsxs6("div", { className: "a24-ask-user space-y-3 rounded-xl border border-border/50 bg-background p-4 shadow-sm", children: [
1996
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-start justify-between gap-4", children: [
1997
+ /* @__PURE__ */ jsx8(
1833
1998
  "h3",
1834
1999
  {
1835
2000
  className: "min-w-0 flex-1 text-base font-medium leading-6 text-foreground outline-none",
@@ -1838,8 +2003,8 @@ function AskUserInteraction({
1838
2003
  children: question.question
1839
2004
  }
1840
2005
  ),
1841
- /* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-1 text-muted-foreground", children: [
1842
- /* @__PURE__ */ jsx7(
2006
+ /* @__PURE__ */ jsxs6("div", { className: "flex shrink-0 items-center gap-1 text-muted-foreground", children: [
2007
+ /* @__PURE__ */ jsx8(
1843
2008
  "button",
1844
2009
  {
1845
2010
  "aria-label": "Previous question",
@@ -1847,7 +2012,7 @@ function AskUserInteraction({
1847
2012
  disabled: isBusy || step === 0,
1848
2013
  onClick: () => setStep((current) => Math.max(0, current - 1)),
1849
2014
  type: "button",
1850
- children: /* @__PURE__ */ jsx7(
2015
+ children: /* @__PURE__ */ jsx8(
1851
2016
  ChevronLeft,
1852
2017
  {
1853
2018
  "aria-hidden": "true",
@@ -1856,7 +2021,7 @@ function AskUserInteraction({
1856
2021
  )
1857
2022
  }
1858
2023
  ),
1859
- /* @__PURE__ */ jsxs5(
2024
+ /* @__PURE__ */ jsxs6(
1860
2025
  "span",
1861
2026
  {
1862
2027
  "aria-label": `Question ${step + 1} of ${questions.length}`,
@@ -1868,7 +2033,7 @@ function AskUserInteraction({
1868
2033
  ]
1869
2034
  }
1870
2035
  ),
1871
- /* @__PURE__ */ jsx7(
2036
+ /* @__PURE__ */ jsx8(
1872
2037
  "button",
1873
2038
  {
1874
2039
  "aria-label": isLastQuestion ? "Submit answers" : "Next question",
@@ -1876,7 +2041,7 @@ function AskUserInteraction({
1876
2041
  disabled: isBusy || !onSubmit || !canMoveForward,
1877
2042
  onClick: () => completeStep(drafts),
1878
2043
  type: "button",
1879
- children: /* @__PURE__ */ jsx7(
2044
+ children: /* @__PURE__ */ jsx8(
1880
2045
  ChevronRight,
1881
2046
  {
1882
2047
  "aria-hidden": "true",
@@ -1887,10 +2052,10 @@ function AskUserInteraction({
1887
2052
  )
1888
2053
  ] })
1889
2054
  ] }),
1890
- /* @__PURE__ */ jsxs5("div", { className: "space-y-1", children: [
2055
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
1891
2056
  question.options.map((option, index) => {
1892
2057
  const selected = draft.selectedOptionIds.includes(option.id);
1893
- return /* @__PURE__ */ jsxs5(
2058
+ return /* @__PURE__ */ jsxs6(
1894
2059
  "button",
1895
2060
  {
1896
2061
  "aria-pressed": selected,
@@ -1902,7 +2067,7 @@ function AskUserInteraction({
1902
2067
  onClick: () => selectOption(option.id),
1903
2068
  type: "button",
1904
2069
  children: [
1905
- /* @__PURE__ */ jsx7(
2070
+ /* @__PURE__ */ jsx8(
1906
2071
  "span",
1907
2072
  {
1908
2073
  className: cn(
@@ -1912,8 +2077,8 @@ function AskUserInteraction({
1912
2077
  children: index + 1
1913
2078
  }
1914
2079
  ),
1915
- /* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1 font-medium text-foreground", children: option.label }),
1916
- /* @__PURE__ */ jsx7(
2080
+ /* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 font-medium text-foreground", children: option.label }),
2081
+ /* @__PURE__ */ jsx8(
1917
2082
  ChevronRight,
1918
2083
  {
1919
2084
  "aria-hidden": "true",
@@ -1925,11 +2090,12 @@ function AskUserInteraction({
1925
2090
  option.id
1926
2091
  );
1927
2092
  }),
1928
- /* @__PURE__ */ jsxs5("div", { className: "flex min-h-11 items-center gap-2 rounded-xl bg-muted px-2.5 py-1.5 focus-within:ring-1 focus-within:ring-ring", children: [
1929
- /* @__PURE__ */ jsx7("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-full border border-border/70 bg-background/70 text-muted-foreground", children: /* @__PURE__ */ jsx7(Pencil, { "aria-hidden": "true", className: "size-4" }) }),
1930
- /* @__PURE__ */ jsx7(
2093
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-h-11 items-center gap-2 rounded-xl bg-muted px-2.5 py-1.5 focus-within:ring-1 focus-within:ring-ring", children: [
2094
+ /* @__PURE__ */ jsx8("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-full border border-border/70 bg-background/70 text-muted-foreground", children: /* @__PURE__ */ jsx8(Pencil, { "aria-hidden": "true", className: "size-4" }) }),
2095
+ /* @__PURE__ */ jsx8(
1931
2096
  "input",
1932
2097
  {
2098
+ ref: otherRef,
1933
2099
  "aria-label": "Other response",
1934
2100
  autoComplete: "off",
1935
2101
  className: "h-8 min-w-0 flex-1 bg-transparent px-1 text-sm text-foreground outline-none placeholder:text-muted-foreground",
@@ -1946,7 +2112,7 @@ function AskUserInteraction({
1946
2112
  value: draft.customText
1947
2113
  }
1948
2114
  ),
1949
- draft.customText.trim() ? /* @__PURE__ */ jsx7(
2115
+ draft.customText.trim() ? /* @__PURE__ */ jsx8(
1950
2116
  "button",
1951
2117
  {
1952
2118
  className: "h-8 shrink-0 rounded-full bg-foreground px-4 text-sm font-medium text-background transition-colors hover:opacity-85 disabled:opacity-50",
@@ -1958,12 +2124,12 @@ function AskUserInteraction({
1958
2124
  ) : null
1959
2125
  ] })
1960
2126
  ] }),
1961
- error ? /* @__PURE__ */ jsx7("div", { className: "text-sm text-destructive", role: "alert", children: error }) : null
2127
+ error ? /* @__PURE__ */ jsx8("div", { className: "text-sm text-destructive", role: "alert", children: error }) : null
1962
2128
  ] });
1963
2129
  }
1964
2130
 
1965
2131
  // src/ui/agent-chat-context-compression-row.tsx
1966
- import { jsx as jsx8 } from "react/jsx-runtime";
2132
+ import { jsx as jsx9 } from "react/jsx-runtime";
1967
2133
  function compressionPresentation(part) {
1968
2134
  if (part.status === "failed") {
1969
2135
  return { label: "Could not compact message history", status: "failed" };
@@ -1978,7 +2144,7 @@ function AgentChatContextCompressionRow({
1978
2144
  part
1979
2145
  }) {
1980
2146
  const presentation = compressionPresentation(part);
1981
- return /* @__PURE__ */ jsx8(
2147
+ return /* @__PURE__ */ jsx9(
1982
2148
  "div",
1983
2149
  {
1984
2150
  "aria-live": "polite",
@@ -1986,11 +2152,11 @@ function AgentChatContextCompressionRow({
1986
2152
  "data-agents24-context-compression": "",
1987
2153
  "data-status": part.status,
1988
2154
  role: "status",
1989
- children: /* @__PURE__ */ jsx8("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ jsx8("div", { className: cn(
2155
+ children: /* @__PURE__ */ jsx9("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ jsx9("div", { className: cn(
1990
2156
  "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--without-orb",
1991
2157
  presentation.status === "failed" && "a24-tool-trigger--error",
1992
2158
  presentation.status === "running" && "a24-tool-trigger--active"
1993
- ), children: /* @__PURE__ */ jsx8("span", { className: cn(
2159
+ ), children: /* @__PURE__ */ jsx9("span", { className: cn(
1994
2160
  "a24-tool-trigger__label",
1995
2161
  presentation.status === "running" && "a24-tool-shimmer"
1996
2162
  ), children: presentation.label }) }) })
@@ -1999,7 +2165,7 @@ function AgentChatContextCompressionRow({
1999
2165
  }
2000
2166
 
2001
2167
  // src/ui/message-response.tsx
2002
- import * as React13 from "react";
2168
+ import * as React14 from "react";
2003
2169
  import { defaultRehypePlugins, Streamdown } from "streamdown";
2004
2170
 
2005
2171
  // src/active-content.ts
@@ -2024,14 +2190,14 @@ function safeChatMarkdownHref(value) {
2024
2190
  }
2025
2191
 
2026
2192
  // src/ui/message-code.tsx
2027
- import * as React12 from "react";
2193
+ import * as React13 from "react";
2028
2194
  import { FileCode2Icon } from "lucide-react";
2029
2195
 
2030
2196
  // src/ui/code-block.tsx
2031
- import * as React10 from "react";
2197
+ import * as React11 from "react";
2032
2198
  import { cva as cva2 } from "class-variance-authority";
2033
2199
  import { CheckIcon, CopyIcon, DownloadIcon, WrapTextIcon } from "lucide-react";
2034
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2200
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2035
2201
  var codeBlockVariants = cva2(
2036
2202
  "a24-code-block",
2037
2203
  {
@@ -2052,7 +2218,7 @@ function CodeBlock({
2052
2218
  size = "default",
2053
2219
  ...props
2054
2220
  }) {
2055
- return /* @__PURE__ */ jsx9(
2221
+ return /* @__PURE__ */ jsx10(
2056
2222
  "div",
2057
2223
  {
2058
2224
  "data-slot": "code-block",
@@ -2064,7 +2230,7 @@ function CodeBlock({
2064
2230
  );
2065
2231
  }
2066
2232
  function CodeBlockHeader({ className, ...props }) {
2067
- return /* @__PURE__ */ jsx9(
2233
+ return /* @__PURE__ */ jsx10(
2068
2234
  "div",
2069
2235
  {
2070
2236
  "data-slot": "code-block-header",
@@ -2077,7 +2243,7 @@ function CodeBlockHeader({ className, ...props }) {
2077
2243
  );
2078
2244
  }
2079
2245
  function CodeBlockTitle({ className, ...props }) {
2080
- return /* @__PURE__ */ jsx9(
2246
+ return /* @__PURE__ */ jsx10(
2081
2247
  "div",
2082
2248
  {
2083
2249
  "data-slot": "code-block-title",
@@ -2093,7 +2259,7 @@ function CodeBlockActions({
2093
2259
  className,
2094
2260
  ...props
2095
2261
  }) {
2096
- return /* @__PURE__ */ jsx9(
2262
+ return /* @__PURE__ */ jsx10(
2097
2263
  "div",
2098
2264
  {
2099
2265
  "data-slot": "code-block-actions",
@@ -2111,16 +2277,16 @@ function CodeBlockCopyButton({
2111
2277
  onClick,
2112
2278
  ...props
2113
2279
  }) {
2114
- const [copied, setCopied] = React10.useState(false);
2115
- React10.useEffect(() => {
2280
+ const [copied, setCopied] = React11.useState(false);
2281
+ React11.useEffect(() => {
2116
2282
  if (!copied) {
2117
2283
  return;
2118
2284
  }
2119
2285
  const timeout = setTimeout(() => setCopied(false), 2e3);
2120
2286
  return () => clearTimeout(timeout);
2121
2287
  }, [copied]);
2122
- return /* @__PURE__ */ jsxs6(Fragment2, { children: [
2123
- /* @__PURE__ */ jsx9(
2288
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
2289
+ /* @__PURE__ */ jsx10(
2124
2290
  "button",
2125
2291
  {
2126
2292
  type: "button",
@@ -2136,10 +2302,10 @@ function CodeBlockCopyButton({
2136
2302
  });
2137
2303
  },
2138
2304
  ...props,
2139
- children: copied ? /* @__PURE__ */ jsx9(CheckIcon, { size: 12, strokeWidth: 1.5 }) : /* @__PURE__ */ jsx9(CopyIcon, { size: 12, strokeWidth: 1.5 })
2305
+ children: copied ? /* @__PURE__ */ jsx10(CheckIcon, { size: 12, strokeWidth: 1.5 }) : /* @__PURE__ */ jsx10(CopyIcon, { size: 12, strokeWidth: 1.5 })
2140
2306
  }
2141
2307
  ),
2142
- /* @__PURE__ */ jsx9("span", { "aria-live": "polite", className: "a24-code-block__announcement", children: copied ? "Copied" : "" })
2308
+ /* @__PURE__ */ jsx10("span", { "aria-live": "polite", className: "a24-code-block__announcement", children: copied ? "Copied" : "" })
2143
2309
  ] });
2144
2310
  }
2145
2311
  function CodeBlockWrapButton({
@@ -2149,7 +2315,7 @@ function CodeBlockWrapButton({
2149
2315
  onClick,
2150
2316
  ...props
2151
2317
  }) {
2152
- return /* @__PURE__ */ jsx9(
2318
+ return /* @__PURE__ */ jsx10(
2153
2319
  "button",
2154
2320
  {
2155
2321
  type: "button",
@@ -2163,7 +2329,7 @@ function CodeBlockWrapButton({
2163
2329
  if (!event.defaultPrevented) onWrapChange(!wrap);
2164
2330
  },
2165
2331
  ...props,
2166
- children: /* @__PURE__ */ jsx9(WrapTextIcon, { size: 12, strokeWidth: 1.5 })
2332
+ children: /* @__PURE__ */ jsx10(WrapTextIcon, { size: 12, strokeWidth: 1.5 })
2167
2333
  }
2168
2334
  );
2169
2335
  }
@@ -2174,7 +2340,7 @@ function CodeBlockDownloadButton({
2174
2340
  onClick,
2175
2341
  ...props
2176
2342
  }) {
2177
- return /* @__PURE__ */ jsx9(
2343
+ return /* @__PURE__ */ jsx10(
2178
2344
  "button",
2179
2345
  {
2180
2346
  type: "button",
@@ -2195,7 +2361,7 @@ function CodeBlockDownloadButton({
2195
2361
  setTimeout(() => URL.revokeObjectURL(url), 1e3);
2196
2362
  },
2197
2363
  ...props,
2198
- children: /* @__PURE__ */ jsx9(DownloadIcon, { size: 12, strokeWidth: 1.5 })
2364
+ children: /* @__PURE__ */ jsx10(DownloadIcon, { size: 12, strokeWidth: 1.5 })
2199
2365
  }
2200
2366
  );
2201
2367
  }
@@ -2208,7 +2374,7 @@ function CodeBlockContent({
2208
2374
  startLine = 1,
2209
2375
  ...props
2210
2376
  }) {
2211
- return /* @__PURE__ */ jsx9(
2377
+ return /* @__PURE__ */ jsx10(
2212
2378
  "pre",
2213
2379
  {
2214
2380
  "data-slot": "code-block-content",
@@ -2222,12 +2388,12 @@ function CodeBlockContent({
2222
2388
  className
2223
2389
  ),
2224
2390
  ...props,
2225
- children: /* @__PURE__ */ jsx9(
2391
+ children: /* @__PURE__ */ jsx10(
2226
2392
  "code",
2227
2393
  {
2228
2394
  "data-slot": "code-block-code",
2229
2395
  className: "a24-code-block__code",
2230
- children: lineNumbers && typeof children === "string" ? children.replace(/\n$/, "").split("\n").map((line, index) => /* @__PURE__ */ jsx9(CodeBlockLine, { children: line }, index)) : children
2396
+ children: lineNumbers && typeof children === "string" ? children.replace(/\n$/, "").split("\n").map((line, index) => /* @__PURE__ */ jsx10(CodeBlockLine, { children: line }, index)) : children
2231
2397
  }
2232
2398
  )
2233
2399
  }
@@ -2256,19 +2422,19 @@ function CodeBlockLine({
2256
2422
  ...props
2257
2423
  }) {
2258
2424
  const empty = children === void 0 || children === null || children === "" || Array.isArray(children) && children.length === 0;
2259
- return /* @__PURE__ */ jsx9(
2425
+ return /* @__PURE__ */ jsx10(
2260
2426
  "span",
2261
2427
  {
2262
2428
  "data-slot": "code-block-line",
2263
2429
  "data-variant": variant,
2264
2430
  className: cn(codeBlockLineVariants({ variant }), className),
2265
2431
  ...props,
2266
- children: /* @__PURE__ */ jsx9("span", { "data-slot": "code-block-line-content", className: "a24-code-block__line-content", children: empty ? "\n" : children })
2432
+ children: /* @__PURE__ */ jsx10("span", { "data-slot": "code-block-line-content", className: "a24-code-block__line-content", children: empty ? "\n" : children })
2267
2433
  }
2268
2434
  );
2269
2435
  }
2270
2436
  function CodeBlockFooter({ className, ...props }) {
2271
- return /* @__PURE__ */ jsx9(
2437
+ return /* @__PURE__ */ jsx10(
2272
2438
  "div",
2273
2439
  {
2274
2440
  "data-slot": "code-block-footer",
@@ -2282,7 +2448,7 @@ function CodeBlockFooter({ className, ...props }) {
2282
2448
  }
2283
2449
 
2284
2450
  // src/ui/use-highlighted-code.ts
2285
- import * as React11 from "react";
2451
+ import * as React12 from "react";
2286
2452
 
2287
2453
  // src/ui/code-highlighter.tsx
2288
2454
  import {
@@ -2290,7 +2456,7 @@ import {
2290
2456
  } from "shiki/core";
2291
2457
  import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
2292
2458
  import { bundledLanguages, bundledLanguagesAlias } from "shiki/langs";
2293
- import { jsx as jsx10 } from "react/jsx-runtime";
2459
+ import { jsx as jsx11 } from "react/jsx-runtime";
2294
2460
  var languageLoaders = {
2295
2461
  ...bundledLanguages,
2296
2462
  ...bundledLanguagesAlias
@@ -2335,7 +2501,7 @@ async function loadHighlighter(language) {
2335
2501
  const tokens = lang === "ansi" ? code.split("\n").flatMap((line) => tokenize(line)) : tokenize(code);
2336
2502
  return {
2337
2503
  lines: tokens.map(
2338
- (line) => line.map((token, index) => /* @__PURE__ */ jsx10(
2504
+ (line) => line.map((token, index) => /* @__PURE__ */ jsx11(
2339
2505
  "span",
2340
2506
  {
2341
2507
  style: token.htmlStyle,
@@ -2354,9 +2520,9 @@ async function loadHighlighter(language) {
2354
2520
  // src/ui/use-highlighted-code.ts
2355
2521
  function useHighlightedCode(value, language) {
2356
2522
  const code = value.endsWith("\n") ? value.slice(0, -1) : value;
2357
- const [loaded, setLoaded] = React11.useState(null);
2523
+ const [loaded, setLoaded] = React12.useState(null);
2358
2524
  const highlighter2 = loaded?.language === language ? loaded.highlighter : null;
2359
- React11.useEffect(() => {
2525
+ React12.useEffect(() => {
2360
2526
  let cancelled = false;
2361
2527
  loadHighlighter(language).then((next2) => {
2362
2528
  if (!cancelled) {
@@ -2368,7 +2534,7 @@ function useHighlightedCode(value, language) {
2368
2534
  cancelled = true;
2369
2535
  };
2370
2536
  }, [language]);
2371
- const [done, setDone] = React11.useState({ highlighter: null, text: "", lines: [] });
2537
+ const [done, setDone] = React12.useState({ highlighter: null, text: "", lines: [] });
2372
2538
  let next = done;
2373
2539
  if (next.highlighter !== highlighter2 || !code.startsWith(next.text)) {
2374
2540
  next = { highlighter: highlighter2, text: "", lines: [] };
@@ -2390,7 +2556,7 @@ function useHighlightedCode(value, language) {
2390
2556
  setDone(next);
2391
2557
  }
2392
2558
  const tail = code.slice(end);
2393
- return React11.useMemo(() => {
2559
+ return React12.useMemo(() => {
2394
2560
  if (!highlighter2) {
2395
2561
  return code.split("\n");
2396
2562
  }
@@ -2399,7 +2565,7 @@ function useHighlightedCode(value, language) {
2399
2565
  }
2400
2566
 
2401
2567
  // src/ui/message-code.tsx
2402
- import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2568
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2403
2569
  var CODE_EXTENSIONS = {
2404
2570
  bash: "sh",
2405
2571
  shell: "sh",
@@ -2441,32 +2607,32 @@ var CODE_EXTENSIONS = {
2441
2607
  plaintext: "txt"
2442
2608
  };
2443
2609
  function MessageCodeBlock({ code, language = "text" }) {
2444
- const [wrap, setWrap] = React12.useState(false);
2610
+ const [wrap, setWrap] = React13.useState(false);
2445
2611
  const lines = useHighlightedCode(code, language);
2446
2612
  const extension = Object.prototype.hasOwnProperty.call(CODE_EXTENSIONS, language.toLowerCase()) ? CODE_EXTENSIONS[language.toLowerCase()] : "txt";
2447
- return /* @__PURE__ */ jsxs7(CodeBlock, { children: [
2448
- /* @__PURE__ */ jsxs7(CodeBlockHeader, { children: [
2449
- /* @__PURE__ */ jsxs7(CodeBlockTitle, { children: [
2450
- /* @__PURE__ */ jsx11(FileCode2Icon, { size: 14, strokeWidth: 1.5, "aria-hidden": "true" }),
2451
- /* @__PURE__ */ jsx11("span", { children: language })
2613
+ return /* @__PURE__ */ jsxs8(CodeBlock, { children: [
2614
+ /* @__PURE__ */ jsxs8(CodeBlockHeader, { children: [
2615
+ /* @__PURE__ */ jsxs8(CodeBlockTitle, { children: [
2616
+ /* @__PURE__ */ jsx12(FileCode2Icon, { size: 14, strokeWidth: 1.5, "aria-hidden": "true" }),
2617
+ /* @__PURE__ */ jsx12("span", { children: language })
2452
2618
  ] }),
2453
- /* @__PURE__ */ jsxs7(CodeBlockActions, { children: [
2454
- /* @__PURE__ */ jsx11(CodeBlockWrapButton, { wrap, onWrapChange: setWrap }),
2455
- /* @__PURE__ */ jsx11(CodeBlockDownloadButton, { value: code, filename: `code.${extension}` }),
2456
- /* @__PURE__ */ jsx11(CodeBlockCopyButton, { value: code })
2619
+ /* @__PURE__ */ jsxs8(CodeBlockActions, { children: [
2620
+ /* @__PURE__ */ jsx12(CodeBlockWrapButton, { wrap, onWrapChange: setWrap }),
2621
+ /* @__PURE__ */ jsx12(CodeBlockDownloadButton, { value: code, filename: `code.${extension}` }),
2622
+ /* @__PURE__ */ jsx12(CodeBlockCopyButton, { value: code })
2457
2623
  ] })
2458
2624
  ] }),
2459
- /* @__PURE__ */ jsx11(CodeBlockContent, { "aria-label": `${language} code`, lineNumbers: true, wrap, children: lines.map((line, index) => /* @__PURE__ */ jsx11(CodeBlockLine, { children: line }, index)) })
2625
+ /* @__PURE__ */ jsx12(CodeBlockContent, { "aria-label": `${language} code`, lineNumbers: true, wrap, children: lines.map((line, index) => /* @__PURE__ */ jsx12(CodeBlockLine, { children: line }, index)) })
2460
2626
  ] });
2461
2627
  }
2462
2628
  function MessageMarkdownCode({ children, className, node, ...props }) {
2463
2629
  const language = className?.match(/(?:^|\s)language-([^\s]+)/)?.[1];
2464
2630
  const multiline = node?.position?.start?.line !== node?.position?.end?.line;
2465
2631
  if (props["data-block"] === void 0 && !language && !multiline) {
2466
- return /* @__PURE__ */ jsx11("code", { ...props, className: cn("a24-inline-code", className), "data-streamdown": "inline-code", children });
2632
+ return /* @__PURE__ */ jsx12("code", { ...props, className: cn("a24-inline-code", className), "data-streamdown": "inline-code", children });
2467
2633
  }
2468
2634
  const code = typeof children === "string" ? children.replace(/\n$/, "") : "";
2469
- return /* @__PURE__ */ jsx11(MessageCodeBlock, { code, language });
2635
+ return /* @__PURE__ */ jsx12(MessageCodeBlock, { code, language });
2470
2636
  }
2471
2637
  function formatMessageJson(text) {
2472
2638
  const trimmed = text.trim();
@@ -2500,17 +2666,17 @@ ${" ".repeat(depth)}`;
2500
2666
  }
2501
2667
 
2502
2668
  // src/ui/message-response.tsx
2503
- import { Fragment as Fragment3, jsx as jsx12 } from "react/jsx-runtime";
2669
+ import { Fragment as Fragment3, jsx as jsx13 } from "react/jsx-runtime";
2504
2670
  function SafeMarkdownLink({ children, href, ...props }) {
2505
2671
  const domProps = { ...props };
2506
2672
  delete domProps.node;
2507
2673
  const safeHref = safeChatMarkdownHref(href);
2508
- if (!safeHref) return /* @__PURE__ */ jsx12("span", { children });
2509
- if (safeHref.startsWith("#")) return /* @__PURE__ */ jsx12("a", { ...domProps, href: safeHref, children });
2510
- return /* @__PURE__ */ jsx12("a", { ...domProps, href: safeHref, rel: "noopener noreferrer", target: "_blank", children });
2674
+ if (!safeHref) return /* @__PURE__ */ jsx13("span", { children });
2675
+ if (safeHref.startsWith("#")) return /* @__PURE__ */ jsx13("a", { ...domProps, href: safeHref, children });
2676
+ return /* @__PURE__ */ jsx13("a", { ...domProps, href: safeHref, rel: "noopener noreferrer", target: "_blank", children });
2511
2677
  }
2512
2678
  function BlockedMarkdownImage({ alt }) {
2513
- return alt ? /* @__PURE__ */ jsx12("span", { "aria-label": `Image blocked: ${alt}`, role: "img", children: alt }) : null;
2679
+ return alt ? /* @__PURE__ */ jsx13("span", { "aria-label": `Image blocked: ${alt}`, role: "img", children: alt }) : null;
2514
2680
  }
2515
2681
  var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
2516
2682
  "blockquote",
@@ -2531,7 +2697,7 @@ function isMultilineCodeNode(node) {
2531
2697
  return node?.tagName === "code" && node.position?.start?.line !== void 0 && node.position?.end?.line !== void 0 && node.position.start.line !== node.position.end.line;
2532
2698
  }
2533
2699
  function hasBlockMarkdownChild(child) {
2534
- if (!React13.isValidElement(child)) {
2700
+ if (!React14.isValidElement(child)) {
2535
2701
  return false;
2536
2702
  }
2537
2703
  if (typeof child.type === "string" && BLOCK_MARKDOWN_TAGS.has(child.type)) {
@@ -2541,7 +2707,7 @@ function hasBlockMarkdownChild(child) {
2541
2707
  if (BLOCK_MARKDOWN_TAGS.has(props.node?.tagName || "") || isMultilineCodeNode(props.node)) {
2542
2708
  return true;
2543
2709
  }
2544
- return React13.Children.toArray(props.children).some(hasBlockMarkdownChild);
2710
+ return React14.Children.toArray(props.children).some(hasBlockMarkdownChild);
2545
2711
  }
2546
2712
  function MessageMarkdownParagraph({
2547
2713
  children,
@@ -2549,17 +2715,17 @@ function MessageMarkdownParagraph({
2549
2715
  }) {
2550
2716
  const domProps = { ...props };
2551
2717
  delete domProps.node;
2552
- const childArray = React13.Children.toArray(children).filter(
2718
+ const childArray = React14.Children.toArray(children).filter(
2553
2719
  (child) => child !== null && child !== ""
2554
2720
  );
2555
- const isImageOnly = childArray.length === 1 && React13.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
2721
+ const isImageOnly = childArray.length === 1 && React14.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
2556
2722
  if (isImageOnly) {
2557
- return /* @__PURE__ */ jsx12(Fragment3, { children });
2723
+ return /* @__PURE__ */ jsx13(Fragment3, { children });
2558
2724
  }
2559
2725
  if (childArray.some(hasBlockMarkdownChild)) {
2560
- return /* @__PURE__ */ jsx12("div", { ...domProps, children });
2726
+ return /* @__PURE__ */ jsx13("div", { ...domProps, children });
2561
2727
  }
2562
- return /* @__PURE__ */ jsx12("p", { ...domProps, children });
2728
+ return /* @__PURE__ */ jsx13("p", { ...domProps, children });
2563
2729
  }
2564
2730
  var MESSAGE_RESPONSE_COMPONENTS = {
2565
2731
  a: SafeMarkdownLink,
@@ -2580,7 +2746,7 @@ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
2580
2746
  ]
2581
2747
  ] : []
2582
2748
  ];
2583
- var MessageResponse = React13.memo(
2749
+ var MessageResponse = React14.memo(
2584
2750
  ({
2585
2751
  children,
2586
2752
  className,
@@ -2598,13 +2764,13 @@ var MessageResponse = React13.memo(
2598
2764
  maxCatchupChars: 32,
2599
2765
  text
2600
2766
  });
2601
- const streamdownComponents = React13.useMemo(
2767
+ const streamdownComponents = React14.useMemo(
2602
2768
  () => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
2603
2769
  [components]
2604
2770
  );
2605
- const json = React13.useMemo(() => formatMessageJson(text), [text]);
2771
+ const json = React14.useMemo(() => formatMessageJson(text), [text]);
2606
2772
  if (json !== null && !components?.code) {
2607
- return /* @__PURE__ */ jsx12("div", { className: cn("a24-message-response", className), children: /* @__PURE__ */ jsx12(
2773
+ return /* @__PURE__ */ jsx13("div", { className: cn("a24-message-response", className), children: /* @__PURE__ */ jsx13(
2608
2774
  MessageCodeBlock,
2609
2775
  {
2610
2776
  code: streaming || streamingText.isAnimating ? streamingText.displayedText : json,
@@ -2612,7 +2778,7 @@ var MessageResponse = React13.memo(
2612
2778
  }
2613
2779
  ) });
2614
2780
  }
2615
- return /* @__PURE__ */ jsx12(
2781
+ return /* @__PURE__ */ jsx13(
2616
2782
  Streamdown,
2617
2783
  {
2618
2784
  className: cn("a24-message-response", className),
@@ -2664,10 +2830,10 @@ function resolvedHitlLabel(part) {
2664
2830
  }
2665
2831
 
2666
2832
  // src/ui/tool-sessions.tsx
2667
- import * as React14 from "react";
2833
+ import * as React15 from "react";
2668
2834
  import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight2 } from "lucide-react";
2669
2835
  import { ThinkingOrb } from "thinking-orbs";
2670
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2836
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2671
2837
  function toolSlotContext(isActive2, label, part, slots) {
2672
2838
  return {
2673
2839
  isActive: isActive2,
@@ -2685,7 +2851,7 @@ function ToolResourceAction({ context }) {
2685
2851
  const target = context.resourceTargets[0];
2686
2852
  if (!target) return null;
2687
2853
  const name = resourceTargetName(target);
2688
- return /* @__PURE__ */ jsx13(
2854
+ return /* @__PURE__ */ jsx14(
2689
2855
  "button",
2690
2856
  {
2691
2857
  "aria-label": `Open ${target.kind} ${target.path}`,
@@ -2699,8 +2865,8 @@ function ToolResourceAction({ context }) {
2699
2865
  );
2700
2866
  }
2701
2867
  function toolAccessory(context, slots) {
2702
- return /* @__PURE__ */ jsxs8(Fragment4, { children: [
2703
- slots?.onResourceAction ? /* @__PURE__ */ jsx13(ToolResourceAction, { context }) : null,
2868
+ return /* @__PURE__ */ jsxs9(Fragment4, { children: [
2869
+ slots?.onResourceAction ? /* @__PURE__ */ jsx14(ToolResourceAction, { context }) : null,
2704
2870
  slots?.renderToolAccessory?.(context)
2705
2871
  ] });
2706
2872
  }
@@ -2777,12 +2943,12 @@ function ToolActivityReel({
2777
2943
  }) {
2778
2944
  const initial = initialLabel && initialLabel !== label ? initialLabel : label;
2779
2945
  const parsedInitialShownAt = initialShownAt ? Date.parse(initialShownAt) : Number.NaN;
2780
- const [displayed, setDisplayed] = React14.useState(initial);
2781
- const [previous, setPrevious] = React14.useState(null);
2782
- const displayedRef = React14.useRef(initial);
2783
- const latestRef = React14.useRef(label);
2784
- const shownAtRef = React14.useRef(Number.isFinite(parsedInitialShownAt) ? parsedInitialShownAt : Date.now());
2785
- React14.useEffect(() => {
2946
+ const [displayed, setDisplayed] = React15.useState(initial);
2947
+ const [previous, setPrevious] = React15.useState(null);
2948
+ const displayedRef = React15.useRef(initial);
2949
+ const latestRef = React15.useRef(label);
2950
+ const shownAtRef = React15.useRef(Number.isFinite(parsedInitialShownAt) ? parsedInitialShownAt : Date.now());
2951
+ React15.useEffect(() => {
2786
2952
  latestRef.current = label;
2787
2953
  if (displayedRef.current === label) return;
2788
2954
  const showLatest = () => {
@@ -2802,18 +2968,18 @@ function ToolActivityReel({
2802
2968
  const timer = window.setTimeout(showLatest, remaining);
2803
2969
  return () => window.clearTimeout(timer);
2804
2970
  }, [label]);
2805
- React14.useEffect(() => {
2971
+ React15.useEffect(() => {
2806
2972
  if (!previous) return;
2807
2973
  const timer = window.setTimeout(() => setPrevious(null), 200);
2808
2974
  return () => window.clearTimeout(timer);
2809
2975
  }, [previous]);
2810
- return /* @__PURE__ */ jsxs8("span", { className: "a24-tool-reel", "aria-live": announce ? "polite" : "off", children: [
2811
- previous ? /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", className: "a24-tool-reel__previous", children: previous }) : null,
2812
- /* @__PURE__ */ jsx13("span", { className: previous ? "a24-tool-reel__current" : void 0, children: displayed })
2976
+ return /* @__PURE__ */ jsxs9("span", { className: "a24-tool-reel", "aria-live": announce ? "polite" : "off", children: [
2977
+ previous ? /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", className: "a24-tool-reel__previous", children: previous }) : null,
2978
+ /* @__PURE__ */ jsx14("span", { className: previous ? "a24-tool-reel__current" : void 0, children: displayed })
2813
2979
  ] });
2814
2980
  }
2815
2981
  function ToolActivityOrb({ label = "Working", kind = "tool", part, renderActivityIcon }) {
2816
- return /* @__PURE__ */ jsx13("span", { className: "a24-tool-orb", children: renderActivityIcon ? renderActivityIcon({ label, kind, part }) : /* @__PURE__ */ jsx13(ThinkingOrb, { "aria-label": label, size: 20, speed: 0.8, state: "searching" }) });
2982
+ return /* @__PURE__ */ jsx14("span", { className: "a24-tool-orb", children: renderActivityIcon ? renderActivityIcon({ label, kind, part }) : /* @__PURE__ */ jsx14(ThinkingOrb, { "aria-label": label, size: 20, speed: 0.8, state: "searching" }) });
2817
2983
  }
2818
2984
  function AgentChatActivityRow({
2819
2985
  label,
@@ -2821,22 +2987,22 @@ function AgentChatActivityRow({
2821
2987
  renderActivityIcon,
2822
2988
  onSelect
2823
2989
  }) {
2824
- const content = /* @__PURE__ */ jsxs8(Fragment4, { children: [
2825
- /* @__PURE__ */ jsx13(ToolActivityOrb, { label, kind: "planning", renderActivityIcon }),
2826
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label a24-tool-shimmer", children: /* @__PURE__ */ jsx13(ToolActivityReel, { label }) })
2990
+ const content = /* @__PURE__ */ jsxs9(Fragment4, { children: [
2991
+ /* @__PURE__ */ jsx14(ToolActivityOrb, { label, kind: "planning", renderActivityIcon }),
2992
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label a24-tool-shimmer", children: /* @__PURE__ */ jsx14(ToolActivityReel, { label }) })
2827
2993
  ] });
2828
- return /* @__PURE__ */ jsx13("div", { className: "a24-tool-trigger-row a24-tool-trigger-row--root", "data-agents24-model-turn": modelTurnId, role: "status", children: onSelect ? /* @__PURE__ */ jsx13("button", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", onClick: onSelect, type: "button", children: content }) : /* @__PURE__ */ jsx13("div", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", children: content }) });
2994
+ return /* @__PURE__ */ jsx14("div", { className: "a24-tool-trigger-row a24-tool-trigger-row--root", "data-agents24-model-turn": modelTurnId, role: "status", children: onSelect ? /* @__PURE__ */ jsx14("button", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", onClick: onSelect, type: "button", children: content }) : /* @__PURE__ */ jsx14("div", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", children: content }) });
2829
2995
  }
2830
2996
  function AgentChatModelTurnRow({ part }) {
2831
- return /* @__PURE__ */ jsx13(AgentChatActivityRow, { label: "Planning next moves", modelTurnId: part.modelTurnId });
2997
+ return /* @__PURE__ */ jsx14(AgentChatActivityRow, { label: "Planning next moves", modelTurnId: part.modelTurnId });
2832
2998
  }
2833
2999
  function AgentChatNodeActivityRow({
2834
3000
  renderActivityIcon,
2835
3001
  onSelect,
2836
3002
  part
2837
3003
  }) {
2838
- const [open, setOpen] = React14.useState(false);
2839
- const contentId = React14.useId();
3004
+ const [open, setOpen] = React15.useState(false);
3005
+ const contentId = React15.useId();
2840
3006
  const running = part.status === "running";
2841
3007
  const failed = part.status === "failed";
2842
3008
  const failureMessage = part.failure?.message || "The node could not complete the request.";
@@ -2847,18 +3013,18 @@ function AgentChatNodeActivityRow({
2847
3013
  running && "a24-tool-trigger--active",
2848
3014
  failed && "a24-tool-trigger--error"
2849
3015
  );
2850
- const label = running ? /* @__PURE__ */ jsx13("span", { className: "a24-tool-shimmer", children: /* @__PURE__ */ jsx13(ToolActivityReel, { label: part.label }) }) : part.label;
3016
+ const label = running ? /* @__PURE__ */ jsx14("span", { className: "a24-tool-shimmer", children: /* @__PURE__ */ jsx14(ToolActivityReel, { label: part.label }) }) : part.label;
2851
3017
  if (!failed) {
2852
- return /* @__PURE__ */ jsx13("div", { className: "a24-tool-trigger-row", role: "status", children: onSelect ? /* @__PURE__ */ jsxs8("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
2853
- running ? /* @__PURE__ */ jsx13(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
2854
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label })
2855
- ] }) : /* @__PURE__ */ jsxs8("div", { className: triggerClassName, children: [
2856
- running ? /* @__PURE__ */ jsx13(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
2857
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label })
3018
+ return /* @__PURE__ */ jsx14("div", { className: "a24-tool-trigger-row", role: "status", children: onSelect ? /* @__PURE__ */ jsxs9("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
3019
+ running ? /* @__PURE__ */ jsx14(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
3020
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label })
3021
+ ] }) : /* @__PURE__ */ jsxs9("div", { className: triggerClassName, children: [
3022
+ running ? /* @__PURE__ */ jsx14(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
3023
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label })
2858
3024
  ] }) });
2859
3025
  }
2860
- return /* @__PURE__ */ jsxs8("div", { className: "a24-tool-disclosure", children: [
2861
- /* @__PURE__ */ jsx13("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ jsxs8(
3026
+ return /* @__PURE__ */ jsxs9("div", { className: "a24-tool-disclosure", children: [
3027
+ /* @__PURE__ */ jsx14("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ jsxs9(
2862
3028
  "button",
2863
3029
  {
2864
3030
  "aria-controls": contentId,
@@ -2870,12 +3036,12 @@ function AgentChatNodeActivityRow({
2870
3036
  },
2871
3037
  type: "button",
2872
3038
  children: [
2873
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label }),
2874
- open ? /* @__PURE__ */ jsx13(ChevronDown2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ jsx13(ChevronRight2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
3039
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label }),
3040
+ open ? /* @__PURE__ */ jsx14(ChevronDown2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ jsx14(ChevronRight2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
2875
3041
  ]
2876
3042
  }
2877
3043
  ) }),
2878
- open ? /* @__PURE__ */ jsx13("div", { className: "a24-tool-detail a24-tool-detail--error", id: contentId, children: failureMessage }) : null
3044
+ open ? /* @__PURE__ */ jsx14("div", { className: "a24-tool-detail a24-tool-detail--error", id: contentId, children: failureMessage }) : null
2879
3045
  ] });
2880
3046
  }
2881
3047
  function toolRowLabel(part, separateResource = false) {
@@ -2902,25 +3068,25 @@ function ToolDisclosure({
2902
3068
  renderActivityIcon,
2903
3069
  accessory
2904
3070
  }) {
2905
- const [open, setOpen] = React14.useState(false);
2906
- const contentId = React14.useId();
2907
- const expandable = React14.Children.toArray(children).length > 0;
3071
+ const [open, setOpen] = React15.useState(false);
3072
+ const contentId = React15.useId();
3073
+ const expandable = React15.Children.toArray(children).length > 0;
2908
3074
  if (!expandable) {
2909
3075
  const triggerClassName = cn("a24-tool-trigger", root && "a24-tool-trigger--root", root && !showOrb && "a24-tool-trigger--without-orb", error && "a24-tool-trigger--error", loading && "a24-tool-trigger--active");
2910
- return /* @__PURE__ */ jsxs8("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
2911
- onSelect && part ? /* @__PURE__ */ jsxs8("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
2912
- showOrb ? /* @__PURE__ */ jsx13(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2913
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label })
2914
- ] }) : /* @__PURE__ */ jsxs8("div", { className: triggerClassName, children: [
2915
- showOrb ? /* @__PURE__ */ jsx13(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2916
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label })
3076
+ return /* @__PURE__ */ jsxs9("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
3077
+ onSelect && part ? /* @__PURE__ */ jsxs9("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
3078
+ showOrb ? /* @__PURE__ */ jsx14(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3079
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label })
3080
+ ] }) : /* @__PURE__ */ jsxs9("div", { className: triggerClassName, children: [
3081
+ showOrb ? /* @__PURE__ */ jsx14(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3082
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label })
2917
3083
  ] }),
2918
3084
  accessory
2919
3085
  ] });
2920
3086
  }
2921
- return /* @__PURE__ */ jsxs8("div", { className: "a24-tool-disclosure", children: [
2922
- /* @__PURE__ */ jsxs8("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
2923
- /* @__PURE__ */ jsxs8(
3087
+ return /* @__PURE__ */ jsxs9("div", { className: "a24-tool-disclosure", children: [
3088
+ /* @__PURE__ */ jsxs9("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
3089
+ /* @__PURE__ */ jsxs9(
2924
3090
  "button",
2925
3091
  {
2926
3092
  "aria-controls": contentId,
@@ -2934,25 +3100,25 @@ function ToolDisclosure({
2934
3100
  },
2935
3101
  type: "button",
2936
3102
  children: [
2937
- showOrb ? /* @__PURE__ */ jsx13(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2938
- /* @__PURE__ */ jsx13("span", { className: "a24-tool-trigger__label", children: label }),
2939
- open ? /* @__PURE__ */ jsx13(ChevronDown2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ jsx13(ChevronRight2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
3103
+ showOrb ? /* @__PURE__ */ jsx14(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3104
+ /* @__PURE__ */ jsx14("span", { className: "a24-tool-trigger__label", children: label }),
3105
+ open ? /* @__PURE__ */ jsx14(ChevronDown2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ jsx14(ChevronRight2, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
2940
3106
  ]
2941
3107
  }
2942
3108
  ),
2943
3109
  accessory
2944
3110
  ] }),
2945
- open ? /* @__PURE__ */ jsx13("div", { className: "a24-tool-disclosure__content", id: contentId, children }) : null
3111
+ open ? /* @__PURE__ */ jsx14("div", { className: "a24-tool-disclosure__content", id: contentId, children }) : null
2946
3112
  ] });
2947
3113
  }
2948
3114
  function ToolLabel({ active, label, part, slots }) {
2949
3115
  const rendered = slots?.renderToolLabel?.(toolSlotContext(active, label, part, slots)) ?? label;
2950
- return active ? /* @__PURE__ */ jsx13("span", { className: "a24-tool-shimmer", children: rendered }) : /* @__PURE__ */ jsx13(Fragment4, { children: rendered });
3116
+ return active ? /* @__PURE__ */ jsx14("span", { className: "a24-tool-shimmer", children: rendered }) : /* @__PURE__ */ jsx14(Fragment4, { children: rendered });
2951
3117
  }
2952
3118
  function ToolList({ children }) {
2953
- const listRef = React14.useRef(null);
2954
- const [fades, setFades] = React14.useState({ bottom: false, top: false });
2955
- const updateFades = React14.useCallback(() => {
3119
+ const listRef = React15.useRef(null);
3120
+ const [fades, setFades] = React15.useState({ bottom: false, top: false });
3121
+ const updateFades = React15.useCallback(() => {
2956
3122
  const list = listRef.current;
2957
3123
  if (!list) return;
2958
3124
  const next = {
@@ -2961,7 +3127,7 @@ function ToolList({ children }) {
2961
3127
  };
2962
3128
  setFades((current) => current.bottom === next.bottom && current.top === next.top ? current : next);
2963
3129
  }, []);
2964
- React14.useEffect(() => {
3130
+ React15.useEffect(() => {
2965
3131
  updateFades();
2966
3132
  const list = listRef.current;
2967
3133
  if (!list || typeof ResizeObserver === "undefined") return;
@@ -2969,13 +3135,13 @@ function ToolList({ children }) {
2969
3135
  observer.observe(list);
2970
3136
  return () => observer.disconnect();
2971
3137
  }, [children, updateFades]);
2972
- return /* @__PURE__ */ jsx13(
3138
+ return /* @__PURE__ */ jsx14(
2973
3139
  "div",
2974
3140
  {
2975
3141
  className: "a24-tool-list-frame",
2976
3142
  "data-scroll-fade-bottom": fades.bottom ? "" : void 0,
2977
3143
  "data-scroll-fade-top": fades.top ? "" : void 0,
2978
- children: /* @__PURE__ */ jsx13("div", { className: "a24-tool-list", onScroll: updateFades, ref: listRef, role: "list", children })
3144
+ children: /* @__PURE__ */ jsx14("div", { className: "a24-tool-list", onScroll: updateFades, ref: listRef, role: "list", children })
2979
3145
  }
2980
3146
  );
2981
3147
  }
@@ -2992,13 +3158,13 @@ function AgentChatToolRow({
2992
3158
  const detail = failed ? failureMessage : optionalText(part.presentation.detail);
2993
3159
  const hostDetails = failed ? null : slots?.renderToolDetails?.(part);
2994
3160
  const context = toolSlotContext(active, toolRowLabel(part, Boolean(slots?.onResourceAction)), part, slots);
2995
- return /* @__PURE__ */ jsx13("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ jsxs8(
3161
+ return /* @__PURE__ */ jsx14("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ jsxs9(
2996
3162
  ToolDisclosure,
2997
3163
  {
2998
3164
  renderActivityIcon: slots?.renderActivityIcon,
2999
3165
  error: failed,
3000
3166
  accessory: toolAccessory(context, slots),
3001
- label: /* @__PURE__ */ jsx13(ToolLabel, { active, label: context.label, part, slots }),
3167
+ label: /* @__PURE__ */ jsx14(ToolLabel, { active, label: context.label, part, slots }),
3002
3168
  loading: active,
3003
3169
  onExpandedChange: slots?.onExpandedChange,
3004
3170
  onSelect: slots?.onToolSelect,
@@ -3007,7 +3173,7 @@ function AgentChatToolRow({
3007
3173
  showOrb: showOrb ?? active,
3008
3174
  statusLabel: active ? context.label : void 0,
3009
3175
  children: [
3010
- detail ? /* @__PURE__ */ jsx13("div", { className: cn("a24-tool-detail", failed && "a24-tool-detail--error"), children: detail }) : null,
3176
+ detail ? /* @__PURE__ */ jsx14("div", { className: cn("a24-tool-detail", failed && "a24-tool-detail--error"), children: detail }) : null,
3011
3177
  hostDetails
3012
3178
  ]
3013
3179
  }
@@ -3027,19 +3193,19 @@ function AgentChatToolSession({
3027
3193
  parts,
3028
3194
  slots
3029
3195
  }) {
3030
- const presentedLiveRef = React14.useRef(false);
3196
+ const presentedLiveRef = React15.useRef(false);
3031
3197
  if (isLive && isLatestActivity) presentedLiveRef.current = true;
3032
3198
  const activeIndex = parts.findLastIndex((part) => isActive(part, activeToolId));
3033
3199
  const running = activeIndex >= 0;
3034
- if (parts.length === 1 && !modelTurn && !leadingModelTurn) return /* @__PURE__ */ jsx13(AgentChatToolRow, { activeToolId, part: parts[0], slots });
3200
+ if (parts.length === 1 && !modelTurn && !leadingModelTurn) return /* @__PURE__ */ jsx14(AgentChatToolRow, { activeToolId, part: parts[0], slots });
3035
3201
  const visibleIndex = running ? activeIndex : parts.length - 1;
3036
3202
  const visiblePart = parts[visibleIndex];
3037
3203
  const planning = Boolean(modelTurn);
3038
3204
  const presentingActivity = isLatestActivity && (planning || running || isLive);
3039
3205
  const failed = isLatestActivity && (visiblePart.state === "output-error" || visiblePart.state === "cancelled");
3040
3206
  const label = planning ? "Planning next moves" : isLive && isLatestActivity ? toolRowLabel(visiblePart, true) : sessionLabel(parts, visiblePart, running);
3041
- const labelContent = presentedLiveRef.current ? /* @__PURE__ */ jsx13("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ jsx13(ToolActivityReel, { initialLabel: leadingModelTurn ? "Planning next moves" : void 0, initialShownAt: leadingModelTurn?.timestamp, label }) }) : label;
3042
- return /* @__PURE__ */ jsx13(
3207
+ const labelContent = presentedLiveRef.current ? /* @__PURE__ */ jsx14("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ jsx14(ToolActivityReel, { initialLabel: leadingModelTurn ? "Planning next moves" : void 0, initialShownAt: leadingModelTurn?.timestamp, label }) }) : label;
3208
+ return /* @__PURE__ */ jsx14(
3043
3209
  ToolDisclosure,
3044
3210
  {
3045
3211
  renderActivityIcon: slots?.renderActivityIcon,
@@ -3052,7 +3218,7 @@ function AgentChatToolSession({
3052
3218
  root: true,
3053
3219
  showOrb: isLive && isLatestActivity,
3054
3220
  statusLabel: planning ? "Planning next moves" : label,
3055
- children: /* @__PURE__ */ jsx13(ToolList, { children: parts.map((part) => /* @__PURE__ */ jsx13("div", { role: "listitem", children: /* @__PURE__ */ jsx13(AgentChatToolRow, { activeToolId, part, root: false, showOrb: false, slots }) }, part.id)) })
3221
+ children: /* @__PURE__ */ jsx14(ToolList, { children: parts.map((part) => /* @__PURE__ */ jsx14("div", { role: "listitem", children: /* @__PURE__ */ jsx14(AgentChatToolRow, { activeToolId, part, root: false, showOrb: false, slots }) }, part.id)) })
3056
3222
  }
3057
3223
  );
3058
3224
  }
@@ -3073,7 +3239,7 @@ function subagentLabel(part) {
3073
3239
  return { label: `Agent ${name}, ran ${children.length} ${children.length === 1 ? "tool" : "tools"}`, running: false };
3074
3240
  }
3075
3241
  function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part, slots }) {
3076
- const presentedLiveRef = React14.useRef(false);
3242
+ const presentedLiveRef = React15.useRef(false);
3077
3243
  if (isLive && isLatestActivity) presentedLiveRef.current = true;
3078
3244
  const children = part.presentation.childTools || [];
3079
3245
  const state = subagentLabel(part);
@@ -3082,9 +3248,9 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
3082
3248
  const hostDetails = failed ? null : slots?.renderToolDetails?.(part);
3083
3249
  const failureMessage = part.failure?.message || null;
3084
3250
  const presentingActivity = isLatestActivity && state.running;
3085
- const labelContent = presentedLiveRef.current ? /* @__PURE__ */ jsx13("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ jsx13(ToolActivityReel, { label: state.label }) }) : state.label;
3251
+ const labelContent = presentedLiveRef.current ? /* @__PURE__ */ jsx14("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ jsx14(ToolActivityReel, { label: state.label }) }) : state.label;
3086
3252
  const context = toolSlotContext(presentingActivity, state.label, part, slots);
3087
- return /* @__PURE__ */ jsx13(
3253
+ return /* @__PURE__ */ jsx14(
3088
3254
  ToolDisclosure,
3089
3255
  {
3090
3256
  renderActivityIcon: slots?.renderActivityIcon,
@@ -3098,12 +3264,12 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
3098
3264
  root: true,
3099
3265
  showOrb: isLive && isLatestActivity,
3100
3266
  statusLabel: state.label,
3101
- children: /* @__PURE__ */ jsxs8(ToolList, { children: [
3102
- children.map((child) => /* @__PURE__ */ jsx13("div", { className: cn("a24-child-tool", child.status === "failed" && "a24-child-tool--error"), role: "listitem", children: slots?.renderChildTool?.(child, part) ?? /* @__PURE__ */ jsxs8(Fragment4, { children: [
3103
- /* @__PURE__ */ jsx13("span", { className: cn(isLive && isLatestActivity && child.status === "running" && "a24-tool-shimmer"), children: childLabel(child) }),
3104
- child.detail ? /* @__PURE__ */ jsx13("span", { className: "a24-child-tool__detail", children: child.detail }) : null
3267
+ children: /* @__PURE__ */ jsxs9(ToolList, { children: [
3268
+ children.map((child) => /* @__PURE__ */ jsx14("div", { className: cn("a24-child-tool", child.status === "failed" && "a24-child-tool--error"), role: "listitem", children: slots?.renderChildTool?.(child, part) ?? /* @__PURE__ */ jsxs9(Fragment4, { children: [
3269
+ /* @__PURE__ */ jsx14("span", { className: cn(isLive && isLatestActivity && child.status === "running" && "a24-tool-shimmer"), children: childLabel(child) }),
3270
+ child.detail ? /* @__PURE__ */ jsx14("span", { className: "a24-child-tool__detail", children: child.detail }) : null
3105
3271
  ] }) }, child.id)),
3106
- failureMessage ? /* @__PURE__ */ jsx13("div", { className: "a24-tool-detail a24-tool-detail--error", children: failureMessage }) : null,
3272
+ failureMessage ? /* @__PURE__ */ jsx14("div", { className: "a24-tool-detail a24-tool-detail--error", children: failureMessage }) : null,
3107
3273
  hostDetails
3108
3274
  ] })
3109
3275
  }
@@ -3111,41 +3277,51 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
3111
3277
  }
3112
3278
 
3113
3279
  // src/ui/agent-response-timeline.tsx
3114
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
3280
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3115
3281
  function isInternalAskUserTool(part) {
3116
3282
  return [part.toolName, part.toolKey, part.action].some((value) => value?.trim().toLowerCase() === "runtime__ask_user");
3117
3283
  }
3118
3284
  function Shimmer({ children, className }) {
3119
- return /* @__PURE__ */ jsx14("span", { className: cn("inline-block animate-pulse", className), children });
3285
+ return /* @__PURE__ */ jsx15("span", { className: cn("inline-block animate-pulse", className), children });
3120
3286
  }
3121
3287
  function AgentChatToolPart({
3122
3288
  activeToolId,
3123
3289
  part
3124
3290
  }) {
3125
- return /* @__PURE__ */ jsx14(AgentChatToolRow, { activeToolId, part });
3291
+ return /* @__PURE__ */ jsx15(AgentChatToolRow, { activeToolId, part });
3126
3292
  }
3127
3293
  function AgentChatToolGroup({
3128
3294
  activeToolId,
3129
3295
  parts
3130
3296
  }) {
3131
- return /* @__PURE__ */ jsx14(AgentChatToolSession, { activeToolId, parts });
3297
+ return /* @__PURE__ */ jsx15(AgentChatToolSession, { activeToolId, parts });
3132
3298
  }
3133
3299
  function HitlPartRow({
3134
3300
  getHitlActionState,
3301
+ hitlLabels,
3302
+ onHitlPaint,
3135
3303
  isLoading,
3136
3304
  onHitlAction,
3137
3305
  part
3138
3306
  }) {
3139
3307
  const state = getHitlActionState?.(part);
3140
- const [comment, setComment] = React15.useState("");
3308
+ const [comment, setComment] = React16.useState("");
3309
+ const commentRef = React16.useRef(null);
3310
+ const retryActionRef = React16.useRef(null);
3311
+ React16.useEffect(() => {
3312
+ if (state?.status === "error") (commentRef.current || retryActionRef.current)?.focus();
3313
+ }, [state?.status]);
3141
3314
  const presentation = part.presentation || {};
3142
3315
  const requireComment = presentation.require_comment === true;
3143
3316
  const isTerminal = part.status !== "pending";
3144
3317
  if (part.hitlKind === "user_input") {
3145
- return /* @__PURE__ */ jsx14(
3318
+ return /* @__PURE__ */ jsx15(
3146
3319
  AskUserInteraction,
3147
3320
  {
3148
3321
  error: state?.error,
3322
+ submission: state,
3323
+ submissionLabels: hitlLabels,
3324
+ onSubmissionPaint: onHitlPaint,
3149
3325
  isBusy: isLoading || state?.status === "resuming",
3150
3326
  onSubmit: onHitlAction ? (answers) => onHitlAction(part, {
3151
3327
  action: "respond",
@@ -3159,12 +3335,14 @@ function HitlPartRow({
3159
3335
  }
3160
3336
  );
3161
3337
  }
3338
+ if (isHitlSubmissionCompact(state)) return /* @__PURE__ */ jsx15(HitlSubmissionStatus, { state, labels: hitlLabels, onPaint: onHitlPaint });
3162
3339
  if (isTerminal) return null;
3163
- return /* @__PURE__ */ jsxs9("div", { className: "a24-hitl space-y-2.5 px-1 py-2", children: [
3164
- /* @__PURE__ */ jsx14("div", { className: "a24-hitl__title text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
3165
- requireComment ? /* @__PURE__ */ jsx14(
3340
+ return /* @__PURE__ */ jsxs10("div", { className: "a24-hitl space-y-2.5 px-1 py-2", children: [
3341
+ /* @__PURE__ */ jsx15("div", { className: "a24-hitl__title text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
3342
+ requireComment ? /* @__PURE__ */ jsx15(
3166
3343
  "textarea",
3167
3344
  {
3345
+ ref: commentRef,
3168
3346
  "aria-label": "Approval comment",
3169
3347
  autoComplete: "off",
3170
3348
  className: "a24-hitl__comment min-h-20 w-full resize-y rounded-md border border-border/60 bg-background px-3 py-2 text-sm outline-none focus-visible:border-neutral-300 focus-visible:ring-0 dark:focus-visible:border-neutral-600",
@@ -3174,10 +3352,11 @@ function HitlPartRow({
3174
3352
  value: comment
3175
3353
  }
3176
3354
  ) : null,
3177
- state?.error ? /* @__PURE__ */ jsx14("div", { className: "a24-hitl__error text-sm text-destructive", children: state.error }) : null,
3178
- /* @__PURE__ */ jsx14("div", { className: "a24-hitl__actions flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ jsx14(
3355
+ state?.error ? /* @__PURE__ */ jsx15("div", { className: "a24-hitl__error text-sm text-destructive", children: state.error }) : null,
3356
+ /* @__PURE__ */ jsx15("div", { className: "a24-hitl__actions flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ jsx15(
3179
3357
  "button",
3180
3358
  {
3359
+ ref: state?.action === action || !state?.action && action === part.allowedActions[0] ? retryActionRef : void 0,
3181
3360
  "aria-label": hitlActionLabel(part, action),
3182
3361
  className: cn(
3183
3362
  "a24-hitl__action min-h-10 rounded-md px-3 text-sm font-medium transition-[background-color,color,opacity,transform] duration-150 ease-out active:scale-[0.96] disabled:pointer-events-none disabled:opacity-60",
@@ -3199,6 +3378,8 @@ function HitlPartRow({
3199
3378
  function AgentChatPart({
3200
3379
  activeToolId,
3201
3380
  getHitlActionState,
3381
+ hitlLabels,
3382
+ onHitlPaint,
3202
3383
  isLoading,
3203
3384
  isTextStreaming,
3204
3385
  message,
@@ -3208,7 +3389,7 @@ function AgentChatPart({
3208
3389
  toolSlots
3209
3390
  }) {
3210
3391
  if (part.kind === "text") {
3211
- return /* @__PURE__ */ jsx14(
3392
+ return /* @__PURE__ */ jsx15(
3212
3393
  MessageResponse,
3213
3394
  {
3214
3395
  ...responseProps,
@@ -3218,44 +3399,46 @@ function AgentChatPart({
3218
3399
  }
3219
3400
  );
3220
3401
  }
3221
- if (part.kind === "tool") return isAgentChatSubagent(part) ? /* @__PURE__ */ jsx14(AgentChatSubagentGroup, { part, slots: toolSlots }) : /* @__PURE__ */ jsx14(AgentChatToolRow, { activeToolId, part, slots: toolSlots });
3222
- if (part.kind === "model-turn") return /* @__PURE__ */ jsx14(AgentChatModelTurnRow, { part });
3402
+ if (part.kind === "tool") return isAgentChatSubagent(part) ? /* @__PURE__ */ jsx15(AgentChatSubagentGroup, { part, slots: toolSlots }) : /* @__PURE__ */ jsx15(AgentChatToolRow, { activeToolId, part, slots: toolSlots });
3403
+ if (part.kind === "model-turn") return /* @__PURE__ */ jsx15(AgentChatModelTurnRow, { part });
3223
3404
  if (part.kind === "reasoning") {
3224
3405
  const label = part.text || part.label || "Thinking";
3225
- return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ jsx14(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ jsx14("div", { className: "text-sm text-muted-foreground", children: label });
3406
+ return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ jsx15(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ jsx15("div", { className: "text-sm text-muted-foreground", children: label });
3226
3407
  }
3227
3408
  if (part.kind === "context-compression") {
3228
- return /* @__PURE__ */ jsx14(AgentChatContextCompressionRow, { part });
3409
+ return /* @__PURE__ */ jsx15(AgentChatContextCompressionRow, { part });
3229
3410
  }
3230
3411
  if (part.kind === "ui-blocks") {
3231
3412
  if (part.state === "output-error") {
3232
- return /* @__PURE__ */ jsx14("div", { className: "a24-timeline-error text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
3413
+ return /* @__PURE__ */ jsx15("div", { className: "a24-timeline-error text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
3233
3414
  }
3234
- return part.bundle ? /* @__PURE__ */ jsx14(SafeUiBlocks, { bundle: part.bundle }) : /* @__PURE__ */ jsx14("div", { className: "text-sm text-muted-foreground", children: part.state === "input-streaming" ? /* @__PURE__ */ jsx14(Shimmer, { children: "Rendering UI block" }) : "Rendered UI block" });
3415
+ return part.bundle ? /* @__PURE__ */ jsx15(SafeUiBlocks, { bundle: part.bundle }) : /* @__PURE__ */ jsx15("div", { className: "text-sm text-muted-foreground", children: part.state === "input-streaming" ? /* @__PURE__ */ jsx15(Shimmer, { children: "Rendering UI block" }) : "Rendered UI block" });
3235
3416
  }
3236
3417
  if (part.kind === "hitl") {
3237
- return /* @__PURE__ */ jsx14(
3418
+ return /* @__PURE__ */ jsx15(
3238
3419
  HitlPartRow,
3239
3420
  {
3240
3421
  getHitlActionState,
3422
+ hitlLabels,
3423
+ onHitlPaint,
3241
3424
  isLoading,
3242
3425
  onHitlAction,
3243
3426
  part
3244
3427
  }
3245
3428
  );
3246
3429
  }
3247
- if (part.kind === "error") return /* @__PURE__ */ jsx14("div", { className: "a24-timeline-error text-sm text-destructive", role: "alert", children: part.errorText });
3430
+ if (part.kind === "error") return /* @__PURE__ */ jsx15("div", { className: "a24-timeline-error text-sm text-destructive", role: "alert", children: part.errorText });
3248
3431
  if (part.kind === "source") {
3249
3432
  const href = safeExternalUrl(part.url);
3250
- return href ? /* @__PURE__ */ jsx14("a", { className: "a24-source-link", href, rel: "noopener noreferrer", target: "_blank", children: part.title }) : /* @__PURE__ */ jsx14("span", { className: "a24-source-link", children: part.title });
3433
+ return href ? /* @__PURE__ */ jsx15("a", { className: "a24-source-link", href, rel: "noopener noreferrer", target: "_blank", children: part.title }) : /* @__PURE__ */ jsx15("span", { className: "a24-source-link", children: part.title });
3251
3434
  }
3252
3435
  if (part.kind === "citation") {
3253
3436
  const href = safeExternalUrl(part.url);
3254
3437
  const label = part.label || "Citation";
3255
- return href ? /* @__PURE__ */ jsx14("a", { className: "a24-citation", href, rel: "noopener noreferrer", target: "_blank", children: label }) : /* @__PURE__ */ jsx14("span", { className: "a24-citation", children: label });
3438
+ return href ? /* @__PURE__ */ jsx15("a", { className: "a24-citation", href, rel: "noopener noreferrer", target: "_blank", children: label }) : /* @__PURE__ */ jsx15("span", { className: "a24-citation", children: label });
3256
3439
  }
3257
- if (part.kind === "attachment") return /* @__PURE__ */ jsx14("div", { className: "a24-output-attachment", children: part.attachment.filename || "Attachment" });
3258
- if (part.kind === "data") return /* @__PURE__ */ jsx14("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
3440
+ if (part.kind === "attachment") return /* @__PURE__ */ jsx15("div", { className: "a24-output-attachment", children: part.attachment.filename || "Attachment" });
3441
+ if (part.kind === "data") return /* @__PURE__ */ jsx15("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
3259
3442
  return null;
3260
3443
  }
3261
3444
  function safeExternalUrl(value) {
@@ -3269,28 +3452,28 @@ function safeExternalUrl(value) {
3269
3452
  }
3270
3453
  function SafeUiBlocks({ bundle }) {
3271
3454
  const rows = Array.isArray(bundle.rows) ? bundle.rows : [];
3272
- return /* @__PURE__ */ jsxs9("section", { "aria-label": typeof bundle.title === "string" ? bundle.title : "Agent result", className: "a24-ui-blocks", children: [
3273
- typeof bundle.title === "string" ? /* @__PURE__ */ jsx14("h3", { children: bundle.title }) : null,
3455
+ return /* @__PURE__ */ jsxs10("section", { "aria-label": typeof bundle.title === "string" ? bundle.title : "Agent result", className: "a24-ui-blocks", children: [
3456
+ typeof bundle.title === "string" ? /* @__PURE__ */ jsx15("h3", { children: bundle.title }) : null,
3274
3457
  rows.map((rawRow, rowIndex) => {
3275
3458
  const row = rawRow && typeof rawRow === "object" && !Array.isArray(rawRow) ? rawRow : {};
3276
3459
  const blocks = Array.isArray(row.blocks) ? row.blocks : [];
3277
- return /* @__PURE__ */ jsx14("div", { className: "a24-ui-blocks__row", children: blocks.map((rawBlock, blockIndex) => {
3460
+ return /* @__PURE__ */ jsx15("div", { className: "a24-ui-blocks__row", children: blocks.map((rawBlock, blockIndex) => {
3278
3461
  const block = rawBlock && typeof rawBlock === "object" && !Array.isArray(rawBlock) ? rawBlock : {};
3279
3462
  const title = typeof block.title === "string" ? block.title : "Result";
3280
3463
  const kind = String(block.kind || "note");
3281
3464
  if (kind === "table" && Array.isArray(block.columns) && Array.isArray(block.rows)) {
3282
- return /* @__PURE__ */ jsxs9("div", { className: "a24-ui-block", children: [
3283
- /* @__PURE__ */ jsx14("h4", { children: title }),
3284
- /* @__PURE__ */ jsx14("div", { className: "a24-ui-table-scroll", children: /* @__PURE__ */ jsxs9("table", { children: [
3285
- /* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsx14("tr", { children: block.columns.map((column, index) => /* @__PURE__ */ jsx14("th", { children: String(column) }, index)) }) }),
3286
- /* @__PURE__ */ jsx14("tbody", { children: block.rows.map((rawCells, index) => /* @__PURE__ */ jsx14("tr", { children: (Array.isArray(rawCells) ? rawCells : []).map((cell, cellIndex) => /* @__PURE__ */ jsx14("td", { children: String(cell) }, cellIndex)) }, index)) })
3465
+ return /* @__PURE__ */ jsxs10("div", { className: "a24-ui-block", children: [
3466
+ /* @__PURE__ */ jsx15("h4", { children: title }),
3467
+ /* @__PURE__ */ jsx15("div", { className: "a24-ui-table-scroll", children: /* @__PURE__ */ jsxs10("table", { children: [
3468
+ /* @__PURE__ */ jsx15("thead", { children: /* @__PURE__ */ jsx15("tr", { children: block.columns.map((column, index) => /* @__PURE__ */ jsx15("th", { children: String(column) }, index)) }) }),
3469
+ /* @__PURE__ */ jsx15("tbody", { children: block.rows.map((rawCells, index) => /* @__PURE__ */ jsx15("tr", { children: (Array.isArray(rawCells) ? rawCells : []).map((cell, cellIndex) => /* @__PURE__ */ jsx15("td", { children: String(cell) }, cellIndex)) }, index)) })
3287
3470
  ] }) })
3288
3471
  ] }, String(block.id || blockIndex));
3289
3472
  }
3290
3473
  const value = block.value ?? block.text ?? "";
3291
- return /* @__PURE__ */ jsxs9("div", { className: "a24-ui-block", children: [
3292
- /* @__PURE__ */ jsx14("h4", { children: title }),
3293
- /* @__PURE__ */ jsx14("p", { children: String(value) })
3474
+ return /* @__PURE__ */ jsxs10("div", { className: "a24-ui-block", children: [
3475
+ /* @__PURE__ */ jsx15("h4", { children: title }),
3476
+ /* @__PURE__ */ jsx15("p", { children: String(value) })
3294
3477
  ] }, String(block.id || blockIndex));
3295
3478
  }) }, `row-${rowIndex}`);
3296
3479
  })
@@ -3298,6 +3481,8 @@ function SafeUiBlocks({ bundle }) {
3298
3481
  }
3299
3482
  function AgentResponseTimeline({
3300
3483
  getHitlActionState,
3484
+ hitlLabels,
3485
+ onHitlPaint,
3301
3486
  isLoading = false,
3302
3487
  message,
3303
3488
  nodeActivityMode = "default",
@@ -3310,7 +3495,7 @@ function AgentResponseTimeline({
3310
3495
  toolViewMode = "closed"
3311
3496
  }) {
3312
3497
  isLoading = isLoading && !message.responseCompletion;
3313
- const parts = (displayParts || message.parts || []).filter((part) => (part.kind !== "tool" || !isInternalAskUserTool(part)) && (part.kind !== "hitl" || part.hitlKind === "user_input" || part.status === "pending") && (part.kind !== "model-turn" || part.turnKind === "agent") && (part.kind !== "node-activity" || nodeActivityMode === "all" || nodeActivityMode === "default" && part.defaultChatVisible));
3498
+ const parts = (displayParts || message.parts || []).filter((part) => (part.kind !== "tool" || !isInternalAskUserTool(part)) && (part.kind !== "hitl" || part.hitlKind === "user_input" || part.status === "pending" || getHitlActionState?.(part)?.status === "accepted") && (part.kind !== "model-turn" || part.turnKind === "agent") && (part.kind !== "node-activity" || nodeActivityMode === "all" || nodeActivityMode === "default" && part.defaultChatVisible));
3314
3499
  const toolParts = parts.filter((part) => part.kind === "tool");
3315
3500
  const activeToolId = latestRunningAgentChatToolId(toolParts);
3316
3501
  const activeTextPartId = getActiveStreamingTextPartId(
@@ -3324,42 +3509,44 @@ function AgentResponseTimeline({
3324
3509
  if (segment.kind === "tool") {
3325
3510
  const isLatestActivity = segmentIndex === segments.length - 1;
3326
3511
  const showOrb = toolViewMode === "closed" ? isLoading && isLatestActivity : Boolean(activeToolId && (segment.part.id === activeToolId || segment.part.toolCallId === activeToolId));
3327
- rendered.push(/* @__PURE__ */ jsx14(AgentChatToolRow, { activeToolId, part: segment.part, showOrb, slots: toolSlots }, segment.part.id));
3512
+ rendered.push(/* @__PURE__ */ jsx15(AgentChatToolRow, { activeToolId, part: segment.part, showOrb, slots: toolSlots }, segment.part.id));
3328
3513
  continue;
3329
3514
  }
3330
3515
  if (segment.kind === "tool-session") {
3331
- rendered.push(/* @__PURE__ */ jsx14(AgentChatToolSession, { activeToolId, isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, leadingModelTurn: segment.leadingModelTurn, modelTurn: segment.modelTurn, parts: segment.parts, slots: toolSlots }, `tool-session-${segment.parts[0].id}`));
3516
+ rendered.push(/* @__PURE__ */ jsx15(AgentChatToolSession, { activeToolId, isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, leadingModelTurn: segment.leadingModelTurn, modelTurn: segment.modelTurn, parts: segment.parts, slots: toolSlots }, `tool-session-${segment.parts[0].id}`));
3332
3517
  continue;
3333
3518
  }
3334
3519
  if (segment.kind === "subagent") {
3335
- rendered.push(/* @__PURE__ */ jsx14(AgentChatSubagentGroup, { isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, part: segment.part, slots: toolSlots }, segment.part.id));
3520
+ rendered.push(/* @__PURE__ */ jsx15(AgentChatSubagentGroup, { isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, part: segment.part, slots: toolSlots }, segment.part.id));
3336
3521
  continue;
3337
3522
  }
3338
3523
  const part = segment.part;
3339
3524
  if (part.kind === "model-turn") {
3340
3525
  const key = activeActivityClaimed ? part.id : `${message.id}-active-activity`;
3341
3526
  activeActivityClaimed = true;
3342
- rendered.push(/* @__PURE__ */ jsx14(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Planning next moves", modelTurnId: part.modelTurnId }, key));
3527
+ rendered.push(/* @__PURE__ */ jsx15(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Planning next moves", modelTurnId: part.modelTurnId }, key));
3343
3528
  continue;
3344
3529
  }
3345
3530
  if (part.kind === "node-activity") {
3346
3531
  const key = activeActivityClaimed ? part.id : `${message.id}-active-activity`;
3347
3532
  if (part.status === "running") activeActivityClaimed = true;
3348
3533
  rendered.push(
3349
- part.status === "running" ? /* @__PURE__ */ jsx14(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: part.label, onSelect: onNodeSelect ? () => onNodeSelect(part) : void 0 }, key) : /* @__PURE__ */ jsx14(AgentChatNodeActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, onSelect: onNodeSelect, part }, part.id)
3534
+ part.status === "running" ? /* @__PURE__ */ jsx15(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: part.label, onSelect: onNodeSelect ? () => onNodeSelect(part) : void 0 }, key) : /* @__PURE__ */ jsx15(AgentChatNodeActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, onSelect: onNodeSelect, part }, part.id)
3350
3535
  );
3351
3536
  continue;
3352
3537
  }
3353
3538
  if (part.kind === "ui-blocks" && renderUiBlocks) {
3354
- rendered.push(/* @__PURE__ */ jsx14(React15.Fragment, { children: renderUiBlocks(part) }, part.id));
3539
+ rendered.push(/* @__PURE__ */ jsx15(React16.Fragment, { children: renderUiBlocks(part) }, part.id));
3355
3540
  continue;
3356
3541
  }
3357
3542
  rendered.push(
3358
- /* @__PURE__ */ jsx14(React15.Fragment, { children: /* @__PURE__ */ jsx14(
3543
+ /* @__PURE__ */ jsx15(React16.Fragment, { children: /* @__PURE__ */ jsx15(
3359
3544
  AgentChatPart,
3360
3545
  {
3361
3546
  activeToolId,
3362
3547
  getHitlActionState,
3548
+ hitlLabels,
3549
+ onHitlPaint,
3363
3550
  isLoading,
3364
3551
  isTextStreaming: part.kind === "text" && part.id === activeTextPartId,
3365
3552
  message,
@@ -3372,16 +3559,16 @@ function AgentResponseTimeline({
3372
3559
  );
3373
3560
  }
3374
3561
  if (rendered.length === 0 && message.content) {
3375
- rendered.push(/* @__PURE__ */ jsx14(MessageResponse, { children: message.content }, `${message.id}-fallback`));
3562
+ rendered.push(/* @__PURE__ */ jsx15(MessageResponse, { children: message.content }, `${message.id}-fallback`));
3376
3563
  }
3377
3564
  if (rendered.length === 0 && isLoading) {
3378
- rendered.push(/* @__PURE__ */ jsx14(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Thinking" }, `${message.id}-active-activity`));
3565
+ rendered.push(/* @__PURE__ */ jsx15(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Thinking" }, `${message.id}-active-activity`));
3379
3566
  }
3380
- return /* @__PURE__ */ jsx14("div", { className: "space-y-3", children: rendered });
3567
+ return /* @__PURE__ */ jsx15("div", { className: "space-y-3", children: rendered });
3381
3568
  }
3382
3569
 
3383
3570
  // src/ui/agent-chat-message.tsx
3384
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3571
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
3385
3572
  var DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD = 360;
3386
3573
  var DEFAULT_USER_MESSAGE_COLLAPSED_LINES = 4;
3387
3574
  function shouldCollapseUserMessage(content, threshold = DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD) {
@@ -3394,8 +3581,8 @@ function AgentChatUserMessageContent({
3394
3581
  showLessLabel = "Show less",
3395
3582
  showMoreLabel = "Show more"
3396
3583
  }) {
3397
- const [isExpanded, setIsExpanded] = React16.useState(false);
3398
- const contentId = React16.useId();
3584
+ const [isExpanded, setIsExpanded] = React17.useState(false);
3585
+ const contentId = React17.useId();
3399
3586
  const shouldCollapse = shouldCollapseUserMessage(content, collapseThreshold);
3400
3587
  const Icon = isExpanded ? ChevronUp : ChevronDown3;
3401
3588
  const clampedStyle = shouldCollapse && !isExpanded ? {
@@ -3404,9 +3591,9 @@ function AgentChatUserMessageContent({
3404
3591
  display: "-webkit-box",
3405
3592
  overflow: "hidden"
3406
3593
  } : void 0;
3407
- return /* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 flex-col gap-3", children: [
3408
- /* @__PURE__ */ jsx15("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
3409
- shouldCollapse ? /* @__PURE__ */ jsxs10(
3594
+ return /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-col gap-3", children: [
3595
+ /* @__PURE__ */ jsx16("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
3596
+ shouldCollapse ? /* @__PURE__ */ jsxs11(
3410
3597
  "button",
3411
3598
  {
3412
3599
  "aria-controls": contentId,
@@ -3419,7 +3606,7 @@ function AgentChatUserMessageContent({
3419
3606
  type: "button",
3420
3607
  children: [
3421
3608
  isExpanded ? showLessLabel : showMoreLabel,
3422
- /* @__PURE__ */ jsx15(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
3609
+ /* @__PURE__ */ jsx16(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
3423
3610
  ]
3424
3611
  }
3425
3612
  ) : null
@@ -3429,9 +3616,9 @@ function AgentChatUserMessageActionRow({
3429
3616
  children,
3430
3617
  className
3431
3618
  }) {
3432
- const rowRef = React16.useRef(null);
3433
- const [visible, setVisible] = React16.useState(false);
3434
- React16.useEffect(() => {
3619
+ const rowRef = React17.useRef(null);
3620
+ const [visible, setVisible] = React17.useState(false);
3621
+ React17.useEffect(() => {
3435
3622
  const message = rowRef.current?.closest('[data-slot="message"]');
3436
3623
  if (!message) return;
3437
3624
  const show = () => setVisible(true);
@@ -3450,7 +3637,7 @@ function AgentChatUserMessageActionRow({
3450
3637
  message.removeEventListener("focusout", hideWhenFocusLeaves);
3451
3638
  };
3452
3639
  }, []);
3453
- return /* @__PURE__ */ jsx15(
3640
+ return /* @__PURE__ */ jsx16(
3454
3641
  "div",
3455
3642
  {
3456
3643
  ref: rowRef,
@@ -3470,6 +3657,8 @@ function AgentChatMessage({
3470
3657
  contentClassName,
3471
3658
  dir,
3472
3659
  getHitlActionState,
3660
+ hitlLabels,
3661
+ onHitlPaint,
3473
3662
  message,
3474
3663
  nodeActivityMode,
3475
3664
  onHitlAction,
@@ -3489,7 +3678,7 @@ function AgentChatMessage({
3489
3678
  const resolvedUserContent = userMessageContent ?? message.content;
3490
3679
  const shouldRenderContent = isAssistant || Boolean(renderUserContent || resolvedUserContent);
3491
3680
  const showAttachments = Boolean(message.attachments?.length) && (message.role === "user" || showAssistantAttachments);
3492
- const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ jsx15(
3681
+ const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ jsx16(
3493
3682
  AgentChatDefaultActions,
3494
3683
  {
3495
3684
  additionalActions,
@@ -3499,14 +3688,14 @@ function AgentChatMessage({
3499
3688
  }
3500
3689
  ) : null);
3501
3690
  const defaultUserActions = !actions && Boolean(actionHandlers) && !isAssistant;
3502
- return /* @__PURE__ */ jsxs10(
3691
+ return /* @__PURE__ */ jsxs11(
3503
3692
  ChatMessage,
3504
3693
  {
3505
3694
  className,
3506
3695
  dir,
3507
3696
  from: message.role,
3508
3697
  children: [
3509
- showAttachments ? /* @__PURE__ */ jsx15(
3698
+ showAttachments ? /* @__PURE__ */ jsx16(
3510
3699
  ChatAttachmentRows,
3511
3700
  {
3512
3701
  attachments: message.attachments || [],
@@ -3515,17 +3704,19 @@ function AgentChatMessage({
3515
3704
  resolveContent: attachmentContentResolver
3516
3705
  }
3517
3706
  ) : null,
3518
- shouldRenderContent ? /* @__PURE__ */ jsxs10(
3707
+ shouldRenderContent ? /* @__PURE__ */ jsxs11(
3519
3708
  ChatMessageContent,
3520
3709
  {
3521
3710
  className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
3522
3711
  dir,
3523
3712
  from: message.role,
3524
3713
  children: [
3525
- isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ jsx15(
3714
+ isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ jsx16(
3526
3715
  Timeline,
3527
3716
  {
3528
3717
  getHitlActionState,
3718
+ hitlLabels,
3719
+ onHitlPaint,
3529
3720
  isLoading: isStreaming,
3530
3721
  message,
3531
3722
  nodeActivityMode,
@@ -3533,7 +3724,7 @@ function AgentChatMessage({
3533
3724
  parts: message.parts
3534
3725
  }
3535
3726
  ) : null,
3536
- !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ jsx15(
3727
+ !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ jsx16(
3537
3728
  AgentChatUserMessageContent,
3538
3729
  {
3539
3730
  collapsedLines: userMessageCollapsedLines,
@@ -3546,7 +3737,11 @@ function AgentChatMessage({
3546
3737
  ]
3547
3738
  }
3548
3739
  ) : null,
3549
- renderedActions ? defaultUserActions ? /* @__PURE__ */ jsx15(AgentChatUserMessageActionRow, { className: actionsClassName, children: renderedActions }) : /* @__PURE__ */ jsx15("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
3740
+ renderedActions ? defaultUserActions ? /* @__PURE__ */ jsx16(AgentChatUserMessageActionRow, { className: actionsClassName, children: renderedActions }) : /* @__PURE__ */ jsx16("div", { className: cn(
3741
+ dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2",
3742
+ isAssistant && "a24-chat-message-action-row--assistant",
3743
+ actionsClassName
3744
+ ), children: renderedActions }) : null
3550
3745
  ]
3551
3746
  }
3552
3747
  );
@@ -3555,9 +3750,9 @@ function AgentChatMessage({
3555
3750
  // src/ui/bubble.tsx
3556
3751
  import { cva as cva3 } from "class-variance-authority";
3557
3752
  import { Slot as Slot2 } from "@radix-ui/react-slot";
3558
- import { jsx as jsx16 } from "react/jsx-runtime";
3753
+ import { jsx as jsx17 } from "react/jsx-runtime";
3559
3754
  function BubbleGroup({ className, ...props }) {
3560
- return /* @__PURE__ */ jsx16(
3755
+ return /* @__PURE__ */ jsx17(
3561
3756
  "div",
3562
3757
  {
3563
3758
  "data-slot": "bubble-group",
@@ -3591,7 +3786,7 @@ function Bubble({
3591
3786
  className,
3592
3787
  ...props
3593
3788
  }) {
3594
- return /* @__PURE__ */ jsx16(
3789
+ return /* @__PURE__ */ jsx17(
3595
3790
  "div",
3596
3791
  {
3597
3792
  "data-slot": "bubble",
@@ -3608,7 +3803,7 @@ function BubbleContent({
3608
3803
  ...props
3609
3804
  }) {
3610
3805
  const Comp = asChild ? Slot2 : "div";
3611
- return /* @__PURE__ */ jsx16(
3806
+ return /* @__PURE__ */ jsx17(
3612
3807
  Comp,
3613
3808
  {
3614
3809
  "data-slot": "bubble-content",
@@ -3645,7 +3840,7 @@ function BubbleReactions({
3645
3840
  className,
3646
3841
  ...props
3647
3842
  }) {
3648
- return /* @__PURE__ */ jsx16(
3843
+ return /* @__PURE__ */ jsx17(
3649
3844
  "div",
3650
3845
  {
3651
3846
  "data-slot": "bubble-reactions",
@@ -3660,7 +3855,7 @@ function BubbleReactions({
3660
3855
  // src/ui/marker.tsx
3661
3856
  import { cva as cva4 } from "class-variance-authority";
3662
3857
  import { Slot as Slot3 } from "@radix-ui/react-slot";
3663
- import { jsx as jsx17 } from "react/jsx-runtime";
3858
+ import { jsx as jsx18 } from "react/jsx-runtime";
3664
3859
  var markerVariants = cva4(
3665
3860
  "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
3666
3861
  {
@@ -3680,7 +3875,7 @@ function Marker({
3680
3875
  ...props
3681
3876
  }) {
3682
3877
  const Comp = asChild ? Slot3 : "div";
3683
- return /* @__PURE__ */ jsx17(
3878
+ return /* @__PURE__ */ jsx18(
3684
3879
  Comp,
3685
3880
  {
3686
3881
  "data-slot": "marker",
@@ -3691,7 +3886,7 @@ function Marker({
3691
3886
  );
3692
3887
  }
3693
3888
  function MarkerIcon({ className, ...props }) {
3694
- return /* @__PURE__ */ jsx17(
3889
+ return /* @__PURE__ */ jsx18(
3695
3890
  "span",
3696
3891
  {
3697
3892
  "data-slot": "marker-icon",
@@ -3705,7 +3900,7 @@ function MarkerIcon({ className, ...props }) {
3705
3900
  );
3706
3901
  }
3707
3902
  function MarkerContent({ className, ...props }) {
3708
- return /* @__PURE__ */ jsx17(
3903
+ return /* @__PURE__ */ jsx18(
3709
3904
  "span",
3710
3905
  {
3711
3906
  "data-slot": "marker-content",
@@ -3719,7 +3914,7 @@ function MarkerContent({ className, ...props }) {
3719
3914
  }
3720
3915
 
3721
3916
  // src/ui/mcp-connect-required-card.tsx
3722
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
3917
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
3723
3918
  var STATUS_LABELS = {
3724
3919
  pending: "Connect",
3725
3920
  connecting: "Connecting",
@@ -3743,7 +3938,7 @@ function McpConnectRequiredCard({
3743
3938
  const isBusy = loading || status === "connecting" || status === "resuming";
3744
3939
  const isConnected = status === "connected";
3745
3940
  const buttonDisabled = disabled || isBusy || isConnected || !onConnect;
3746
- return /* @__PURE__ */ jsx18(
3941
+ return /* @__PURE__ */ jsx19(
3747
3942
  "div",
3748
3943
  {
3749
3944
  "data-agents24-mcp-connect-card": true,
@@ -3753,13 +3948,13 @@ function McpConnectRequiredCard({
3753
3948
  className
3754
3949
  ),
3755
3950
  ...props,
3756
- children: /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
3757
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
3758
- /* @__PURE__ */ jsx18("div", { className: "truncate text-sm font-medium", children: label }),
3759
- /* @__PURE__ */ jsx18("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
3760
- status === "error" && error ? /* @__PURE__ */ jsx18("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
3951
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
3952
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
3953
+ /* @__PURE__ */ jsx19("div", { className: "truncate text-sm font-medium", children: label }),
3954
+ /* @__PURE__ */ jsx19("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
3955
+ status === "error" && error ? /* @__PURE__ */ jsx19("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
3761
3956
  ] }),
3762
- /* @__PURE__ */ jsx18(
3957
+ /* @__PURE__ */ jsx19(
3763
3958
  "button",
3764
3959
  {
3765
3960
  type: "button",
@@ -3826,6 +4021,7 @@ export {
3826
4021
  CodeBlockLine,
3827
4022
  CodeBlockTitle,
3828
4023
  CodeBlockWrapButton,
4024
+ HitlSubmissionStatus,
3829
4025
  Marker,
3830
4026
  MarkerContent,
3831
4027
  MarkerIcon,
@@ -3852,10 +4048,12 @@ export {
3852
4048
  cn,
3853
4049
  contextStatusMetrics,
3854
4050
  createAgentChatComposerFile,
4051
+ defaultHitlSubmissionLabels,
3855
4052
  hitlActionLabel,
3856
4053
  hitlTitle,
3857
4054
  isAgentChatSubagent,
3858
4055
  isAgentChatToolRunning,
4056
+ isHitlSubmissionCompact,
3859
4057
  latestRunningAgentChatToolId,
3860
4058
  markerVariants,
3861
4059
  partitionAgentChatToolTimeline,