@autobe/ui 0.30.0-dev.20260315 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -661
- package/lib/components/AutoBeChatMain.js +5 -5
- package/lib/components/AutoBeConfigModal.js +9 -9
- package/package.json +2 -2
- package/src/components/AutoBeAssistantMessageMovie.tsx +22 -22
- package/src/components/AutoBeChatMain.tsx +376 -376
- package/src/components/AutoBeChatSidebar.tsx +414 -414
- package/src/components/AutoBeConfigButton.tsx +83 -83
- package/src/components/AutoBeConfigModal.tsx +443 -443
- package/src/components/AutoBeStatusButton.tsx +75 -75
- package/src/components/AutoBeStatusModal.tsx +486 -486
- package/src/components/AutoBeUserMessageMovie.tsx +27 -27
- package/src/components/common/ActionButton.tsx +205 -205
- package/src/components/common/ActionButtonGroup.tsx +80 -80
- package/src/components/common/AutoBeConfigInput.tsx +185 -185
- package/src/components/common/ChatBubble.tsx +119 -119
- package/src/components/common/Collapsible.tsx +95 -95
- package/src/components/common/CompactSessionIndicator.tsx +73 -73
- package/src/components/common/CompactSessionList.tsx +82 -82
- package/src/components/common/index.ts +8 -8
- package/src/components/common/openai/OpenAIContent.tsx +53 -53
- package/src/components/common/openai/OpenAIUserAudioContent.tsx +70 -70
- package/src/components/common/openai/OpenAIUserFileContent.tsx +76 -76
- package/src/components/common/openai/OpenAIUserImageContent.tsx +34 -34
- package/src/components/common/openai/OpenAIUserTextContent.tsx +15 -15
- package/src/components/common/openai/index.ts +5 -5
- package/src/components/events/AutoBeCompleteEventMovie.tsx +402 -402
- package/src/components/events/AutoBeCorrectEventMovie.tsx +354 -354
- package/src/components/events/AutoBeEventGroupMovie.tsx +18 -18
- package/src/components/events/AutoBeEventMovie.tsx +158 -158
- package/src/components/events/AutoBeProgressEventMovie.tsx +217 -217
- package/src/components/events/AutoBeScenarioEventMovie.tsx +135 -135
- package/src/components/events/AutoBeStartEventMovie.tsx +82 -82
- package/src/components/events/AutoBeValidateEventMovie.tsx +249 -249
- package/src/components/events/README.md +300 -300
- package/src/components/events/common/CollapsibleEventGroup.tsx +211 -211
- package/src/components/events/common/EventCard.tsx +61 -61
- package/src/components/events/common/EventContent.tsx +31 -31
- package/src/components/events/common/EventHeader.tsx +85 -85
- package/src/components/events/common/EventIcon.tsx +82 -82
- package/src/components/events/common/ProgressBar.tsx +64 -64
- package/src/components/events/common/index.ts +13 -13
- package/src/components/events/groups/CorrectEventGroup.tsx +183 -183
- package/src/components/events/groups/ValidateEventGroup.tsx +143 -143
- package/src/components/events/groups/index.ts +8 -8
- package/src/components/events/index.ts +16 -16
- package/src/components/events/utils/eventGrouper.tsx +116 -116
- package/src/components/events/utils/index.ts +1 -1
- package/src/components/index.ts +13 -13
- package/src/components/upload/AutoBeChatUploadBox.tsx +425 -425
- package/src/components/upload/AutoBeChatUploadSendButton.tsx +66 -66
- package/src/components/upload/AutoBeFileUploadBox.tsx +123 -123
- package/src/components/upload/AutoBeUploadConfig.ts +5 -5
- package/src/components/upload/AutoBeVoiceRecoderButton.tsx +100 -100
- package/src/components/upload/index.ts +5 -5
- package/src/constant/color.ts +28 -28
- package/src/context/AutoBeAgentContext.tsx +245 -245
- package/src/context/AutoBeAgentSessionList.tsx +58 -58
- package/src/context/SearchParamsContext.tsx +49 -49
- package/src/hooks/index.ts +3 -3
- package/src/hooks/useEscapeKey.ts +24 -24
- package/src/hooks/useIsomorphicLayoutEffect.ts +8 -8
- package/src/hooks/useMediaQuery.ts +73 -73
- package/src/hooks/useSessionStorage.ts +10 -10
- package/src/icons/Receipt.tsx +74 -74
- package/src/index.ts +9 -9
- package/src/strategy/AutoBeAgentSessionStorageStrategy.ts +127 -127
- package/src/structure/AutoBeListener.ts +373 -373
- package/src/structure/AutoBeListenerState.ts +53 -53
- package/src/structure/IAutoBeAgentSessionStorageStrategy.ts +87 -87
- package/src/structure/IAutoBeEventGroup.ts +6 -6
- package/src/structure/index.ts +4 -4
- package/src/types/config.ts +44 -44
- package/src/types/index.ts +1 -1
- package/src/utils/AutoBeFileUploader.ts +279 -279
- package/src/utils/AutoBeVoiceRecorder.ts +95 -95
- package/src/utils/__tests__/crypto.test.ts +286 -286
- package/src/utils/__tests__/storage.test.ts +229 -229
- package/src/utils/crypto.ts +95 -95
- package/src/utils/index.ts +6 -6
- package/src/utils/number.ts +17 -17
- package/src/utils/storage.ts +96 -96
- package/src/utils/time.ts +14 -14
- package/tsconfig.json +9 -9
- package/vitest.config.ts +15 -15
- package/README.md +0 -261
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
import { AutoBeUserMessageAudioContent } from "@autobe/interface";
|
|
2
|
-
|
|
3
|
-
import { AutoBeFileUploader } from "./AutoBeFileUploader";
|
|
4
|
-
|
|
5
|
-
export namespace AutoBeVoiceRecorder {
|
|
6
|
-
export const start = async (
|
|
7
|
-
onComplete: (content: {
|
|
8
|
-
file: File;
|
|
9
|
-
content: AutoBeUserMessageAudioContent;
|
|
10
|
-
}) => void,
|
|
11
|
-
): Promise<MediaRecorder> => {
|
|
12
|
-
const stream: MediaStream = await navigator.mediaDevices.getUserMedia({
|
|
13
|
-
audio: true,
|
|
14
|
-
});
|
|
15
|
-
const recorder: MediaRecorder = new MediaRecorder(stream);
|
|
16
|
-
const chunks: Blob[] = [];
|
|
17
|
-
|
|
18
|
-
recorder.ondataavailable = (event) => {
|
|
19
|
-
if (event.data.size > 0) chunks.push(event.data);
|
|
20
|
-
};
|
|
21
|
-
recorder.onstop = async () => {
|
|
22
|
-
try {
|
|
23
|
-
const audioBlob = new Blob(chunks, { type: "audio/webm" });
|
|
24
|
-
const wavBlob = await convertToWav(audioBlob);
|
|
25
|
-
const audioFile = new File([wavBlob], `recording-${Date.now()}.wav`, {
|
|
26
|
-
type: "audio/wav",
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const base64 = await AutoBeFileUploader.convertToBase64(audioFile);
|
|
30
|
-
const content: AutoBeUserMessageAudioContent = {
|
|
31
|
-
type: "audio",
|
|
32
|
-
data: base64,
|
|
33
|
-
format: "wav",
|
|
34
|
-
};
|
|
35
|
-
onComplete({
|
|
36
|
-
file: audioFile,
|
|
37
|
-
content,
|
|
38
|
-
});
|
|
39
|
-
} finally {
|
|
40
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
return recorder;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const convertToWav = async (audioBlob: Blob): Promise<Blob> => {
|
|
48
|
-
const audioContext = new AudioContext();
|
|
49
|
-
const arrayBuffer = await audioBlob.arrayBuffer();
|
|
50
|
-
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
51
|
-
|
|
52
|
-
// Create WAV file
|
|
53
|
-
const length = audioBuffer.length;
|
|
54
|
-
const sampleRate = audioBuffer.sampleRate;
|
|
55
|
-
const numberOfChannels = audioBuffer.numberOfChannels;
|
|
56
|
-
|
|
57
|
-
// Calculate WAV file size
|
|
58
|
-
const wavLength = 44 + length * numberOfChannels * 2;
|
|
59
|
-
const buffer = new ArrayBuffer(wavLength);
|
|
60
|
-
const view = new DataView(buffer);
|
|
61
|
-
|
|
62
|
-
// WAV file header
|
|
63
|
-
const writeString = (offset: number, string: string) => {
|
|
64
|
-
for (let i = 0; i < string.length; i++) {
|
|
65
|
-
view.setUint8(offset + i, string.charCodeAt(i));
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
writeString(0, "RIFF");
|
|
70
|
-
view.setUint32(4, wavLength - 8, true);
|
|
71
|
-
writeString(8, "WAVE");
|
|
72
|
-
writeString(12, "fmt ");
|
|
73
|
-
view.setUint32(16, 16, true); // fmt chunk size
|
|
74
|
-
view.setUint16(20, 1, true); // PCM format
|
|
75
|
-
view.setUint16(22, numberOfChannels, true);
|
|
76
|
-
view.setUint32(24, sampleRate, true);
|
|
77
|
-
view.setUint32(28, sampleRate * numberOfChannels * 2, true); // byte rate
|
|
78
|
-
view.setUint16(32, numberOfChannels * 2, true); // block align
|
|
79
|
-
view.setUint16(34, 16, true); // bits per sample
|
|
80
|
-
writeString(36, "data");
|
|
81
|
-
view.setUint32(40, length * numberOfChannels * 2, true);
|
|
82
|
-
|
|
83
|
-
// Write audio data
|
|
84
|
-
let offset = 44;
|
|
85
|
-
for (let i = 0; i < length; i++) {
|
|
86
|
-
for (let channel = 0; channel < numberOfChannels; channel++) {
|
|
87
|
-
const sample = audioBuffer.getChannelData(channel)[i]!;
|
|
88
|
-
const value = Math.max(-1, Math.min(1, sample));
|
|
89
|
-
view.setInt16(offset, value * 0x7fff, true);
|
|
90
|
-
offset += 2;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return new Blob([buffer], { type: "audio/wav" });
|
|
95
|
-
};
|
|
1
|
+
import { AutoBeUserMessageAudioContent } from "@autobe/interface";
|
|
2
|
+
|
|
3
|
+
import { AutoBeFileUploader } from "./AutoBeFileUploader";
|
|
4
|
+
|
|
5
|
+
export namespace AutoBeVoiceRecorder {
|
|
6
|
+
export const start = async (
|
|
7
|
+
onComplete: (content: {
|
|
8
|
+
file: File;
|
|
9
|
+
content: AutoBeUserMessageAudioContent;
|
|
10
|
+
}) => void,
|
|
11
|
+
): Promise<MediaRecorder> => {
|
|
12
|
+
const stream: MediaStream = await navigator.mediaDevices.getUserMedia({
|
|
13
|
+
audio: true,
|
|
14
|
+
});
|
|
15
|
+
const recorder: MediaRecorder = new MediaRecorder(stream);
|
|
16
|
+
const chunks: Blob[] = [];
|
|
17
|
+
|
|
18
|
+
recorder.ondataavailable = (event) => {
|
|
19
|
+
if (event.data.size > 0) chunks.push(event.data);
|
|
20
|
+
};
|
|
21
|
+
recorder.onstop = async () => {
|
|
22
|
+
try {
|
|
23
|
+
const audioBlob = new Blob(chunks, { type: "audio/webm" });
|
|
24
|
+
const wavBlob = await convertToWav(audioBlob);
|
|
25
|
+
const audioFile = new File([wavBlob], `recording-${Date.now()}.wav`, {
|
|
26
|
+
type: "audio/wav",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const base64 = await AutoBeFileUploader.convertToBase64(audioFile);
|
|
30
|
+
const content: AutoBeUserMessageAudioContent = {
|
|
31
|
+
type: "audio",
|
|
32
|
+
data: base64,
|
|
33
|
+
format: "wav",
|
|
34
|
+
};
|
|
35
|
+
onComplete({
|
|
36
|
+
file: audioFile,
|
|
37
|
+
content,
|
|
38
|
+
});
|
|
39
|
+
} finally {
|
|
40
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return recorder;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const convertToWav = async (audioBlob: Blob): Promise<Blob> => {
|
|
48
|
+
const audioContext = new AudioContext();
|
|
49
|
+
const arrayBuffer = await audioBlob.arrayBuffer();
|
|
50
|
+
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
51
|
+
|
|
52
|
+
// Create WAV file
|
|
53
|
+
const length = audioBuffer.length;
|
|
54
|
+
const sampleRate = audioBuffer.sampleRate;
|
|
55
|
+
const numberOfChannels = audioBuffer.numberOfChannels;
|
|
56
|
+
|
|
57
|
+
// Calculate WAV file size
|
|
58
|
+
const wavLength = 44 + length * numberOfChannels * 2;
|
|
59
|
+
const buffer = new ArrayBuffer(wavLength);
|
|
60
|
+
const view = new DataView(buffer);
|
|
61
|
+
|
|
62
|
+
// WAV file header
|
|
63
|
+
const writeString = (offset: number, string: string) => {
|
|
64
|
+
for (let i = 0; i < string.length; i++) {
|
|
65
|
+
view.setUint8(offset + i, string.charCodeAt(i));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
writeString(0, "RIFF");
|
|
70
|
+
view.setUint32(4, wavLength - 8, true);
|
|
71
|
+
writeString(8, "WAVE");
|
|
72
|
+
writeString(12, "fmt ");
|
|
73
|
+
view.setUint32(16, 16, true); // fmt chunk size
|
|
74
|
+
view.setUint16(20, 1, true); // PCM format
|
|
75
|
+
view.setUint16(22, numberOfChannels, true);
|
|
76
|
+
view.setUint32(24, sampleRate, true);
|
|
77
|
+
view.setUint32(28, sampleRate * numberOfChannels * 2, true); // byte rate
|
|
78
|
+
view.setUint16(32, numberOfChannels * 2, true); // block align
|
|
79
|
+
view.setUint16(34, 16, true); // bits per sample
|
|
80
|
+
writeString(36, "data");
|
|
81
|
+
view.setUint32(40, length * numberOfChannels * 2, true);
|
|
82
|
+
|
|
83
|
+
// Write audio data
|
|
84
|
+
let offset = 44;
|
|
85
|
+
for (let i = 0; i < length; i++) {
|
|
86
|
+
for (let channel = 0; channel < numberOfChannels; channel++) {
|
|
87
|
+
const sample = audioBuffer.getChannelData(channel)[i]!;
|
|
88
|
+
const value = Math.max(-1, Math.min(1, sample));
|
|
89
|
+
view.setInt16(offset, value * 0x7fff, true);
|
|
90
|
+
offset += 2;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return new Blob([buffer], { type: "audio/wav" });
|
|
95
|
+
};
|