diff --git a/app/components/chat.module.scss b/app/components/chat.module.scss index 9e901e27b..f272d1d2a 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat.module.scss @@ -815,3 +815,34 @@ } } } + +.chat-message-checkmark { + display: inline-block; + margin-right: 5px; + height: 12px; + width: 12px; + color: #13a10e; + fill: #13a10e; + user-select: none; + backface-visibility: hidden; + transform: translateZ(0px); +} + +.chat-message-tools-status { + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; + margin-top: 5px; + line-height: 1.5; +} + +.chat-message-tools-name { + color: #aaa; +} + +.chat-message-tools-details { + margin-left: 5px; + font-weight: bold; + color: #999; +} \ No newline at end of file diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 3a045936d..8697c00ba 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -2039,6 +2039,30 @@ function _Chat() { )} + {!isUser && + message.toolMessages && + message.toolMessages.map((tool, index) => ( +
+
+ + {tool.toolName}: + + {tool.toolInput} + +
+
+ ))} {message?.tools?.length == 0 && showTyping && (
{Locale.Chat.Typing} diff --git a/app/components/openai-voice-visualizer/index.ts b/app/components/openai-voice-visualizer/index.ts new file mode 100644 index 000000000..b7d2d1042 --- /dev/null +++ b/app/components/openai-voice-visualizer/index.ts @@ -0,0 +1 @@ +export * from "./openai-voice-visualizer"; diff --git a/app/components/openai-voice-visualizer/openai-voice-visualizer.module.scss b/app/components/openai-voice-visualizer/openai-voice-visualizer.module.scss new file mode 100644 index 000000000..d6ea660bb --- /dev/null +++ b/app/components/openai-voice-visualizer/openai-voice-visualizer.module.scss @@ -0,0 +1,9 @@ +.openai-voice-visualizer { + width: 100%; + height: 100%; + + canvas { + width: 100%; + height: 100%; + } +} diff --git a/app/components/openai-voice-visualizer/openai-voice-visualizer.tsx b/app/components/openai-voice-visualizer/openai-voice-visualizer.tsx new file mode 100644 index 000000000..5c4f56cae --- /dev/null +++ b/app/components/openai-voice-visualizer/openai-voice-visualizer.tsx @@ -0,0 +1,372 @@ +import { useEffect, useRef, useCallback, useState } from "react"; +import styles from "./openai-voice-visualizer.module.scss"; +import { initWebGL } from "../../utils/webgl"; +import vertexShaderSource from "../../shaders/vertex.glsl"; +import fragmentShaderSource from "../../shaders/fragment.glsl"; +import { loadImage } from "canvas"; + +const CANVAS_SIZE = 208; +const DEFAULT_VIEWPORT_SIZE: [number, number] = [300, 300]; +const NOISE_TEXTURE_OPTIONS = { + format: "webp", + width: 512, + height: 512, + space: "srgb", + channels: 3, + depth: "uchar", + density: 72, + isProgressive: false, + paletteBitDepth: 8, + hasProfile: false, + hasAlpha: false, + src: "./noise-texture.webp", +} as const; + +interface ColorTheme { + bloopColorMain: Float32Array; + bloopColorLow: Float32Array; + bloopColorMid: Float32Array; + bloopColorHigh: Float32Array; +} + +export interface AudioData { + avgMag: Float32Array; + micLevel: number; + cumulativeAudio: Float32Array; +} + +const hexToFloatArray = (hex: string): Float32Array => { + const hexWithoutHash = hex.replace("#", ""); + const red = parseInt(hexWithoutHash.substring(0, 2), 16) / 255; + const green = parseInt(hexWithoutHash.substring(2, 4), 16) / 255; + const blue = parseInt(hexWithoutHash.substring(4, 6), 16) / 255; + return new Float32Array([red, green, blue]); +}; + +const colorThemes = { + BLUE: { + bloopColorMain: hexToFloatArray("#DCF7FF"), + bloopColorLow: hexToFloatArray("#0181FE"), + bloopColorMid: hexToFloatArray("#A4EFFF"), + bloopColorHigh: hexToFloatArray("#FFFDEF"), + }, + DARK_BLUE: { + bloopColorMain: hexToFloatArray("#DAF5FF"), + bloopColorLow: hexToFloatArray("#0066CC"), + bloopColorMid: hexToFloatArray("#2EC6F5"), + bloopColorHigh: hexToFloatArray("#72EAF5"), + }, + GREYSCALE: { + bloopColorMain: hexToFloatArray("#D7D7D7"), + bloopColorLow: hexToFloatArray("#303030"), + bloopColorMid: hexToFloatArray("#989898"), + bloopColorHigh: hexToFloatArray("#FFFFFF"), + }, + WHITE: { + bloopColorMain: hexToFloatArray("#FFFFFF"), + bloopColorLow: hexToFloatArray("#FFFFFF"), + bloopColorMid: hexToFloatArray("#FFFFFF"), + bloopColorHigh: hexToFloatArray("#FFFFFF"), + }, + BLACK: { + bloopColorMain: hexToFloatArray("#000000"), + bloopColorLow: hexToFloatArray("#000000"), + bloopColorMid: hexToFloatArray("#000000"), + bloopColorHigh: hexToFloatArray("#000000"), + }, +} as const; + +interface OpenAIVoiceVisualizerProps { + audioData?: AudioData; + isActive?: boolean; +} + +export class NormalBlorpUniformsSetter { + static uniformBlockName = "BlorbUniformsObject"; + private gl: WebGL2RenderingContext; + private uniformBuffer: WebGLBuffer; + private uniformNames: string[]; + private uniformOffsets: { [key: string]: number }; + private dataBuffer: ArrayBuffer; + private floatView: Float32Array; + private intView: Int32Array; + + constructor(gl: WebGL2RenderingContext, program: WebGLProgram) { + this.gl = gl; + const uniformBlockIndex = gl.getUniformBlockIndex( + program, + NormalBlorpUniformsSetter.uniformBlockName, + ); + const uniformBlockSize = gl.getActiveUniformBlockParameter( + program, + uniformBlockIndex, + gl.UNIFORM_BLOCK_DATA_SIZE, + ); + + this.uniformBuffer = gl.createBuffer()!; + gl.bindBuffer(gl.UNIFORM_BUFFER, this.uniformBuffer); + gl.bufferData(gl.UNIFORM_BUFFER, uniformBlockSize, gl.DYNAMIC_DRAW); + + const bindingPoint = 0; + gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, this.uniformBuffer); + gl.uniformBlockBinding(program, uniformBlockIndex, bindingPoint); + + const uniformIndices = gl.getActiveUniformBlockParameter( + program, + uniformBlockIndex, + gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, + ); + + this.uniformNames = []; + this.uniformOffsets = {}; + for (let i = 0; i < uniformIndices.length; i++) { + const uniformIndex = uniformIndices[i]; + const uniformInfo = gl.getActiveUniform(program, uniformIndex); + if (!uniformInfo) { + throw new Error("No uniformInfo for index " + uniformIndex); + } + let uniformName = uniformInfo.name; + uniformName = uniformName.replace(/\[0\]$/, ""); + const uniformOffset = gl.getActiveUniforms( + program, + [uniformIndex], + gl.UNIFORM_OFFSET, + )[0]; + this.uniformNames.push(uniformName); + this.uniformOffsets[uniformName] = uniformOffset; + } + + this.dataBuffer = new ArrayBuffer(uniformBlockSize); + this.floatView = new Float32Array(this.dataBuffer); + this.intView = new Int32Array(this.dataBuffer); + } + + setVariablesAndRender(variables: { + [key: string]: number | boolean | number[]; + }) { + for (const uniformName of this.uniformNames) { + const [, name] = uniformName.split("."); + const offset = this.uniformOffsets[uniformName] / 4; + const value = variables[name]; + + if (typeof value === "number") { + this.floatView[offset] = value; + } else if (typeof value === "boolean") { + this.intView[offset] = value ? 1 : 0; + } else if (Array.isArray(value)) { + this.floatView.set(value, offset); + } + } + + this.gl.bindBuffer(this.gl.UNIFORM_BUFFER, this.uniformBuffer); + this.gl.bufferSubData(this.gl.UNIFORM_BUFFER, 0, this.dataBuffer); + this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 6); + } +} + +export function OpenAIVoiceVisualizer({ + audioData, + isActive, +}: OpenAIVoiceVisualizerProps) { + const canvasRef = useRef(null); + const glRef = useRef(null); + const programRef = useRef(null); + const animationFrameRef = useRef(0); + const uniformSetterRef = useRef(null); + const startTimeRef = useRef(performance.now() / 1000); + const readyTimeRef = useRef(performance.now() / 1000); + + const variablesRef = useRef({ + time: 0, + micLevel: 0, + stateListen: 0, + listenTimestamp: 0, + stateThink: 0.0, + thinkTimestamp: 0.0, + stateSpeak: 1, + speakTimestamp: 0, + readyTimestamp: 0, + stateHalt: 0.0, + haltTimestamp: 0.0, + touchDownTimestamp: 0.0, + touchUpTimestamp: 0.0, + stateFailedToConnect: 0.0, + failedToConnectTimestamp: 0.0, + avgMag: new Array(4).fill(0), + cumulativeAudio: new Array(4).fill(0), + isNewBloop: true, + isAdvancedBloop: true, + bloopColorMain: [0, 0, 0], + bloopColorLow: [0, 0, 0], + bloopColorMid: [0, 0, 0], + bloopColorHigh: [0, 0, 0], + isDarkMode: false, + screenScaleFactor: 1.0, + viewport: DEFAULT_VIEWPORT_SIZE, + silenceAmount: 0.0, + silenceTimestamp: 0.0, + fadeBloopWhileListening: false, + }); + + const audioDataRef = useRef({ + avgMag: new Float32Array(4), + micLevel: 0, + cumulativeAudio: new Float32Array(4), + }); + + const handleAudioData = useCallback((data: AudioData) => { + audioDataRef.current = data; + }, []); + + const [viewportSize] = useState<[number, number]>(DEFAULT_VIEWPORT_SIZE); + const [noiseTextureImage, setNoiseTextureImage] = + useState(null); + const getColorTheme = useCallback((isAdvanced: boolean): ColorTheme => { + return colorThemes.BLUE; + }, []); + + const initializeWebGL = useCallback(() => { + if (!canvasRef.current) return; + + canvasRef.current.width = CANVAS_SIZE; + canvasRef.current.height = CANVAS_SIZE; + + const { gl, program } = initWebGL( + canvasRef.current, + vertexShaderSource, + fragmentShaderSource, + ); + + if (!gl || !program) { + console.error("WebGL 初始化失败"); + return; + } + + glRef.current = gl; + programRef.current = program; + uniformSetterRef.current = new NormalBlorpUniformsSetter(gl, program); + + return { gl, program }; + }, []); + + const initializeNoiseTexture = useCallback( + (gl: WebGL2RenderingContext, program: WebGLProgram) => { + const noiseTexture = gl.createTexture(); + if (!noiseTexture) { + console.error("创建噪声纹理失败"); + return; + } + + gl.bindTexture(gl.TEXTURE_2D, noiseTexture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + + if (noiseTextureImage) { + gl.texImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + gl.RGBA, + gl.UNSIGNED_BYTE, + noiseTextureImage, + ); + } + + const location = gl.getUniformLocation(program, "uTextureNoise"); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, noiseTexture); + gl.uniform1i(location, 0); + + return noiseTexture; + }, + [noiseTextureImage], + ); + + const renderFrame = useCallback(() => { + if (!glRef.current || !uniformSetterRef.current) return; + + if (!audioData) { + handleAudioData({ + avgMag: new Float32Array(4), + micLevel: 0, + cumulativeAudio: new Float32Array(4), + }); + // return; + } else { + handleAudioData(audioData); + } + + const currentFrameTime = performance.now() / 1000; + const colorTheme = getColorTheme(true); + + const variables = variablesRef.current; + variables.time = currentFrameTime; + variables.micLevel = audioDataRef.current.micLevel; + variables.speakTimestamp = readyTimeRef.current; + variables.readyTimestamp = startTimeRef.current; + variables.avgMag = Array.from(audioDataRef.current.avgMag); + variables.cumulativeAudio = Array.from( + audioDataRef.current.cumulativeAudio, + ); + variables.bloopColorMain = Array.from(colorTheme.bloopColorMain); + variables.bloopColorLow = Array.from(colorTheme.bloopColorLow); + variables.bloopColorMid = Array.from(colorTheme.bloopColorMid); + variables.bloopColorHigh = Array.from(colorTheme.bloopColorHigh); + variables.screenScaleFactor = window.devicePixelRatio || 1.0; + variables.viewport = viewportSize; + + uniformSetterRef.current.setVariablesAndRender(variables); + animationFrameRef.current = requestAnimationFrame(renderFrame); + }, [audioData, getColorTheme, handleAudioData, viewportSize]); + + useEffect(() => { + const loadNoiseTexture = async () => { + try { + const image = await loadImage(NOISE_TEXTURE_OPTIONS.src); + setNoiseTextureImage(image as unknown as HTMLImageElement); + } catch (error) { + console.error("加载噪声纹理失败:", error); + } + }; + loadNoiseTexture(); + }, []); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const webglContext = initializeWebGL(); + if (!webglContext) return; + + const { gl, program } = webglContext; + const noiseTexture = initializeNoiseTexture(gl, program); + + renderFrame(); + + return () => { + if (animationFrameRef.current) { + cancelAnimationFrame(animationFrameRef.current); + } + if (gl) { + if (noiseTexture) { + gl.deleteTexture(noiseTexture); + } + gl.deleteProgram(program); + } + }; + }, [ + initializeWebGL, + initializeNoiseTexture, + renderFrame, + audioData, + isActive, + ]); + + return ( +
+ +
+ ); +} diff --git a/app/components/realtime-chat/realtime-chat.module.scss b/app/components/realtime-chat/realtime-chat.module.scss index ef58bebb6..7df7016f8 100644 --- a/app/components/realtime-chat/realtime-chat.module.scss +++ b/app/components/realtime-chat/realtime-chat.module.scss @@ -8,15 +8,15 @@ height: 100%; padding: 20px; box-sizing: border-box; - .circle-mic { - width: 150px; - height: 150px; - border-radius: 50%; - background: linear-gradient(to bottom right, #a0d8ef, #f0f8ff); - display: flex; - justify-content: center; - align-items: center; - } + // .circle-mic { + // width: 150px; + // height: 150px; + // border-radius: 50%; + // background: linear-gradient(to bottom right, #a0d8ef, #f0f8ff); + // display: flex; + // justify-content: center; + // align-items: center; + // } .icon-center { font-size: 24px; } diff --git a/app/components/realtime-chat/realtime-chat.tsx b/app/components/realtime-chat/realtime-chat.tsx index faa36373a..ffbab0f3b 100644 --- a/app/components/realtime-chat/realtime-chat.tsx +++ b/app/components/realtime-chat/realtime-chat.tsx @@ -21,6 +21,10 @@ import { import { AudioHandler } from "@/app/lib/audio"; import { uploadImage } from "@/app/utils/chat"; import { VoicePrint } from "@/app/components/voice-print"; +import { + OpenAIVoiceVisualizer, + AudioData, +} from "../openai-voice-visualizer/openai-voice-visualizer"; interface RealtimeChatProps { onClose?: () => void; @@ -43,6 +47,7 @@ export function RealtimeChat({ const [modality, setModality] = useState("audio"); const [useVAD, setUseVAD] = useState(true); const [frequencies, setFrequencies] = useState(); + const [audioData, setAudioData] = useState(); const clientRef = useRef(null); const audioHandlerRef = useRef(null); @@ -292,6 +297,9 @@ export function RealtimeChat({ if (audioHandlerRef.current) { const freqData = audioHandlerRef.current.getByteFrequencyData(); setFrequencies(freqData); + + const audioData = audioHandlerRef.current.getAudioData(); + setAudioData(audioData); } animationFrameId = requestAnimationFrame(animationFrame); }; @@ -299,6 +307,7 @@ export function RealtimeChat({ animationFrameId = requestAnimationFrame(animationFrame); } else { setFrequencies(undefined); + setAudioData(undefined); } return () => { @@ -327,11 +336,11 @@ export function RealtimeChat({ return (
- +
diff --git a/app/global.d.ts b/app/global.d.ts index 897871fec..d76510ab6 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -10,6 +10,11 @@ declare module "*.scss" { declare module "*.svg"; +declare module "*.glsl" { + const content: string; + export default content; +} + declare interface Window { __TAURI__?: { writeText(text: string): Promise; diff --git a/app/lib/audio.ts b/app/lib/audio.ts index a4937d773..0fbb865e6 100644 --- a/app/lib/audio.ts +++ b/app/lib/audio.ts @@ -21,6 +21,9 @@ export class AudioHandler { this.analyser = new AnalyserNode(this.context, { fftSize: 256 }); this.analyserData = new Uint8Array(this.analyser.frequencyBinCount); this.mergeNode.connect(this.analyser); + + this.dataArray = new Float32Array(this.analyser.frequencyBinCount); + this.initializeBands(this.analyser.frequencyBinCount); } getByteFrequencyData() { @@ -94,6 +97,7 @@ export class AudioHandler { this.source.disconnect(); this.stream.getTracks().forEach((track) => track.stop()); } + startStreamingPlayback() { this.isPlaying = true; this.nextPlayTime = this.context.currentTime; @@ -148,6 +152,7 @@ export class AudioHandler { this.nextPlayTime = this.context.currentTime; } } + _saveData(data: Int16Array, bytesPerSample = 16): Blob { const headerLength = 44; const numberOfChannels = 1; @@ -171,10 +176,12 @@ export class AudioHandler { // using data.buffer, so no need to setUint16 to view. return new Blob([view, data.buffer], { type: "audio/mpeg" }); } + savePlayFile() { // @ts-ignore return this._saveData(new Int16Array(this.playBuffer)); } + saveRecordFile( audioStartMillis: number | undefined, audioEndMillis: number | undefined, @@ -190,6 +197,7 @@ export class AudioHandler { new Int16Array(this.recordBuffer.slice(startIndex, endIndex)), ); } + async close() { this.recordBuffer = []; this.workletNode?.disconnect(); @@ -197,4 +205,75 @@ export class AudioHandler { this.stream?.getTracks().forEach((track) => track.stop()); await this.context.close(); } + + private readonly NUM_BANDS = 4; + private avgMag: Float32Array = new Float32Array(this.NUM_BANDS); + private dataArray: Float32Array | null = null; + private cumulativeAudio: Float32Array = new Float32Array(this.NUM_BANDS); + private binSize: number = 0; + + private initializeBands = (frequencyBinCount: number) => { + this.binSize = Math.floor(frequencyBinCount / this.NUM_BANDS); + }; + + private createMagnitudeLookupTable = () => { + const GAIN_MULTIPLIER = 1.2; + const table = new Float32Array(100); + for (let i = 0; i < 100; i++) { + const db = -100 + i; + let magnitude = 1 - (Math.max(-100, Math.min(-10, db)) * -1) / 100; + magnitude = Math.pow(magnitude, 0.7) * GAIN_MULTIPLIER; + table[i] = Math.min(1, magnitude); + } + return table; + }; + + private magnitudeLookupTable = this.createMagnitudeLookupTable(); + + decibelToMagnitude = (db: number): number => { + if (db === -Infinity) return 0; + const index = Math.floor(db + 100); + if (index < 0) return 0; + if (index >= 100) return 1; + return this.magnitudeLookupTable[index]; + }; + + getAudioData() { + if (!this.analyser || !this.dataArray) return; + + const SMOOTHING_FACTOR = 0.2; + const FREQUENCY_WEIGHTS = [1.2, 1.0, 0.8, 0.6]; + + this.analyser.getFloatFrequencyData(this.dataArray); + + let totalMagnitude = 0; + + for (let i = 0; i < this.NUM_BANDS; i++) { + const startBin = i * this.binSize; + const endBin = startBin + this.binSize; + let sum = 0; + + const bandData = this.dataArray.subarray(startBin, endBin); + for (let j = 0; j < bandData.length; j++) { + const magnitude = + this.decibelToMagnitude(bandData[j]) * FREQUENCY_WEIGHTS[i]; + sum += magnitude; + } + + this.avgMag[i] = sum / this.binSize; + totalMagnitude += this.avgMag[i]; + + this.cumulativeAudio[i] = + this.cumulativeAudio[i] * (1 - SMOOTHING_FACTOR) + + this.avgMag[i] * SMOOTHING_FACTOR; + } + + const micLevel = Math.min(1, (totalMagnitude / this.NUM_BANDS) * 1.2); + + return { + avgMag: this.avgMag, + micLevel, + cumulativeAudio: this.cumulativeAudio, + }; + } } diff --git a/app/shaders/fragment.glsl b/app/shaders/fragment.glsl new file mode 100644 index 000000000..b240fd3d6 --- /dev/null +++ b/app/shaders/fragment.glsl @@ -0,0 +1,1326 @@ +#version 300 es +#define E (2.71828182846) +#define pi (3.14159265358979323844) +#define NUM_OCTAVES (4) + +precision highp float; + +struct ColoredSDF { + float distance; + vec4 color; +}; + +struct SDFArgs { + vec2 st; + float amount; + float duration; + float time; + float mainRadius; +}; + +float triangle(float t, float p) { + return 2.0 * abs(t / p - floor(t / p + 0.5)); +} + +float spring(float t, float d) { + return 1.0 - exp(-E * 2.0 * t) * cos((1.0 - d) * 115.0 * t); +} + +float silkySmooth(float t, float k) { + return atan(k * sin((t - 0.5) * pi)) / atan(k) * 0.5 + 0.5; +} + +float scaled(float edge0, float edge1, float x) { + return clamp((x - edge0) / (edge1 - edge0), float(0), float(1)); +} + +float fixedSpring(float t, float d) { + float s = mix( + 1.0 - exp(-E * 2.0 * t) * cos((1.0 - d) * 115.0 * t), + 1.0, + scaled(0.0, 1.0, t) + ); + return s * (1.0 - t) + t; +} + +float bounce(float t, float d) { + return -sin(pi * (1.0 - d) * t) * + (1.0 - t) * + exp(-2.71828182846 * 2.0 * t) * + t * + 10.0; +} + +float random(vec2 st) { + return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + +float random(ivec2 st) { + return random(vec2(st)); +} + +float random(float p) { + return random(vec2(p)); +} + +float opSmoothUnion(float d1, float d2, float k) { + if (k <= 0.0) { + k = 0.000001; + } + float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0); + return mix(d2, d1, h) - k * h * (1.0 - h); +} + +float opSmoothSubtraction(float d1, float d2, float k) { + if (k <= 0.0) { + k = 0.000001; + } + float h = clamp(0.5 - 0.5 * (d2 + d1) / k, 0.0, 1.0); + return mix(d2, -d1, h) + k * h * (1.0 - h); +} + +float opSmoothIntersection(float d1, float d2, float k) { + if (k <= 0.0) { + k = 0.000001; + } + float h = clamp(0.5 - 0.5 * (d2 - d1) / k, 0.0, 1.0); + return mix(d2, d1, h) + k * h * (1.0 - h); +} + +float sdRoundedBox(vec2 p, vec2 b, vec4 r) { + r.xy = p.x > 0.0 ? r.xy : r.zw; + r.x = p.y > 0.0 ? r.x : r.y; + vec2 q = abs(p) - b + r.x; + return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x; +} + +float sdSegment(vec2 p, vec2 a, vec2 b) { + vec2 pa = p - a; + vec2 ba = b - a; + float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); + return length(pa - ba * h); +} + +float sdArc(vec2 p, vec2 sca, vec2 scb, float ra, float rb) { + p *= mat2(sca.x, sca.y, -sca.y, sca.x); + p.x = abs(p.x); + return scb.y * p.x > scb.x * p.y + ? length(p - ra * scb) - rb + : abs(length(p) - ra) - rb; +} + +float arc(vec2 st, float startAngle, float length, float radius, float width) { + return sdArc( + st, + vec2(sin(startAngle), cos(startAngle)), + vec2(sin(length), cos(length)), + radius, + width + ); +} + +vec2 rotate(vec2 v, float a) { + float s = sin(a); + float c = cos(a); + mat2 m = mat2(c, s, -s, c); + return m * v; +} + +vec3 blendLinearBurn_13_5(vec3 base, vec3 blend) { + + return max(base + blend - vec3(1.0), vec3(0.0)); +} + +vec3 blendLinearBurn_13_5(vec3 base, vec3 blend, float opacity) { + return blendLinearBurn_13_5(base, blend) * opacity + base * (1.0 - opacity); +} + +float blendScreen_21_19(float base, float blend) { + return 1.0 - (1.0 - base) * (1.0 - blend); +} + +vec3 blendScreen_21_19(vec3 base, vec3 blend) { + return vec3( + blendScreen_21_19(base.r, blend.r), + blendScreen_21_19(base.g, blend.g), + blendScreen_21_19(base.b, blend.b) + ); +} + +vec3 blendScreen_21_19(vec3 base, vec3 blend, float opacity) { + return blendScreen_21_19(base, blend) * opacity + base * (1.0 - opacity); +} + +vec4 permute(vec4 x) { + return mod((x * 34.0 + 1.0) * x, 289.0); +} +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} +vec3 fade(vec3 t) { + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float cnoise(vec3 P) { + vec3 Pi0 = floor(P); + vec3 Pi1 = Pi0 + vec3(1.0); + Pi0 = mod(Pi0, 289.0); + Pi1 = mod(Pi1, 289.0); + vec3 Pf0 = fract(P); + vec3 Pf1 = Pf0 - vec3(1.0); + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = vec4(Pi0.z); + vec4 iz1 = vec4(Pi1.z); + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 / 7.0; + vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(vec4(0.0), gx0) - 0.5); + gy0 -= sz0 * (step(vec4(0.0), gy0) - 0.5); + + vec4 gx1 = ixy1 / 7.0; + vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(vec4(0.0), gx1) - 0.5); + gy1 -= sz1 * (step(vec4(0.0), gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt( + vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)) + ); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt( + vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)) + ); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix( + vec4(n000, n100, n010, n110), + vec4(n001, n101, n011, n111), + fade_xyz.z + ); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +float rand(vec2 n) { + return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); +} + +float noise(vec2 p) { + vec2 ip = floor(p); + vec2 u = fract(p); + u = u * u * (3.0 - 2.0 * u); + + float res = mix( + mix(rand(ip), rand(ip + vec2(1.0, 0.0)), u.x), + mix(rand(ip + vec2(0.0, 1.0)), rand(ip + vec2(1.0, 1.0)), u.x), + u.y + ); + return res * res; +} + +float fbm(vec2 x) { + float v = 0.0; + float a = 0.5; + vec2 shift = vec2(100.0); + + mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); + for (int i = 0; i < NUM_OCTAVES; ++i) { + v += a * noise(x); + x = rot * x * 2.0 + shift; + a *= 0.5; + } + return v; +} + +#define HASHSCALE1 (0.1031) +#define HASHSCALE3 (vec3(0.1031, 0.103, 0.0973)) +#define HASHSCALE4 (vec3(0.1031, 0.103, 0.0973, 0.1099)) + +float Hash11(float p) { + vec3 p3 = fract(vec3(p) * HASHSCALE1); + p3 += dot(p3, p3.yzx + 19.19); + return fract((p3.x + p3.y) * p3.z); +} + +vec2 Hash22(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * HASHSCALE3); + p3 += dot(p3, p3.yzx + 19.19); + return fract((p3.xx + p3.yz) * p3.zy); +} + +vec2 Rand22(vec2 co) { + float x = fract(sin(dot(co.xy, vec2(122.9898, 783.233))) * 43758.5453); + float y = fract(sin(dot(co.xy, vec2(457.6537, 537.2793))) * 37573.5913); + return vec2(x, y); +} + +vec3 SnowSingleLayer( + vec2 uv, + float layer, + vec2 speed, + vec4 uCumulativeAudio, + float uTime +) { + uv = uv * (1.5 + layer); + float size = 0.01; + + float xOffset = + uv.y * (((Hash11(layer) * 2.0 - 1.0) * 0.5 + 1.0) * speed.x) + + sin( + layer * 2963.0 + uCumulativeAudio.y * 0.05625 + uCumulativeAudio.z * 0.075 + ); + float yOffset = + speed.y + uTime * 1.75 + uCumulativeAudio.x * 0.07125 + cos(uTime) * 0.1; + xOffset += sin(uTime * 2.0 + uv.x + layer * 2938.0) * 0.25; + uv += vec2(xOffset, yOffset); + + vec2 rgrid = Hash22(floor(uv) + 31.1759 * layer); + uv = fract(uv); + uv -= (rgrid * 2.0 - 1.0) * 0.35; + uv -= 0.5; + + float r = length(uv); + + float circleSize = 0.05 * (1.0 + 0.2 * sin(uTime * size + layer)); + float val = smoothstep(circleSize, -circleSize, r); + val = smoothstep(0.0, 0.2, val); + + vec3 col = vec3(val, val, val) * rgrid.x; + return col; + +} + +/** + * End new code for colored orb + */ + +ColoredSDF applyIdleState( + ColoredSDF sdf, + SDFArgs args, + bool isDarkMode /** + * new bool + */ +) { + float midRadius = 0.12; + float maxRadius = 0.3; + float t1 = 1.0; + float gamma = 3.0; + float omega = pi / 2.0; + + + float k = exp(-gamma) * omega; + + float radius; + if (args.time <= t1) { + + float t_prime = args.time / t1; + + float springValue = 1.0 - exp(-gamma * t_prime) * cos(omega * t_prime); + radius = midRadius * springValue; + } else { + + float adjustedTime = args.time - t1; + + radius = + midRadius + (maxRadius - midRadius) * (1.0 - exp(-k * adjustedTime)); + } + + + float distance = length(args.st) - radius; + + + sdf.distance = mix(sdf.distance, distance, args.amount); + + + + float alpha = sin(pi / 0.7 * args.time) * 0.3 + 0.7; + vec4 color = vec4(isDarkMode ? vec3(1.0) : vec3(0.0), alpha); + + + sdf.color = mix(sdf.color, color, args.amount); + + return sdf; +} + +ColoredSDF applyIdleStateLegacy(ColoredSDF sdf, SDFArgs args, bool isDarkMode) { + float connectedLinearAnimation = scaled(0.0, 2.0, args.duration); + float connectedAnimation = fixedSpring(connectedLinearAnimation, 0.96); + float circleSize = + mix( + pow(scaled(0.0, 3.0, args.time), 2.0) * 0.75 + 0.1, + 1.0, + connectedAnimation + ) * + 0.33; + vec2 rotatedCoords = rotate( + args.st, + -args.time * pi - + connectedAnimation * pi * 2.0 - + pi * 2.0 * 5.0 * silkySmooth(scaled(0.0, 5.0, args.time), 2.0) + ); + + float strokeWidth = mix(circleSize / 2.0, circleSize, connectedAnimation); + float connecting = abs(length(args.st) - circleSize) - strokeWidth; + + float connected = length(args.st) - circleSize; + float idleDist = mix(connecting, connected, connectedAnimation); + + float d = min(sdf.distance, idleDist); + sdf.distance = mix(sdf.distance, d, args.amount); + float angle = atan(rotatedCoords.y, rotatedCoords.x); + float alpha = mix( + min(1.0, scaled(-pi, pi, angle)), + 1.0, + connectedLinearAnimation + ); + + float spinningCircleDist = + length( + rotatedCoords - + vec2(-mix(circleSize, strokeWidth, connectedAnimation), 0.0) + ) - + strokeWidth; + + alpha = min( + 1.0, + max( + alpha, + smoothstep(0.005, 0.0, spinningCircleDist) + connectedAnimation * 4.0 + ) + ); + + sdf.color = mix( + sdf.color, + vec4(isDarkMode ? vec3(1.0) : vec3(0.0), alpha), + args.amount + ); + return sdf; +} + +ColoredSDF applyListenState( + ColoredSDF sdf, + SDFArgs args, + float micLevel, + float listenTimestamp, /* new */ + float touchDownTimestamp, /* new */ + float touchUpTimestamp, /* new */ + bool fadeBloopWhileListening /* new */ +) { + float breathingSequence = sin(args.time) * 0.5 + 0.5; + float entryAnimation = fixedSpring(scaled(0.0, 3.0, args.duration), 0.9); + + float touch = + fixedSpring(scaled(0.0, 1.0, args.time - touchDownTimestamp), 0.99) - + fixedSpring(scaled(0.0, 0.8, args.time - touchUpTimestamp), 1.0); + + float listenAnimation = clamp( + spring(scaled(0.0, 0.9, args.duration), 1.0), + 0.0, + 1.0 + ); + float radius = 0.0; + float smoothlevel = micLevel; + float l1 = smoothlevel; + radius = 0.38 + l1 * 0.05 + breathingSequence * 0.03; + radius *= 1.0 - (1.0 - entryAnimation) * 0.25; + + float ring = 10000.0; + + + if (touch > 0.0) { + touch = min(touch, listenAnimation); + float arcWidth = radius * 0.1; + + + radius -= touch * arcWidth * 2.3; + + radius = min( + radius, + mix(radius, args.mainRadius - arcWidth * 2.3 - l1 * 0.01, touch) + ); + + float startAngle = 0.0; + float arcLengthTouch = + smoothstep(0.04, 1.0, touch) * pi * (1.0 - arcWidth / 3.0 / radius); + + float arcLength = 0.0; + float radiusTouch = + radius * fixedSpring(scaled(0.0, 1.0, args.duration), 1.0) * args.amount + + l1 * 0.01; + + radiusTouch += + arcWidth * 1.3 * mix(-1.0, 1.0, smoothstep(0.0, 0.12, touch)); + + float ringRadius = 0.0; + arcLength = arcLengthTouch; + ringRadius = radiusTouch; + startAngle = pi / 2.0 - (args.time - touchDownTimestamp) / 2.0; + + ring = arc(args.st, startAngle, arcLength, ringRadius, arcWidth); + } + + float d = length(args.st) - radius; + + d = min(d, ring); + + sdf.distance = mix(sdf.distance, d, args.amount); + + if (fadeBloopWhileListening) { + + sdf.color.a = mix( + sdf.color.a, + mix(1.0, 1.0 - l1 * 0.6, listenAnimation), + args.amount + ); + } else { + sdf.color.a = 1.0; + } + + return sdf; +} + +ColoredSDF applyThinkState(ColoredSDF sdf, SDFArgs args) { + float d = 1000.0; + int count = 5; + float entryAnimation = spring(scaled(0.0, 1.0, args.duration), 1.0); + + float thinkingDotEntryAnimation = spring( + scaled(0.1, 1.1, args.duration), + 1.0 + ); + float thinkingDotRadius = + mix(0.2, 0.06, thinkingDotEntryAnimation) * args.amount; + + + args.st.x -= thinkingDotRadius * 0.5 * thinkingDotEntryAnimation; + + for (int i = 0; i < count; i++) { + float f = float(float(i) + 0.5) / float(count); + float a = + -f * pi * 2.0 + + args.time / 3.0 + + spring(scaled(0.0, 10.0, args.duration), 1.0) * pi / 2.0; + float ringRadi = args.mainRadius * 0.45 * entryAnimation; + + + ringRadi -= + (sin( + entryAnimation * pi * 4.0 + + a * pi * 2.0 + + args.time * 3.0 - + silkySmooth(args.time / 4.0, 2.0) * pi * 1.0 + ) * + 0.5 + + 0.5) * + args.mainRadius * + 0.1; + + vec2 pos = vec2(cos(a), sin(a)) * ringRadi; + float dd = length(args.st - pos) - args.mainRadius * 0.5; + + + d = opSmoothUnion( + d, + dd, + 0.03 * scaled(0.0, 10.0, args.duration) + 0.8 * (1.0 - entryAnimation) + ); + + + float dotAngle = f * pi * 2.0; + float dotRingRadius = + (sin( + thinkingDotEntryAnimation * pi * 4.0 + + a * pi * 2.0 + + args.time * 0.1 * pi * 4.0 + ) * + 0.5 + + 0.5) * + thinkingDotRadius * + 0.3; + vec2 dotPos = + vec2(-args.mainRadius, args.mainRadius) * 0.8 * thinkingDotEntryAnimation; + vec2 dotOffset = + vec2(cos(dotAngle + args.time), sin(dotAngle + args.time)) * + dotRingRadius; + float dotD = length(args.st - dotPos - dotOffset) - thinkingDotRadius * 0.8; + d = opSmoothUnion( + d, + dotD, + (1.0 - min(thinkingDotEntryAnimation, args.amount)) * thinkingDotRadius + ); + } + sdf.distance = mix(sdf.distance, d, args.amount); + sdf.color.a = 1.0; + return sdf; +} + +ColoredSDF applySpeakState( + ColoredSDF sdf, + SDFArgs args, + vec4 avgMag, + float silenceAmount, + float silenceDuration +) { + float d = 1000.0; + int barCount = 4; + for (int i = 0; i < barCount; i++) { + float f = float(float(i) + 0.5) / float(barCount); + + + float w = 1.0 / float(barCount) * 0.44; + float h = w; + + + float wave = sin(f * pi * 0.8 + args.time) * 0.5 + 0.5; + float entryAnimation = spring( + scaled(0.1 + wave * 0.4, 1.0 + wave * 0.4, args.duration), + 0.98 + ); + vec2 pos = vec2(f - 0.5, 0.0) * args.mainRadius * 1.9; + pos.y = 0.25 * (1.0 - entryAnimation); + + + if (silenceAmount > 0.0) { + float bounceStagger = f / 5.0; + float bounceDelay = 0.6; + float bounceTimer = scaled( + bounceDelay, + bounceDelay + 1.0, + fract((silenceDuration + bounceStagger) / 2.0) * 2.0 + ); + pos.y += + bounce(bounceTimer, 6.0) * + w * + 0.25 * + silenceAmount * + pow(entryAnimation, 4.0) * + pow(args.amount, 4.0); + } + + + h += avgMag[i] * (0.1 + (1.0 - abs(f - 0.5) * 2.0) * 0.1); + + float dd = sdRoundedBox(args.st - pos, vec2(w, h), vec4(w)); + d = opSmoothUnion(d, dd, 0.2 * (1.0 - args.amount)); + + } + + sdf.distance = mix(sdf.distance, d, args.amount); + sdf.color.a = 1.0; + return sdf; +} + +ColoredSDF applyListenAndSpeakState( + ColoredSDF sdf, + SDFArgs args, + float micLevel, + vec4 avgMag, + vec4 cumulativeAudio, + int binCount, + vec3 bloopColorMain, + vec3 bloopColorLow, + vec3 bloopColorMid, + vec3 bloopColorHigh, + sampler2D uTextureNoise, + bool listening, + bool isAdvancedBloop, + float xmassMode +) { + float entryAnimation = fixedSpring(scaled(0.0, 2.0, args.duration), 0.92); + + + + float radius = + (listening ? 0.37 : 0.43) * (1.0 - (1.0 - entryAnimation) * 0.25) + + micLevel * 0.065; + + + + + float maxDisplacement = 0.01; + + + float oscillationPeriod = 4.0; + + float displacementOffset = + maxDisplacement * sin(2.0 * pi / oscillationPeriod * args.time); + + vec2 adjusted_st = args.st - vec2(0.0, displacementOffset); + + + if (!isAdvancedBloop) { + sdf.color = mix(sdf.color, vec4(bloopColorMain, 1.0), args.amount); + sdf.distance = mix(sdf.distance, length(adjusted_st) - radius, args.amount); + return sdf; + } + + + + vec4 uAudioAverage = avgMag; + vec4 uCumulativeAudio = cumulativeAudio; + + + float scaleFactor = 1.0 / (2.0 * radius); + vec2 uv = adjusted_st * scaleFactor + 0.5; + uv.y = 1.0 - uv.y; + vec3 color; + + + float noiseScale = 1.25; + float windSpeed = 0.075; + float warpPower = 0.19; + float waterColorNoiseScale = 18.0; + float waterColorNoiseStrength = 0.01; + float textureNoiseScale = 1.0; + float textureNoiseStrength = 0.08; + float verticalOffset = 0.09; + float waveSpread = 1.0; + float layer1Amplitude = 1.0; + float layer1Frequency = 1.0; + float layer2Amplitude = 1.0; + float layer2Frequency = 1.0; + float layer3Amplitude = 1.0; + float layer3Frequency = 1.0; + float fbmStrength = 1.0; + float fbmPowerDamping = 0.55; + float overallSoundScale = 1.0; + float blurRadius = 1.0; + float timescale = 1.0; + + + float time = args.time * timescale * 0.85; + + + noiseScale = mix(1.25, 2.0, xmassMode); + waterColorNoiseStrength = mix(0.01, 0.005, xmassMode); + textureNoiseStrength = mix(0.03, 0.01, xmassMode); + blurRadius = mix(0.9, 0.7, xmassMode); + verticalOffset = mix(0.09, 0.0, xmassMode); + layer1Amplitude = mix(1.0, 0.5, xmassMode); + layer1Frequency = mix(1.0, 0.5, xmassMode); + layer2Amplitude = mix(1.0, 0.5, xmassMode); + layer2Frequency = mix(1.0, 0.5, xmassMode); + layer3Amplitude = mix(1.0, 0.5, xmassMode); + layer3Frequency = mix(1.0, 0.5, xmassMode); + waveSpread = mix(1.0, 0.25, xmassMode); + overallSoundScale = mix(1.0, 1.2, xmassMode); + + vec3 sinOffsets = vec3( + uCumulativeAudio.x * 0.15 * overallSoundScale, + -uCumulativeAudio.y * 0.5 * overallSoundScale, + uCumulativeAudio.z * 1.5 * overallSoundScale + ); + verticalOffset += 1.0 - waveSpread; + + + vec3 sinOffsetsXmass = vec3( + uCumulativeAudio.x * 0.15 * overallSoundScale * 0.9, + -uCumulativeAudio.y * 0.5 * overallSoundScale * 0.1875, + uCumulativeAudio.z * 1.5 * overallSoundScale * 0.45 + ); + sinOffsets = mix(sinOffsets, sinOffsetsXmass, xmassMode); + + + float noiseX = cnoise( + vec3( + uv * 1.0 + vec2(0.0, 74.8572), + (time + uCumulativeAudio.x * 0.05 * overallSoundScale) * 0.3 + ) + ); + float noiseY = cnoise( + vec3( + uv * 1.0 + vec2(203.91282, 10.0), + (time + uCumulativeAudio.z * 0.05 * overallSoundScale) * 0.3 + ) + ); + + vec2 uvBis = uv + vec2(noiseX * 2.0, noiseY) * warpPower * 0.25; + uv += vec2(noiseX * 2.0, noiseY) * warpPower; + + + float noiseA = + cnoise(vec3(uv * waterColorNoiseScale + vec2(344.91282, 0.0), time * 0.3)) + + cnoise( + vec3(uv * waterColorNoiseScale * 2.2 + vec2(723.937, 0.0), time * 0.4) + ) * + 0.5; + uv += noiseA * waterColorNoiseStrength; + uv.y -= verticalOffset; + + + vec2 textureUv = uv * textureNoiseScale; + float textureSampleR0 = texture(uTextureNoise, textureUv).r; + float textureSampleG0 = texture( + uTextureNoise, + vec2(textureUv.x, 1.0 - textureUv.y) + ).g; + float textureNoiseDisp0 = + mix( + textureSampleR0 - 0.5, + textureSampleG0 - 0.5, + (sin(time + uCumulativeAudio.a * 2.0) + 1.0) * 0.5 + ) * + textureNoiseStrength; + textureUv += vec2(63.861 + uCumulativeAudio.x * 0.05, 368.937); + float textureSampleR1 = texture(uTextureNoise, textureUv).r; + float textureSampleG1 = texture( + uTextureNoise, + vec2(textureUv.x, 1.0 - textureUv.y) + ).g; + float textureNoiseDisp1 = + mix( + textureSampleR1 - 0.5, + textureSampleG1 - 0.5, + (sin(time + uCumulativeAudio.a * 2.0) + 1.0) * 0.5 + ) * + textureNoiseStrength; + textureUv += vec2(272.861, 829.937 + uCumulativeAudio.y * 0.1); + textureUv += vec2(180.302 - uCumulativeAudio.z * 0.1, 819.871); + float textureSampleR3 = texture(uTextureNoise, textureUv).r; + float textureSampleG3 = texture( + uTextureNoise, + vec2(textureUv.x, 1.0 - textureUv.y) + ).g; + float textureNoiseDisp3 = + mix( + textureSampleR3 - 0.5, + textureSampleG3 - 0.5, + (sin(time + uCumulativeAudio.a * 2.0) + 1.0) * 0.5 + ) * + textureNoiseStrength; + uv += textureNoiseDisp0; + + + vec2 st = uv * noiseScale; + + vec2 q = vec2(0.0); + q.x = fbm( + st * 0.5 + + windSpeed * (time + uCumulativeAudio.a * 0.175 * overallSoundScale) + ); + q.y = fbm( + st * 0.5 + + windSpeed * (time + uCumulativeAudio.x * 0.136 * overallSoundScale) + ); + + vec2 r = vec2(0.0); + r.x = fbm( + st + + 1.0 * q + + vec2(0.3, 9.2) + + 0.15 * (time + uCumulativeAudio.y * 0.234 * overallSoundScale) + ); + r.y = fbm( + st + + 1.0 * q + + vec2(8.3, 0.8) + + 0.126 * (time + uCumulativeAudio.z * 0.165 * overallSoundScale) + ); + + float f = fbm(st + r - q); + float fullFbm = (f + 0.6 * f * f + 0.7 * f + 0.5) * 0.5; + fullFbm = pow(fullFbm, fbmPowerDamping); + fullFbm *= fbmStrength; + + + blurRadius = blurRadius * 1.5; + vec2 snUv = + (uv + vec2((fullFbm - 0.5) * 1.2) + vec2(0.0, 0.025) + textureNoiseDisp0) * + vec2(layer1Frequency, 1.0); + float sn = + noise( + snUv * 2.0 + vec2(sin(sinOffsets.x * 0.25), time * 0.5 + sinOffsets.x) + ) * + 2.0 * + layer1Amplitude; + float sn2 = smoothstep( + sn - 1.2 * blurRadius, + sn + 1.2 * blurRadius, + (snUv.y - 0.5 * waveSpread) * + (5.0 - uAudioAverage.x * 0.1 * overallSoundScale * 0.5) + + 0.5 + ); + + vec2 snUvBis = + (uv + vec2((fullFbm - 0.5) * 0.85) + vec2(0.0, 0.025) + textureNoiseDisp1) * + vec2(layer2Frequency, 1.0); + float snBis = + noise( + snUvBis * 4.0 + + vec2( + sin(sinOffsets.y * 0.15) * 2.4 + 293.0, + time * 1.0 + sinOffsets.y * 0.5 + ) + ) * + 2.0 * + layer2Amplitude; + float sn2Bis = smoothstep( + snBis - (0.9 + uAudioAverage.y * 0.4 * overallSoundScale) * blurRadius, + snBis + (0.9 + uAudioAverage.y * 0.8 * overallSoundScale) * blurRadius, + (snUvBis.y - 0.6 * waveSpread) * (5.0 - uAudioAverage.y * 0.75) + 0.5 + ); + + vec2 snUvThird = + (uv + vec2((fullFbm - 0.5) * 1.1) + textureNoiseDisp3) * + vec2(layer3Frequency, 1.0); + float snThird = + noise( + snUvThird * 6.0 + + vec2( + sin(sinOffsets.z * 0.1) * 2.4 + 153.0, + time * 1.2 + sinOffsets.z * 0.8 + ) + ) * + 2.0 * + layer3Amplitude; + float sn2Third = smoothstep( + snThird - 0.7 * blurRadius, + snThird + 0.7 * blurRadius, + (snUvThird.y - 0.9 * waveSpread) * 6.0 + 0.5 + ); + + sn2 = pow(sn2, 0.8); + sn2Bis = pow(sn2Bis, 0.9); + + + vec3 sinColor; + sinColor = blendLinearBurn_13_5(bloopColorMain, bloopColorLow, 1.0 - sn2); + sinColor = blendLinearBurn_13_5( + sinColor, + mix(bloopColorMain, bloopColorMid, 1.0 - sn2Bis), + sn2 + ); + sinColor = mix( + sinColor, + mix(bloopColorMain, bloopColorHigh, 1.0 - sn2Third), + sn2 * sn2Bis + ); + + + color = sinColor; + + + float XSPEED = noise(vec2(time * 0.5, time * 0.1)) * 0.75; + float YSPEED = cos(time + uCumulativeAudio.y * 0.05) * 0.75; + + vec2 wind = vec2(XSPEED, YSPEED); + + vec3 acc = vec3(0, 0, 0); + for (float i = 0.0; i < 9.0; i++) { + acc += SnowSingleLayer( + uvBis, + i * 0.85 + 0.75, + wind, + uCumulativeAudio, + time + ); + } + vec3 xmassColor; + xmassColor = mix( + vec3(0.004, 0.506, 0.996), + vec3(0.973, 0.984, 1.0), + 1.0 - sn2 + ); + xmassColor = mix( + xmassColor, + mix(vec3(0.004, 0.506, 0.996), vec3(1.0), 1.0 - sn2Bis), + sn2 + ); + xmassColor = mix( + xmassColor, + mix(vec3(0.004, 0.506, 0.996), vec3(1.0), 1.0 - sn2Third), + sn2 * sn2Bis + ); + xmassColor = mix(xmassColor, vec3(1.0), acc); + + + color.rgb = mix(color, xmassColor, xmassMode); + + + sdf.color = mix(sdf.color, vec4(color, 1), args.amount); + + + sdf.distance = mix(sdf.distance, length(adjusted_st) - radius, args.amount); + + return sdf; +} + +float micSdf(vec2 st, float muted) { + float d = 100.0; + float strokeWidth = 0.03; + vec2 elementSize = vec2(0.12, 0.26); + vec2 elementPos = vec2(0.0, elementSize.y * 0.585); + float element = sdRoundedBox( + st - elementPos, + elementSize, + vec4(min(elementSize.x, elementSize.y)) + ); + element = element - strokeWidth; + d = min(d, element); + + vec2 standSize = elementSize * 2.2; + vec2 standPos = vec2(elementPos.x, elementPos.y - 0.05); + st.y += 0.08; + float ta = -pi / 2.0; + float tb = pi / 2.0; + float w = 0.0; + float stand = sdArc( + st - standPos, + vec2(sin(ta), cos(ta)), + vec2(sin(tb), cos(tb)), + standSize.x, + w + ); + stand = min( + stand, + sdSegment(st - standPos, vec2(standSize.x, 0.06), vec2(standSize.x, 0.0)) + ); + stand = min( + stand, + sdSegment(st - standPos, vec2(-standSize.x, 0.06), vec2(-standSize.x, 0.0)) + ); + + float foot = sdSegment( + st - standPos, + vec2(0.0, -standSize.x), + vec2(0.0, -standSize.x * 1.66) + ); + foot = min( + foot, + sdSegment( + st - standPos, + vec2(-standSize.x * 0.68, -standSize.x * 1.66), + vec2(standSize.x * 0.68, -standSize.x * 1.66) + ) + ); + stand = min(stand, foot); + + d = min(d, abs(stand) - strokeWidth); + + return d; +} + +ColoredSDF applyBottomAlignedBarsAndMicState( + ColoredSDF sdf, + SDFArgs args, + vec4 avgMag, + float micLevel, + bool isDarkMode +) { + float d = 1000.0; + int barCount = 5; + int loopCount = barCount; + if (args.amount == 0.0) { + loopCount = 1; + } + for (int i = 0; i < loopCount; i++) { + float f = float(float(i) + 0.5) / float(barCount); + + + float w = 1.0 / float(barCount) * 0.42; + float h = w; + + + float entryDuration = 1.8; + float entryAnimation = + fixedSpring(scaled(0.0, entryDuration, args.duration), 0.94) * + args.amount; + vec2 pos = vec2(f - 0.5, 0.0) * args.mainRadius * 1.9; + pos.x *= entryAnimation; + + if (i == 0) { + float micScale = mix(6.0 - micLevel * 2.0, 6.0, args.amount); + float yOffset = w * 2.0; + d = + micSdf( + (args.st - pos + vec2(-w * 0.15 * args.amount, yOffset)) * micScale, + 1.0 - args.amount + ) / + micScale; + } else { + + h += avgMag[i - 1] * (0.1 + (1.0 - abs(f - 0.5) * 2.0) * 0.1) * 0.7; + h = mix(w, h, smoothstep(0.8, 1.0, entryAnimation)); + + float bubbleInDur = 0.5; + float bubbleOutDur = 0.4; + + + float bubbleEffect = + fixedSpring( + scaled( + f / 4.0, + f / 4.0 + bubbleInDur, + args.duration - entryDuration / 8.0 + ), + 1.0 + ) * + pow( + 1.0 - + scaled( + f / 8.0 + bubbleInDur / 8.0, + f / 4.0 + bubbleInDur / 8.0 + bubbleOutDur, + args.duration - entryDuration / 8.0 + ), + 2.0 + ); + + h += bubbleEffect * min(h, w); + + + w *= args.amount; + h *= args.amount; + + h = min(h, 0.23); + + pos.y -= 0.25; + pos.y += h; + pos.y += bubbleEffect * w * 0.5; + + float dd = sdRoundedBox(args.st - pos, vec2(w, h), vec4(w)); + d = min(d, dd); + } + } + + sdf.distance = d; + sdf.color = mix( + sdf.color, + isDarkMode + ? vec4(1.0) + : vec4(0.0, 0.0, 0.0, 1.0), + args.amount + ); + return sdf; +} + +ColoredSDF applyHaltState(ColoredSDF sdf, SDFArgs args) { + + float radius = mix( + 0.4, + mix(0.4, 0.45, args.amount), + sin(args.time * 0.25) * 0.5 + 0.5 + ); + float strokeWidth = mix(radius / 2.0, 0.02, args.amount); + + + radius -= strokeWidth; + + radius *= mix(0.7, 1.0, args.amount); + float circle = abs(length(args.st) - radius) - strokeWidth; + + sdf.distance = mix(sdf.distance, circle, args.amount); + sdf.color.a = mix(sdf.color.a, pow(0.8, 2.2), scaled(0.5, 1.0, args.amount)); + return sdf; +} + +vec3 blendNormal(vec3 base, vec3 blend) { + return blend; +} + +vec3 blendNormal(vec3 base, vec3 blend, float opacity) { + return blendNormal(base, blend) * opacity + base * (1.0 - opacity); +} + +in vec2 out_uv; +out vec4 fragColor; + +layout(std140) uniform BlorbUniformsObject { + float time; + float micLevel; + float touchDownTimestamp; + float touchUpTimestamp; + float stateListen; + float listenTimestamp; + float stateThink; + float thinkTimestamp; + float stateSpeak; + float speakTimestamp; + float readyTimestamp; + float stateHalt; + float haltTimestamp; + float stateFailedToConnect; + float failedToConnectTimestamp; + vec4 avgMag; + vec4 cumulativeAudio; + vec2 viewport; + float screenScaleFactor; + float silenceAmount; + float silenceTimestamp; + float xmassMode; + bool isDarkMode; + bool fadeBloopWhileListening; + bool isNewBloop; + bool isAdvancedBloop; + vec3 bloopColorMain; + vec3 bloopColorLow; + vec3 bloopColorMid; + vec3 bloopColorHigh; +} ubo; + +uniform sampler2D uTextureNoise; + +void main() { + vec2 st = out_uv - 0.5; + float viewRatio = ubo.viewport.y / ubo.viewport.x; + st.y *= viewRatio; + + ColoredSDF sdf; + sdf.distance = 1000.0; + sdf.color = vec4(1.0); + + SDFArgs args; + args.st = st; + args.time = ubo.time; + args.mainRadius = 0.49; + + SDFArgs idleArgs = args; + SDFArgs listenArgs = args; + SDFArgs thinkArgs = args; + SDFArgs speakArgs = args; + SDFArgs haltArgs = args; + SDFArgs failedToConnectArgs = args; + + idleArgs.amount = 1.0; + listenArgs.amount = ubo.stateListen; + thinkArgs.amount = ubo.stateThink; + speakArgs.amount = ubo.stateSpeak; + haltArgs.amount = ubo.stateHalt; + failedToConnectArgs.amount = ubo.stateFailedToConnect; + + idleArgs.duration = ubo.time - ubo.readyTimestamp; + listenArgs.duration = ubo.time - ubo.listenTimestamp; + thinkArgs.duration = ubo.time - ubo.thinkTimestamp; + speakArgs.duration = ubo.time - ubo.speakTimestamp; + haltArgs.duration = ubo.time - ubo.haltTimestamp; + failedToConnectArgs.duration = ubo.time - ubo.failedToConnectTimestamp; + + if (ubo.isNewBloop) { + sdf = applyIdleState(sdf, idleArgs, ubo.isDarkMode); + } else { + sdf = applyIdleStateLegacy(sdf, idleArgs, ubo.isDarkMode); + } + + if (failedToConnectArgs.amount > 0.0) { + sdf = applyHaltState(sdf, failedToConnectArgs); + } + + if (listenArgs.amount > 0.0) { + if (ubo.isAdvancedBloop) { + if (speakArgs.amount > 0.0) { + listenArgs.amount = 1.0; + } + + + int binCount = 1; + sdf = applyListenAndSpeakState( + sdf, + listenArgs, + ubo.micLevel, + ubo.avgMag, + ubo.cumulativeAudio, + binCount, + ubo.bloopColorMain, + ubo.bloopColorLow, + ubo.bloopColorMid, + ubo.bloopColorHigh, + uTextureNoise, + true, + ubo.isAdvancedBloop, + ubo.xmassMode + ); + } else { + sdf = applyListenState( + sdf, + listenArgs, + ubo.micLevel, + ubo.listenTimestamp, + ubo.touchDownTimestamp, + ubo.touchUpTimestamp, + ubo.fadeBloopWhileListening + ); + } + } + + if (thinkArgs.amount > 0.0) { + sdf = applyThinkState(sdf, thinkArgs); + } + + if (speakArgs.amount > 0.0) { + if (ubo.isAdvancedBloop) { + int binCount = 1; + sdf = applyListenAndSpeakState( + sdf, + speakArgs, + ubo.micLevel, + ubo.avgMag, + ubo.cumulativeAudio, + binCount, + ubo.bloopColorMain, + ubo.bloopColorLow, + ubo.bloopColorMid, + ubo.bloopColorHigh, + uTextureNoise, + false, + ubo.isAdvancedBloop, + ubo.xmassMode + ); + } else { + float silenceDuration = ubo.time - ubo.silenceTimestamp; + sdf = applySpeakState( + sdf, + speakArgs, + ubo.avgMag, + ubo.silenceAmount, + silenceDuration + ); + } + } + + if (haltArgs.amount > 0.0) { + sdf = applyHaltState(sdf, haltArgs); + } + + float clampingTolerance = 0.0075 / ubo.screenScaleFactor; + float clampedShape = smoothstep(clampingTolerance, 0.0, sdf.distance); + float alpha = sdf.color.a * clampedShape; + if (!ubo.isNewBloop) { + alpha *= scaled(0.0, 1.0, ubo.time); + } + fragColor = vec4(sdf.color.rgb * alpha, alpha); +} \ No newline at end of file diff --git a/app/shaders/vertex.glsl b/app/shaders/vertex.glsl new file mode 100644 index 000000000..f8e79d449 --- /dev/null +++ b/app/shaders/vertex.glsl @@ -0,0 +1,20 @@ +#version 300 es + +out vec4 out_position; +out vec2 out_uv; + +const vec4 blitFullscreenTrianglePositions[6] = vec4[]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(3.0, -1.0, 0.0, 1.0), + vec4(-1.0, 3.0, 0.0, 1.0), + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(3.0, -1.0, 0.0, 1.0), + vec4(-1.0, 3.0, 0.0, 1.0) +); + +void main() { + out_position = blitFullscreenTrianglePositions[gl_VertexID]; + out_uv = out_position.xy * 0.5 + 0.5; + out_uv.y = 1.0 - out_uv.y; + gl_Position = out_position; +} \ No newline at end of file diff --git a/app/store/chat.ts b/app/store/chat.ts index 0835d7519..910769c7d 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -1,4 +1,8 @@ -import { getMessageTextContent, trimTopic } from "../utils"; +import { + getMessageTextContent, + isFunctionCallModel, + trimTopic, +} from "../utils"; import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; import { nanoid } from "nanoid"; @@ -448,74 +452,157 @@ export const useChatStore = createPersistStore( }); const api: ClientApi = getClientApi(modelConfig.providerName); - // make request - api.llm.chat({ - messages: sendMessages, - config: { ...modelConfig, stream: true }, - onUpdate(message) { - botMessage.streaming = true; - if (message) { - botMessage.content = message; - } - get().updateTargetSession(session, (session) => { - session.messages = session.messages.concat(); - }); - }, - onFinish(message) { - botMessage.streaming = false; - if (message) { - botMessage.content = message; - botMessage.date = new Date().toLocaleString(); - get().onNewMessage(botMessage, session); - } - ChatControllerPool.remove(session.id, botMessage.id); - }, - onBeforeTool(tool: ChatMessageTool) { - (botMessage.tools = botMessage?.tools || []).push(tool); - get().updateTargetSession(session, (session) => { - session.messages = session.messages.concat(); - }); - }, - onAfterTool(tool: ChatMessageTool) { - botMessage?.tools?.forEach((t, i, tools) => { - if (tool.id == t.id) { - tools[i] = { ...tool }; - } - }); - get().updateTargetSession(session, (session) => { - session.messages = session.messages.concat(); - }); - }, - onError(error) { - const isAborted = error.message?.includes?.("aborted"); - botMessage.content += - "\n\n" + - prettyObject({ - error: true, - message: error.message, - }); - botMessage.streaming = false; - userMessage.isError = !isAborted; - botMessage.isError = !isAborted; - get().updateTargetSession(session, (session) => { - session.messages = session.messages.concat(); - }); - ChatControllerPool.remove( - session.id, - botMessage.id ?? messageIndex, - ); + if ( + config.pluginConfig.enable && + session.mask.usePlugins && + (allPlugins.length > 0 || isEnableRAG) && + isFunctionCallModel(modelConfig.model) + ) { + console.log("[ToolAgent] start"); + let pluginToolNames = allPlugins.map((m) => m.toolName); + if (isEnableRAG) { + // other plugins will affect rag + // clear existing plugins here + pluginToolNames = []; + pluginToolNames.push("myfiles_browser"); + } + const agentCall = () => { + api.llm.toolAgentChat({ + chatSessionId: session.id, + messages: sendMessages, + config: { ...modelConfig, stream: true }, + agentConfig: { ...pluginConfig, useTools: pluginToolNames }, + onUpdate(message) { + botMessage.streaming = true; + if (message) { + botMessage.content = message; + } + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + }, + onToolUpdate(toolName, toolInput) { + botMessage.streaming = true; + if (toolName && toolInput) { + botMessage.toolMessages!.push({ + toolName, + toolInput, + }); + } + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + }, + onFinish(message) { + botMessage.streaming = false; + if (message) { + botMessage.content = message; + get().onNewMessage(botMessage, session); + } + ChatControllerPool.remove(session.id, botMessage.id); + }, + onError(error) { + const isAborted = error.message.includes("aborted"); + botMessage.content += + "\n\n" + + prettyObject({ + error: true, + message: error.message, + }); + botMessage.streaming = false; + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + ChatControllerPool.remove( + session.id, + botMessage.id ?? messageIndex, + ); - console.error("[Chat] failed ", error); - }, - onController(controller) { - // collect controller for stop/retry - ChatControllerPool.addController( - session.id, - botMessage.id ?? messageIndex, - controller, - ); - }, - }); + console.error("[Chat] failed ", error); + }, + onController(controller) { + // collect controller for stop/retry + ChatControllerPool.addController( + session.id, + botMessage.id ?? messageIndex, + controller, + ); + }, + }); + }; + agentCall(); + } else { + // make request + api.llm.chat({ + messages: sendMessages, + config: { ...modelConfig, stream: true }, + onUpdate(message) { + botMessage.streaming = true; + if (message) { + botMessage.content = message; + } + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + }, + onFinish(message) { + botMessage.streaming = false; + if (message) { + botMessage.content = message; + botMessage.date = new Date().toLocaleString(); + get().onNewMessage(botMessage, session); + } + ChatControllerPool.remove(session.id, botMessage.id); + }, + onBeforeTool(tool: ChatMessageTool) { + (botMessage.tools = botMessage?.tools || []).push(tool); + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + }, + onAfterTool(tool: ChatMessageTool) { + botMessage?.tools?.forEach((t, i, tools) => { + if (tool.id == t.id) { + tools[i] = { ...tool }; + } + }); + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + }, + onError(error) { + const isAborted = error.message?.includes?.("aborted"); + botMessage.content += + "\n\n" + + prettyObject({ + error: true, + message: error.message, + }); + botMessage.streaming = false; + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + get().updateTargetSession(session, (session) => { + session.messages = session.messages.concat(); + }); + ChatControllerPool.remove( + session.id, + botMessage.id ?? messageIndex, + ); + + console.error("[Chat] failed ", error); + }, + onController(controller) { + // collect controller for stop/retry + ChatControllerPool.addController( + session.id, + botMessage.id ?? messageIndex, + controller, + ); + }, + }); + } }, getMemoryPrompt() { diff --git a/app/utils/webgl.ts b/app/utils/webgl.ts new file mode 100644 index 000000000..f06d19eae --- /dev/null +++ b/app/utils/webgl.ts @@ -0,0 +1,95 @@ +export function initWebGL( + canvas: HTMLCanvasElement, + vertexShaderSource: string, + fragmentShaderSource: string, +) { + // 获取WebGL上下文 + const gl = canvas.getContext("webgl2", { + premultipliedAlpha: true, + }); + if (!gl) { + console.error("无法初始化WebGL2上下文"); + return { gl: null, program: null }; + } + + // 创建着色器程序 + const program = createShaderProgram( + gl, + vertexShaderSource, + fragmentShaderSource, + ); + if (!program) { + console.error("无法创建着色器程序"); + return { gl: null, program: null }; + } + + // 设置视口 + gl.viewport(0, 0, canvas.width, canvas.height); + + // 使用着色器程序 + gl.useProgram(program); + + return { gl, program }; +} + +function createShaderProgram( + gl: WebGL2RenderingContext, + vertexShaderSource: string, + fragmentShaderSource: string, +): WebGLProgram | null { + // 创建顶点着色器 + const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); + if (!vertexShader) return null; + + // 创建片段着色器 + const fragmentShader = createShader( + gl, + gl.FRAGMENT_SHADER, + fragmentShaderSource, + ); + if (!fragmentShader) return null; + + // 创建着色器程序 + const program = gl.createProgram(); + if (!program) return null; + + // 附加着色器 + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + + // 链接程序 + gl.linkProgram(program); + + // 检查链接状态 + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.error("无法初始化着色器程序:", gl.getProgramInfoLog(program)); + return null; + } + + return program; +} + +function createShader( + gl: WebGL2RenderingContext, + type: number, + source: string, +): WebGLShader | null { + // 创建着色器 + const shader = gl.createShader(type); + if (!shader) return null; + + // 设置着色器源代码 + gl.shaderSource(shader, source); + + // 编译着色器 + gl.compileShader(shader); + + // 检查编译状态 + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + console.error("着色器编译错误:", gl.getShaderInfoLog(shader)); + gl.deleteShader(shader); + return null; + } + + return shader; +} diff --git a/next.config.mjs b/next.config.mjs index 74c6782d2..73e8913f0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -13,7 +13,10 @@ const nextConfig = { test: /\.svg$/, use: ["@svgr/webpack"], }); - + config.module.rules.push({ + test: /\.(glsl|vs|fs|vert|frag)$/, + use: ["raw-loader"] + }); if (disableChunk) { config.plugins.push( new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }) diff --git a/package.json b/package.json index c6011d4eb..235b3c34a 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "@langchain/langgraph": "^0.0.33", "@langchain/ollama": "^0.0.4", "@langchain/openai": "^0.2.6", - "langchain": "0.2.15", "@next/third-parties": "^14.1.0", "@pinecone-database/pinecone": "^2.2.0", "@qdrant/js-client-rest": "^1.8.2", @@ -38,8 +37,9 @@ "@vercel/analytics": "^0.1.11", "@vercel/speed-insights": "^1.0.2", "axios": "^1.7.5", - "clsx": "^2.1.1", + "canvas": "^3.0.1", "cheerio": "^1.0.0-rc.12", + "clsx": "^2.1.1", "d3-dsv": "2", "duck-duck-scrape": "^2.2.4", "emoji-picker-react": "^4.9.2", @@ -49,9 +49,10 @@ "heic2any": "^0.0.4", "html-entities": "^2.4.0", "html-to-image": "^1.11.11", - "idb-keyval": "^6.2.1", "html-to-text": "^9.0.5", "https-proxy-agent": "^7.0.2", + "idb-keyval": "^6.2.1", + "langchain": "0.2.15", "mammoth": "^1.7.1", "markdown-to-txt": "^2.0.1", "md5": "^2.3.0", @@ -60,8 +61,8 @@ "nanoid": "^5.0.3", "next": "^14.1.1", "node-fetch": "^3.3.1", - "openapi-client-axios": "^7.5.5", "officeparser": "^4.0.8", + "openapi-client-axios": "^7.5.5", "pdf-parse": "^1.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -72,13 +73,13 @@ "remark-breaks": "^3.0.2", "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", + "rt-client": "https://github.com/Azure-Samples/aoai-realtime-audio-sdk/releases/download/js/v0.5.0/rt-client-0.5.0.tgz", "sass": "^1.59.2", "sharp": "^0.33.3", "spark-md5": "^3.0.2", "srt-parser-2": "^1.2.3", "use-debounce": "^9.0.4", - "zustand": "^4.3.8", - "rt-client": "https://github.com/Azure-Samples/aoai-realtime-audio-sdk/releases/download/js/v0.5.0/rt-client-0.5.0.tgz" + "zustand": "^4.3.8" }, "devDependencies": { "@tauri-apps/api": "^1.6.0", @@ -86,16 +87,16 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.2", "@testing-library/react": "^16.0.1", + "@types/html-to-text": "^9.0.1", "@types/jest": "^29.5.14", "@types/js-yaml": "4.0.9", "@types/lodash-es": "^4.17.12", + "@types/md5": "^2.3.5", "@types/node": "^20.11.30", "@types/react": "^18.2.70", "@types/react-dom": "^18.2.7", "@types/react-katex": "^3.0.0", "@types/spark-md5": "^3.0.4", - "@types/html-to-text": "^9.0.1", - "@types/md5": "^2.3.5", "concurrently": "^8.2.2", "cross-env": "^7.0.3", "eslint": "^8.49.0", @@ -112,11 +113,12 @@ "tsx": "^4.16.0", "typescript": "5.2.2", "watch": "^1.0.2", - "webpack": "^5.88.1" + "webpack": "^5.88.1", + "raw-loader": "^4.0.2" }, "resolutions": { "lint-staged/yaml": "^2.2.2", "@langchain/core": "0.2.23" }, "packageManager": "yarn@1.22.19" -} \ No newline at end of file +} diff --git a/public/noise-texture.webp b/public/noise-texture.webp new file mode 100644 index 000000000..f987e2f54 Binary files /dev/null and b/public/noise-texture.webp differ diff --git a/yarn.lock b/yarn.lock index 3ffe192aa..0a45f4b4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4446,6 +4446,11 @@ bath-es5@^3.0.3: resolved "https://registry.yarnpkg.com/bath-es5/-/bath-es5-3.0.3.tgz#4e2808e8b33b4a5e3328ec1e9032f370f042193d" integrity sha512-PdCioDToH3t84lP40kUFCKWCOCH389Dl1kbC8FGoqOwamxsmqxxnJSXdkTOsPoNHXjem4+sJ+bbNoQm5zeCqxg== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^2.0.0, binary-extensions@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -4464,6 +4469,15 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -4561,7 +4575,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.2.1: +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -4612,6 +4626,15 @@ caniuse-lite@^1.0.30001669: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz#27c2e2c637e007cfa864a16f7dfe7cde66b38b5f" integrity sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog== +canvas@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-3.0.1.tgz#b536df1d5c8c33c64f7752c499b3ff96a43eaf27" + integrity sha512-PcpVF4f8RubAeN/jCQQ/UymDKzOiLmRPph8fOTzDnlsUihkO/AUlxuhaa7wGRc3vMcCbV1fzuvyu5cWZlIcn1w== + dependencies: + node-addon-api "^7.0.0" + prebuild-install "^7.1.1" + simple-get "^3.0.3" + ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" @@ -4702,6 +4725,11 @@ cheerio@^1.0.0-rc.12: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chrome-trace-event@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" @@ -5423,6 +5451,20 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" @@ -5512,6 +5554,11 @@ deep-equal@^2.0.5: which-collection "^1.0.1" which-typed-array "^1.1.13" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -5562,7 +5609,7 @@ dereference-json-schema@^0.2.1: resolved "https://registry.yarnpkg.com/dereference-json-schema/-/dereference-json-schema-0.2.1.tgz#fcad3c98e0116f7124b0989d39d947fa318cae09" integrity sha512-uzJsrg225owJyRQ8FNTPHIuBOdSzIZlHhss9u6W8mp7jJldHqGuLv9cULagP/E26QVJDnjtG8U7Dw139mM1ydA== -detect-libc@^2.0.3: +detect-libc@^2.0.0, detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== @@ -5747,6 +5794,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -5754,7 +5806,7 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -6317,6 +6369,11 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" @@ -6643,6 +6700,11 @@ get-tsconfig@^4.5.0, get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -7058,11 +7120,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + inline-style-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" @@ -7908,7 +7975,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.3: +json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -8123,6 +8190,15 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -8825,6 +8901,16 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -8844,11 +8930,16 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + ml-array-mean@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/ml-array-mean/-/ml-array-mean-1.1.6.tgz#d951a700dc8e3a17b3e0a583c2c64abd0c619c56" @@ -8915,6 +9006,11 @@ nanoid@^5.0.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.7.tgz#6452e8c5a816861fd9d2b898399f7e5fd6944cc6" integrity sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ== +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -8956,6 +9052,18 @@ next@^14.1.1: "@next/swc-win32-ia32-msvc" "14.2.5" "@next/swc-win32-x64-msvc" "14.2.5" +node-abi@^3.3.0: + version "3.71.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.71.0.tgz#52d84bbcd8575efb71468fbaa1f9a49b2c242038" + integrity sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw== + dependencies: + semver "^7.3.5" + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + node-domexception@1.0.0, node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" @@ -9126,7 +9234,7 @@ ollama@^0.5.6: dependencies: whatwg-fetch "^3.6.20" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -9438,6 +9546,24 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" +prebuild-install@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.2.tgz#a5fd9986f5a6251fbc47e1e5c65de71e68c0a056" + integrity sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -9510,6 +9636,14 @@ psl@^1.1.33: resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== +pump@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -9542,6 +9676,24 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +raw-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" + integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-dom@^18.2.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" @@ -9633,7 +9785,7 @@ readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -9952,7 +10104,7 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -10004,7 +10156,7 @@ scheduler@^0.23.2: dependencies: loose-envify "^1.1.0" -schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -10032,7 +10184,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: +semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -10132,6 +10284,29 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -10392,6 +10567,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + strnum@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" @@ -10486,6 +10666,16 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -10499,6 +10689,17 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + terser-webpack-plugin@^5.3.10: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" @@ -10684,6 +10885,13 @@ tsx@^4.16.0: optionalDependencies: fsevents "~2.3.3" +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"