@agents24/chat-react 0.5.35 → 0.5.37

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 (46) hide show
  1. package/compatibility.json +5 -5
  2. package/dist/{chunk-INO5DSSJ.js → chunk-DWDHK4FZ.js} +3 -4
  3. package/dist/chunk-DWDHK4FZ.js.map +1 -0
  4. package/dist/generated/delegation-types.d.ts +3 -2
  5. package/dist/generated/run-usage.d.ts +11 -0
  6. package/dist/registry/agents24-chat.json +13 -13
  7. package/dist/runtime/index.cjs +25 -9
  8. package/dist/runtime/index.cjs.map +1 -1
  9. package/dist/runtime/index.js +24 -7
  10. package/dist/runtime/index.js.map +1 -1
  11. package/dist/runtime/input-contract.d.ts +1 -1
  12. package/dist/runtime/use-agent-chat-hitl.d.ts +2 -2
  13. package/dist/runtime/use-agent-chat-runtime.d.ts +4 -6
  14. package/dist/scaffold/app.d.ts +2 -2
  15. package/dist/scaffold/components/chat/chat-composer.d.ts +2 -1
  16. package/dist/scaffold/components/chat/chat-message.d.ts +2 -2
  17. package/dist/scaffold/components/chat/message-parts.d.ts +2 -2
  18. package/dist/scaffold/index.cjs +17 -13
  19. package/dist/scaffold/index.cjs.map +1 -1
  20. package/dist/scaffold/index.js +11 -7
  21. package/dist/scaffold/index.js.map +1 -1
  22. package/dist/styles.css +55 -0
  23. package/dist/ui/agent-chat-composer.d.ts +2 -1
  24. package/dist/ui/agent-chat-message.d.ts +6 -2
  25. package/dist/ui/agent-response-timeline.d.ts +11 -3
  26. package/dist/ui/ask-user-interaction.d.ts +5 -1
  27. package/dist/ui/bubble.d.ts +1 -1
  28. package/dist/ui/code-block.d.ts +33 -0
  29. package/dist/ui/code-highlighter.d.ts +8 -0
  30. package/dist/ui/hitl-submission-status.d.ts +22 -0
  31. package/dist/ui/index.cjs +985 -301
  32. package/dist/ui/index.cjs.map +1 -1
  33. package/dist/ui/index.d.ts +3 -0
  34. package/dist/ui/index.js +969 -296
  35. package/dist/ui/index.js.map +1 -1
  36. package/dist/ui/message-code.d.ts +21 -0
  37. package/dist/ui/use-agent-chat-composer.d.ts +17 -2
  38. package/dist/ui/use-audio-recorder.d.ts +15 -2
  39. package/dist/ui/use-highlighted-code.d.ts +2 -0
  40. package/package.json +4 -3
  41. package/scaffold/src/app.tsx +2 -1
  42. package/scaffold/src/components/chat/chat-composer.tsx +5 -3
  43. package/scaffold/src/components/chat/chat-message.tsx +3 -3
  44. package/scaffold/src/components/chat/chat-shell.tsx +2 -1
  45. package/scaffold/src/components/chat/message-parts.tsx +6 -6
  46. package/dist/chunk-INO5DSSJ.js.map +0 -1
