|
|
|
@ -14,6 +14,7 @@ import VoiceAnalysis from "../comps/voiceanalysis"; |
|
|
|
import { sendOsc, OSC_ADDRESS, updatePrompt, onOscMessageReceived, sendOscStatus } from "../util/osc"; |
|
|
|
import { sendOsc, OSC_ADDRESS, updatePrompt, onOscMessageReceived, sendOscStatus } from "../util/osc"; |
|
|
|
import { DebugControl, TEST_PROMPT } from "../comps/debug"; |
|
|
|
import { DebugControl, TEST_PROMPT } from "../comps/debug"; |
|
|
|
import { useUser } from "../util/useUser"; |
|
|
|
import { useUser } from "../util/useUser"; |
|
|
|
|
|
|
|
import { set } from 'zod/v4'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const CUELIST_FILE = 'cuelist_demo3.json'; |
|
|
|
const CUELIST_FILE = 'cuelist_demo3.json'; |
|
|
|
@ -56,6 +57,9 @@ export function FreeFlow(){ |
|
|
|
const [audioInput, setAudioInput] = useState(true); |
|
|
|
const [audioInput, setAudioInput] = useState(true); |
|
|
|
const [autoSend, setAutoSend] = useState(true); |
|
|
|
const [autoSend, setAutoSend] = useState(true); |
|
|
|
const [chatStatus, setChatStatus] = useState(ChatStatus.System); // System, User, Processing |
|
|
|
const [chatStatus, setChatStatus] = useState(ChatStatus.System); // System, User, Processing |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [padInput, setPadInput] = useState(null); |
|
|
|
|
|
|
|
|
|
|
|
const { userId, setUserId, getFileId, setPassword, reset:resetUser, uploadHistory, setSummary, summary,setChoice,choice, getUploadFolder,getDataId } = useUser(); |
|
|
|
const { userId, setUserId, getFileId, setPassword, reset:resetUser, uploadHistory, setSummary, summary,setChoice,choice, getUploadFolder,getDataId } = useUser(); |
|
|
|
|
|
|
|
|
|
|
|
const refTimer=useRef(); |
|
|
|
const refTimer=useRef(); |
|
|
|
@ -93,6 +97,7 @@ export function FreeFlow(){ |
|
|
|
|
|
|
|
|
|
|
|
reset(); |
|
|
|
reset(); |
|
|
|
sendOsc(OSC_ADDRESS.CHOICE, 'reset'); |
|
|
|
sendOsc(OSC_ADDRESS.CHOICE, 'reset'); |
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'stop'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function onOsc(payload){ |
|
|
|
function onOsc(payload){ |
|
|
|
@ -234,6 +239,9 @@ export function FreeFlow(){ |
|
|
|
if(!cue) return; |
|
|
|
if(!cue) return; |
|
|
|
console.log('Playing cue:', cue); |
|
|
|
console.log('Playing cue:', cue); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// stop audio |
|
|
|
|
|
|
|
if(refAudio.current) refAudio.current.pause(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setCurrentCue(cue); |
|
|
|
setCurrentCue(cue); |
|
|
|
@ -254,6 +262,7 @@ export function FreeFlow(){ |
|
|
|
// clear unity hint |
|
|
|
// clear unity hint |
|
|
|
sendOsc(OSC_ADDRESS.HINT, ''); // Clear hint message |
|
|
|
sendOsc(OSC_ADDRESS.HINT, ''); // Clear hint message |
|
|
|
sendOsc(OSC_ADDRESS.INPUT, ''); // Clear input message |
|
|
|
sendOsc(OSC_ADDRESS.INPUT, ''); // Clear input message |
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'stop'); |
|
|
|
|
|
|
|
|
|
|
|
switch(cue.type){ |
|
|
|
switch(cue.type){ |
|
|
|
case 'chat': |
|
|
|
case 'chat': |
|
|
|
@ -280,6 +289,16 @@ export function FreeFlow(){ |
|
|
|
setChatStatus(ChatStatus.Clear); // Set chat status to Processing |
|
|
|
setChatStatus(ChatStatus.Clear); // Set chat status to Processing |
|
|
|
|
|
|
|
|
|
|
|
let message=refInput.current?.value?.trim() || history.map(el=>`${el.role}:${el.content}`).join('\n'); |
|
|
|
let message=refInput.current?.value?.trim() || history.map(el=>`${el.role}:${el.content}`).join('\n'); |
|
|
|
|
|
|
|
console.log('Summary input message:', message); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!message || message.length==0) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setSummary(); |
|
|
|
|
|
|
|
console.log('no message input, clear summary'); |
|
|
|
|
|
|
|
onCueEnd(); // End the current cue after getting summary |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
|
|
|
|
getSummary(message, data).then(summary_ => { |
|
|
|
getSummary(message, data).then(summary_ => { |
|
|
|
|
|
|
|
|
|
|
|
console.log('Summary:', summary_); |
|
|
|
console.log('Summary:', summary_); |
|
|
|
@ -291,6 +310,7 @@ export function FreeFlow(){ |
|
|
|
}).catch(error => { |
|
|
|
}).catch(error => { |
|
|
|
console.error('Error getting summary:', error); |
|
|
|
console.error('Error getting summary:', error); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
@ -363,7 +383,7 @@ export function FreeFlow(){ |
|
|
|
}else{ |
|
|
|
}else{ |
|
|
|
sendOsc(OSC_ADDRESS.HINT, ''); // Clear hint message |
|
|
|
sendOsc(OSC_ADDRESS.HINT, ''); // Clear hint message |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'stop'); |
|
|
|
|
|
|
|
|
|
|
|
refAudio.current?.pause(); // Pause any playing audio |
|
|
|
refAudio.current?.pause(); // Pause any playing audio |
|
|
|
console.log('onCueEnd:', cue.id); |
|
|
|
console.log('onCueEnd:', cue.id); |
|
|
|
@ -395,23 +415,34 @@ export function FreeFlow(){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function onNumpad(mess){ |
|
|
|
function onNumpad(mess){ |
|
|
|
console.log('Numpad input:', mess); |
|
|
|
setPadInput(mess); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(padInput==null) return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Numpad input:', padInput); |
|
|
|
if(refCurrentCue.current?.callback!='numpad') return; |
|
|
|
if(refCurrentCue.current?.callback!='numpad') return; |
|
|
|
|
|
|
|
|
|
|
|
let cue=refCurrentCue.current; |
|
|
|
let cue=refCurrentCue.current; |
|
|
|
let next=cue.nextcue; |
|
|
|
let next=cue.nextcue; |
|
|
|
switch(cue.numpad_type){ |
|
|
|
switch(cue.numpad_type){ |
|
|
|
case NUMPAD_TYPE.USERID: |
|
|
|
case NUMPAD_TYPE.USERID: |
|
|
|
setUserId(()=>mess); |
|
|
|
setUserId(()=>padInput); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case NUMPAD_TYPE.CHOICE: |
|
|
|
case NUMPAD_TYPE.CHOICE: |
|
|
|
next=cue.branch[mess.toString()].nextcue; |
|
|
|
next=cue.branch[padInput.toString()].nextcue; |
|
|
|
setChoice(cue.branch[mess.toString()].description); // Set choice for user input |
|
|
|
setChoice(()=>cue.branch[padInput.toString()].description); // Set choice for user input |
|
|
|
break; |
|
|
|
break; |
|
|
|
case NUMPAD_TYPE.PASSWORD: |
|
|
|
case NUMPAD_TYPE.PASSWORD: |
|
|
|
setPassword(()=>mess); |
|
|
|
setPassword(()=>padInput); |
|
|
|
// sendOsc(OSC_ADDRESS.PASSWORD, mess); // Send OSC password message |
|
|
|
// sendOsc(OSC_ADDRESS.PASSWORD, mess); // Send OSC password message |
|
|
|
sendOsc(OSC_ADDRESS.EXPORT, `${getUploadFolder()}#${getDataId()}#${summary}#${getFileId(mess)}`); |
|
|
|
const user_input = history.find(msg => msg.role === 'user'); |
|
|
|
|
|
|
|
const default_image=!(user_input && user_input.content.trim() !== ''); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.EXPORT, `${getUploadFolder()}#${getDataId()}#${summary||''}#${getFileId(padInput)}#${choice||''}#${default_image?'default':'generated'}`); // Send OSC export message |
|
|
|
sendOsc(OSC_ADDRESS.CHOICE, choice); // Send OSC save choice message |
|
|
|
sendOsc(OSC_ADDRESS.CHOICE, choice); // Send OSC save choice message |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -421,10 +452,9 @@ export function FreeFlow(){ |
|
|
|
console.log('Finish enter number, next cue:', next); |
|
|
|
console.log('Finish enter number, next cue:', next); |
|
|
|
playCue(cuelist.find(c => c.id === next)); |
|
|
|
playCue(cuelist.find(c => c.id === next)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function saveImage(){ |
|
|
|
|
|
|
|
sendOsc('/export', 'output/test.png'); // Send OSC message to save image |
|
|
|
},[padInput]); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
useEffect(()=>{ |
|
|
|
|
|
|
|
|
|
|
|
@ -437,6 +467,8 @@ export function FreeFlow(){ |
|
|
|
|
|
|
|
|
|
|
|
function onSpeechEnd(){ |
|
|
|
function onSpeechEnd(){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'stop'); |
|
|
|
|
|
|
|
|
|
|
|
if(currentCue?.type!='chat') return; // Only process if current cue is user input |
|
|
|
if(currentCue?.type!='chat') return; // Only process if current cue is user input |
|
|
|
if(chatStatus!=ChatStatus.User) return; // Only process if chat status is User |
|
|
|
if(chatStatus!=ChatStatus.User) return; // Only process if chat status is User |
|
|
|
|
|
|
|
|
|
|
|
@ -556,7 +588,12 @@ export function FreeFlow(){ |
|
|
|
refSpeechPaused.current=false; |
|
|
|
refSpeechPaused.current=false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sendOscStatus(OSC_ADDRESS.CLIENT_INPUT, `${data.id}#${transcript}`); // Send current input via OSC |
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'start'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sendOscStatus(OSC_ADDRESS.CLIENT_INPUT, `${data.id}#${transcript}`); |
|
|
|
|
|
|
|
// Send current input via OSC |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
},[transcript]); |
|
|
|
},[transcript]); |
|
|
|
@ -590,6 +627,7 @@ export function FreeFlow(){ |
|
|
|
text = ''; |
|
|
|
text = ''; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sendOsc(OSC_ADDRESS.SPEECH, 'stop'); |
|
|
|
sendOsc(OSC_ADDRESS.INPUT, text); |
|
|
|
sendOsc(OSC_ADDRESS.INPUT, text); |
|
|
|
|
|
|
|
|
|
|
|
},[chatStatus]); |
|
|
|
},[chatStatus]); |
|
|
|
@ -626,6 +664,8 @@ export function FreeFlow(){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}else{ |
|
|
|
}else{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
playCue(next); |
|
|
|
playCue(next); |
|
|
|
setNextCue(null); |
|
|
|
setNextCue(null); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -693,9 +733,7 @@ export function FreeFlow(){ |
|
|
|
<span></span> |
|
|
|
<span></span> |
|
|
|
<span>UserId</span><span>{userId}</span> |
|
|
|
<span>UserId</span><span>{userId}</span> |
|
|
|
<span>FileId</span><span>{getFileId()}</span> |
|
|
|
<span>FileId</span><span>{getFileId()}</span> |
|
|
|
<button className="!bg-yellow-300 col-span-2" onClick={()=>{ |
|
|
|
<span>Choice</span><span>{choice || ''}</span> |
|
|
|
saveHistory(history); |
|
|
|
|
|
|
|
}}>Save Log</button> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|