Merge branch 'ji' into master
This commit is contained in:
commit
6c47da82c4
28 files changed
+1297
-92
No files matched your search
@@ -26,14 +26,17 @@ import { useI18n } from "@/core/i18n/hooks";
|
||||
import { useModels } from "@/core/models/hooks";
|
||||
import { useNotification } from "@/core/notification/hooks";
|
||||
import { saveLastAgentId, useThreadSettings } from "@/core/settings";
|
||||
import { useThreadStream } from "@/core/threads/hooks";
|
||||
import { stopThreadRun, useThreadStream } from "@/core/threads/hooks";
|
||||
import { textOfMessage } from "@/core/threads/utils";
|
||||
import { env } from "@/env";
|
||||
import { readTaskContext } from "@/core/auth/task-purpose";
|
||||
import { TaskPurposePanel } from "@/strategy-components/components/task-components/TaskPurposePanel";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
|
||||
export default function AgentChatPage({
|
||||
embeddedAgentId,
|
||||
chatBasePath,
|
||||
taskGate,
|
||||
}: {
|
||||
/** 当作为「通用问答右侧嵌入」渲染时由父组件传入的 agent id(替代路由参数)。
|
||||
* 传入即视为嵌入态:路由仍停留在 /chats/new,仅右侧问答区换成该智能体的对话。 */
|
||||
@@ -43,6 +46,9 @@ export default function AgentChatPage({
|
||||
* 传入如 `/page/strategy/task-management/plan-task-sentiment/agent/${id}/chats`,
|
||||
* 使开新会话 / 首条消息后的 URL 改写都停留在任务管理上下文(侧边栏保持对应业务高亮)。 */
|
||||
chatBasePath?: string;
|
||||
/** rwfx 任务深链闸门:新建对话时顶部展示目的树面板(覆盖确认后才开始问答),
|
||||
* 并给新建 thread 打 `metadata.taskId` 标签(任务↔对话 1:N)。见 task-purpose。 */
|
||||
taskGate?: boolean;
|
||||
} = {}) {
|
||||
const routeBase = useRouteBase();
|
||||
const { t } = useI18n();
|
||||
@@ -57,6 +63,16 @@ export default function AgentChatPage({
|
||||
// 对话路由前缀:调用方可覆盖(任务深链嵌入态),否则用当前 routeBase 下的独立智能体对话路径。
|
||||
const agentChatsBase = chatBasePath ?? `${routeBase}/agents/${agent_id}/chats`;
|
||||
|
||||
// rwfx 任务闸门:读取登录深链/「新建对话」暂存的任务上下文(taskId + 开场信息)。
|
||||
const taskContext = useMemo(
|
||||
() => (taskGate ? readTaskContext() : null),
|
||||
[taskGate],
|
||||
);
|
||||
const taskId =
|
||||
taskGate && taskContext && taskContext.agentId === agent_id
|
||||
? taskContext.taskId
|
||||
: "";
|
||||
|
||||
// If ChatPage stashed an opening message for this agent, skip the landing
|
||||
// screen on first render so the user doesn't see a flash of the welcome UI
|
||||
// before the auto-sent message takes over.
|
||||
@@ -101,6 +117,8 @@ export default function AgentChatPage({
|
||||
threadId: isNewThread ? undefined : threadId,
|
||||
assistantId: agent_id,
|
||||
context: { ...settings.context, agent_id },
|
||||
// 任务闸门:新建 thread 打 metadata.taskId 标签,供任务对话列表(1:N)按任务过滤。
|
||||
threadMetadata: taskId ? { taskId } : undefined,
|
||||
onStart: (createdThreadId) => {
|
||||
setThreadId(createdThreadId);
|
||||
setIsNewThread(false);
|
||||
@@ -143,6 +161,30 @@ export default function AgentChatPage({
|
||||
[sendMessage, threadId, agent_id],
|
||||
);
|
||||
|
||||
// 任务流程:切换 / 新建会话时,停掉「上一会话服务端在跑」的 run(老对话要停止)。
|
||||
// 仅 taskGate(rwfx 任务工作区)启用——普通问答页保留后台续跑行为不变。
|
||||
const prevTaskThreadRef = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
if (!taskGate) return;
|
||||
const prev = prevTaskThreadRef.current;
|
||||
if (prev && prev !== threadId) void stopThreadRun(prev);
|
||||
prevTaskThreadRef.current = threadId ?? null;
|
||||
}, [taskGate, threadId]);
|
||||
useEffect(() => {
|
||||
// 离开任务问答页(卸载)时也停掉当前会话的服务端 run。
|
||||
return () => {
|
||||
if (taskGate) void stopThreadRun(prevTaskThreadRef.current);
|
||||
};
|
||||
}, [taskGate]);
|
||||
|
||||
// 任务闸门通过(无目的数据 / 覆盖成功):发出开场信息开始问答;无开场信息则
|
||||
// 仅切到对话态(隐藏面板),让用户手动输入。
|
||||
const handleGateStart = useCallback(() => {
|
||||
const text = taskContext?.openingText?.trim();
|
||||
if (text) handleSubmit({ text, files: [] });
|
||||
else setHasStartedConversation(true);
|
||||
}, [handleSubmit, taskContext]);
|
||||
|
||||
// ChatPage stashes the opening message in sessionStorage when the user picks
|
||||
// an agent on the landing screen, then redirects here. Replay it once so the
|
||||
// user doesn't have to re-type the question on the agent chat page.
|
||||
@@ -181,6 +223,8 @@ export default function AgentChatPage({
|
||||
}, [thread]);
|
||||
|
||||
const isLandingState = isNewThread && !hasStartedConversation;
|
||||
// 任务闸门面板:仅在新建对话且尚未开始时,于问答页顶部展示目的树 + 覆盖确认。
|
||||
const showTaskGate = !!taskId && isNewThread && !hasStartedConversation;
|
||||
const isDemoMode = env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true";
|
||||
|
||||
const status = thread.error
|
||||
@@ -245,6 +289,10 @@ export default function AgentChatPage({
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{showTaskGate && (
|
||||
<TaskPurposePanel taskId={taskId} onStart={handleGateStart} />
|
||||
)}
|
||||
|
||||
{isLandingState ? (
|
||||
/* Home: centered hero, suggested questions, and input.
|
||||
Everything lives inside the scrollable main column. No fixed,
|
||||
|
||||
@@ -164,7 +164,7 @@ export default function LoginPage() {
|
||||
if (cancelled) return;
|
||||
if (detail) {
|
||||
persistCopTaskDetail(detail);
|
||||
const target = await resolveTaskDeeplinkTarget(goPath, detail);
|
||||
const target = await resolveTaskDeeplinkTarget(goPath, detail, taskId);
|
||||
if (cancelled) return;
|
||||
if (target) {
|
||||
navigate(target.path, { replace: true, state: target.state });
|
||||
|
||||
@@ -11,6 +11,11 @@ import TaskPgFrom from "@/strategy-components/components/task-components/TaskPgF
|
||||
import TaskTyFrom from "@/strategy-components/components/task-components/TaskTyFrom";
|
||||
import TaskXkFrom from "@/strategy-components/components/task-components/TaskXkFrom";
|
||||
import TaskAnalyzes from "@/strategy-components/components/task-components/TaskAnalyzes";
|
||||
import {
|
||||
TaskFxChat,
|
||||
TaskFxIndexResolver,
|
||||
TaskFxWorkspace,
|
||||
} from "@/strategy-components/components/task-components/TaskFxWorkspace";
|
||||
import { ActionAnalyzes } from "@/strategy-components/components/task-components/ActionAnalyzes";
|
||||
import KnowledgeBaseResourceManagement from "@/strategy-components/components/resource-management/KnowledgeBaseResourceManagement";
|
||||
import NetworkActorResourceManagement from "@/strategy-components/components/resource-management/NetworkActorResourceManagement";
|
||||
@@ -162,12 +167,26 @@ export default function StrategyRoutes() {
|
||||
</ChatRuntime>
|
||||
}
|
||||
/>
|
||||
{/* 任务FX:任务工作区(左对话列表 1:N + 右问答;新建对话顶部目的树闸门)。 */}
|
||||
<Route
|
||||
path="plan-task/plan-task-fx/agent/:agent_id/chats/:thread_id"
|
||||
path="plan-task/plan-task-fx/agent/:agent_id/chats"
|
||||
element={
|
||||
<TaskEmbeddedAgentChat taskBase="/page/strategy/task-management/plan-task/plan-task-fx" />
|
||||
<TaskFxWorkspace taskBase="/page/strategy/task-management/plan-task/plan-task-fx" />
|
||||
}
|
||||
/>
|
||||
>
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<TaskFxIndexResolver taskBase="/page/strategy/task-management/plan-task/plan-task-fx" />
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path=":thread_id"
|
||||
element={
|
||||
<TaskFxChat taskBase="/page/strategy/task-management/plan-task/plan-task-fx" />
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="plan-task/plan-task-action"
|
||||
element={
|
||||
|
||||
Reference in new issue
Block a user