feat: extend agent-driven map workbench
This commit is contained in:
@@ -8,6 +8,7 @@ import useSWRImmutable from "swr/immutable";
|
||||
import type { PersonaState } from "@/shared/ai-elements/persona";
|
||||
import { showMapNotice } from "@/features/map/core/components/notice";
|
||||
import type {
|
||||
AgentApprovalMode,
|
||||
AgentChatMessage,
|
||||
AgentModelOption,
|
||||
AgentPermissionReply,
|
||||
@@ -34,11 +35,11 @@ import {
|
||||
import type { FrontendActionRequest } from "@/features/agent/frontend-action";
|
||||
import { FrontendActionExecutor } from "@/features/agent/frontend-action/executor";
|
||||
import {
|
||||
appendStreamRenderToken,
|
||||
applySessionStreamEvent,
|
||||
createCompletedStreamRenderState,
|
||||
getDataString,
|
||||
markLastAssistantStreamDone,
|
||||
markStreamRenderPending,
|
||||
readBodyString,
|
||||
toAgentChatMessages,
|
||||
toAgentUiMessages,
|
||||
@@ -62,10 +63,9 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
const collapseTimerRef = useRef<number | null>(null);
|
||||
const mobileCollapseTimerRef = useRef<number | null>(null);
|
||||
const sessionStreamAbortRef = useRef<AbortController | null>(null);
|
||||
const sessionStreamIdRef = useRef<string | null>(null);
|
||||
const streamRenderChunkIdRef = useRef(0);
|
||||
const clientRef = useRef(createAgentApiClient());
|
||||
const sessionIdRef = useRef<string | null>(null);
|
||||
const approvalModeRef = useRef<AgentApprovalMode>("request");
|
||||
const registryRef = useRef<UIRegistry | null>(null);
|
||||
const frontendActionEnabledRef = useRef(false);
|
||||
const onFrontendActionRef = useRef(onFrontendAction);
|
||||
@@ -82,6 +82,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
const [resumedStreaming, setResumedStreaming] = useState(false);
|
||||
const [modelOptions, setModelOptions] = useState<AgentModelOption[]>([]);
|
||||
const [selectedModel, setSelectedModel] = useState("");
|
||||
const [approvalMode, setApprovalModeState] = useState<AgentApprovalMode>("request");
|
||||
const [streamRenderState, setStreamRenderState] = useState<AgentStreamRenderState>({});
|
||||
const [permissionOverrides, setPermissionOverrides] = useState<Record<string, PermissionOverride>>({});
|
||||
const [questionOverrides, setQuestionOverrides] = useState<Record<string, QuestionOverride>>({});
|
||||
@@ -90,6 +91,11 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
sessionIdRef.current = sessionId;
|
||||
}, [sessionId]);
|
||||
|
||||
const setApprovalMode = useCallback((mode: AgentApprovalMode) => {
|
||||
approvalModeRef.current = mode;
|
||||
setApprovalModeState(mode);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
registryRef.current = registry;
|
||||
}, [registry]);
|
||||
@@ -148,11 +154,10 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
applySessionId(eventSessionId);
|
||||
|
||||
if (part.type === "data-stream_token") {
|
||||
appendStreamRenderToken(
|
||||
markStreamRenderPending(
|
||||
part.data,
|
||||
chatRef.current.messages,
|
||||
setStreamRenderState,
|
||||
streamRenderChunkIdRef
|
||||
setStreamRenderState
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -214,7 +219,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
trigger,
|
||||
messageId,
|
||||
session_id: readBodyString(body, "session_id") ?? sessionIdRef.current ?? undefined,
|
||||
approval_mode: readBodyString(body, "approval_mode") ?? "request",
|
||||
approval_mode: readBodyString(body, "approval_mode") ?? approvalModeRef.current,
|
||||
capabilities: frontendActionEnabledRef.current ? ["frontend-action@1"] : []
|
||||
}
|
||||
};
|
||||
@@ -281,7 +286,6 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
const stopSessionStreamSubscription = useCallback(() => {
|
||||
sessionStreamAbortRef.current?.abort();
|
||||
sessionStreamAbortRef.current = null;
|
||||
sessionStreamIdRef.current = null;
|
||||
setResumedStreaming(false);
|
||||
}, []);
|
||||
|
||||
@@ -418,11 +422,10 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
setSessionTitle(title);
|
||||
}
|
||||
} else if (event.type === "token") {
|
||||
appendStreamRenderToken(
|
||||
markStreamRenderPending(
|
||||
event.data,
|
||||
chatRef.current.messages,
|
||||
setStreamRenderState,
|
||||
streamRenderChunkIdRef
|
||||
setStreamRenderState
|
||||
);
|
||||
} else if (event.type === "ui_envelope") {
|
||||
const payload = parseUiEnvelopePayload(event.data);
|
||||
@@ -473,7 +476,6 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
|
||||
const controller = new AbortController();
|
||||
sessionStreamAbortRef.current = controller;
|
||||
sessionStreamIdRef.current = nextSessionId;
|
||||
setResumedStreaming(true);
|
||||
|
||||
void clientRef.current
|
||||
@@ -496,7 +498,6 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
.finally(() => {
|
||||
if (sessionStreamAbortRef.current === controller) {
|
||||
sessionStreamAbortRef.current = null;
|
||||
sessionStreamIdRef.current = null;
|
||||
setResumedStreaming(false);
|
||||
void refreshSessionHistory();
|
||||
}
|
||||
@@ -608,7 +609,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
async (nextSessionId: string) => {
|
||||
if (streaming) {
|
||||
showMapNotice({ tone: "warning", message: "Agent 正在处理上一条指令,完成后再删除会话。" });
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -623,6 +624,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
}
|
||||
|
||||
await refreshSessionHistory();
|
||||
return true;
|
||||
} catch (error) {
|
||||
showMapNotice({
|
||||
id: "agent-history-status",
|
||||
@@ -630,6 +632,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
title: "Agent 历史记录删除失败",
|
||||
message: error instanceof Error ? error.message : "无法删除这个历史会话。"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[mutateSessionHistory, refreshSessionHistory, resetDraftSession, streaming]
|
||||
@@ -664,12 +667,12 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
body: {
|
||||
session_id: sessionIdRef.current ?? undefined,
|
||||
model: selectedModel || undefined,
|
||||
approval_mode: "request"
|
||||
approval_mode: approvalMode
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
[chat, selectedModel, streaming]
|
||||
[approvalMode, chat, selectedModel, streaming]
|
||||
);
|
||||
|
||||
const stopPrompt = useCallback(() => {
|
||||
@@ -788,6 +791,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
}, []);
|
||||
|
||||
return {
|
||||
approvalMode,
|
||||
collapsePanel,
|
||||
expandPanel,
|
||||
mobileOpen,
|
||||
@@ -811,6 +815,7 @@ export function useWorkbenchAgent({ onUiEnvelope, onFrontendAction }: UseWorkben
|
||||
statusLabel,
|
||||
streamRenderState,
|
||||
selectedModel,
|
||||
setApprovalMode,
|
||||
setSelectedModel,
|
||||
stopPrompt,
|
||||
streaming,
|
||||
|
||||
Reference in New Issue
Block a user