141 lines
4.5 KiB
JavaScript
141 lines
4.5 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { Header } from '@/components/Header';
|
|
import { Sidebar } from '@/components/Sidebar';
|
|
import { FloatingButton } from '@/components/FloatingButton';
|
|
import { ContentEditor } from '@/components/editors/ContentEditor';
|
|
import { StandardEditor } from '@/components/editors/StandardEditor';
|
|
import { useWebSocket } from '@/hooks/useWebSocket';
|
|
import { AgentState, Tabs, ClientMessageType, ServerMessageType } from '@/constants';
|
|
|
|
|
|
const App = () => {
|
|
// Editor content state
|
|
const [originalContext, setOriginalContext] = useState('');
|
|
const [modifiedContext, setModifiedContext] = useState('');
|
|
const [originalResponse, setOriginalResponse] = useState('');
|
|
const [modifiedResponse, setModifiedResponse] = useState('');
|
|
const [validationError, setValidationError] = useState(null);
|
|
const [input, setInput] = useState('');
|
|
const [output, setOutput] = useState('');
|
|
|
|
// UI state
|
|
const [activeTab, setActiveTab] = useState(Tabs.CONTEXT);
|
|
const [showDiff, setShowDiff] = useState(false);
|
|
const [showSidebar, setShowSidebar] = useState(false);
|
|
const [agentState, setAgentState] = useState(AgentState.CONTEXT_APPROVAL);
|
|
|
|
const { wsState, sendMessage, setMessageHandler } = useWebSocket('ws://localhost:8080/ws');
|
|
|
|
// Set up WebSocket message handlers
|
|
useEffect(() => {
|
|
setMessageHandler(ServerMessageType.STATE_CHANGE, (message) => {
|
|
setAgentState(message.state);
|
|
});
|
|
|
|
setMessageHandler(ServerMessageType.CONTEXT_UPDATE, (message) => {
|
|
setOriginalContext(message.context);
|
|
setModifiedContext(message.context);
|
|
});
|
|
|
|
setMessageHandler(ServerMessageType.RESPONSE_UPDATE, (message) => {
|
|
setOriginalResponse(message.response);
|
|
setModifiedResponse(message.response);
|
|
setValidationError(message.validation_error);
|
|
});
|
|
|
|
setMessageHandler(ServerMessageType.OUTPUT_UPDATE, (message) => {
|
|
setOutput(prev => prev + message.data);
|
|
});
|
|
}, [setMessageHandler]);
|
|
|
|
const handleApprove = () => {
|
|
if (agentState === AgentState.CONTEXT_APPROVAL) {
|
|
sendMessage(ClientMessageType.APPROVE_CONTEXT);
|
|
} else if (agentState === AgentState.RESPONSE_APPROVAL) {
|
|
sendMessage(ClientMessageType.APPROVE_RESPONSE, modifiedResponse);
|
|
}
|
|
};
|
|
|
|
const handleSendInput = () => {
|
|
if (input.trim()) {
|
|
sendMessage(ClientMessageType.SEND_INPUT, input);
|
|
setInput('');
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
switch (agentState) {
|
|
case AgentState.CONTEXT_APPROVAL:
|
|
setActiveTab(Tabs.CONTEXT);
|
|
break;
|
|
case AgentState.RESPONSE_APPROVAL:
|
|
setActiveTab(Tabs.RESPONSE);
|
|
break;
|
|
}
|
|
}, [agentState]);
|
|
|
|
return (
|
|
<div className="h-screen bg-gray-100 flex flex-col overflow-hidden">
|
|
<Header
|
|
wsState={wsState}
|
|
agentState={agentState}
|
|
activeTab={activeTab}
|
|
setActiveTab={setActiveTab}
|
|
/>
|
|
|
|
<div className="flex flex-1 overflow-hidden">
|
|
<main className="flex-1 p-4 overflow-auto">
|
|
{activeTab === Tabs.CONTEXT && (
|
|
<ContentEditor
|
|
showDiff={showDiff}
|
|
originalContent={originalContext}
|
|
modifiedContent={modifiedContext}
|
|
onChange={value => setModifiedContext(value)}
|
|
validationError={null}
|
|
/>
|
|
)}
|
|
{activeTab === Tabs.RESPONSE && (
|
|
<ContentEditor
|
|
showDiff={showDiff}
|
|
originalContent={originalResponse}
|
|
modifiedContent={modifiedResponse}
|
|
onChange={value => setModifiedResponse(value)}
|
|
validationError={validationError}
|
|
/>
|
|
)}
|
|
{activeTab === Tabs.INPUT && (
|
|
<StandardEditor
|
|
content={input}
|
|
onChange={value => setInput(value)}
|
|
language="plaintext"
|
|
/>
|
|
)}
|
|
{activeTab === Tabs.OUTPUT && (
|
|
<StandardEditor
|
|
content={output}
|
|
readOnly={true}
|
|
language="plaintext"
|
|
/>
|
|
)}
|
|
</main>
|
|
|
|
<Sidebar
|
|
showSidebar={showSidebar}
|
|
activeTab={activeTab}
|
|
agentState={agentState}
|
|
validationError={validationError}
|
|
showDiff={showDiff}
|
|
input={input}
|
|
onApprove={handleApprove}
|
|
onToggleDiff={() => setShowDiff(!showDiff)}
|
|
onSendInput={handleSendInput}
|
|
onClearOutput={() => setOutput('')}
|
|
/>
|
|
|
|
<FloatingButton onClick={() => setShowSidebar(!showSidebar)} />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App; |