Integrate role asset studio into custom world agent flow
This commit is contained in:
102
src/components/custom-world-agent/CustomWorldAgentComposer.tsx
Normal file
102
src/components/custom-world-agent/CustomWorldAgentComposer.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import type { RefObject } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import type { SendCustomWorldAgentMessageRequest } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
|
||||
type CustomWorldAgentComposerProps = {
|
||||
disabled: boolean;
|
||||
onSubmit: (payload: SendCustomWorldAgentMessageRequest) => void;
|
||||
textareaRef?: RefObject<HTMLTextAreaElement | null>;
|
||||
onSummaryClick?: () => void;
|
||||
onAutoCompleteClick?: () => void;
|
||||
showAutoComplete?: boolean;
|
||||
};
|
||||
|
||||
function createClientMessageId() {
|
||||
if (
|
||||
typeof crypto !== 'undefined' &&
|
||||
typeof crypto.randomUUID === 'function'
|
||||
) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
return `client-message-${Date.now()}`;
|
||||
}
|
||||
|
||||
export function CustomWorldAgentComposer({
|
||||
disabled,
|
||||
onSubmit,
|
||||
textareaRef,
|
||||
onSummaryClick,
|
||||
onAutoCompleteClick,
|
||||
showAutoComplete = true,
|
||||
}: CustomWorldAgentComposerProps) {
|
||||
const [text, setText] = useState('');
|
||||
|
||||
const submit = () => {
|
||||
const nextText = text.trim();
|
||||
if (!nextText || disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
onSubmit({
|
||||
clientMessageId: createClientMessageId(),
|
||||
text: nextText,
|
||||
focusCardId: null,
|
||||
selectedCardIds: [],
|
||||
});
|
||||
setText('');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="rounded-[1.75rem] border border-white/10 bg-[#111318]/95 p-4">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSummaryClick}
|
||||
disabled={disabled}
|
||||
className="rounded-full border border-white/10 bg-white/5 px-3 py-1.5 text-xs text-zinc-200 transition hover:text-white disabled:cursor-not-allowed disabled:opacity-45"
|
||||
>
|
||||
总结当前设定
|
||||
</button>
|
||||
{showAutoComplete ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onAutoCompleteClick}
|
||||
disabled={disabled}
|
||||
className="rounded-full border border-white/10 bg-white/5 px-3 py-1.5 text-xs text-zinc-200 transition hover:text-white disabled:cursor-not-allowed disabled:opacity-45"
|
||||
>
|
||||
自动补全剩余设定
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
value={text}
|
||||
onChange={(event) => setText(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
submit();
|
||||
}
|
||||
}}
|
||||
rows={2}
|
||||
disabled={disabled}
|
||||
placeholder="输入消息"
|
||||
className="w-full resize-none rounded-[1.35rem] border border-white/10 bg-black/30 px-4 py-2.5 text-sm leading-6 text-white outline-none transition focus:border-emerald-300/35 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
/>
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
onClick={submit}
|
||||
disabled={disabled || !text.trim()}
|
||||
className="rounded-full border border-emerald-300/20 bg-emerald-500/10 px-4 py-2 text-sm font-medium text-emerald-100 transition hover:text-white disabled:cursor-not-allowed disabled:opacity-45"
|
||||
>
|
||||
发送
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user