package/dist/ui/index.cjs CHANGED
@@ -69,6 +69,17 @@ __export(ui_exports, {
69
69
  ChatMessageAction: () => ChatMessageAction,
70
70
  ChatMessageActions: () => ChatMessageActions,
71
71
  ChatMessageContent: () => ChatMessageContent,
72
+ CodeBlock: () => CodeBlock,
73
+ CodeBlockActions: () => CodeBlockActions,
74
+ CodeBlockContent: () => CodeBlockContent,
75
+ CodeBlockCopyButton: () => CodeBlockCopyButton,
76
+ CodeBlockDownloadButton: () => CodeBlockDownloadButton,
77
+ CodeBlockFooter: () => CodeBlockFooter,
78
+ CodeBlockHeader: () => CodeBlockHeader,
79
+ CodeBlockLine: () => CodeBlockLine,
80
+ CodeBlockTitle: () => CodeBlockTitle,
81
+ CodeBlockWrapButton: () => CodeBlockWrapButton,
82
+ HitlSubmissionStatus: () => HitlSubmissionStatus,
72
83
  Marker: () => Marker,
73
84
  MarkerContent: () => MarkerContent,
74
85
  MarkerIcon: () => MarkerIcon,
@@ -95,10 +106,12 @@ __export(ui_exports, {
95
106
  cn: () => cn,
96
107
  contextStatusMetrics: () => contextStatusMetrics,
97
108
  createAgentChatComposerFile: () => createAgentChatComposerFile,
109
+ defaultHitlSubmissionLabels: () => defaultHitlSubmissionLabels,
98
110
  hitlActionLabel: () => hitlActionLabel,
99
111
  hitlTitle: () => hitlTitle,
100
112
  isAgentChatSubagent: () => isAgentChatSubagent,
101
113
  isAgentChatToolRunning: () => isAgentChatToolRunning,
114
+ isHitlSubmissionCompact: () => isHitlSubmissionCompact,
102
115
  latestRunningAgentChatToolId: () => latestRunningAgentChatToolId,
103
116
  markerVariants: () => markerVariants,
104
117
  partitionAgentChatToolTimeline: () => partitionAgentChatToolTimeline,
@@ -110,6 +123,7 @@ __export(ui_exports, {
110
123
  useAudioRecorder: () => useAudioRecorder,
111
124
  useChatComposerFocus: () => useChatComposerFocus,
112
125
  useCompletionActionEntrance: () => useCompletionActionEntrance,
126
+ useHighlightedCode: () => useHighlightedCode,
113
127
  useLiveCompletionRuns: () => useLiveCompletionRuns
114
128
  });
115
129
  module.exports = __toCommonJS(ui_exports);
@@ -850,13 +864,12 @@ function uploadByteSize(data) {
850
864
  function inputMimeTypes(contract) {
851
865
  if (!contract) return [];
852
866
  return [
853
- ...contract.modalities.files.allowed_mime_types,
854
- ...contract.modalities.images.allowed_mime_types,
855
- ...contract.modalities.audio.allowed_mime_types
867
+ ...["files", "images", "audio"].flatMap((key) => contract.modalities[key].enabled ? contract.modalities[key].allowed_mime_types : [])
856
868
  ];
857
869
  }
858
870
  function validateAgentChatSubmission(contract, text, files) {
859
871
  const { modalities, limits } = contract;
872
+ if (files.length && contract.validation_issues?.length) return contract.validation_issues[0].message;
860
873
  const normalizedText = text.trim();
861
874
  if (normalizedText && !modalities.text.enabled) return "This agent does not accept text input.";
862
875
  if (modalities.text.required && !normalizedText) return "Text input is required.";
@@ -947,47 +960,69 @@ function useChatComposerFocus({ textareaRef, disabled, focusKey, restoredDraft,
947
960
 
948
961
  // src/ui/use-audio-recorder.ts
949
962
  var React3 = __toESM(require("react"), 1);
963
+ var import_client4 = require("@agents24/client");
950
964
  var RECORDING_CANDIDATES = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4"];
951
965
  function useAudioRecorder(onRecorded, options = {}) {
952
966
  const recorderRef = React3.useRef(null);
953
967
  const streamRef = React3.useRef(null);
968
+ const operationRef = React3.useRef(null);
954
969
  const pendingRef = React3.useRef(false);
955
- const generationRef = React3.useRef(0);
956
- const onRecordedRef = React3.useRef(onRecorded);
957
- const onStreamChangeRef = React3.useRef(options.onStreamChange);
958
- React3.useEffect(() => {
959
- onRecordedRef.current = onRecorded;
960
- onStreamChangeRef.current = options.onStreamChange;
970
+ const callbacksRef = React3.useRef({ onRecorded, onStreamChange: options.onStreamChange, acceptedMimeTypes: options.acceptedMimeTypes });
971
+ React3.useLayoutEffect(() => {
972
+ callbacksRef.current = { onRecorded, onStreamChange: options.onStreamChange, acceptedMimeTypes: options.acceptedMimeTypes };
961
973
  });
962
974
  const [isRecording, setIsRecording] = React3.useState(false);
975
+ const [isStarting, setIsStarting] = React3.useState(false);
976
+ const [isProcessing, setIsProcessing] = React3.useState(false);
963
977
  const [error, setError] = React3.useState(null);
964
978
  const release = React3.useCallback(() => {
965
979
  streamRef.current?.getTracks().forEach((track) => track.stop());
966
980
  streamRef.current = null;
967
981
  recorderRef.current = null;
968
- onStreamChangeRef.current?.(null);
982
+ callbacksRef.current.onStreamChange?.(null);
969
983
  }, []);
984
+ const discard = React3.useCallback(() => {
985
+ operationRef.current?.controller.abort();
986
+ operationRef.current = null;
987
+ pendingRef.current = false;
988
+ const recorder = recorderRef.current;
989
+ if (recorder) {
990
+ recorder.onstop = null;
991
+ recorder.onerror = null;
992
+ recorder.ondataavailable = null;
993
+ if (recorder.state !== "inactive") recorder.stop();
994
+ }
995
+ release();
996
+ }, [release]);
997
+ const cancel = React3.useCallback(() => {
998
+ discard();
999
+ setIsStarting(false);
1000
+ setIsRecording(false);
1001
+ setIsProcessing(false);
1002
+ setError(null);
1003
+ }, [discard]);
970
1004
  const stop = React3.useCallback(() => {
971
1005
  const recorder = recorderRef.current;
972
1006
  if (recorder && recorder.state !== "inactive") recorder.stop();
973
1007
  }, []);
974
- const start = React3.useCallback(async () => {
975
- if (pendingRef.current || recorderRef.current) return;
1008
+ const isCapturing = React3.useCallback(() => pendingRef.current || recorderRef.current !== null, []);
1009
+ const start = React3.useCallback(async (startOptions = {}) => {
1010
+ if (operationRef.current) return;
976
1011
  setError(null);
977
1012
  if (!navigator.mediaDevices?.getUserMedia || typeof MediaRecorder === "undefined") {
978
1013
  setError("Audio recording is not supported in this browser.");
979
1014
  return;
980
1015
  }
1016
+ const controller = new AbortController();
1017
+ const operation = { operationId: startOptions.operationId ?? crypto.randomUUID(), signal: controller.signal, controller };
1018
+ operationRef.current = operation;
981
1019
  pendingRef.current = true;
982
- const generation = generationRef.current;
1020
+ setIsStarting(true);
983
1021
  try {
984
- const mimeType = RECORDING_CANDIDATES.find((candidate) => MediaRecorder.isTypeSupported(candidate));
985
- if (!mimeType) {
986
- setError("Audio recording is not supported in this browser.");
987
- return;
988
- }
1022
+ const mimeType = RECORDING_CANDIDATES.find((candidate) => MediaRecorder.isTypeSupported(candidate) && (callbacksRef.current.acceptedMimeTypes === void 0 || callbacksRef.current.acceptedMimeTypes.includes((0, import_client4.normalizeAttachmentMimeType)(candidate))));
1023
+ if (!mimeType) throw new Error("unsupported");
989
1024
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
990
- if (generation !== generationRef.current) {
1025
+ if (operation.signal.aborted) {
991
1026
  stream.getTracks().forEach((track) => track.stop());
992
1027
  return;
993
1028
  }
@@ -999,48 +1034,54 @@ function useAudioRecorder(onRecorded, options = {}) {
999
1034
  if (event.data.size) chunks.push(event.data);
1000
1035
  };
1001
1036
  recorder.onstop = () => {
1002
- if (generation !== generationRef.current) return;
1037
+ if (operation.signal.aborted) return;
1003
1038
  const actualType = recorder.mimeType || mimeType;
1004
- const extension = actualType.startsWith("audio/mp4") ? "m4a" : "webm";
1005
- try {
1006
- onRecordedRef.current(new File([new Blob(chunks, { type: actualType })], `recording-${Date.now()}.${extension}`, { type: actualType }));
1007
- } finally {
1008
- release();
1009
- setIsRecording(false);
1039
+ const accepted = callbacksRef.current.acceptedMimeTypes;
1040
+ if (accepted !== void 0 && !accepted.includes((0, import_client4.normalizeAttachmentMimeType)(actualType))) {
1041
+ cancel();
1042
+ setError("This Agent does not accept the recorded audio format.");
1043
+ return;
1010
1044
  }
1011
- };
1012
- recorder.onerror = () => {
1013
- recorder.onstop = null;
1014
- if (recorder.state !== "inactive") recorder.stop();
1045
+ const extension = actualType.startsWith("audio/mp4") ? "m4a" : "webm";
1046
+ const file = new File(chunks, `recording-${Date.now()}.${extension}`, { type: actualType });
1015
1047
  release();
1016
1048
  setIsRecording(false);
1049
+ setIsProcessing(true);
1050
+ void Promise.resolve().then(() => {
1051
+ if (!operation.signal.aborted) return callbacksRef.current.onRecorded(file, operation);
1052
+ }).catch(() => {
1053
+ if (!operation.signal.aborted) setError("Recording processing failed.");
1054
+ }).finally(() => {
1055
+ if (operationRef.current === operation) {
1056
+ operationRef.current = null;
1057
+ setIsProcessing(false);
1058
+ }
1059
+ });
1060
+ };
1061
+ recorder.onerror = () => {
1062
+ cancel();
1017
1063
  setError("Audio recording failed. Try again.");
1018
1064
  };
1019
1065
  recorder.start();
1020
1066
  setIsRecording(true);
1021
- onStreamChangeRef.current?.(stream);
1067
+ callbacksRef.current.onStreamChange?.(stream);
1022
1068
  } catch {
1023
- if (generation === generationRef.current) {
1024
- release();
1025
- setIsRecording(false);
1026
- setError("Microphone access is unavailable.");
1069
+ if (!operation.signal.aborted) {
1070
+ cancel();
1071
+ setError("Microphone access or audio recording is unavailable.");
1027
1072
  }
1028
1073
  } finally {
1029
- if (generation === generationRef.current) pendingRef.current = false;
1030
- }
1031
- }, [release]);
1032
- React3.useEffect(() => () => {
1033
- generationRef.current += 1;
1034
- pendingRef.current = false;
1035
- const recorder = recorderRef.current;
1036
- if (recorder) {
1037
- recorder.onstop = null;
1038
- recorder.onerror = null;
1039
- if (recorder.state !== "inactive") recorder.stop();
1074
+ if (!operation.signal.aborted) {
1075
+ pendingRef.current = false;
1076
+ setIsStarting(false);
1077
+ }
1040
1078
  }
1041
- release();
1042
- }, [release]);
1043
- return { error, isRecording, start, stop };
1079
+ }, [cancel, discard, release]);
1080
+ React3.useLayoutEffect(() => {
1081
+ cancel();
1082
+ return discard;
1083
+ }, [options.scopeKey, cancel, discard]);
1084
+ return { error, isRecording, isStarting, isProcessing, isCapturing, start, stop, cancel };
1044
1085
  }
1045
1086
 
1046
1087
  // src/ui/use-agent-chat-composer.ts
@@ -1052,16 +1093,29 @@ function useAgentChatComposer(options) {
1052
1093
  const localTextareaRef = React4.useRef(null);
1053
1094
  const textareaRef = options.textareaRef ?? localTextareaRef;
1054
1095
  const filesRef = React4.useRef(files);
1055
- const inFlightFilesRef = React4.useRef([]);
1096
+ const inFlightFilesRef = React4.useRef(/* @__PURE__ */ new Map());
1056
1097
  const revisionRef = React4.useRef(0);
1057
1098
  const submittingRef = React4.useRef(false);
1058
- React4.useEffect(() => {
1059
- filesRef.current = files;
1060
- }, [files]);
1099
+ const generationRef = React4.useRef(0);
1100
+ const mountedRef = React4.useRef(true);
1101
+ const textRef = React4.useRef(text);
1102
+ React4.useLayoutEffect(() => {
1103
+ mountedRef.current = true;
1104
+ submittingRef.current = false;
1105
+ setIsSubmitting(false);
1106
+ return () => {
1107
+ mountedRef.current = false;
1108
+ generationRef.current += 1;
1109
+ };
1110
+ }, [options.scopeKey]);
1061
1111
  React4.useEffect(() => () => {
1062
1112
  revokeAgentChatComposerFiles(filesRef.current);
1063
- revokeAgentChatComposerFiles(inFlightFilesRef.current);
1113
+ revokeAgentChatComposerFiles([...inFlightFilesRef.current.values()].flat());
1064
1114
  }, []);
1115
+ const revokeUnownedFiles = (candidates) => {
1116
+ const retained = new Set([...filesRef.current, ...[...inFlightFilesRef.current.values()].flat()].map((file) => file.url));
1117
+ revokeAgentChatComposerFiles(candidates.filter((file) => !retained.has(file.url)));
1118
+ };
1065
1119
  const focusComposer = useChatComposerFocus({
1066
1120
  textareaRef,
1067
1121
  disabled: Boolean(options.disabled),
@@ -1069,7 +1123,10 @@ function useAgentChatComposer(options) {
1069
1123
  restoredDraft: options.restoredDraft,
1070
1124
  onRestore: (draft) => {
1071
1125
  revisionRef.current += 1;
1072
- revokeAgentChatComposerFiles(filesRef.current);
1126
+ const previousFiles = filesRef.current;
1127
+ textRef.current = draft.text;
1128
+ filesRef.current = draft.files;
1129
+ revokeUnownedFiles(previousFiles);
1073
1130
  setTextState(draft.text);
1074
1131
  setFiles(draft.files);
1075
1132
  }
@@ -1077,52 +1134,80 @@ function useAgentChatComposer(options) {
1077
1134
  const attachmentMimeTypes = inputMimeTypes(options.inputContract);
1078
1135
  const setText = (value) => {
1079
1136
  revisionRef.current += 1;
1137
+ textRef.current = value;
1080
1138
  setTextState(value);
1081
1139
  };
1082
1140
  const addFiles = (selected) => {
1083
1141
  const accepted = selected.filter((file) => attachmentMimeTypes.includes(canonicalInputMimeType(file.type, file.name)));
1084
1142
  revisionRef.current += 1;
1085
- const additions = accepted.map(createAgentChatComposerFile);
1086
- setFiles((current) => [...current, ...additions]);
1143
+ const additions = selected.map(createAgentChatComposerFile);
1144
+ filesRef.current = [...filesRef.current, ...additions];
1145
+ setFiles(filesRef.current);
1087
1146
  setAttachmentError(accepted.length === selected.length ? null : "One or more selected file types are not supported by this Agent.");
1088
1147
  };
1089
1148
  const removeFile = (id) => {
1090
1149
  revisionRef.current += 1;
1091
1150
  const removed = filesRef.current.find((file) => file.id === id);
1092
- if (removed) revokeAgentChatComposerFiles([removed]);
1093
- setFiles((current) => current.filter((file) => file.id !== id));
1151
+ filesRef.current = filesRef.current.filter((file) => file.id !== id);
1152
+ if (removed) revokeUnownedFiles([removed]);
1153
+ setFiles(filesRef.current);
1094
1154
  };
1095
- const recorder = useAudioRecorder((file) => addFiles([file]), { onStreamChange: options.onRecordingStreamChange });
1155
+ const recorder = useAudioRecorder(
1156
+ (file, context) => options.onRecordingComplete ? options.onRecordingComplete(file, context) : addFiles([file]),
1157
+ {
1158
+ onStreamChange: options.onRecordingStreamChange,
1159
+ scopeKey: options.scopeKey,
1160
+ acceptedMimeTypes: options.onRecordingComplete ? void 0 : options.inputContract?.modalities.audio.allowed_mime_types ?? []
1161
+ }
1162
+ );
1096
1163
  const validationError = options.inputContract ? validateAgentChatSubmission(
1097
1164
  options.inputContract,
1098
1165
  text,
1099
1166
  files.map((file) => ({ data: file.source || new Uint8Array(), mediaType: file.mediaType, name: file.filename, byteSize: file.byteSize }))
1100
1167
  ) : null;
1101
- const canSubmit = Boolean(text.trim() || files.length) && !options.disabled && !options.isCancelling && !isSubmitting && !recorder.isRecording && !validationError;
1102
- const submit = async () => {
1103
- if (!canSubmit || submittingRef.current) return;
1104
- const value = text;
1105
- const selectedFiles = files;
1168
+ const canSubmit = Boolean(text.trim() || files.length) && !options.disabled && !options.isCancelling && !isSubmitting && !recorder.isRecording && !recorder.isStarting && !recorder.isProcessing && !validationError;
1169
+ const submit = async (submission) => {
1170
+ const value = submission?.text ?? textRef.current;
1171
+ const selectedFiles = submission?.files ?? filesRef.current;
1172
+ const suppliedError = options.inputContract ? validateAgentChatSubmission(
1173
+ options.inputContract,
1174
+ value,
1175
+ selectedFiles.map((file) => ({ data: file.source || new Uint8Array(), mediaType: file.mediaType, name: file.filename, byteSize: file.byteSize }))
1176
+ ) : null;
1177
+ if (!mountedRef.current || !value.trim() && !selectedFiles.length || options.disabled || options.isCancelling || submittingRef.current || recorder.isCapturing() || !submission && recorder.isProcessing || suppliedError) return false;
1178
+ const generation = generationRef.current;
1106
1179
  const clearedRevision = ++revisionRef.current;
1107
1180
  submittingRef.current = true;
1108
1181
  setIsSubmitting(true);
1109
- inFlightFilesRef.current = selectedFiles;
1182
+ const selectedUrls = new Set(selectedFiles.map((file) => file.url));
1183
+ const replacedFiles = filesRef.current.filter((file) => !selectedUrls.has(file.url));
1184
+ const submissionId = /* @__PURE__ */ Symbol();
1185
+ inFlightFilesRef.current.set(submissionId, selectedFiles);
1186
+ textRef.current = "";
1187
+ filesRef.current = [];
1188
+ revokeUnownedFiles(replacedFiles);
1110
1189
  setTextState("");
1111
1190
  setFiles([]);
1112
1191
  focusComposer();
1113
1192
  try {
1114
1193
  await options.onSubmit(value, selectedFiles);
1115
- revokeAgentChatComposerFiles(selectedFiles);
1194
+ return true;
1116
1195
  } catch {
1117
- if (revisionRef.current === clearedRevision) {
1196
+ if (mountedRef.current && generationRef.current === generation && revisionRef.current === clearedRevision) {
1118
1197
  revisionRef.current += 1;
1198
+ textRef.current = value;
1199
+ filesRef.current = selectedFiles;
1119
1200
  setTextState(value);
1120
1201
  setFiles(selectedFiles);
1121
- } else revokeAgentChatComposerFiles(selectedFiles);
1202
+ }
1203
+ return false;
1122
1204
  } finally {
1123
- inFlightFilesRef.current = [];
1124
- submittingRef.current = false;
1125
- setIsSubmitting(false);
1205
+ inFlightFilesRef.current.delete(submissionId);
1206
+ revokeUnownedFiles(selectedFiles);
1207
+ if (mountedRef.current && generationRef.current === generation) {
1208
+ submittingRef.current = false;
1209
+ setIsSubmitting(false);
1210
+ }
1126
1211
  }
1127
1212
  };
1128
1213
  return {
@@ -1139,6 +1224,7 @@ function useAgentChatComposer(options) {
1139
1224
  attachmentMimeTypes,
1140
1225
  validationError,
1141
1226
  recorder,
1227
+ isProcessing: recorder.isProcessing,
1142
1228
  recordingAllowed: options.recordingEnabled ?? options.inputContract?.modalities.audio.recording_enabled ?? false,
1143
1229
  fileAccept: (0, import_client2.attachmentFileAccept)(attachmentMimeTypes),
1144
1230
  onKeyDown: (event) => {
@@ -1272,6 +1358,7 @@ function AgentChatComposer({
1272
1358
  disabled = false,
1273
1359
  forceExpanded = false,
1274
1360
  focusKey,
1361
+ scopeKey,
1275
1362
  inputToolbarContent,
1276
1363
  isRunning = false,
1277
1364
  isCancelling = false,
@@ -1290,6 +1377,7 @@ function AgentChatComposer({
1290
1377
  disabled,
1291
1378
  isRunning,
1292
1379
  isCancelling,
1380
+ scopeKey,
1293
1381
  focusKey,
1294
1382
  restoredDraft,
1295
1383
  textareaRef: localTextareaRef,
@@ -1524,7 +1612,7 @@ function QueueRow({ message, onRemove, onEdit }) {
1524
1612
  }
1525
1613
  function AgentChatQueue({ pending, queue, onRemove, onEdit, onResume, className }) {
1526
1614
  const [resumeError, setResumeError] = React7.useState(null);
1527
- if (!pending.length && !queue?.paused) return null;
1615
+ if (!pending.length) return null;
1528
1616
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { "aria-label": "Message queue", className: cn("a24-queue relative z-0 -mb-2 overflow-visible rounded-t-xl border border-b-0 border-border/50 bg-background pb-2", className), children: [
1529
1617
  queue?.paused ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-h-9 items-center justify-between gap-2 px-3 text-xs text-muted-foreground", children: [
1530
1618
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Queue paused" }),
@@ -1771,11 +1859,68 @@ function AgentChatDefaultActions({
1771
1859
  }
1772
1860
 
1773
1861
  // src/ui/agent-chat-message.tsx
1774
- var React13 = __toESM(require("react"), 1);
1775
- var import_lucide_react7 = require("lucide-react");
1862
+ var React17 = __toESM(require("react"), 1);
1863
+ var import_lucide_react9 = require("lucide-react");
1864
+
1865
+ // src/ui/hitl-submission-status.tsx
1866
+ var React9 = __toESM(require("react"), 1);
1867
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1868
+ var defaultHitlSubmissionLabels = {
1869
+ submitting: "Submitting\u2026",
1870
+ checking: "Checking submission\u2026",
1871
+ uncertain: "Submission could not be confirmed.",
1872
+ retry: "Retry submission",
1873
+ accepted: "Accepted; agent continuing",
1874
+ approved: "Approved; agent continuing",
1875
+ rejected: "Rejected"
1876
+ };
1877
+ function isHitlSubmissionCompact(state) {
1878
+ return ["submitting", "resuming", "checking", "uncertain", "accepted"].includes(state?.status || "");
1879
+ }
1880
+ function HitlSubmissionStatus({ state, labels: overrides, onPaint }) {
1881
+ const labels = { ...defaultHitlSubmissionLabels, ...overrides };
1882
+ const started = React9.useRef(performance.now());
1883
+ const ref = React9.useRef(null);
1884
+ const paintCallback = React9.useRef(onPaint);
1885
+ paintCallback.current = onPaint;
1886
+ React9.useEffect(() => {
1887
+ const frame = requestAnimationFrame(() => paintCallback.current?.(performance.now() - started.current));
1888
+ return () => cancelAnimationFrame(frame);
1889
+ }, []);
1890
+ React9.useEffect(() => {
1891
+ ref.current?.focus({ preventScroll: true });
1892
+ }, []);
1893
+ 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;
1894
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1895
+ "div",
1896
+ {
1897
+ ref,
1898
+ tabIndex: -1,
1899
+ role: "status",
1900
+ "aria-live": "polite",
1901
+ "aria-atomic": "true",
1902
+ "data-hitl-submission": state.status,
1903
+ className: "a24-hitl-submission flex items-center gap-2 py-1 text-start text-sm text-muted-foreground outline-none",
1904
+ children: [
1905
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: text }),
1906
+ state.status === "uncertain" && state.retry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1907
+ "button",
1908
+ {
1909
+ type: "button",
1910
+ className: "rounded px-2 py-1 text-foreground underline underline-offset-2",
1911
+ onClick: () => {
1912
+ void state.retry?.().catch(() => void 0);
1913
+ },
1914
+ children: labels.retry
1915
+ }
1916
+ )
1917
+ ]
1918
+ }
1919
+ );
1920
+ }
1776
1921
 
1777
1922
  // src/ui/agent-response-timeline.tsx
1778
- var React12 = __toESM(require("react"), 1);
1923
+ var React16 = __toESM(require("react"), 1);
1779
1924
 
1780
1925
  // src/streaming-text.ts
1781
1926
  var import_react = require("react");
@@ -1960,7 +2105,7 @@ function useStreamingText({
1960
2105
  }
1961
2106
 
1962
2107
  // src/ui/ask-user-interaction.tsx
1963
- var React9 = __toESM(require("react"), 1);
2108
+ var React10 = __toESM(require("react"), 1);
1964
2109
  var import_lucide_react5 = require("lucide-react");
1965
2110
 
1966
2111
  // src/ui/ask-user-interaction-state.ts
@@ -2017,7 +2162,7 @@ function askUserAnswersFromDrafts(questions, drafts) {
2017
2162
  }
2018
2163
 
2019
2164
  // src/ui/ask-user-interaction.tsx
2020
- var import_jsx_runtime7 = require("react/jsx-runtime");
2165
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2021
2166
  function resolvedAnswerText(question, answer) {
2022
2167
  if (!answer) return ["No response recorded"];
2023
2168
  const labels = answer.selectedOptionIds.flatMap((optionId) => {
@@ -2031,7 +2176,7 @@ function ResolvedQuestions({
2031
2176
  buttonRef,
2032
2177
  part
2033
2178
  }) {
2034
- const [open, setOpen] = React9.useState(false);
2179
+ const [open, setOpen] = React10.useState(false);
2035
2180
  const count = part.questions.length;
2036
2181
  const answers = new Map(
2037
2182
  (part.resolution?.answers || []).map((answer) => [
@@ -2039,8 +2184,8 @@ function ResolvedQuestions({
2039
2184
  answer
2040
2185
  ])
2041
2186
  );
2042
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "a24-ask-user a24-ask-user--resolved w-full", children: [
2043
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2187
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "a24-ask-user a24-ask-user--resolved w-full", children: [
2188
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2044
2189
  "button",
2045
2190
  {
2046
2191
  "aria-expanded": open,
@@ -2049,13 +2194,13 @@ function ResolvedQuestions({
2049
2194
  ref: buttonRef,
2050
2195
  type: "button",
2051
2196
  children: [
2052
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2197
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
2053
2198
  "Asked ",
2054
2199
  count,
2055
2200
  " question",
2056
2201
  count === 1 ? "" : "s"
2057
2202
  ] }),
2058
- open ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.ChevronDown, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2203
+ open ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.ChevronDown, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2059
2204
  import_lucide_react5.ChevronRight,
2060
2205
  {
2061
2206
  "aria-hidden": "true",
@@ -2065,12 +2210,12 @@ function ResolvedQuestions({
2065
2210
  ]
2066
2211
  }
2067
2212
  ),
2068
- open ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-2 space-y-3 ps-4", children: part.questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0", children: [
2069
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm font-medium text-foreground", children: question.question }),
2070
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-1 space-y-1 text-sm text-muted-foreground", children: resolvedAnswerText(
2213
+ open ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mt-2 space-y-3 ps-4", children: part.questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "min-w-0", children: [
2214
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-sm font-medium text-foreground", children: question.question }),
2215
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mt-1 space-y-1 text-sm text-muted-foreground", children: resolvedAnswerText(
2071
2216
  question,
2072
2217
  answers.get(question.id)
2073
- ).map((value, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2218
+ ).map((value, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2074
2219
  "div",
2075
2220
  {
2076
2221
  className: "whitespace-pre-wrap break-words",
@@ -2083,40 +2228,50 @@ function ResolvedQuestions({
2083
2228
  }
2084
2229
  function AskUserInteraction({
2085
2230
  error,
2231
+ submission,
2232
+ submissionLabels,
2233
+ onSubmissionPaint,
2086
2234
  isBusy = false,
2087
2235
  onSubmit,
2088
2236
  part
2089
2237
  }) {
2090
2238
  const questions = part.questions;
2091
- const [step, setStep] = React9.useState(0);
2092
- const [drafts, setDrafts] = React9.useState(
2239
+ const [step, setStep] = React10.useState(0);
2240
+ const [drafts, setDrafts] = React10.useState(
2093
2241
  () => emptyAskUserDrafts(questions)
2094
2242
  );
2095
- const headingRef = React9.useRef(null);
2096
- const questionsRef = React9.useRef(questions);
2097
- const resolvedButtonRef = React9.useRef(null);
2098
- const wasResolvedRef = React9.useRef(part.status !== "pending");
2243
+ const otherRef = React10.useRef(null);
2244
+ const headingRef = React10.useRef(null);
2245
+ const questionsRef = React10.useRef(questions);
2246
+ const resolvedButtonRef = React10.useRef(null);
2247
+ const wasResolvedRef = React10.useRef(part.status !== "pending");
2099
2248
  questionsRef.current = questions;
2100
- React9.useEffect(() => {
2249
+ React10.useEffect(() => {
2101
2250
  setStep(0);
2102
2251
  setDrafts(emptyAskUserDrafts(questionsRef.current));
2103
2252
  }, [part.interruptId]);
2104
- React9.useEffect(() => {
2253
+ React10.useEffect(() => {
2105
2254
  headingRef.current?.focus();
2106
2255
  }, [step]);
2107
- React9.useEffect(() => {
2256
+ React10.useEffect(() => {
2108
2257
  const isResolved = part.status !== "pending";
2109
2258
  if (isResolved && !wasResolvedRef.current) {
2110
2259
  resolvedButtonRef.current?.focus();
2111
2260
  }
2112
2261
  wasResolvedRef.current = isResolved;
2113
2262
  }, [part.status]);
2263
+ React10.useEffect(() => {
2264
+ if (submission?.status === "error") (otherRef.current?.value ? otherRef.current : headingRef.current)?.focus();
2265
+ }, [submission?.status]);
2266
+ if (part.status === "pending" && isHitlSubmissionCompact(submission)) {
2267
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HitlSubmissionStatus, { state: submission, labels: submissionLabels, onPaint: onSubmissionPaint });
2268
+ }
2114
2269
  if (part.status !== "pending") {
2115
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ResolvedQuestions, { buttonRef: resolvedButtonRef, part });
2270
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ResolvedQuestions, { buttonRef: resolvedButtonRef, part });
2116
2271
  }
2117
2272
  const question = questions[step];
2118
2273
  if (!question) {
2119
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-destructive", role: "alert", children: "This question request is unavailable." });
2274
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-sm text-destructive", role: "alert", children: "This question request is unavailable." });
2120
2275
  }
2121
2276
  const draft = drafts[question.id] || {
2122
2277
  customText: "",
@@ -2150,9 +2305,9 @@ function AskUserInteraction({
2150
2305
  })
2151
2306
  );
2152
2307
  };
2153
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "a24-ask-user space-y-3 rounded-xl border border-border/50 bg-background p-4 shadow-sm", children: [
2154
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-4", children: [
2155
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2308
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "a24-ask-user space-y-3 rounded-xl border border-border/50 bg-background p-4 shadow-sm", children: [
2309
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-4", children: [
2310
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2156
2311
  "h3",
2157
2312
  {
2158
2313
  className: "min-w-0 flex-1 text-base font-medium leading-6 text-foreground outline-none",
@@ -2161,8 +2316,8 @@ function AskUserInteraction({
2161
2316
  children: question.question
2162
2317
  }
2163
2318
  ),
2164
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex shrink-0 items-center gap-1 text-muted-foreground", children: [
2165
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2319
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex shrink-0 items-center gap-1 text-muted-foreground", children: [
2320
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2166
2321
  "button",
2167
2322
  {
2168
2323
  "aria-label": "Previous question",
@@ -2170,7 +2325,7 @@ function AskUserInteraction({
2170
2325
  disabled: isBusy || step === 0,
2171
2326
  onClick: () => setStep((current) => Math.max(0, current - 1)),
2172
2327
  type: "button",
2173
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2328
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2174
2329
  import_lucide_react5.ChevronLeft,
2175
2330
  {
2176
2331
  "aria-hidden": "true",
@@ -2179,7 +2334,7 @@ function AskUserInteraction({
2179
2334
  )
2180
2335
  }
2181
2336
  ),
2182
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2337
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2183
2338
  "span",
2184
2339
  {
2185
2340
  "aria-label": `Question ${step + 1} of ${questions.length}`,
@@ -2191,7 +2346,7 @@ function AskUserInteraction({
2191
2346
  ]
2192
2347
  }
2193
2348
  ),
2194
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2349
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2195
2350
  "button",
2196
2351
  {
2197
2352
  "aria-label": isLastQuestion ? "Submit answers" : "Next question",
@@ -2199,7 +2354,7 @@ function AskUserInteraction({
2199
2354
  disabled: isBusy || !onSubmit || !canMoveForward,
2200
2355
  onClick: () => completeStep(drafts),
2201
2356
  type: "button",
2202
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2357
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2203
2358
  import_lucide_react5.ChevronRight,
2204
2359
  {
2205
2360
  "aria-hidden": "true",
@@ -2210,10 +2365,10 @@ function AskUserInteraction({
2210
2365
  )
2211
2366
  ] })
2212
2367
  ] }),
2213
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
2368
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
2214
2369
  question.options.map((option, index) => {
2215
2370
  const selected = draft.selectedOptionIds.includes(option.id);
2216
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2371
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2217
2372
  "button",
2218
2373
  {
2219
2374
  "aria-pressed": selected,
@@ -2225,7 +2380,7 @@ function AskUserInteraction({
2225
2380
  onClick: () => selectOption(option.id),
2226
2381
  type: "button",
2227
2382
  children: [
2228
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2383
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2229
2384
  "span",
2230
2385
  {
2231
2386
  className: cn(
@@ -2235,8 +2390,8 @@ function AskUserInteraction({
2235
2390
  children: index + 1
2236
2391
  }
2237
2392
  ),
2238
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 flex-1 font-medium text-foreground", children: option.label }),
2239
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2393
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "min-w-0 flex-1 font-medium text-foreground", children: option.label }),
2394
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2240
2395
  import_lucide_react5.ChevronRight,
2241
2396
  {
2242
2397
  "aria-hidden": "true",
@@ -2248,11 +2403,12 @@ function AskUserInteraction({
2248
2403
  option.id
2249
2404
  );
2250
2405
  }),
2251
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
2252
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Pencil, { "aria-hidden": "true", className: "size-4" }) }),
2253
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2406
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("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: [
2407
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("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__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Pencil, { "aria-hidden": "true", className: "size-4" }) }),
2408
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2254
2409
  "input",
2255
2410
  {
2411
+ ref: otherRef,
2256
2412
  "aria-label": "Other response",
2257
2413
  autoComplete: "off",
2258
2414
  className: "h-8 min-w-0 flex-1 bg-transparent px-1 text-sm text-foreground outline-none placeholder:text-muted-foreground",
@@ -2269,7 +2425,7 @@ function AskUserInteraction({
2269
2425
  value: draft.customText
2270
2426
  }
2271
2427
  ),
2272
- draft.customText.trim() ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2428
+ draft.customText.trim() ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2273
2429
  "button",
2274
2430
  {
2275
2431
  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",
@@ -2281,12 +2437,12 @@ function AskUserInteraction({
2281
2437
  ) : null
2282
2438
  ] })
2283
2439
  ] }),
2284
- error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-destructive", role: "alert", children: error }) : null
2440
+ error ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-sm text-destructive", role: "alert", children: error }) : null
2285
2441
  ] });
2286
2442
  }
2287
2443
 
2288
2444
  // src/ui/agent-chat-context-compression-row.tsx
2289
- var import_jsx_runtime8 = require("react/jsx-runtime");
2445
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2290
2446
  function compressionPresentation(part) {
2291
2447
  if (part.status === "failed") {
2292
2448
  return { label: "Could not compact message history", status: "failed" };
@@ -2301,7 +2457,7 @@ function AgentChatContextCompressionRow({
2301
2457
  part
2302
2458
  }) {
2303
2459
  const presentation = compressionPresentation(part);
2304
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2460
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2305
2461
  "div",
2306
2462
  {
2307
2463
  "aria-live": "polite",
@@ -2309,11 +2465,11 @@ function AgentChatContextCompressionRow({
2309
2465
  "data-agents24-context-compression": "",
2310
2466
  "data-status": part.status,
2311
2467
  role: "status",
2312
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn(
2468
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: cn(
2313
2469
  "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--without-orb",
2314
2470
  presentation.status === "failed" && "a24-tool-trigger--error",
2315
2471
  presentation.status === "running" && "a24-tool-trigger--active"
2316
- ), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cn(
2472
+ ), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: cn(
2317
2473
  "a24-tool-trigger__label",
2318
2474
  presentation.status === "running" && "a24-tool-shimmer"
2319
2475
  ), children: presentation.label }) }) })
@@ -2322,7 +2478,7 @@ function AgentChatContextCompressionRow({
2322
2478
  }
2323
2479
 
2324
2480
  // src/ui/message-response.tsx
2325
- var React10 = __toESM(require("react"), 1);
2481
+ var React14 = __toESM(require("react"), 1);
2326
2482
  var import_streamdown = require("streamdown");
2327
2483
 
2328
2484
  // src/active-content.ts
@@ -2346,18 +2502,492 @@ function safeChatMarkdownHref(value) {
2346
2502
  }
2347
2503
  }
2348
2504
 
2505
+ // src/ui/message-code.tsx
2506
+ var React13 = __toESM(require("react"), 1);
2507
+ var import_lucide_react7 = require("lucide-react");
2508
+
2509
+ // src/ui/code-block.tsx
2510
+ var React11 = __toESM(require("react"), 1);
2511
+ var import_class_variance_authority2 = require("class-variance-authority");
2512
+ var import_lucide_react6 = require("lucide-react");
2513
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2514
+ var codeBlockVariants = (0, import_class_variance_authority2.cva)(
2515
+ "a24-code-block",
2516
+ {
2517
+ variants: {
2518
+ variant: {
2519
+ default: "a24-code-block--default",
2520
+ destructive: "a24-code-block--destructive"
2521
+ }
2522
+ },
2523
+ defaultVariants: {
2524
+ variant: "default"
2525
+ }
2526
+ }
2527
+ );
2528
+ function CodeBlock({
2529
+ className,
2530
+ variant = "default",
2531
+ size = "default",
2532
+ ...props
2533
+ }) {
2534
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2535
+ "div",
2536
+ {
2537
+ "data-slot": "code-block",
2538
+ "data-variant": variant,
2539
+ "data-size": size,
2540
+ className: cn(codeBlockVariants({ variant }), className),
2541
+ ...props
2542
+ }
2543
+ );
2544
+ }
2545
+ function CodeBlockHeader({ className, ...props }) {
2546
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2547
+ "div",
2548
+ {
2549
+ "data-slot": "code-block-header",
2550
+ className: cn(
2551
+ "a24-code-block__header",
2552
+ className
2553
+ ),
2554
+ ...props
2555
+ }
2556
+ );
2557
+ }
2558
+ function CodeBlockTitle({ className, ...props }) {
2559
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2560
+ "div",
2561
+ {
2562
+ "data-slot": "code-block-title",
2563
+ className: cn(
2564
+ "a24-code-block__title",
2565
+ className
2566
+ ),
2567
+ ...props
2568
+ }
2569
+ );
2570
+ }
2571
+ function CodeBlockActions({
2572
+ className,
2573
+ ...props
2574
+ }) {
2575
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2576
+ "div",
2577
+ {
2578
+ "data-slot": "code-block-actions",
2579
+ className: cn(
2580
+ "a24-code-block__actions",
2581
+ className
2582
+ ),
2583
+ ...props
2584
+ }
2585
+ );
2586
+ }
2587
+ function CodeBlockCopyButton({
2588
+ value,
2589
+ className,
2590
+ onClick,
2591
+ ...props
2592
+ }) {
2593
+ const [copied, setCopied] = React11.useState(false);
2594
+ React11.useEffect(() => {
2595
+ if (!copied) {
2596
+ return;
2597
+ }
2598
+ const timeout = setTimeout(() => setCopied(false), 2e3);
2599
+ return () => clearTimeout(timeout);
2600
+ }, [copied]);
2601
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2602
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2603
+ "button",
2604
+ {
2605
+ type: "button",
2606
+ "data-slot": "code-block-copy-button",
2607
+ "data-copied": copied || void 0,
2608
+ "aria-label": copied ? "Copied" : "Copy",
2609
+ title: copied ? "Copied" : "Copy code",
2610
+ className: cn("a24-code-block__action", className),
2611
+ onClick: (event) => {
2612
+ onClick?.(event);
2613
+ if (event.defaultPrevented || !navigator.clipboard) return;
2614
+ navigator.clipboard.writeText(value).then(() => setCopied(true)).catch(() => {
2615
+ });
2616
+ },
2617
+ ...props,
2618
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.CheckIcon, { size: 12, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.CopyIcon, { size: 12, strokeWidth: 1.5 })
2619
+ }
2620
+ ),
2621
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-live": "polite", className: "a24-code-block__announcement", children: copied ? "Copied" : "" })
2622
+ ] });
2623
+ }
2624
+ function CodeBlockWrapButton({
2625
+ wrap,
2626
+ onWrapChange,
2627
+ className,
2628
+ onClick,
2629
+ ...props
2630
+ }) {
2631
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2632
+ "button",
2633
+ {
2634
+ type: "button",
2635
+ "data-slot": "code-block-wrap-button",
2636
+ "aria-label": "Wrap lines",
2637
+ "aria-pressed": wrap,
2638
+ title: wrap ? "Unwrap lines" : "Wrap lines",
2639
+ className: cn("a24-code-block__action", className),
2640
+ onClick: (event) => {
2641
+ onClick?.(event);
2642
+ if (!event.defaultPrevented) onWrapChange(!wrap);
2643
+ },
2644
+ ...props,
2645
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.WrapTextIcon, { size: 12, strokeWidth: 1.5 })
2646
+ }
2647
+ );
2648
+ }
2649
+ function CodeBlockDownloadButton({
2650
+ value,
2651
+ filename = "code.txt",
2652
+ className,
2653
+ onClick,
2654
+ ...props
2655
+ }) {
2656
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2657
+ "button",
2658
+ {
2659
+ type: "button",
2660
+ "data-slot": "code-block-download-button",
2661
+ "aria-label": "Download code",
2662
+ title: "Download code",
2663
+ className: cn("a24-code-block__action", className),
2664
+ onClick: (event) => {
2665
+ onClick?.(event);
2666
+ if (event.defaultPrevented) return;
2667
+ const url = URL.createObjectURL(new Blob([value], { type: "text/plain;charset=utf-8" }));
2668
+ const link = document.createElement("a");
2669
+ link.href = url;
2670
+ link.download = filename;
2671
+ document.body.append(link);
2672
+ link.click();
2673
+ link.remove();
2674
+ setTimeout(() => URL.revokeObjectURL(url), 1e3);
2675
+ },
2676
+ ...props,
2677
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.DownloadIcon, { size: 12, strokeWidth: 1.5 })
2678
+ }
2679
+ );
2680
+ }
2681
+ function CodeBlockContent({
2682
+ className,
2683
+ children,
2684
+ style,
2685
+ wrap = false,
2686
+ lineNumbers = false,
2687
+ startLine = 1,
2688
+ ...props
2689
+ }) {
2690
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2691
+ "pre",
2692
+ {
2693
+ "data-slot": "code-block-content",
2694
+ "data-wrap": wrap || void 0,
2695
+ "data-numbered": lineNumbers || void 0,
2696
+ dir: "ltr",
2697
+ tabIndex: 0,
2698
+ style: { counterReset: `line ${startLine - 1}`, ...style },
2699
+ className: cn(
2700
+ "a24-code-block__content",
2701
+ className
2702
+ ),
2703
+ ...props,
2704
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2705
+ "code",
2706
+ {
2707
+ "data-slot": "code-block-code",
2708
+ className: "a24-code-block__code",
2709
+ children: lineNumbers && typeof children === "string" ? children.replace(/\n$/, "").split("\n").map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CodeBlockLine, { children: line }, index)) : children
2710
+ }
2711
+ )
2712
+ }
2713
+ );
2714
+ }
2715
+ var codeBlockLineVariants = (0, import_class_variance_authority2.cva)(
2716
+ "a24-code-block__line",
2717
+ {
2718
+ variants: {
2719
+ variant: {
2720
+ default: "",
2721
+ added: "a24-code-block__line--added",
2722
+ removed: "a24-code-block__line--removed",
2723
+ highlighted: "a24-code-block__line--highlighted"
2724
+ }
2725
+ },
2726
+ defaultVariants: {
2727
+ variant: "default"
2728
+ }
2729
+ }
2730
+ );
2731
+ function CodeBlockLine({
2732
+ className,
2733
+ variant = "default",
2734
+ children,
2735
+ ...props
2736
+ }) {
2737
+ const empty = children === void 0 || children === null || children === "" || Array.isArray(children) && children.length === 0;
2738
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2739
+ "span",
2740
+ {
2741
+ "data-slot": "code-block-line",
2742
+ "data-variant": variant,
2743
+ className: cn(codeBlockLineVariants({ variant }), className),
2744
+ ...props,
2745
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-slot": "code-block-line-content", className: "a24-code-block__line-content", children: empty ? "\n" : children })
2746
+ }
2747
+ );
2748
+ }
2749
+ function CodeBlockFooter({ className, ...props }) {
2750
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2751
+ "div",
2752
+ {
2753
+ "data-slot": "code-block-footer",
2754
+ className: cn(
2755
+ "a24-code-block__footer",
2756
+ className
2757
+ ),
2758
+ ...props
2759
+ }
2760
+ );
2761
+ }
2762
+
2763
+ // src/ui/use-highlighted-code.ts
2764
+ var React12 = __toESM(require("react"), 1);
2765
+
2766
+ // src/ui/code-highlighter.tsx
2767
+ var import_core = require("shiki/core");
2768
+ var import_javascript = require("shiki/engine/javascript");
2769
+ var import_langs = require("shiki/langs");
2770
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2771
+ var languageLoaders = {
2772
+ ...import_langs.bundledLanguages,
2773
+ ...import_langs.bundledLanguagesAlias
2774
+ };
2775
+ var highlighter;
2776
+ function getHighlighter() {
2777
+ highlighter ?? (highlighter = (0, import_core.createHighlighterCore)({
2778
+ themes: [
2779
+ import("shiki/themes/github-light.mjs"),
2780
+ import("shiki/themes/github-dark.mjs")
2781
+ ],
2782
+ langs: [],
2783
+ engine: (0, import_javascript.createJavaScriptRegexEngine)({ forgiving: true })
2784
+ }));
2785
+ return highlighter;
2786
+ }
2787
+ function getLanguage(language) {
2788
+ const name = language.toLowerCase();
2789
+ if (name === "ansi") return name;
2790
+ if (Object.prototype.hasOwnProperty.call(languageLoaders, name)) return name;
2791
+ return null;
2792
+ }
2793
+ async function loadHighlighter(language) {
2794
+ const lang = getLanguage(language);
2795
+ if (!lang) {
2796
+ return null;
2797
+ }
2798
+ const shiki = await getHighlighter();
2799
+ if (lang !== "ansi" && !shiki.getLoadedLanguages().includes(lang)) {
2800
+ await shiki.loadLanguage(languageLoaders[lang]);
2801
+ }
2802
+ return {
2803
+ // Returns one React node per line, and the grammar state after the last
2804
+ // line. Pass that state back to continue where the code left off.
2805
+ highlight(code, state) {
2806
+ const tokenize = (text) => shiki.codeToTokens(text, {
2807
+ lang,
2808
+ themes: { light: "github-light", dark: "github-dark" },
2809
+ defaultColor: false,
2810
+ grammarState: state
2811
+ }).tokens;
2812
+ const tokens = lang === "ansi" ? code.split("\n").flatMap((line) => tokenize(line)) : tokenize(code);
2813
+ return {
2814
+ lines: tokens.map(
2815
+ (line) => line.map((token, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2816
+ "span",
2817
+ {
2818
+ style: token.htmlStyle,
2819
+ className: "a24-code-token",
2820
+ children: token.content
2821
+ },
2822
+ index
2823
+ ))
2824
+ ),
2825
+ state: shiki.getLastGrammarState(tokens)
2826
+ };
2827
+ }
2828
+ };
2829
+ }
2830
+
2831
+ // src/ui/use-highlighted-code.ts
2832
+ function useHighlightedCode(value, language) {
2833
+ const code = value.endsWith("\n") ? value.slice(0, -1) : value;
2834
+ const [loaded, setLoaded] = React12.useState(null);
2835
+ const highlighter2 = loaded?.language === language ? loaded.highlighter : null;
2836
+ React12.useEffect(() => {
2837
+ let cancelled = false;
2838
+ loadHighlighter(language).then((next2) => {
2839
+ if (!cancelled) {
2840
+ setLoaded({ language, highlighter: next2 });
2841
+ }
2842
+ }).catch(() => {
2843
+ });
2844
+ return () => {
2845
+ cancelled = true;
2846
+ };
2847
+ }, [language]);
2848
+ const [done, setDone] = React12.useState({ highlighter: null, text: "", lines: [] });
2849
+ let next = done;
2850
+ if (next.highlighter !== highlighter2 || !code.startsWith(next.text)) {
2851
+ next = { highlighter: highlighter2, text: "", lines: [] };
2852
+ }
2853
+ const end = code.lastIndexOf("\n") + 1;
2854
+ if (highlighter2 && end > next.text.length) {
2855
+ const result = highlighter2.highlight(
2856
+ code.slice(next.text.length, end - 1),
2857
+ next.state
2858
+ );
2859
+ next = {
2860
+ highlighter: highlighter2,
2861
+ text: code.slice(0, end),
2862
+ lines: [...next.lines, ...result.lines],
2863
+ state: result.state
2864
+ };
2865
+ }
2866
+ if (next !== done) {
2867
+ setDone(next);
2868
+ }
2869
+ const tail = code.slice(end);
2870
+ return React12.useMemo(() => {
2871
+ if (!highlighter2) {
2872
+ return code.split("\n");
2873
+ }
2874
+ return [...next.lines, highlighter2.highlight(tail, next.state).lines[0]];
2875
+ }, [code, highlighter2, next, tail]);
2876
+ }
2877
+
2878
+ // src/ui/message-code.tsx
2879
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2880
+ var CODE_EXTENSIONS = {
2881
+ bash: "sh",
2882
+ shell: "sh",
2883
+ shellscript: "sh",
2884
+ sh: "sh",
2885
+ zsh: "sh",
2886
+ javascript: "js",
2887
+ js: "js",
2888
+ jsx: "jsx",
2889
+ typescript: "ts",
2890
+ ts: "ts",
2891
+ tsx: "tsx",
2892
+ python: "py",
2893
+ py: "py",
2894
+ ruby: "rb",
2895
+ rust: "rs",
2896
+ rs: "rs",
2897
+ go: "go",
2898
+ java: "java",
2899
+ kotlin: "kt",
2900
+ swift: "swift",
2901
+ c: "c",
2902
+ cpp: "cpp",
2903
+ csharp: "cs",
2904
+ json: "json",
2905
+ jsonc: "jsonc",
2906
+ yaml: "yaml",
2907
+ yml: "yml",
2908
+ toml: "toml",
2909
+ html: "html",
2910
+ xml: "xml",
2911
+ css: "css",
2912
+ scss: "scss",
2913
+ sql: "sql",
2914
+ markdown: "md",
2915
+ md: "md",
2916
+ diff: "diff",
2917
+ text: "txt",
2918
+ plaintext: "txt"
2919
+ };
2920
+ function MessageCodeBlock({ code, language = "text" }) {
2921
+ const [wrap, setWrap] = React13.useState(false);
2922
+ const lines = useHighlightedCode(code, language);
2923
+ const extension = Object.prototype.hasOwnProperty.call(CODE_EXTENSIONS, language.toLowerCase()) ? CODE_EXTENSIONS[language.toLowerCase()] : "txt";
2924
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CodeBlock, { children: [
2925
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CodeBlockHeader, { children: [
2926
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CodeBlockTitle, { children: [
2927
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.FileCode2Icon, { size: 14, strokeWidth: 1.5, "aria-hidden": "true" }),
2928
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: language })
2929
+ ] }),
2930
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CodeBlockActions, { children: [
2931
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeBlockWrapButton, { wrap, onWrapChange: setWrap }),
2932
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeBlockDownloadButton, { value: code, filename: `code.${extension}` }),
2933
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeBlockCopyButton, { value: code })
2934
+ ] })
2935
+ ] }),
2936
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeBlockContent, { "aria-label": `${language} code`, lineNumbers: true, wrap, children: lines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeBlockLine, { children: line }, index)) })
2937
+ ] });
2938
+ }
2939
+ function MessageMarkdownCode({ children, className, node, ...props }) {
2940
+ const language = className?.match(/(?:^|\s)language-([^\s]+)/)?.[1];
2941
+ const multiline = node?.position?.start?.line !== node?.position?.end?.line;
2942
+ if (props["data-block"] === void 0 && !language && !multiline) {
2943
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { ...props, className: cn("a24-inline-code", className), "data-streamdown": "inline-code", children });
2944
+ }
2945
+ const code = typeof children === "string" ? children.replace(/\n$/, "") : "";
2946
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MessageCodeBlock, { code, language });
2947
+ }
2948
+ function formatMessageJson(text) {
2949
+ const trimmed = text.trim();
2950
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return null;
2951
+ try {
2952
+ JSON.parse(trimmed);
2953
+ } catch {
2954
+ return null;
2955
+ }
2956
+ const tokens = trimmed.match(/"(?:\\.|[^"\\])*"|[{}\[\],:]|[^\s{}\[\],:]+/g) || [];
2957
+ let depth = 0;
2958
+ let result = "";
2959
+ const newline = () => `
2960
+ ${" ".repeat(depth)}`;
2961
+ tokens.forEach((token, index) => {
2962
+ const previous = tokens[index - 1];
2963
+ const next = tokens[index + 1];
2964
+ if (token === "{" || token === "[") {
2965
+ result += token;
2966
+ depth += 1;
2967
+ if (next !== "}" && next !== "]") result += newline();
2968
+ } else if (token === "}" || token === "]") {
2969
+ depth -= 1;
2970
+ if (previous !== "{" && previous !== "[") result += newline();
2971
+ result += token;
2972
+ } else if (token === ",") result += `,${newline()}`;
2973
+ else if (token === ":") result += ": ";
2974
+ else result += token;
2975
+ });
2976
+ return result;
2977
+ }
2978
+
2349
2979
  // src/ui/message-response.tsx
2350
- var import_jsx_runtime9 = require("react/jsx-runtime");
2980
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2351
2981
  function SafeMarkdownLink({ children, href, ...props }) {
2352
2982
  const domProps = { ...props };
2353
2983
  delete domProps.node;
2354
2984
  const safeHref = safeChatMarkdownHref(href);
2355
- if (!safeHref) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children });
2356
- if (safeHref.startsWith("#")) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { ...domProps, href: safeHref, children });
2357
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { ...domProps, href: safeHref, rel: "noopener noreferrer", target: "_blank", children });
2985
+ if (!safeHref) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children });
2986
+ if (safeHref.startsWith("#")) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("a", { ...domProps, href: safeHref, children });
2987
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("a", { ...domProps, href: safeHref, rel: "noopener noreferrer", target: "_blank", children });
2358
2988
  }
2359
2989
  function BlockedMarkdownImage({ alt }) {
2360
- return alt ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "aria-label": `Image blocked: ${alt}`, role: "img", children: alt }) : null;
2990
+ return alt ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { "aria-label": `Image blocked: ${alt}`, role: "img", children: alt }) : null;
2361
2991
  }
2362
2992
  var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
2363
2993
  "blockquote",
@@ -2378,7 +3008,7 @@ function isMultilineCodeNode(node) {
2378
3008
  return node?.tagName === "code" && node.position?.start?.line !== void 0 && node.position?.end?.line !== void 0 && node.position.start.line !== node.position.end.line;
2379
3009
  }
2380
3010
  function hasBlockMarkdownChild(child) {
2381
- if (!React10.isValidElement(child)) {
3011
+ if (!React14.isValidElement(child)) {
2382
3012
  return false;
2383
3013
  }
2384
3014
  if (typeof child.type === "string" && BLOCK_MARKDOWN_TAGS.has(child.type)) {
@@ -2388,7 +3018,7 @@ function hasBlockMarkdownChild(child) {
2388
3018
  if (BLOCK_MARKDOWN_TAGS.has(props.node?.tagName || "") || isMultilineCodeNode(props.node)) {
2389
3019
  return true;
2390
3020
  }
2391
- return React10.Children.toArray(props.children).some(hasBlockMarkdownChild);
3021
+ return React14.Children.toArray(props.children).some(hasBlockMarkdownChild);
2392
3022
  }
2393
3023
  function MessageMarkdownParagraph({
2394
3024
  children,
@@ -2396,22 +3026,23 @@ function MessageMarkdownParagraph({
2396
3026
  }) {
2397
3027
  const domProps = { ...props };
2398
3028
  delete domProps.node;
2399
- const childArray = React10.Children.toArray(children).filter(
3029
+ const childArray = React14.Children.toArray(children).filter(
2400
3030
  (child) => child !== null && child !== ""
2401
3031
  );
2402
- const isImageOnly = childArray.length === 1 && React10.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
3032
+ const isImageOnly = childArray.length === 1 && React14.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
2403
3033
  if (isImageOnly) {
2404
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children });
3034
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children });
2405
3035
  }
2406
3036
  if (childArray.some(hasBlockMarkdownChild)) {
2407
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ...domProps, children });
3037
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { ...domProps, children });
2408
3038
  }
2409
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { ...domProps, children });
3039
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { ...domProps, children });
2410
3040
  }
2411
3041
  var MESSAGE_RESPONSE_COMPONENTS = {
2412
3042
  a: SafeMarkdownLink,
2413
3043
  img: BlockedMarkdownImage,
2414
- p: MessageMarkdownParagraph
3044
+ p: MessageMarkdownParagraph,
3045
+ code: MessageMarkdownCode
2415
3046
  };
2416
3047
  var streamdownDefaultRehypePlugins = import_streamdown.defaultRehypePlugins || {};
2417
3048
  var streamdownHardenPlugin = Array.isArray(
@@ -2426,7 +3057,7 @@ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
2426
3057
  ]
2427
3058
  ] : []
2428
3059
  ];
2429
- var MessageResponse = React10.memo(
3060
+ var MessageResponse = React14.memo(
2430
3061
  ({
2431
3062
  children,
2432
3063
  className,
@@ -2444,11 +3075,21 @@ var MessageResponse = React10.memo(
2444
3075
  maxCatchupChars: 32,
2445
3076
  text
2446
3077
  });
2447
- const streamdownComponents = React10.useMemo(
3078
+ const streamdownComponents = React14.useMemo(
2448
3079
  () => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
2449
3080
  [components]
2450
3081
  );
2451
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3082
+ const json = React14.useMemo(() => formatMessageJson(text), [text]);
3083
+ if (json !== null && !components?.code) {
3084
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("a24-message-response", className), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3085
+ MessageCodeBlock,
3086
+ {
3087
+ code: streaming || streamingText.isAnimating ? streamingText.displayedText : json,
3088
+ language: "json"
3089
+ }
3090
+ ) });
3091
+ }
3092
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2452
3093
  import_streamdown.Streamdown,
2453
3094
  {
2454
3095
  className: cn("a24-message-response", className),
@@ -2500,10 +3141,10 @@ function resolvedHitlLabel(part) {
2500
3141
  }
2501
3142
 
2502
3143
  // src/ui/tool-sessions.tsx
2503
- var React11 = __toESM(require("react"), 1);
2504
- var import_lucide_react6 = require("lucide-react");
3144
+ var React15 = __toESM(require("react"), 1);
3145
+ var import_lucide_react8 = require("lucide-react");
2505
3146
  var import_thinking_orbs = require("thinking-orbs");
2506
- var import_jsx_runtime10 = require("react/jsx-runtime");
3147
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2507
3148
  function toolSlotContext(isActive2, label, part, slots) {
2508
3149
  return {
2509
3150
  isActive: isActive2,
@@ -2521,7 +3162,7 @@ function ToolResourceAction({ context }) {
2521
3162
  const target = context.resourceTargets[0];
2522
3163
  if (!target) return null;
2523
3164
  const name = resourceTargetName(target);
2524
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3165
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2525
3166
  "button",
2526
3167
  {
2527
3168
  "aria-label": `Open ${target.kind} ${target.path}`,
@@ -2535,8 +3176,8 @@ function ToolResourceAction({ context }) {
2535
3176
  );
2536
3177
  }
2537
3178
  function toolAccessory(context, slots) {
2538
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2539
- slots?.onResourceAction ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolResourceAction, { context }) : null,
3179
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3180
+ slots?.onResourceAction ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolResourceAction, { context }) : null,
2540
3181
  slots?.renderToolAccessory?.(context)
2541
3182
  ] });
2542
3183
  }
@@ -2613,12 +3254,12 @@ function ToolActivityReel({
2613
3254
  }) {
2614
3255
  const initial = initialLabel && initialLabel !== label ? initialLabel : label;
2615
3256
  const parsedInitialShownAt = initialShownAt ? Date.parse(initialShownAt) : Number.NaN;
2616
- const [displayed, setDisplayed] = React11.useState(initial);
2617
- const [previous, setPrevious] = React11.useState(null);
2618
- const displayedRef = React11.useRef(initial);
2619
- const latestRef = React11.useRef(label);
2620
- const shownAtRef = React11.useRef(Number.isFinite(parsedInitialShownAt) ? parsedInitialShownAt : Date.now());
2621
- React11.useEffect(() => {
3257
+ const [displayed, setDisplayed] = React15.useState(initial);
3258
+ const [previous, setPrevious] = React15.useState(null);
3259
+ const displayedRef = React15.useRef(initial);
3260
+ const latestRef = React15.useRef(label);
3261
+ const shownAtRef = React15.useRef(Number.isFinite(parsedInitialShownAt) ? parsedInitialShownAt : Date.now());
3262
+ React15.useEffect(() => {
2622
3263
  latestRef.current = label;
2623
3264
  if (displayedRef.current === label) return;
2624
3265
  const showLatest = () => {
@@ -2638,18 +3279,18 @@ function ToolActivityReel({
2638
3279
  const timer = window.setTimeout(showLatest, remaining);
2639
3280
  return () => window.clearTimeout(timer);
2640
3281
  }, [label]);
2641
- React11.useEffect(() => {
3282
+ React15.useEffect(() => {
2642
3283
  if (!previous) return;
2643
3284
  const timer = window.setTimeout(() => setPrevious(null), 200);
2644
3285
  return () => window.clearTimeout(timer);
2645
3286
  }, [previous]);
2646
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "a24-tool-reel", "aria-live": announce ? "polite" : "off", children: [
2647
- previous ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": "true", className: "a24-tool-reel__previous", children: previous }) : null,
2648
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: previous ? "a24-tool-reel__current" : void 0, children: displayed })
3287
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "a24-tool-reel", "aria-live": announce ? "polite" : "off", children: [
3288
+ previous ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { "aria-hidden": "true", className: "a24-tool-reel__previous", children: previous }) : null,
3289
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: previous ? "a24-tool-reel__current" : void 0, children: displayed })
2649
3290
  ] });
2650
3291
  }
2651
3292
  function ToolActivityOrb({ label = "Working", kind = "tool", part, renderActivityIcon }) {
2652
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-orb", children: renderActivityIcon ? renderActivityIcon({ label, kind, part }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_thinking_orbs.ThinkingOrb, { "aria-label": label, size: 20, speed: 0.8, state: "searching" }) });
3293
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-orb", children: renderActivityIcon ? renderActivityIcon({ label, kind, part }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_thinking_orbs.ThinkingOrb, { "aria-label": label, size: 20, speed: 0.8, state: "searching" }) });
2653
3294
  }
2654
3295
  function AgentChatActivityRow({
2655
3296
  label,
@@ -2657,22 +3298,22 @@ function AgentChatActivityRow({
2657
3298
  renderActivityIcon,
2658
3299
  onSelect
2659
3300
  }) {
2660
- const content = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2661
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label, kind: "planning", renderActivityIcon }),
2662
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label a24-tool-shimmer", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityReel, { label }) })
3301
+ const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3302
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label, kind: "planning", renderActivityIcon }),
3303
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label a24-tool-shimmer", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityReel, { label }) })
2663
3304
  ] });
