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