fix(agent): Chat Agent 全链路 P0-P5 整改
封堵鉴权旁路与导出 IDOR,DocGov 改服务端身份;对话层 PendingAction 接真实 docgov/taskrun;修复流式租约假死与会话级任务流;加固配置/doc_id/NULL;补齐 slog 与测试;前端 ErrorBoundary 与受控文档重试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
weichen
co-authored by
Cursor
parent
21de3bc39e
commit
f4e4357ddb
@@ -0,0 +1,102 @@
|
||||
import { useCallback, useRef, useSyncExternalStore } from 'react';
|
||||
|
||||
export interface TaskRunRuntime {
|
||||
sessionId: string;
|
||||
runId: string | null;
|
||||
thinking: boolean;
|
||||
controller: AbortController | null;
|
||||
}
|
||||
|
||||
type Listener = () => void;
|
||||
|
||||
/** 按 sessionId 隔离长任务流状态,对齐 useTurnRuntime 模式 */
|
||||
export function useTaskRunStream(activeSessionId: string) {
|
||||
const storeRef = useRef({
|
||||
sessions: new Map<string, TaskRunRuntime>(),
|
||||
listeners: new Set<Listener>(),
|
||||
});
|
||||
|
||||
const subscribe = useCallback((listener: Listener) => {
|
||||
storeRef.current.listeners.add(listener);
|
||||
return () => {
|
||||
storeRef.current.listeners.delete(listener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const notify = useCallback(() => {
|
||||
for (const l of storeRef.current.listeners) {
|
||||
l();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getRuntime = useCallback(
|
||||
(sessionId: string): TaskRunRuntime => {
|
||||
const store = storeRef.current;
|
||||
if (!store.sessions.has(sessionId)) {
|
||||
store.sessions.set(sessionId, {
|
||||
sessionId,
|
||||
runId: null,
|
||||
thinking: false,
|
||||
controller: null,
|
||||
});
|
||||
}
|
||||
return store.sessions.get(sessionId)!;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const snapshot = useSyncExternalStore(
|
||||
subscribe,
|
||||
() => getRuntime(activeSessionId),
|
||||
() => getRuntime(activeSessionId),
|
||||
);
|
||||
|
||||
const setThinking = useCallback(
|
||||
(sessionId: string, thinking: boolean) => {
|
||||
const rt = getRuntime(sessionId);
|
||||
rt.thinking = thinking;
|
||||
notify();
|
||||
},
|
||||
[getRuntime, notify],
|
||||
);
|
||||
|
||||
const setRunId = useCallback(
|
||||
(sessionId: string, runId: string | null) => {
|
||||
const rt = getRuntime(sessionId);
|
||||
rt.runId = runId;
|
||||
notify();
|
||||
},
|
||||
[getRuntime, notify],
|
||||
);
|
||||
|
||||
const setController = useCallback(
|
||||
(sessionId: string, controller: AbortController | null) => {
|
||||
const rt = getRuntime(sessionId);
|
||||
rt.controller = controller;
|
||||
notify();
|
||||
},
|
||||
[getRuntime, notify],
|
||||
);
|
||||
|
||||
const abortSession = useCallback(
|
||||
(sessionId: string) => {
|
||||
const rt = getRuntime(sessionId);
|
||||
rt.controller?.abort();
|
||||
rt.controller = null;
|
||||
rt.thinking = false;
|
||||
notify();
|
||||
},
|
||||
[getRuntime, notify],
|
||||
);
|
||||
|
||||
return {
|
||||
runtime: snapshot,
|
||||
isThinking: snapshot.thinking,
|
||||
activeTaskRunId: snapshot.runId,
|
||||
taskStreamAbortRef: { current: snapshot.controller },
|
||||
setThinking,
|
||||
setRunId,
|
||||
setController,
|
||||
abortSession,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user