2664
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-trigger-row a24-tool-trigger-row--root", "data-agents24-model-turn": modelTurnId, role: "status", children: onSelect ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", onClick: onSelect, type: "button", children: content }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", children: content }) });
3305
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-trigger-row a24-tool-trigger-row--root", "data-agents24-model-turn": modelTurnId, role: "status", children: onSelect ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", onClick: onSelect, type: "button", children: content }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-trigger a24-tool-trigger--root a24-tool-trigger--active", children: content }) });
2665
3306
  }
2666
3307
  function AgentChatModelTurnRow({ part }) {
2667
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AgentChatActivityRow, { label: "Planning next moves", modelTurnId: part.modelTurnId });
3308
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AgentChatActivityRow, { label: "Planning next moves", modelTurnId: part.modelTurnId });
2668
3309
  }
2669
3310
  function AgentChatNodeActivityRow({
2670
3311
  renderActivityIcon,
2671
3312
  onSelect,
2672
3313
  part
2673
3314
  }) {
2674
- const [open, setOpen] = React11.useState(false);
2675
- const contentId = React11.useId();
3315
+ const [open, setOpen] = React15.useState(false);
3316
+ const contentId = React15.useId();
2676
3317
  const running = part.status === "running";
2677
3318
  const failed = part.status === "failed";
2678
3319
  const failureMessage = part.failure?.message || "The node could not complete the request.";
@@ -2683,18 +3324,18 @@ function AgentChatNodeActivityRow({
2683
3324
  running && "a24-tool-trigger--active",
2684
3325
  failed && "a24-tool-trigger--error"
2685
3326
  );
2686
- const label = running ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-shimmer", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityReel, { label: part.label }) }) : part.label;
3327
+ const label = running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-shimmer", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityReel, { label: part.label }) }) : part.label;
2687
3328
  if (!failed) {
2688
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-trigger-row", role: "status", children: onSelect ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
2689
- running ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
2690
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label })
2691
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: triggerClassName, children: [
2692
- running ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
2693
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label })
3329
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-trigger-row", role: "status", children: onSelect ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
3330
+ running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
3331
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label })
3332
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: triggerClassName, children: [
3333
+ running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label: part.label, kind: "node", part, renderActivityIcon }) : null,
3334
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label })
2694
3335
  ] }) });
