be89296492
拆分 App 认证、壳层、运行配置与项目摘要模块 拆分 Tauri 项目能力与 Rust 测试领域模块 拆分界面测试与 Agent Runtime 真实 E2E 套件 补充源码扫描和客户端模块化文档约定
735 lines
26 KiB
TypeScript
735 lines
26 KiB
TypeScript
import { Archive, GitFork, Plus } from 'lucide-react';
|
|
|
|
import { closeDialogOnEscape } from '../../app/dialogs';
|
|
import type { AgentBackgroundSubmitMode } from '../../app/types';
|
|
import {
|
|
AgentGoalStatusPanel,
|
|
AgentRuntimeStatusPanel,
|
|
formatAgentConversationSessionMeta,
|
|
} from '../agent-runtime';
|
|
import {
|
|
taskGroupLabels,
|
|
taskStatusLabels,
|
|
} from '../project-summary/projectSummary';
|
|
import type { DeveloperAgentPanelController } from './useDeveloperAgentPanel';
|
|
|
|
export function DeveloperAgentPanel({
|
|
controller,
|
|
onRuntimeConfigOpen,
|
|
}: {
|
|
controller: DeveloperAgentPanelController;
|
|
onRuntimeConfigOpen: () => void;
|
|
}) {
|
|
const {
|
|
agentChatActiveSessionId,
|
|
agentChatBackgroundBusy,
|
|
agentChatBusy,
|
|
agentChatConversationPath,
|
|
agentChatGoal,
|
|
agentChatGoalError,
|
|
agentChatInput,
|
|
agentChatInteractionMode,
|
|
agentChatLegacySessionMode,
|
|
agentChatLlmStatus,
|
|
agentChatLoadVersionRef,
|
|
agentChatMessages,
|
|
agentChatMessagesRef,
|
|
agentChatProjectPath,
|
|
agentChatResumeConfirmation,
|
|
agentChatRunSubmitMode,
|
|
agentChatRuntime,
|
|
agentChatRuntimeError,
|
|
agentChatRuntimeResumeProjectPathRef,
|
|
agentChatSelectedAgentId,
|
|
agentChatSelectedSessionId,
|
|
agentChatSessionStatus,
|
|
agentChatSessions,
|
|
agentChatStatus,
|
|
cancelAgentChatRuntimeResume,
|
|
confirmAgentChatRuntimeResume,
|
|
currentAgentChatActiveSessions,
|
|
currentAgentChatAgent,
|
|
currentAgentChatArchivedSessions,
|
|
currentAgentChatGoalDialogMode,
|
|
currentAgentChatGoalStatus,
|
|
currentAgentChatLlmWarning,
|
|
currentAgentChatNeedsUserInput,
|
|
currentAgentChatSession,
|
|
currentAgentChatSessionArchived,
|
|
currentAgentChatSessionMutationBlocked,
|
|
currentAgentChatSteerRuntime,
|
|
currentAgentChatWaiting,
|
|
currentAgentChatWaitingDetail,
|
|
currentAgentChatWaitingStatus,
|
|
handleAgentChatArchiveSession,
|
|
handleAgentChatCancelRuntimeTask,
|
|
handleAgentChatCompactContext,
|
|
handleAgentChatConfirmRuntimeTask,
|
|
handleAgentChatCreateSession,
|
|
handleAgentChatForkSession,
|
|
handleAgentChatGoalControl,
|
|
handleAgentChatMessagesScroll,
|
|
handleAgentChatPickProjectDirectory,
|
|
handleAgentChatRejectRuntimeTask,
|
|
handleAgentChatRetryRuntimeTask,
|
|
handleAgentChatSelectSession,
|
|
handleAgentChatStartBackgroundTask,
|
|
handleAgentChatSubmit,
|
|
handleAgentChatSubmitUserInput,
|
|
handleOpenProjectSupervisorChatWindow,
|
|
launcherAgentChatAgents,
|
|
loadAgentChatConversation,
|
|
loadAgentChatLlmStatus,
|
|
openAgentChatGoalDialog,
|
|
resetAgentChatSessionView,
|
|
setAgentChatInput,
|
|
setAgentChatInteractionMode,
|
|
setAgentChatProjectPath,
|
|
setAgentChatResumeConfirmation,
|
|
setAgentChatRunSubmitMode,
|
|
setAgentChatSelectedAgentId,
|
|
setAgentChatStatus,
|
|
} = controller;
|
|
return (
|
|
<section className="launcher-page launcher-agent-chat-page">
|
|
<header>
|
|
<div>
|
|
<h1>Agent 聊天</h1>
|
|
<p>{agentChatStatus}</p>
|
|
</div>
|
|
<div className="launcher-project-list-actions">
|
|
<button
|
|
type="button"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
onClick={() => void handleOpenProjectSupervisorChatWindow()}
|
|
>
|
|
总控对话
|
|
</button>
|
|
<button
|
|
type="button"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
onClick={() => void loadAgentChatLlmStatus()}
|
|
>
|
|
LLM状态
|
|
</button>
|
|
<button type="button" onClick={() => onRuntimeConfigOpen()}>
|
|
配置
|
|
</button>
|
|
<button
|
|
type="button"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
onClick={() =>
|
|
void loadAgentChatConversation(
|
|
agentChatSelectedAgentId,
|
|
agentChatProjectPath,
|
|
agentChatSelectedSessionId,
|
|
)
|
|
}
|
|
>
|
|
读取历史
|
|
</button>
|
|
</div>
|
|
</header>
|
|
<section className="launcher-agent-chat-layout">
|
|
<aside className="launcher-agent-chat-sidebar">
|
|
<form
|
|
className="launcher-agent-chat-project"
|
|
onSubmit={(event) => {
|
|
event.preventDefault();
|
|
void loadAgentChatConversation(
|
|
agentChatSelectedAgentId,
|
|
agentChatProjectPath,
|
|
agentChatSelectedSessionId,
|
|
);
|
|
}}
|
|
>
|
|
<label>
|
|
项目目录
|
|
<input
|
|
aria-label="Agent 聊天项目目录"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
value={agentChatProjectPath}
|
|
onChange={(event) => {
|
|
agentChatLoadVersionRef.current += 1;
|
|
agentChatRuntimeResumeProjectPathRef.current = null;
|
|
setAgentChatResumeConfirmation(null);
|
|
setAgentChatProjectPath(event.currentTarget.value);
|
|
resetAgentChatSessionView();
|
|
setAgentChatStatus('请选择并读取会话');
|
|
}}
|
|
/>
|
|
</label>
|
|
<div className="launcher-page-actions">
|
|
<button
|
|
type="button"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
onClick={() => void handleAgentChatPickProjectDirectory()}
|
|
>
|
|
选择
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
>
|
|
读取
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<div className="launcher-agent-picker" aria-label="选择 Agent">
|
|
{launcherAgentChatAgents.map((agent) => (
|
|
<button
|
|
key={agent.id}
|
|
type="button"
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
className={
|
|
agent.id === currentAgentChatAgent?.id
|
|
? 'launcher-agent-active'
|
|
: ''
|
|
}
|
|
onClick={() => {
|
|
agentChatLoadVersionRef.current += 1;
|
|
setAgentChatSelectedAgentId(agent.id);
|
|
resetAgentChatSessionView();
|
|
void loadAgentChatConversation(agent.id);
|
|
}}
|
|
>
|
|
<strong>{agent.title}</strong>
|
|
<span>{`${taskGroupLabels[agent.group]} / ${agent.role}`}</span>
|
|
<small>{agent.summary}</small>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</aside>
|
|
<section className="launcher-agent-chat-main">
|
|
<header>
|
|
<div>
|
|
<h2>{currentAgentChatAgent?.title ?? '未选择 Agent'}</h2>
|
|
{currentAgentChatAgent ? (
|
|
<p>{`${taskGroupLabels[currentAgentChatAgent.group]} / ${currentAgentChatAgent.role} · ${taskStatusLabels[currentAgentChatAgent.status]}`}</p>
|
|
) : null}
|
|
<p>{agentChatLlmStatus}</p>
|
|
</div>
|
|
<small>{agentChatConversationPath || '请选择并读取会话'}</small>
|
|
</header>
|
|
<section
|
|
className="launcher-agent-session-bar"
|
|
aria-label="Agent 会话"
|
|
>
|
|
<div className="launcher-agent-session-actions">
|
|
<button
|
|
type="button"
|
|
aria-label="新建 Agent 会话"
|
|
title="新建会话"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
agentChatLegacySessionMode ||
|
|
agentChatSessions.length === 0 ||
|
|
!currentAgentChatAgent ||
|
|
currentAgentChatSessionMutationBlocked
|
|
}
|
|
onClick={() => void handleAgentChatCreateSession()}
|
|
>
|
|
<Plus size={16} aria-hidden="true" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
aria-label="分叉当前 Agent 会话"
|
|
title="从当前历史分叉会话"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
agentChatLegacySessionMode ||
|
|
currentAgentChatSessionMutationBlocked ||
|
|
!currentAgentChatSession
|
|
}
|
|
onClick={() => void handleAgentChatForkSession()}
|
|
>
|
|
<GitFork size={16} aria-hidden="true" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
aria-label="归档当前 Agent 会话"
|
|
title="归档当前会话"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
agentChatLegacySessionMode ||
|
|
currentAgentChatSessionMutationBlocked ||
|
|
!currentAgentChatSession ||
|
|
currentAgentChatSession.legacy ||
|
|
currentAgentChatSessionArchived
|
|
}
|
|
onClick={() => void handleAgentChatArchiveSession()}
|
|
>
|
|
<Archive size={16} aria-hidden="true" />
|
|
</button>
|
|
</div>
|
|
<div className="launcher-agent-session-list">
|
|
{currentAgentChatActiveSessions.map((session) => (
|
|
<button
|
|
key={session.sessionId}
|
|
type="button"
|
|
className={
|
|
session.sessionId === agentChatSelectedSessionId
|
|
? 'launcher-agent-session-active'
|
|
: ''
|
|
}
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatSessionMutationBlocked
|
|
}
|
|
onClick={() => void handleAgentChatSelectSession(session)}
|
|
>
|
|
<span>{session.title}</span>
|
|
<small>
|
|
{formatAgentConversationSessionMeta(
|
|
session,
|
|
agentChatSessions,
|
|
agentChatActiveSessionId,
|
|
)}
|
|
</small>
|
|
</button>
|
|
))}
|
|
{currentAgentChatArchivedSessions.map((session) => (
|
|
<button
|
|
key={session.sessionId}
|
|
type="button"
|
|
className={`launcher-agent-session-archived${
|
|
session.sessionId === agentChatSelectedSessionId
|
|
? ' launcher-agent-session-active'
|
|
: ''
|
|
}`}
|
|
disabled={agentChatBusy || agentChatBackgroundBusy}
|
|
onClick={() => void handleAgentChatSelectSession(session)}
|
|
>
|
|
<span>{session.title}</span>
|
|
<small>{`已归档 · ${formatAgentConversationSessionMeta(
|
|
session,
|
|
agentChatSessions,
|
|
agentChatActiveSessionId,
|
|
)}`}</small>
|
|
</button>
|
|
))}
|
|
</div>
|
|
<small className="launcher-agent-session-status">
|
|
{agentChatSessionStatus}
|
|
</small>
|
|
</section>
|
|
<section className="launcher-agent-runtime-stack">
|
|
{currentAgentChatLlmWarning ? (
|
|
<div className="agent-llm-warning" role="status">
|
|
<strong>{currentAgentChatLlmWarning}</strong>
|
|
<button type="button" onClick={() => onRuntimeConfigOpen()}>
|
|
打开配置
|
|
</button>
|
|
</div>
|
|
) : null}
|
|
<AgentGoalStatusPanel
|
|
goal={agentChatGoal}
|
|
runtime={agentChatRuntime}
|
|
error={agentChatGoalError}
|
|
controlBusy={agentChatBusy || agentChatBackgroundBusy}
|
|
readOnly={currentAgentChatSessionArchived}
|
|
onStart={
|
|
agentChatSelectedSessionId && !agentChatGoalError
|
|
? () => openAgentChatGoalDialog('create')
|
|
: undefined
|
|
}
|
|
onEdit={
|
|
agentChatSelectedSessionId
|
|
? () => openAgentChatGoalDialog('edit')
|
|
: undefined
|
|
}
|
|
onPause={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: () => void handleAgentChatGoalControl('pause')
|
|
}
|
|
onResume={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: () => void handleAgentChatGoalControl('resume')
|
|
}
|
|
onClear={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: () => void handleAgentChatGoalControl('clear')
|
|
}
|
|
/>
|
|
<AgentRuntimeStatusPanel
|
|
runtime={agentChatRuntime}
|
|
error={agentChatRuntimeError}
|
|
controlBusy={agentChatBusy || agentChatBackgroundBusy}
|
|
onCancelRuntimeTask={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: (runId) => void handleAgentChatCancelRuntimeTask(runId)
|
|
}
|
|
onRetryRuntimeTask={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: (runId) => void handleAgentChatRetryRuntimeTask(runId)
|
|
}
|
|
onConfirmRuntimeTask={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: (runId, actionId) =>
|
|
void handleAgentChatConfirmRuntimeTask(runId, actionId)
|
|
}
|
|
onRejectRuntimeTask={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: (runId, actionId) =>
|
|
void handleAgentChatRejectRuntimeTask(runId, actionId)
|
|
}
|
|
onSubmitUserInput={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: handleAgentChatSubmitUserInput
|
|
}
|
|
onCompactContext={
|
|
currentAgentChatSessionArchived
|
|
? undefined
|
|
: () => void handleAgentChatCompactContext()
|
|
}
|
|
onRefreshRuntime={() =>
|
|
void loadAgentChatConversation(
|
|
agentChatSelectedAgentId,
|
|
agentChatProjectPath,
|
|
agentChatSelectedSessionId,
|
|
)
|
|
}
|
|
/>
|
|
</section>
|
|
<div className="launcher-agent-resume-slot">
|
|
{agentChatResumeConfirmation ? (
|
|
<div className="pending-command" role="status">
|
|
<span>
|
|
agent.resume
|
|
<small>{agentChatResumeConfirmation.detail}</small>
|
|
</span>
|
|
<button type="button" onClick={cancelAgentChatRuntimeResume}>
|
|
取消
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => void confirmAgentChatRuntimeResume()}
|
|
>
|
|
确认
|
|
</button>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
<div
|
|
ref={agentChatMessagesRef}
|
|
className="launcher-agent-chat-messages"
|
|
role="log"
|
|
aria-label="Agent 聊天记录"
|
|
aria-busy={currentAgentChatWaiting}
|
|
onScroll={handleAgentChatMessagesScroll}
|
|
tabIndex={0}
|
|
>
|
|
{agentChatMessages.length > 0 ? (
|
|
agentChatMessages.map((message, index) => (
|
|
<p
|
|
key={`${message.updatedAt}-${index}`}
|
|
className={`message message--${message.role}`}
|
|
>
|
|
{message.content}
|
|
</p>
|
|
))
|
|
) : (
|
|
<p className="status-line">暂无对话</p>
|
|
)}
|
|
{currentAgentChatWaiting ? (
|
|
<div
|
|
className="launcher-agent-chat-waiting"
|
|
role="status"
|
|
aria-live="polite"
|
|
aria-atomic="true"
|
|
>
|
|
<span aria-hidden="true" />
|
|
<div>
|
|
<strong>{currentAgentChatWaitingStatus}</strong>
|
|
<small>{currentAgentChatWaitingDetail}</small>
|
|
</div>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
<form
|
|
className="launcher-agent-chat-composer"
|
|
onSubmit={(event) => {
|
|
if (agentChatInteractionMode === 'run') {
|
|
event.preventDefault();
|
|
void handleAgentChatStartBackgroundTask();
|
|
return;
|
|
}
|
|
if (agentChatInteractionMode === 'goal') {
|
|
event.preventDefault();
|
|
openAgentChatGoalDialog(currentAgentChatGoalDialogMode);
|
|
return;
|
|
}
|
|
void handleAgentChatSubmit(event);
|
|
}}
|
|
>
|
|
<div
|
|
className="launcher-agent-chat-mode"
|
|
role="group"
|
|
aria-label="Agent 交互模式"
|
|
>
|
|
<button
|
|
type="button"
|
|
aria-pressed={agentChatInteractionMode === 'run'}
|
|
className={
|
|
agentChatInteractionMode === 'run' ? 'is-active' : ''
|
|
}
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput ||
|
|
currentAgentChatSessionArchived
|
|
}
|
|
onClick={() => setAgentChatInteractionMode('run')}
|
|
>
|
|
执行
|
|
</button>
|
|
<button
|
|
type="button"
|
|
aria-pressed={agentChatInteractionMode === 'chat'}
|
|
className={
|
|
agentChatInteractionMode === 'chat' ? 'is-active' : ''
|
|
}
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput ||
|
|
currentAgentChatSessionArchived
|
|
}
|
|
onClick={() => setAgentChatInteractionMode('chat')}
|
|
>
|
|
聊天
|
|
</button>
|
|
<button
|
|
type="button"
|
|
aria-pressed={agentChatInteractionMode === 'goal'}
|
|
className={
|
|
agentChatInteractionMode === 'goal' ? 'is-active' : ''
|
|
}
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput ||
|
|
currentAgentChatSessionArchived
|
|
}
|
|
onClick={() => setAgentChatInteractionMode('goal')}
|
|
>
|
|
目标
|
|
</button>
|
|
</div>
|
|
{agentChatInteractionMode === 'goal' ? (
|
|
<div
|
|
className="launcher-agent-goal-composer-summary"
|
|
aria-label="当前持久目标"
|
|
>
|
|
{agentChatGoal
|
|
? `${currentAgentChatGoalStatus ?? '-'} · Revision ${
|
|
agentChatGoal.revision
|
|
} · ${agentChatGoal.outcome}`
|
|
: '尚未开始'}
|
|
</div>
|
|
) : (
|
|
<input
|
|
aria-label="Agent 聊天内容"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput ||
|
|
currentAgentChatLlmWarning !== null ||
|
|
currentAgentChatSessionArchived
|
|
}
|
|
value={agentChatInput}
|
|
onChange={(event) =>
|
|
setAgentChatInput(event.currentTarget.value)
|
|
}
|
|
/>
|
|
)}
|
|
{agentChatInteractionMode === 'run' &&
|
|
currentAgentChatSteerRuntime ? (
|
|
<select
|
|
aria-label="后台任务提交方式"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput
|
|
}
|
|
value={agentChatRunSubmitMode}
|
|
onChange={(event) =>
|
|
setAgentChatRunSubmitMode(
|
|
event.currentTarget.value as AgentBackgroundSubmitMode,
|
|
)
|
|
}
|
|
>
|
|
<option value="steer">追加当前 Run</option>
|
|
<option value="queue">排队新任务</option>
|
|
</select>
|
|
) : null}
|
|
<button
|
|
type="submit"
|
|
disabled={
|
|
agentChatBusy ||
|
|
agentChatBackgroundBusy ||
|
|
currentAgentChatNeedsUserInput ||
|
|
currentAgentChatLlmWarning !== null ||
|
|
currentAgentChatSessionArchived ||
|
|
(agentChatInteractionMode === 'goal' &&
|
|
(!agentChatSelectedSessionId ||
|
|
Boolean(agentChatGoalError) ||
|
|
(currentAgentChatGoalDialogMode === 'edit' &&
|
|
!['active', 'pause-requested', 'paused'].includes(
|
|
currentAgentChatGoalStatus ?? '',
|
|
))))
|
|
}
|
|
>
|
|
{agentChatInteractionMode === 'goal'
|
|
? currentAgentChatGoalDialogMode === 'create'
|
|
? '开始目标'
|
|
: '编辑目标'
|
|
: agentChatInteractionMode === 'run' &&
|
|
currentAgentChatSteerRuntime
|
|
? agentChatRunSubmitMode === 'queue'
|
|
? '排队任务'
|
|
: '追加指令'
|
|
: '发送'}
|
|
</button>
|
|
</form>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export function DeveloperAgentDialogs({
|
|
controller,
|
|
}: {
|
|
controller: DeveloperAgentPanelController;
|
|
}) {
|
|
const {
|
|
agentChatBackgroundBusy,
|
|
agentChatGoalDialog,
|
|
agentChatGoalDialogError,
|
|
closeAgentChatGoalDialog,
|
|
handleAgentChatGoalDialogSubmit,
|
|
setAgentChatGoalDialog,
|
|
} = controller;
|
|
return (
|
|
<>
|
|
{agentChatGoalDialog ? (
|
|
<div
|
|
className="launcher-dialog-backdrop"
|
|
role="presentation"
|
|
onMouseDown={(event) => {
|
|
if (event.target === event.currentTarget) {
|
|
closeAgentChatGoalDialog();
|
|
}
|
|
}}
|
|
>
|
|
<form
|
|
aria-labelledby="launcher-agent-goal-dialog-title"
|
|
aria-modal="true"
|
|
className="launcher-dialog launcher-agent-goal-dialog"
|
|
role="dialog"
|
|
onSubmit={(event) => void handleAgentChatGoalDialogSubmit(event)}
|
|
onKeyDown={(event) =>
|
|
closeDialogOnEscape(event, closeAgentChatGoalDialog)
|
|
}
|
|
>
|
|
<h2 id="launcher-agent-goal-dialog-title">
|
|
{agentChatGoalDialog.mode === 'create'
|
|
? '创建持久目标'
|
|
: '编辑持久目标'}
|
|
</h2>
|
|
<div className="launcher-agent-goal-fields">
|
|
<label>
|
|
Outcome
|
|
<textarea
|
|
aria-label="Goal outcome"
|
|
autoFocus
|
|
disabled={agentChatBackgroundBusy}
|
|
maxLength={4_000}
|
|
rows={5}
|
|
value={agentChatGoalDialog.outcome}
|
|
onChange={(event) => {
|
|
const outcome = event.currentTarget.value;
|
|
setAgentChatGoalDialog((current) =>
|
|
current ? { ...current, outcome } : current,
|
|
);
|
|
}}
|
|
/>
|
|
</label>
|
|
<label>
|
|
Constraints
|
|
<textarea
|
|
aria-label="Goal constraints"
|
|
disabled={agentChatBackgroundBusy}
|
|
rows={4}
|
|
value={agentChatGoalDialog.constraintsText}
|
|
onChange={(event) => {
|
|
const constraintsText = event.currentTarget.value;
|
|
setAgentChatGoalDialog((current) =>
|
|
current
|
|
? {
|
|
...current,
|
|
constraintsText,
|
|
}
|
|
: current,
|
|
);
|
|
}}
|
|
/>
|
|
</label>
|
|
<label>
|
|
Verification
|
|
<textarea
|
|
aria-label="Goal verification"
|
|
disabled={agentChatBackgroundBusy}
|
|
rows={4}
|
|
value={agentChatGoalDialog.verificationText}
|
|
onChange={(event) => {
|
|
const verificationText = event.currentTarget.value;
|
|
setAgentChatGoalDialog((current) =>
|
|
current
|
|
? {
|
|
...current,
|
|
verificationText,
|
|
}
|
|
: current,
|
|
);
|
|
}}
|
|
/>
|
|
</label>
|
|
</div>
|
|
{agentChatGoalDialogError ? (
|
|
<p className="launcher-agent-goal-dialog-error" role="alert">
|
|
{agentChatGoalDialogError}
|
|
</p>
|
|
) : null}
|
|
<div className="launcher-dialog-actions">
|
|
<button
|
|
type="button"
|
|
disabled={agentChatBackgroundBusy}
|
|
onClick={closeAgentChatGoalDialog}
|
|
>
|
|
取消
|
|
</button>
|
|
<button type="submit" disabled={agentChatBackgroundBusy}>
|
|
{agentChatGoalDialog.mode === 'create' ? '开始' : '保存'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|