@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.
- package/compatibility.json +5 -5
- package/dist/{chunk-INO5DSSJ.js → chunk-DWDHK4FZ.js} +3 -4
- package/dist/chunk-DWDHK4FZ.js.map +1 -0
- package/dist/generated/delegation-types.d.ts +3 -2
- package/dist/generated/run-usage.d.ts +11 -0
- package/dist/registry/agents24-chat.json +13 -13
- package/dist/runtime/index.cjs +25 -9
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +24 -7
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/input-contract.d.ts +1 -1
- package/dist/runtime/use-agent-chat-hitl.d.ts +2 -2
- package/dist/runtime/use-agent-chat-runtime.d.ts +4 -6
- package/dist/scaffold/app.d.ts +2 -2
- package/dist/scaffold/components/chat/chat-composer.d.ts +2 -1
- package/dist/scaffold/components/chat/chat-message.d.ts +2 -2
- package/dist/scaffold/components/chat/message-parts.d.ts +2 -2
- package/dist/scaffold/index.cjs +17 -13
- package/dist/scaffold/index.cjs.map +1 -1
- package/dist/scaffold/index.js +11 -7
- package/dist/scaffold/index.js.map +1 -1
- package/dist/styles.css +55 -0
- package/dist/ui/agent-chat-composer.d.ts +2 -1
- package/dist/ui/agent-chat-message.d.ts +6 -2
- package/dist/ui/agent-response-timeline.d.ts +11 -3
- package/dist/ui/ask-user-interaction.d.ts +5 -1
- package/dist/ui/bubble.d.ts +1 -1
- package/dist/ui/code-block.d.ts +33 -0
- package/dist/ui/code-highlighter.d.ts +8 -0
- package/dist/ui/hitl-submission-status.d.ts +22 -0
- package/dist/ui/index.cjs +985 -301
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.js +969 -296
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/message-code.d.ts +21 -0
- package/dist/ui/use-agent-chat-composer.d.ts +17 -2
- package/dist/ui/use-audio-recorder.d.ts +15 -2
- package/dist/ui/use-highlighted-code.d.ts +2 -0
- package/package.json +4 -3
- package/scaffold/src/app.tsx +2 -1
- package/scaffold/src/components/chat/chat-composer.tsx +5 -3
- package/scaffold/src/components/chat/chat-message.tsx +3 -3
- package/scaffold/src/components/chat/chat-shell.tsx +2 -1
- package/scaffold/src/components/chat/message-parts.tsx +6 -6
- 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.
|
|
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
|
|
956
|
-
|
|
957
|
-
|
|
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
|
-
|
|
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
|
|
975
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
1037
|
+
if (operation.signal.aborted) return;
|
|
1003
1038
|
const actualType = recorder.mimeType || mimeType;
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1067
|
+
callbacksRef.current.onStreamChange?.(stream);
|
|
1022
1068
|
} catch {
|
|
1023
|
-
if (
|
|
1024
|
-
|
|
1025
|
-
|
|
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 (
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
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
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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.
|
|
1059
|
-
|
|
1060
|
-
|
|
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
|
-
|
|
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 =
|
|
1086
|
-
|
|
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
|
-
|
|
1093
|
-
|
|
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(
|
|
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
|
-
|
|
1104
|
-
const
|
|
1105
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
1202
|
+
}
|
|
1203
|
+
return false;
|
|
1122
1204
|
} finally {
|
|
1123
|
-
inFlightFilesRef.current
|
|
1124
|
-
|
|
1125
|
-
|
|
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
|
|
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
|
|
1775
|
-
var
|
|
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
|
|
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
|
|
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
|
|
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] =
|
|
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,
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2069
|
-
/* @__PURE__ */ (0,
|
|
2070
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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] =
|
|
2092
|
-
const [drafts, setDrafts] =
|
|
2239
|
+
const [step, setStep] = React10.useState(0);
|
|
2240
|
+
const [drafts, setDrafts] = React10.useState(
|
|
2093
2241
|
() => emptyAskUserDrafts(questions)
|
|
2094
2242
|
);
|
|
2095
|
-
const
|
|
2096
|
-
const
|
|
2097
|
-
const
|
|
2098
|
-
const
|
|
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
|
-
|
|
2249
|
+
React10.useEffect(() => {
|
|
2101
2250
|
setStep(0);
|
|
2102
2251
|
setDrafts(emptyAskUserDrafts(questionsRef.current));
|
|
2103
2252
|
}, [part.interruptId]);
|
|
2104
|
-
|
|
2253
|
+
React10.useEffect(() => {
|
|
2105
2254
|
headingRef.current?.focus();
|
|
2106
2255
|
}, [step]);
|
|
2107
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
2154
|
-
/* @__PURE__ */ (0,
|
|
2155
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
2239
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2253
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
2356
|
-
if (safeHref.startsWith("#")) return /* @__PURE__ */ (0,
|
|
2357
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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 (!
|
|
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
|
|
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 =
|
|
3029
|
+
const childArray = React14.Children.toArray(children).filter(
|
|
2400
3030
|
(child) => child !== null && child !== ""
|
|
2401
3031
|
);
|
|
2402
|
-
const isImageOnly = childArray.length === 1 &&
|
|
3032
|
+
const isImageOnly = childArray.length === 1 && React14.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
|
|
2403
3033
|
if (isImageOnly) {
|
|
2404
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
3037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { ...domProps, children });
|
|
2408
3038
|
}
|
|
2409
|
-
return /* @__PURE__ */ (0,
|
|
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 =
|
|
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 =
|
|
3078
|
+
const streamdownComponents = React14.useMemo(
|
|
2448
3079
|
() => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
|
|
2449
3080
|
[components]
|
|
2450
3081
|
);
|
|
2451
|
-
|
|
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
|
|
2504
|
-
var
|
|
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
|
|
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,
|
|
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,
|
|
2539
|
-
slots?.onResourceAction ? /* @__PURE__ */ (0,
|
|
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] =
|
|
2617
|
-
const [previous, setPrevious] =
|
|
2618
|
-
const displayedRef =
|
|
2619
|
-
const latestRef =
|
|
2620
|
-
const shownAtRef =
|
|
2621
|
-
|
|
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
|
-
|
|
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,
|
|
2647
|
-
previous ? /* @__PURE__ */ (0,
|
|
2648
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
2661
|
-
/* @__PURE__ */ (0,
|
|
2662
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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] =
|
|
2675
|
-
const contentId =
|
|
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,
|
|
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,
|
|
2689
|
-
running ? /* @__PURE__ */ (0,
|
|
2690
|
-
/* @__PURE__ */ (0,
|
|
2691
|
-
] }) : /* @__PURE__ */ (0,
|
|
2692
|
-
running ? /* @__PURE__ */ (0,
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2697
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2710
|
-
open ? /* @__PURE__ */ (0,
|
|
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,
|
|
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] =
|
|
2742
|
-
const contentId =
|
|
2743
|
-
const expandable =
|
|
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,
|
|
2747
|
-
onSelect && part ? /* @__PURE__ */ (0,
|
|
2748
|
-
showOrb ? /* @__PURE__ */ (0,
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2750
|
-
] }) : /* @__PURE__ */ (0,
|
|
2751
|
-
showOrb ? /* @__PURE__ */ (0,
|
|
2752
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2758
|
-
/* @__PURE__ */ (0,
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2774
|
-
/* @__PURE__ */ (0,
|
|
2775
|
-
open ? /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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 =
|
|
2790
|
-
const [fades, setFades] =
|
|
2791
|
-
const updateFades =
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 =
|
|
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,
|
|
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,
|
|
2878
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
2938
|
-
children.map((child) => /* @__PURE__ */ (0,
|
|
2939
|
-
/* @__PURE__ */ (0,
|
|
2940
|
-
child.detail ? /* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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] =
|
|
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,
|
|
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,
|
|
3000
|
-
/* @__PURE__ */ (0,
|
|
3001
|
-
requireComment ? /* @__PURE__ */ (0,
|
|
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,
|
|
3014
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3058
|
-
if (part.kind === "model-turn") return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3094
|
-
if (part.kind === "data") return /* @__PURE__ */ (0,
|
|
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,
|
|
3109
|
-
typeof bundle.title === "string" ? /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3119
|
-
/* @__PURE__ */ (0,
|
|
3120
|
-
/* @__PURE__ */ (0,
|
|
3121
|
-
/* @__PURE__ */ (0,
|
|
3122
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3128
|
-
/* @__PURE__ */ (0,
|
|
3129
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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] =
|
|
3234
|
-
const contentId =
|
|
3895
|
+
const [isExpanded, setIsExpanded] = React17.useState(false);
|
|
3896
|
+
const contentId = React17.useId();
|
|
3235
3897
|
const shouldCollapse = shouldCollapseUserMessage(content, collapseThreshold);
|
|
3236
|
-
const Icon = isExpanded ?
|
|
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,
|
|
3244
|
-
/* @__PURE__ */ (0,
|
|
3245
|
-
shouldCollapse ? /* @__PURE__ */ (0,
|
|
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,
|
|
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 =
|
|
3269
|
-
const [visible, setVisible] =
|
|
3270
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
4062
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
3393
4063
|
var import_react_slot2 = require("@radix-ui/react-slot");
|
|
3394
|
-
var
|
|
4064
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3395
4065
|
function BubbleGroup({ className, ...props }) {
|
|
3396
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
4167
|
+
var import_class_variance_authority4 = require("class-variance-authority");
|
|
3498
4168
|
var import_react_slot3 = require("@radix-ui/react-slot");
|
|
3499
|
-
var
|
|
3500
|
-
var markerVariants = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
3593
|
-
/* @__PURE__ */ (0,
|
|
3594
|
-
/* @__PURE__ */ (0,
|
|
3595
|
-
/* @__PURE__ */ (0,
|
|
3596
|
-
status === "error" && error ? /* @__PURE__ */ (0,
|
|
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,
|
|
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
|