2695
3336
  }
2696
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "a24-tool-disclosure", children: [
2697
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3337
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "a24-tool-disclosure", children: [
3338
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-trigger-row", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2698
3339
  "button",
2699
3340
  {
2700
3341
  "aria-controls": contentId,
@@ -2706,12 +3347,12 @@ function AgentChatNodeActivityRow({
2706
3347
  },
2707
3348
  type: "button",
2708
3349
  children: [
2709
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label }),
2710
- open ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.ChevronDown, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.ChevronRight, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
3350
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label }),
3351
+ open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.ChevronDown, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.ChevronRight, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
2711
3352
  ]
2712
3353
  }
2713
3354
  ) }),
2714
- open ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-detail a24-tool-detail--error", id: contentId, children: failureMessage }) : null
3355
+ open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-detail a24-tool-detail--error", id: contentId, children: failureMessage }) : null
2715
3356
  ] });
2716
3357
  }
2717
3358
  function toolRowLabel(part, separateResource = false) {
@@ -2738,25 +3379,25 @@ function ToolDisclosure({
2738
3379
  renderActivityIcon,
2739
3380
  accessory
2740
3381
  }) {
2741
- const [open, setOpen] = React11.useState(false);
2742
- const contentId = React11.useId();
2743
- const expandable = React11.Children.toArray(children).length > 0;
3382
+ const [open, setOpen] = React15.useState(false);
3383
+ const contentId = React15.useId();
3384
+ const expandable = React15.Children.toArray(children).length > 0;
2744
3385
  if (!expandable) {
2745
3386
  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");
2746
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
2747
- onSelect && part ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
2748
- showOrb ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2749
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label })
2750
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: triggerClassName, children: [
2751
- showOrb ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2752
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label })
3387
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
3388
+ onSelect && part ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
3389
+ showOrb ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3390
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label })
3391
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: triggerClassName, children: [
3392
+ showOrb ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3393
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label })
2753
3394
  ] }),
