|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useState, useCallback, useRef, useEffect } from 'react'; |
|
|
import { |
|
|
DEFAULT_MESSAGES, |
|
|
DEFAULT_CONFIG, |
|
|
DEBUG_TABS, |
|
|
MESSAGE_STATUS, |
|
|
} from '../../constants/playground.constants'; |
|
|
import { |
|
|
loadConfig, |
|
|
saveConfig, |
|
|
loadMessages, |
|
|
saveMessages, |
|
|
} from '../../components/playground/configStorage'; |
|
|
import { processIncompleteThinkTags } from '../../helpers'; |
|
|
|
|
|
export const usePlaygroundState = () => { |
|
|
|
|
|
const [savedConfig] = useState(() => loadConfig()); |
|
|
const [initialMessages] = useState(() => loadMessages() || DEFAULT_MESSAGES); |
|
|
|
|
|
|
|
|
const [inputs, setInputs] = useState( |
|
|
savedConfig.inputs || DEFAULT_CONFIG.inputs, |
|
|
); |
|
|
const [parameterEnabled, setParameterEnabled] = useState( |
|
|
savedConfig.parameterEnabled || DEFAULT_CONFIG.parameterEnabled, |
|
|
); |
|
|
const [showDebugPanel, setShowDebugPanel] = useState( |
|
|
savedConfig.showDebugPanel || DEFAULT_CONFIG.showDebugPanel, |
|
|
); |
|
|
const [customRequestMode, setCustomRequestMode] = useState( |
|
|
savedConfig.customRequestMode || DEFAULT_CONFIG.customRequestMode, |
|
|
); |
|
|
const [customRequestBody, setCustomRequestBody] = useState( |
|
|
savedConfig.customRequestBody || DEFAULT_CONFIG.customRequestBody, |
|
|
); |
|
|
|
|
|
|
|
|
const [showSettings, setShowSettings] = useState(false); |
|
|
const [models, setModels] = useState([]); |
|
|
const [groups, setGroups] = useState([]); |
|
|
const [status, setStatus] = useState({}); |
|
|
|
|
|
|
|
|
const [message, setMessage] = useState(initialMessages); |
|
|
|
|
|
|
|
|
const [debugData, setDebugData] = useState({ |
|
|
request: null, |
|
|
response: null, |
|
|
timestamp: null, |
|
|
previewRequest: null, |
|
|
previewTimestamp: null, |
|
|
}); |
|
|
const [activeDebugTab, setActiveDebugTab] = useState(DEBUG_TABS.PREVIEW); |
|
|
const [previewPayload, setPreviewPayload] = useState(null); |
|
|
|
|
|
|
|
|
const [editingMessageId, setEditingMessageId] = useState(null); |
|
|
const [editValue, setEditValue] = useState(''); |
|
|
|
|
|
|
|
|
const sseSourceRef = useRef(null); |
|
|
const chatRef = useRef(null); |
|
|
const saveConfigTimeoutRef = useRef(null); |
|
|
const saveMessagesTimeoutRef = useRef(null); |
|
|
|
|
|
|
|
|
const handleInputChange = useCallback((name, value) => { |
|
|
setInputs((prev) => ({ ...prev, [name]: value })); |
|
|
}, []); |
|
|
|
|
|
const handleParameterToggle = useCallback((paramName) => { |
|
|
setParameterEnabled((prev) => ({ |
|
|
...prev, |
|
|
[paramName]: !prev[paramName], |
|
|
})); |
|
|
}, []); |
|
|
|
|
|
|
|
|
const saveMessagesImmediately = useCallback( |
|
|
(messagesToSave) => { |
|
|
|
|
|
saveMessages(messagesToSave || message); |
|
|
}, |
|
|
[message], |
|
|
); |
|
|
|
|
|
|
|
|
const debouncedSaveConfig = useCallback(() => { |
|
|
if (saveConfigTimeoutRef.current) { |
|
|
clearTimeout(saveConfigTimeoutRef.current); |
|
|
} |
|
|
|
|
|
saveConfigTimeoutRef.current = setTimeout(() => { |
|
|
const configToSave = { |
|
|
inputs, |
|
|
parameterEnabled, |
|
|
showDebugPanel, |
|
|
customRequestMode, |
|
|
customRequestBody, |
|
|
}; |
|
|
saveConfig(configToSave); |
|
|
}, 1000); |
|
|
}, [ |
|
|
inputs, |
|
|
parameterEnabled, |
|
|
showDebugPanel, |
|
|
customRequestMode, |
|
|
customRequestBody, |
|
|
]); |
|
|
|
|
|
|
|
|
const handleConfigImport = useCallback((importedConfig) => { |
|
|
if (importedConfig.inputs) { |
|
|
setInputs((prev) => ({ ...prev, ...importedConfig.inputs })); |
|
|
} |
|
|
if (importedConfig.parameterEnabled) { |
|
|
setParameterEnabled((prev) => ({ |
|
|
...prev, |
|
|
...importedConfig.parameterEnabled, |
|
|
})); |
|
|
} |
|
|
if (typeof importedConfig.showDebugPanel === 'boolean') { |
|
|
setShowDebugPanel(importedConfig.showDebugPanel); |
|
|
} |
|
|
if (importedConfig.customRequestMode) { |
|
|
setCustomRequestMode(importedConfig.customRequestMode); |
|
|
} |
|
|
if (importedConfig.customRequestBody) { |
|
|
setCustomRequestBody(importedConfig.customRequestBody); |
|
|
} |
|
|
|
|
|
if (importedConfig.messages && Array.isArray(importedConfig.messages)) { |
|
|
setMessage(importedConfig.messages); |
|
|
} |
|
|
}, []); |
|
|
|
|
|
const handleConfigReset = useCallback((options = {}) => { |
|
|
const { resetMessages = false } = options; |
|
|
|
|
|
setInputs(DEFAULT_CONFIG.inputs); |
|
|
setParameterEnabled(DEFAULT_CONFIG.parameterEnabled); |
|
|
setShowDebugPanel(DEFAULT_CONFIG.showDebugPanel); |
|
|
setCustomRequestMode(DEFAULT_CONFIG.customRequestMode); |
|
|
setCustomRequestBody(DEFAULT_CONFIG.customRequestBody); |
|
|
|
|
|
|
|
|
if (resetMessages) { |
|
|
setMessage([]); |
|
|
setTimeout(() => { |
|
|
setMessage(DEFAULT_MESSAGES); |
|
|
}, 0); |
|
|
} |
|
|
}, []); |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
return () => { |
|
|
if (saveConfigTimeoutRef.current) { |
|
|
clearTimeout(saveConfigTimeoutRef.current); |
|
|
} |
|
|
}; |
|
|
}, []); |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
if (!Array.isArray(message) || message.length === 0) return; |
|
|
|
|
|
const lastMsg = message[message.length - 1]; |
|
|
if ( |
|
|
lastMsg.status === MESSAGE_STATUS.LOADING || |
|
|
lastMsg.status === MESSAGE_STATUS.INCOMPLETE |
|
|
) { |
|
|
const processed = processIncompleteThinkTags( |
|
|
lastMsg.content || '', |
|
|
lastMsg.reasoningContent || '', |
|
|
); |
|
|
|
|
|
const fixedLastMsg = { |
|
|
...lastMsg, |
|
|
status: MESSAGE_STATUS.COMPLETE, |
|
|
content: processed.content, |
|
|
reasoningContent: processed.reasoningContent || null, |
|
|
isThinkingComplete: true, |
|
|
}; |
|
|
|
|
|
const updatedMessages = [...message.slice(0, -1), fixedLastMsg]; |
|
|
setMessage(updatedMessages); |
|
|
|
|
|
|
|
|
setTimeout(() => saveMessagesImmediately(updatedMessages), 0); |
|
|
} |
|
|
}, []); |
|
|
|
|
|
return { |
|
|
|
|
|
inputs, |
|
|
parameterEnabled, |
|
|
showDebugPanel, |
|
|
customRequestMode, |
|
|
customRequestBody, |
|
|
|
|
|
|
|
|
showSettings, |
|
|
models, |
|
|
groups, |
|
|
status, |
|
|
|
|
|
|
|
|
message, |
|
|
|
|
|
|
|
|
debugData, |
|
|
activeDebugTab, |
|
|
previewPayload, |
|
|
|
|
|
|
|
|
editingMessageId, |
|
|
editValue, |
|
|
|
|
|
|
|
|
sseSourceRef, |
|
|
chatRef, |
|
|
saveConfigTimeoutRef, |
|
|
|
|
|
|
|
|
setInputs, |
|
|
setParameterEnabled, |
|
|
setShowDebugPanel, |
|
|
setCustomRequestMode, |
|
|
setCustomRequestBody, |
|
|
setShowSettings, |
|
|
setModels, |
|
|
setGroups, |
|
|
setStatus, |
|
|
setMessage, |
|
|
setDebugData, |
|
|
setActiveDebugTab, |
|
|
setPreviewPayload, |
|
|
setEditingMessageId, |
|
|
setEditValue, |
|
|
|
|
|
|
|
|
handleInputChange, |
|
|
handleParameterToggle, |
|
|
debouncedSaveConfig, |
|
|
saveMessagesImmediately, |
|
|
handleConfigImport, |
|
|
handleConfigReset, |
|
|
}; |
|
|
}; |
|
|
|