2754
3395
  accessory
2755
3396
  ] });
2756
3397
  }
2757
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "a24-tool-disclosure", children: [
2758
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
2759
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3398
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "a24-tool-disclosure", children: [
3399
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("a24-tool-trigger-row", root && "a24-tool-trigger-row--root"), children: [
3400
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2760
3401
  "button",
2761
3402
  {
2762
3403
  "aria-controls": contentId,
@@ -2770,25 +3411,25 @@ function ToolDisclosure({
2770
3411
  },
2771
3412
  type: "button",
2772
3413
  children: [
2773
- showOrb ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
2774
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-trigger__label", children: label }),
2775
- open ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.ChevronDown, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.ChevronRight, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
3414
+ showOrb ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityOrb, { label: statusLabel || "Working", kind: grouped ? "group" : "tool", part, renderActivityIcon }) : null,
3415
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-trigger__label", children: label }),
3416
+ open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.ChevronDown, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.ChevronRight, { "aria-hidden": "true", className: "a24-tool-trigger__chevron" })
2776
3417
  ]
2777
3418
  }
2778
3419
  ),
2779
3420
  accessory
2780
3421
  ] }),
2781
- open ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-disclosure__content", id: contentId, children }) : null
3422
+ open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-disclosure__content", id: contentId, children }) : null
2782
3423
  ] });
2783
3424
  }
2784
3425
  function ToolLabel({ active, label, part, slots }) {
2785
3426
  const rendered = slots?.renderToolLabel?.(toolSlotContext(active, label, part, slots)) ?? label;
2786
- return active ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-tool-shimmer", children: rendered }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: rendered });
3427
+ return active ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-tool-shimmer", children: rendered }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: rendered });
2787
3428
  }
2788
3429
  function ToolList({ children }) {
2789
- const listRef = React11.useRef(null);
2790
- const [fades, setFades] = React11.useState({ bottom: false, top: false });
2791
- const updateFades = React11.useCallback(() => {
3430
+ const listRef = React15.useRef(null);
3431
+ const [fades, setFades] = React15.useState({ bottom: false, top: false });
3432
+ const updateFades = React15.useCallback(() => {
2792
3433
  const list = listRef.current;
2793
3434
  if (!list) return;
2794
3435
  const next = {
@@ -2797,7 +3438,7 @@ function ToolList({ children }) {
2797
3438
  };
2798
3439
  setFades((current) => current.bottom === next.bottom && current.top === next.top ? current : next);
2799
3440
  }, []);
2800
- React11.useEffect(() => {
3441
+ React15.useEffect(() => {
2801
3442
  updateFades();
2802
3443
  const list = listRef.current;
2803
3444
  if (!list || typeof ResizeObserver === "undefined") return;
@@ -2805,13 +3446,13 @@ function ToolList({ children }) {
2805
3446
  observer.observe(list);
2806
3447
  return () => observer.disconnect();
2807
3448
  }, [children, updateFades]);
2808
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3449
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2809
3450
  "div",
2810
3451
  {
2811
3452
  className: "a24-tool-list-frame",
2812
3453
  "data-scroll-fade-bottom": fades.bottom ? "" : void 0,
2813
3454
  "data-scroll-fade-top": fades.top ? "" : void 0,
2814
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-list", onScroll: updateFades, ref: listRef, role: "list", children })
3455
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-list", onScroll: updateFades, ref: listRef, role: "list", children })
2815
3456
  }
2816
3457
  );
2817
3458
  }
@@ -2828,13 +3469,13 @@ function AgentChatToolRow({
2828
3469
  const detail = failed ? failureMessage : optionalText(part.presentation.detail);
2829
3470
  const hostDetails = failed ? null : slots?.renderToolDetails?.(part);
2830
3471
  const context = toolSlotContext(active, toolRowLabel(part, Boolean(slots?.onResourceAction)), part, slots);
2831
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3472
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2832
3473
  ToolDisclosure,
2833
3474
  {
2834
3475
  renderActivityIcon: slots?.renderActivityIcon,
2835
3476
  error: failed,
2836
3477
  accessory: toolAccessory(context, slots),
2837
- label: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolLabel, { active, label: context.label, part, slots }),
3478
+ label: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolLabel, { active, label: context.label, part, slots }),
2838
3479
  loading: active,
2839
3480
  onExpandedChange: slots?.onExpandedChange,
2840
3481
  onSelect: slots?.onToolSelect,
@@ -2843,7 +3484,7 @@ function AgentChatToolRow({
2843
3484
  showOrb: showOrb ?? active,
2844
3485
  statusLabel: active ? context.label : void 0,
2845
3486
  children: [
2846
- detail ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: cn("a24-tool-detail", failed && "a24-tool-detail--error"), children: detail }) : null,
3487
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("a24-tool-detail", failed && "a24-tool-detail--error"), children: detail }) : null,
2847
3488
  hostDetails
2848
3489
  ]
2849
3490
  }
@@ -2863,19 +3504,19 @@ function AgentChatToolSession({
2863
3504
  parts,
2864
3505
  slots
2865
3506
  }) {
2866
- const presentedLiveRef = React11.useRef(false);
3507
+ const presentedLiveRef = React15.useRef(false);
2867
3508
  if (isLive && isLatestActivity) presentedLiveRef.current = true;
2868
3509
  const activeIndex = parts.findLastIndex((part) => isActive(part, activeToolId));
2869
3510
  const running = activeIndex >= 0;
2870
- if (parts.length === 1 && !modelTurn && !leadingModelTurn) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AgentChatToolRow, { activeToolId, part: parts[0], slots });
3511
+ if (parts.length === 1 && !modelTurn && !leadingModelTurn) return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AgentChatToolRow, { activeToolId, part: parts[0], slots });
2871
3512
  const visibleIndex = running ? activeIndex : parts.length - 1;
2872
3513
  const visiblePart = parts[visibleIndex];
2873
3514
  const planning = Boolean(modelTurn);
2874
3515
  const presentingActivity = isLatestActivity && (planning || running || isLive);
2875
3516
  const failed = isLatestActivity && (visiblePart.state === "output-error" || visiblePart.state === "cancelled");
2876
3517
  const label = planning ? "Planning next moves" : isLive && isLatestActivity ? toolRowLabel(visiblePart, true) : sessionLabel(parts, visiblePart, running);
2877
- const labelContent = presentedLiveRef.current ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityReel, { initialLabel: leadingModelTurn ? "Planning next moves" : void 0, initialShownAt: leadingModelTurn?.timestamp, label }) }) : label;
2878
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3518
+ const labelContent = presentedLiveRef.current ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityReel, { initialLabel: leadingModelTurn ? "Planning next moves" : void 0, initialShownAt: leadingModelTurn?.timestamp, label }) }) : label;
3519
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2879
3520
  ToolDisclosure,
2880
3521
  {
2881
3522
  renderActivityIcon: slots?.renderActivityIcon,
@@ -2888,7 +3529,7 @@ function AgentChatToolSession({
2888
3529
  root: true,
2889
3530
  showOrb: isLive && isLatestActivity,
2890
3531
  statusLabel: planning ? "Planning next moves" : label,
2891
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolList, { children: parts.map((part) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "listitem", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AgentChatToolRow, { activeToolId, part, root: false, showOrb: false, slots }) }, part.id)) })
3532
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolList, { children: parts.map((part) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "listitem", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AgentChatToolRow, { activeToolId, part, root: false, showOrb: false, slots }) }, part.id)) })
2892
3533
  }
2893
3534
  );
2894
3535
  }
@@ -2909,7 +3550,7 @@ function subagentLabel(part) {
2909
3550
  return { label: `Agent ${name}, ran ${children.length} ${children.length === 1 ? "tool" : "tools"}`, running: false };
2910
3551
  }
2911
3552
  function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part, slots }) {
2912
- const presentedLiveRef = React11.useRef(false);
3553
+ const presentedLiveRef = React15.useRef(false);
2913
3554
  if (isLive && isLatestActivity) presentedLiveRef.current = true;
2914
3555
  const children = part.presentation.childTools || [];
2915
3556
  const state = subagentLabel(part);
@@ -2918,9 +3559,9 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
2918
3559
  const hostDetails = failed ? null : slots?.renderToolDetails?.(part);
2919
3560
  const failureMessage = part.failure?.message || null;
2920
3561
  const presentingActivity = isLatestActivity && state.running;
2921
- const labelContent = presentedLiveRef.current ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityReel, { label: state.label }) }) : state.label;
3562
+ const labelContent = presentedLiveRef.current ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: presentingActivity ? "a24-tool-shimmer" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityReel, { label: state.label }) }) : state.label;
2922
3563
  const context = toolSlotContext(presentingActivity, state.label, part, slots);
2923
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3564
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2924
3565
  ToolDisclosure,
2925
3566
  {
2926
3567
  renderActivityIcon: slots?.renderActivityIcon,
@@ -2934,12 +3575,12 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
2934
3575
  root: true,
2935
3576
  showOrb: isLive && isLatestActivity,
2936
3577
  statusLabel: state.label,
2937
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ToolList, { children: [
2938
- children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: cn("a24-child-tool", child.status === "failed" && "a24-child-tool--error"), role: "listitem", children: slots?.renderChildTool?.(child, part) ?? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2939
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn(isLive && isLatestActivity && child.status === "running" && "a24-tool-shimmer"), children: childLabel(child) }),
2940
- child.detail ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "a24-child-tool__detail", children: child.detail }) : null
3578
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(ToolList, { children: [
3579
+ children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("a24-child-tool", child.status === "failed" && "a24-child-tool--error"), role: "listitem", children: slots?.renderChildTool?.(child, part) ?? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3580
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: cn(isLive && isLatestActivity && child.status === "running" && "a24-tool-shimmer"), children: childLabel(child) }),
3581
+ child.detail ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "a24-child-tool__detail", children: child.detail }) : null
2941
3582
  ] }) }, child.id)),
2942
- failureMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "a24-tool-detail a24-tool-detail--error", children: failureMessage }) : null,
3583
+ failureMessage ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "a24-tool-detail a24-tool-detail--error", children: failureMessage }) : null,
2943
3584
  hostDetails
2944
3585
  ] })
2945
3586
  }
@@ -2947,41 +3588,51 @@ function AgentChatSubagentGroup({ isLatestActivity = true, isLive = false, part,
2947
3588
  }
2948
3589
 
2949
3590
  // src/ui/agent-response-timeline.tsx
2950
- var import_jsx_runtime11 = require("react/jsx-runtime");
3591
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2951
3592
  function isInternalAskUserTool(part) {
2952
3593
  return [part.toolName, part.toolKey, part.action].some((value) => value?.trim().toLowerCase() === "runtime__ask_user");
2953
3594
  }
2954
3595
  function Shimmer({ children, className }) {
2955
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: cn("inline-block animate-pulse", className), children });
3596
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: cn("inline-block animate-pulse", className), children });
2956
3597
  }
2957
3598
  function AgentChatToolPart({
2958
3599
  activeToolId,
2959
3600
  part
2960
3601
  }) {
2961
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatToolRow, { activeToolId, part });
3602
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatToolRow, { activeToolId, part });
2962
3603
  }
2963
3604
  function AgentChatToolGroup({
2964
3605
  activeToolId,
2965
3606
  parts
2966
3607
  }) {
2967
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatToolSession, { activeToolId, parts });
3608
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatToolSession, { activeToolId, parts });
2968
3609
  }
2969
3610
  function HitlPartRow({
2970
3611
  getHitlActionState,
3612
+ hitlLabels,
3613
+ onHitlPaint,
2971
3614
  isLoading,
2972
3615
  onHitlAction,
2973
3616
  part
2974
3617
  }) {
2975
3618
  const state = getHitlActionState?.(part);
2976
- const [comment, setComment] = React12.useState("");
3619
+ const [comment, setComment] = React16.useState("");
3620
+ const commentRef = React16.useRef(null);
3621
+ const retryActionRef = React16.useRef(null);
3622
+ React16.useEffect(() => {
3623
+ if (state?.status === "error") (commentRef.current || retryActionRef.current)?.focus();
3624
+ }, [state?.status]);
2977
3625
  const presentation = part.presentation || {};
2978
3626
  const requireComment = presentation.require_comment === true;
2979
3627
  const isTerminal = part.status !== "pending";
2980
3628
  if (part.hitlKind === "user_input") {
2981
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3629
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2982
3630
  AskUserInteraction,
2983
3631
  {
2984
3632
  error: state?.error,
3633
+ submission: state,
3634
+ submissionLabels: hitlLabels,
3635
+ onSubmissionPaint: onHitlPaint,
2985
3636
  isBusy: isLoading || state?.status === "resuming",
2986
3637
  onSubmit: onHitlAction ? (answers) => onHitlAction(part, {
2987
3638
  action: "respond",
@@ -2995,12 +3646,14 @@ function HitlPartRow({
2995
3646
  }
2996
3647
  );
2997
3648
  }
3649
+ if (isHitlSubmissionCompact(state)) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(HitlSubmissionStatus, { state, labels: hitlLabels, onPaint: onHitlPaint });
2998
3650
  if (isTerminal) return null;
2999
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "a24-hitl space-y-2.5 px-1 py-2", children: [
3000
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-hitl__title text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
3001
- requireComment ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3651
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "a24-hitl space-y-2.5 px-1 py-2", children: [
3652
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-hitl__title text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
3653
+ requireComment ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3002
3654
  "textarea",
3003
3655
  {
3656
+ ref: commentRef,
3004
3657
  "aria-label": "Approval comment",
3005
3658
  autoComplete: "off",
3006
3659
  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",
@@ -3010,10 +3663,11 @@ function HitlPartRow({
3010
3663
  value: comment
3011
3664
  }
3012
3665
  ) : null,
3013
- state?.error ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-hitl__error text-sm text-destructive", children: state.error }) : null,
3014
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-hitl__actions flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3666
+ state?.error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-hitl__error text-sm text-destructive", children: state.error }) : null,
3667
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-hitl__actions flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3015
3668
  "button",
3016
3669
  {
3670
+ ref: state?.action === action || !state?.action && action === part.allowedActions[0] ? retryActionRef : void 0,
3017
3671
  "aria-label": hitlActionLabel(part, action),
3018
3672
  className: cn(
3019
3673
  "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",
@@ -3035,6 +3689,8 @@ function HitlPartRow({
3035
3689
  function AgentChatPart({
3036
3690
  activeToolId,
3037
3691
  getHitlActionState,
3692
+ hitlLabels,
3693
+ onHitlPaint,
3038
3694
  isLoading,
3039
3695
  isTextStreaming,
3040
3696
  message,
@@ -3044,7 +3700,7 @@ function AgentChatPart({
3044
3700
  toolSlots
3045
3701
  }) {
3046
3702
  if (part.kind === "text") {
3047
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3703
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3048
3704
  MessageResponse,
3049
3705
  {
3050
3706
  ...responseProps,
@@ -3054,44 +3710,46 @@ function AgentChatPart({
3054
3710
  }
3055
3711
  );
3056
3712
  }
3057
- if (part.kind === "tool") return isAgentChatSubagent(part) ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatSubagentGroup, { part, slots: toolSlots }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatToolRow, { activeToolId, part, slots: toolSlots });
3058
- if (part.kind === "model-turn") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatModelTurnRow, { part });
3713
+ if (part.kind === "tool") return isAgentChatSubagent(part) ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatSubagentGroup, { part, slots: toolSlots }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatToolRow, { activeToolId, part, slots: toolSlots });
3714
+ if (part.kind === "model-turn") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatModelTurnRow, { part });
3059
3715
  if (part.kind === "reasoning") {
3060
3716
  const label = part.text || part.label || "Thinking";
3061
- return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-sm text-muted-foreground", children: label });
3717
+ return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-sm text-muted-foreground", children: label });
3062
3718
  }
3063
3719
  if (part.kind === "context-compression") {
3064
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatContextCompressionRow, { part });
3720
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatContextCompressionRow, { part });
3065
3721
  }
3066
3722
  if (part.kind === "ui-blocks") {
3067
3723
  if (part.state === "output-error") {
3068
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-timeline-error text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
3724
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-timeline-error text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
3069
3725
  }
3070
- return part.bundle ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SafeUiBlocks, { bundle: part.bundle }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-sm text-muted-foreground", children: part.state === "input-streaming" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Shimmer, { children: "Rendering UI block" }) : "Rendered UI block" });
3726
+ return part.bundle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SafeUiBlocks, { bundle: part.bundle }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-sm text-muted-foreground", children: part.state === "input-streaming" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Shimmer, { children: "Rendering UI block" }) : "Rendered UI block" });
3071
3727
  }
3072
3728
  if (part.kind === "hitl") {
3073
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3729
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3074
3730
  HitlPartRow,
3075
3731
  {
3076
3732
  getHitlActionState,
3733
+ hitlLabels,
3734
+ onHitlPaint,
3077
3735
  isLoading,
3078
3736
  onHitlAction,
3079
3737
  part
3080
3738
  }
3081
3739
  );
3082
3740
  }
3083
- if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-timeline-error text-sm text-destructive", role: "alert", children: part.errorText });
3741
+ if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-timeline-error text-sm text-destructive", role: "alert", children: part.errorText });
3084
3742
  if (part.kind === "source") {
3085
3743
  const href = safeExternalUrl(part.url);
3086
- return href ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { className: "a24-source-link", href, rel: "noopener noreferrer", target: "_blank", children: part.title }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "a24-source-link", children: part.title });
3744
+ return href ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("a", { className: "a24-source-link", href, rel: "noopener noreferrer", target: "_blank", children: part.title }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "a24-source-link", children: part.title });
3087
3745
  }
3088
3746
  if (part.kind === "citation") {
3089
3747
  const href = safeExternalUrl(part.url);
3090
3748
  const label = part.label || "Citation";
3091
- return href ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { className: "a24-citation", href, rel: "noopener noreferrer", target: "_blank", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "a24-citation", children: label });
3749
+ return href ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("a", { className: "a24-citation", href, rel: "noopener noreferrer", target: "_blank", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "a24-citation", children: label });
3092
3750
  }
3093
- if (part.kind === "attachment") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-output-attachment", children: part.attachment.filename || "Attachment" });
3094
- if (part.kind === "data") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
3751
+ if (part.kind === "attachment") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-output-attachment", children: part.attachment.filename || "Attachment" });
3752
+ if (part.kind === "data") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
3095
3753
  return null;
3096
3754
  }
3097
3755
  function safeExternalUrl(value) {
@@ -3105,28 +3763,28 @@ function safeExternalUrl(value) {
3105
3763
  }
3106
3764
  function SafeUiBlocks({ bundle }) {
3107
3765
  const rows = Array.isArray(bundle.rows) ? bundle.rows : [];
3108
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { "aria-label": typeof bundle.title === "string" ? bundle.title : "Agent result", className: "a24-ui-blocks", children: [
3109
- typeof bundle.title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { children: bundle.title }) : null,
3766
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { "aria-label": typeof bundle.title === "string" ? bundle.title : "Agent result", className: "a24-ui-blocks", children: [
3767
+ typeof bundle.title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: bundle.title }) : null,
3110
3768
  rows.map((rawRow, rowIndex) => {
3111
3769
  const row = rawRow && typeof rawRow === "object" && !Array.isArray(rawRow) ? rawRow : {};
3112
3770
  const blocks = Array.isArray(row.blocks) ? row.blocks : [];
3113
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-ui-blocks__row", children: blocks.map((rawBlock, blockIndex) => {
3771
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-ui-blocks__row", children: blocks.map((rawBlock, blockIndex) => {
3114
3772
  const block = rawBlock && typeof rawBlock === "object" && !Array.isArray(rawBlock) ? rawBlock : {};
3115
3773
  const title = typeof block.title === "string" ? block.title : "Result";
3116
3774
  const kind = String(block.kind || "note");
3117
3775
  if (kind === "table" && Array.isArray(block.columns) && Array.isArray(block.rows)) {
3118
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "a24-ui-block", children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h4", { children: title }),
3120
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "a24-ui-table-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { children: [
3121
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { children: block.columns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { children: String(column) }, index)) }) }),
3122
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: block.rows.map((rawCells, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { children: (Array.isArray(rawCells) ? rawCells : []).map((cell, cellIndex) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: String(cell) }, cellIndex)) }, index)) })
3776
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "a24-ui-block", children: [
3777
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h4", { children: title }),
3778
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "a24-ui-table-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("table", { children: [
3779
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("tr", { children: block.columns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("th", { children: String(column) }, index)) }) }),
3780
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("tbody", { children: block.rows.map((rawCells, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("tr", { children: (Array.isArray(rawCells) ? rawCells : []).map((cell, cellIndex) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("td", { children: String(cell) }, cellIndex)) }, index)) })
3123
3781
  ] }) })
3124
3782
  ] }, String(block.id || blockIndex));
3125
3783
  }
3126
3784
  const value = block.value ?? block.text ?? "";
3127
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "a24-ui-block", children: [
3128
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h4", { children: title }),
3129
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { children: String(value) })
3785
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "a24-ui-block", children: [
3786
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h4", { children: title }),
3787
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { children: String(value) })
3130
3788
  ] }, String(block.id || blockIndex));
3131
3789
  }) }, `row-${rowIndex}`);
3132
3790
  })
@@ -3134,6 +3792,8 @@ function SafeUiBlocks({ bundle }) {
3134
3792
  }
3135
3793
  function AgentResponseTimeline({
3136
3794
  getHitlActionState,
3795
+ hitlLabels,
3796
+ onHitlPaint,
3137
3797
  isLoading = false,
3138
3798
  message,
3139
3799
  nodeActivityMode = "default",
@@ -3146,7 +3806,7 @@ function AgentResponseTimeline({
3146
3806
  toolViewMode = "closed"
3147
3807
  }) {
3148
3808
  isLoading = isLoading && !message.responseCompletion;
3149
- 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));
3809
+ 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));
3150
3810
  const toolParts = parts.filter((part) => part.kind === "tool");
3151
3811
  const activeToolId = latestRunningAgentChatToolId(toolParts);
3152
3812
  const activeTextPartId = getActiveStreamingTextPartId(
@@ -3160,42 +3820,44 @@ function AgentResponseTimeline({
3160
3820
  if (segment.kind === "tool") {
3161
3821
  const isLatestActivity = segmentIndex === segments.length - 1;
3162
3822
  const showOrb = toolViewMode === "closed" ? isLoading && isLatestActivity : Boolean(activeToolId && (segment.part.id === activeToolId || segment.part.toolCallId === activeToolId));
3163
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatToolRow, { activeToolId, part: segment.part, showOrb, slots: toolSlots }, segment.part.id));
3823
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatToolRow, { activeToolId, part: segment.part, showOrb, slots: toolSlots }, segment.part.id));
3164
3824
  continue;
3165
3825
  }
3166
3826
  if (segment.kind === "tool-session") {
3167
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(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}`));
3827
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(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}`));
3168
3828
  continue;
3169
3829
  }
3170
3830
  if (segment.kind === "subagent") {
3171
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatSubagentGroup, { isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, part: segment.part, slots: toolSlots }, segment.part.id));
3831
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatSubagentGroup, { isLatestActivity: segmentIndex === segments.length - 1, isLive: isLoading, part: segment.part, slots: toolSlots }, segment.part.id));
3172
3832
  continue;
3173
3833
  }
3174
3834
  const part = segment.part;
3175
3835
  if (part.kind === "model-turn") {
3176
3836
  const key = activeActivityClaimed ? part.id : `${message.id}-active-activity`;
3177
3837
  activeActivityClaimed = true;
3178
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Planning next moves", modelTurnId: part.modelTurnId }, key));
3838
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Planning next moves", modelTurnId: part.modelTurnId }, key));
3179
3839
  continue;
3180
3840
  }
3181
3841
  if (part.kind === "node-activity") {
3182
3842
  const key = activeActivityClaimed ? part.id : `${message.id}-active-activity`;
3183
3843
  if (part.status === "running") activeActivityClaimed = true;
3184
3844
  rendered.push(
3185
- part.status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: part.label, onSelect: onNodeSelect ? () => onNodeSelect(part) : void 0 }, key) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatNodeActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, onSelect: onNodeSelect, part }, part.id)
3845
+ part.status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: part.label, onSelect: onNodeSelect ? () => onNodeSelect(part) : void 0 }, key) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatNodeActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, onSelect: onNodeSelect, part }, part.id)
3186
3846
  );
3187
3847
  continue;
3188
3848
  }
3189
3849
  if (part.kind === "ui-blocks" && renderUiBlocks) {
3190
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(React12.Fragment, { children: renderUiBlocks(part) }, part.id));
3850
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(React16.Fragment, { children: renderUiBlocks(part) }, part.id));
3191
3851
  continue;
3192
3852
  }
3193
3853
  rendered.push(
3194
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(React12.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3854
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(React16.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3195
3855
  AgentChatPart,
3196
3856
  {
3197
3857
  activeToolId,
3198
3858
  getHitlActionState,
3859
+ hitlLabels,
3860
+ onHitlPaint,
3199
3861
  isLoading,
3200
3862
  isTextStreaming: part.kind === "text" && part.id === activeTextPartId,
3201
3863
  message,
@@ -3208,16 +3870,16 @@ function AgentResponseTimeline({
3208
3870
  );
3209
3871
  }
3210
3872
  if (rendered.length === 0 && message.content) {
3211
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageResponse, { children: message.content }, `${message.id}-fallback`));
3873
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageResponse, { children: message.content }, `${message.id}-fallback`));
3212
3874
  }
3213
3875
  if (rendered.length === 0 && isLoading) {
3214
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Thinking" }, `${message.id}-active-activity`));
3876
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentChatActivityRow, { renderActivityIcon: toolSlots?.renderActivityIcon, label: "Thinking" }, `${message.id}-active-activity`));
3215
3877
  }
3216
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-3", children: rendered });
3878
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "space-y-3", children: rendered });
3217
3879
  }
3218
3880
 
3219
3881
  // src/ui/agent-chat-message.tsx
3220
- var import_jsx_runtime12 = require("react/jsx-runtime");
3882
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3221
3883
  var DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD = 360;
3222
3884
  var DEFAULT_USER_MESSAGE_COLLAPSED_LINES = 4;
3223
3885
  function shouldCollapseUserMessage(content, threshold = DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD) {
@@ -3230,19 +3892,19 @@ function AgentChatUserMessageContent({
3230
3892
  showLessLabel = "Show less",
3231
3893
  showMoreLabel = "Show more"
3232
3894
  }) {
3233
- const [isExpanded, setIsExpanded] = React13.useState(false);
3234
- const contentId = React13.useId();
3895
+ const [isExpanded, setIsExpanded] = React17.useState(false);
3896
+ const contentId = React17.useId();
3235
3897
  const shouldCollapse = shouldCollapseUserMessage(content, collapseThreshold);
3236
- const Icon = isExpanded ? import_lucide_react7.ChevronUp : import_lucide_react7.ChevronDown;
3898
+ const Icon = isExpanded ? import_lucide_react9.ChevronUp : import_lucide_react9.ChevronDown;
3237
3899
  const clampedStyle = shouldCollapse && !isExpanded ? {
3238
3900
  WebkitBoxOrient: "vertical",
3239
3901
  WebkitLineClamp: Math.max(1, collapsedLines),
3240
3902
  display: "-webkit-box",
3241
3903
  overflow: "hidden"
3242
3904
  } : void 0;
3243
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex min-w-0 flex-col gap-3", children: [
3244
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
3245
- shouldCollapse ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3905
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex min-w-0 flex-col gap-3", children: [
3906
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
3907
+ shouldCollapse ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3246
3908
  "button",
3247
3909
  {
3248
3910
  "aria-controls": contentId,
@@ -3255,7 +3917,7 @@ function AgentChatUserMessageContent({
3255
3917
  type: "button",
3256
3918
  children: [
3257
3919
  isExpanded ? showLessLabel : showMoreLabel,
3258
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
3920
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
3259
3921
  ]
3260
3922
  }
3261
3923
  ) : null
@@ -3265,9 +3927,9 @@ function AgentChatUserMessageActionRow({
3265
3927
  children,
3266
3928
  className
3267
3929
  }) {
3268
- const rowRef = React13.useRef(null);
3269
- const [visible, setVisible] = React13.useState(false);
3270
- React13.useEffect(() => {
3930
+ const rowRef = React17.useRef(null);
3931
+ const [visible, setVisible] = React17.useState(false);
3932
+ React17.useEffect(() => {
3271
3933
  const message = rowRef.current?.closest('[data-slot="message"]');
3272
3934
  if (!message) return;
3273
3935
  const show = () => setVisible(true);
@@ -3286,7 +3948,7 @@ function AgentChatUserMessageActionRow({
3286
3948
  message.removeEventListener("focusout", hideWhenFocusLeaves);
3287
3949
  };
3288
3950
  }, []);
3289
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3951
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3290
3952
  "div",
3291
3953
  {
3292
3954
  ref: rowRef,
@@ -3306,6 +3968,8 @@ function AgentChatMessage({
3306
3968
  contentClassName,
3307
3969
  dir,
3308
3970
  getHitlActionState,
3971
+ hitlLabels,
3972
+ onHitlPaint,
3309
3973
  message,
3310
3974
  nodeActivityMode,
3311
3975
  onHitlAction,
@@ -3325,7 +3989,7 @@ function AgentChatMessage({
3325
3989
  const resolvedUserContent = userMessageContent ?? message.content;
3326
3990
  const shouldRenderContent = isAssistant || Boolean(renderUserContent || resolvedUserContent);
3327
3991
  const showAttachments = Boolean(message.attachments?.length) && (message.role === "user" || showAssistantAttachments);
3328
- const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3992
+ const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3329
3993
  AgentChatDefaultActions,
3330
3994
  {
3331
3995
  additionalActions,
@@ -3335,14 +3999,14 @@ function AgentChatMessage({
3335
3999
  }
3336
4000
  ) : null);
3337
4001
  const defaultUserActions = !actions && Boolean(actionHandlers) && !isAssistant;
3338
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4002
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3339
4003
  ChatMessage,
3340
4004
  {
3341
4005
  className,
3342
4006
  dir,
3343
4007
  from: message.role,
3344
4008
  children: [
3345
- showAttachments ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4009
+ showAttachments ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3346
4010
  ChatAttachmentRows,
3347
4011
  {
3348
4012
  attachments: message.attachments || [],
@@ -3351,17 +4015,19 @@ function AgentChatMessage({
3351
4015
  resolveContent: attachmentContentResolver
3352
4016
  }
3353
4017
  ) : null,
3354
- shouldRenderContent ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4018
+ shouldRenderContent ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3355
4019
  ChatMessageContent,
3356
4020
  {
3357
4021
  className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
3358
4022
  dir,
3359
4023
  from: message.role,
3360
4024
  children: [
3361
- isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4025
+ isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3362
4026
  Timeline,
3363
4027
  {
3364
4028
  getHitlActionState,
4029
+ hitlLabels,
4030
+ onHitlPaint,
3365
4031
  isLoading: isStreaming,
3366
4032
  message,
3367
4033
  nodeActivityMode,
@@ -3369,7 +4035,7 @@ function AgentChatMessage({
3369
4035
  parts: message.parts
3370
4036
  }
3371
4037
  ) : null,
3372
- !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4038
+ !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3373
4039
  AgentChatUserMessageContent,
3374
4040
  {
3375
4041
  collapsedLines: userMessageCollapsedLines,
@@ -3382,18 +4048,22 @@ function AgentChatMessage({
3382
4048
  ]
3383
4049
  }
3384
4050
  ) : null,
3385
- renderedActions ? defaultUserActions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AgentChatUserMessageActionRow, { className: actionsClassName, children: renderedActions }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
4051
+ renderedActions ? defaultUserActions ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AgentChatUserMessageActionRow, { className: actionsClassName, children: renderedActions }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn(
4052
+ dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2",
4053
+ isAssistant && "a24-chat-message-action-row--assistant",
4054
+ actionsClassName
4055
+ ), children: renderedActions }) : null
3386
4056
  ]
3387
4057
  }
3388
4058
  );
3389
4059
  }
3390
4060
 
3391
4061
  // src/ui/bubble.tsx
3392
- var import_class_variance_authority2 = require("class-variance-authority");
4062
+ var import_class_variance_authority3 = require("class-variance-authority");
3393
4063
  var import_react_slot2 = require("@radix-ui/react-slot");
3394
- var import_jsx_runtime13 = require("react/jsx-runtime");
4064
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3395
4065
  function BubbleGroup({ className, ...props }) {
3396
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4066
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3397
4067
  "div",
3398
4068
  {
3399
4069
  "data-slot": "bubble-group",
@@ -3402,7 +4072,7 @@ function BubbleGroup({ className, ...props }) {
3402
4072
  }
3403
4073
  );
3404
4074
  }
3405
- var bubbleVariants = (0, import_class_variance_authority2.cva)(
4075
+ var bubbleVariants = (0, import_class_variance_authority3.cva)(
3406
4076
  "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
3407
4077
  {
3408
4078
  variants: {
@@ -3427,7 +4097,7 @@ function Bubble({
3427
4097
  className,
3428
4098
  ...props
3429
4099
  }) {
3430
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4100
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3431
4101
  "div",
3432
4102
  {
3433
4103
  "data-slot": "bubble",
@@ -3444,7 +4114,7 @@ function BubbleContent({
3444
4114
  ...props
3445
4115
  }) {
3446
4116
  const Comp = asChild ? import_react_slot2.Slot : "div";
3447
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4117
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3448
4118
  Comp,
3449
4119
  {
3450
4120
  "data-slot": "bubble-content",
@@ -3456,7 +4126,7 @@ function BubbleContent({
3456
4126
  }
3457
4127
  );
3458
4128
  }
3459
- var bubbleReactionsVariants = (0, import_class_variance_authority2.cva)(
4129
+ var bubbleReactionsVariants = (0, import_class_variance_authority3.cva)(
3460
4130
  "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
3461
4131
  {
3462
4132
  variants: {
@@ -3481,7 +4151,7 @@ function BubbleReactions({
3481
4151
  className,
3482
4152
  ...props
3483
4153
  }) {
3484
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4154
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3485
4155
  "div",
3486
4156
  {
3487
4157
  "data-slot": "bubble-reactions",
@@ -3494,10 +4164,10 @@ function BubbleReactions({
3494
4164
  }
3495
4165
 
3496
4166
  // src/ui/marker.tsx
3497
- var import_class_variance_authority3 = require("class-variance-authority");
4167
+ var import_class_variance_authority4 = require("class-variance-authority");
3498
4168
  var import_react_slot3 = require("@radix-ui/react-slot");
3499
- var import_jsx_runtime14 = require("react/jsx-runtime");
3500
- var markerVariants = (0, import_class_variance_authority3.cva)(
4169
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4170
+ var markerVariants = (0, import_class_variance_authority4.cva)(
3501
4171
  "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",
3502
4172
  {
3503
4173
  variants: {
@@ -3516,7 +4186,7 @@ function Marker({
3516
4186
  ...props
3517
4187
  }) {
3518
4188
  const Comp = asChild ? import_react_slot3.Slot : "div";
3519
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4189
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3520
4190
  Comp,
3521
4191
  {
3522
4192
  "data-slot": "marker",
@@ -3527,7 +4197,7 @@ function Marker({
3527
4197
  );
3528
4198
  }
3529
4199
  function MarkerIcon({ className, ...props }) {
3530
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4200
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3531
4201
  "span",
3532
4202
  {
3533
4203
  "data-slot": "marker-icon",
@@ -3541,7 +4211,7 @@ function MarkerIcon({ className, ...props }) {
3541
4211
  );
3542
4212
  }
3543
4213
  function MarkerContent({ className, ...props }) {
3544
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4214
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3545
4215
  "span",
3546
4216
  {
3547
4217
  "data-slot": "marker-content",
@@ -3555,7 +4225,7 @@ function MarkerContent({ className, ...props }) {
3555
4225
  }
3556
4226
 
3557
4227
  // src/ui/mcp-connect-required-card.tsx
3558
- var import_jsx_runtime15 = require("react/jsx-runtime");
4228
+ var import_jsx_runtime19 = require("react/jsx-runtime");
3559
4229
  var STATUS_LABELS = {
3560
4230
  pending: "Connect",
3561
4231
  connecting: "Connecting",
@@ -3579,7 +4249,7 @@ function McpConnectRequiredCard({
3579
4249
  const isBusy = loading || status === "connecting" || status === "resuming";
3580
4250
  const isConnected = status === "connected";
3581
4251
  const buttonDisabled = disabled || isBusy || isConnected || !onConnect;
3582
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4252
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3583
4253
  "div",
3584
4254
  {
3585
4255
  "data-agents24-mcp-connect-card": true,
@@ -3589,13 +4259,13 @@ function McpConnectRequiredCard({
3589
4259
  className
3590
4260
  ),
3591
4261
  ...props,
3592
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
3593
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "min-w-0", children: [
3594
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "truncate text-sm font-medium", children: label }),
3595
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
3596
- status === "error" && error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
4262
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
4263
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "min-w-0", children: [
4264
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "truncate text-sm font-medium", children: label }),
4265
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
4266
+ status === "error" && error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
3597
4267
  ] }),
3598
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4268
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3599
4269
  "button",
3600
4270
  {
3601
4271
  type: "button",
@@ -3653,6 +4323,17 @@ function McpConnectRequiredCard({
3653
4323
  ChatMessageAction,
3654
4324
  ChatMessageActions,
3655
4325
  ChatMessageContent,
4326
+ CodeBlock,
4327
+ CodeBlockActions,
4328
+ CodeBlockContent,
4329
+ CodeBlockCopyButton,
4330
+ CodeBlockDownloadButton,
4331
+ CodeBlockFooter,
4332
+ CodeBlockHeader,
4333
+ CodeBlockLine,
4334
+ CodeBlockTitle,
4335
+ CodeBlockWrapButton,
4336
+ HitlSubmissionStatus,
3656
4337
  Marker,
3657
4338
  MarkerContent,
3658
4339
  MarkerIcon,
@@ -3679,10 +4360,12 @@ function McpConnectRequiredCard({
3679
4360
  cn,
3680
4361
  contextStatusMetrics,
3681
4362
  createAgentChatComposerFile,
4363
+ defaultHitlSubmissionLabels,
3682
4364
  hitlActionLabel,
3683
4365
  hitlTitle,
3684
4366
  isAgentChatSubagent,
3685
4367
  isAgentChatToolRunning,
4368
+ isHitlSubmissionCompact,
3686
4369
  latestRunningAgentChatToolId,
3687
4370
  markerVariants,
3688
4371
  partitionAgentChatToolTimeline,
@@ -3694,6 +4377,7 @@ function McpConnectRequiredCard({
3694
4377
  useAudioRecorder,
3695
4378
  useChatComposerFocus,
3696
4379
  useCompletionActionEntrance,
4380
+ useHighlightedCode,
3697
4381
  useLiveCompletionRuns
3698
4382
  });
3699
4383
  //# sourceMappingURL=index.cjs.map