fix: 等待 thread 状态可读以避免过早展示chat页面
This commit is contained in:
parent
0a38e14b3e
commit
f67aa27434
22
Makefile
22
Makefile
|
|
@ -263,11 +263,11 @@ docker-logs-gateway:
|
|||
# ==========================================
|
||||
# Docker Publish Command
|
||||
# ==========================================
|
||||
# Usage: make docker-publish VER=v220.20251202 SVC=frontend
|
||||
# Example: make docker-publish VER=v220.20251202 SVC=frontend
|
||||
# Usage: make docker-publish VER=[version] SVC=[service name] [PUSH=1]
|
||||
# Example: make docker-publish VER=v2.0.20251202 SVC=frontend PUSH=0
|
||||
docker-publish:
|
||||
@if [ -z "$(VER)" ]; then \
|
||||
echo "✗ VER is required (e.g. v220.20251202)"; \
|
||||
echo "✗ VER is required (e.g. v2.0.20251202)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if [ -z "$(SVC)" ]; then \
|
||||
|
|
@ -293,9 +293,13 @@ docker-publish:
|
|||
echo "✗ Docker build failed"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
docker push $$IMAGE; \
|
||||
if [ $$? -ne 0 ]; then \
|
||||
echo "✗ Docker push failed"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "✓ Docker image $$IMAGE built and pushed successfully"
|
||||
if [ "$(PUSH)" = "0" ]; then \
|
||||
echo "✓ Docker image $$IMAGE built successfully (not pushed)"; \
|
||||
else \
|
||||
docker push $$IMAGE; \
|
||||
if [ $$? -ne 0 ]; then \
|
||||
echo "✗ Docker push failed"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "✓ Docker image $$IMAGE built and pushed successfully"; \
|
||||
fi
|
||||
|
|
@ -32,6 +32,7 @@ import { DevTodoList } from "@/components/workspace/dev-todo-list";
|
|||
import { IframeTestPanel } from "@/components/workspace/iframe-test-panel";
|
||||
import { InputBox } from "@/components/workspace/input-box";
|
||||
import { MessageList } from "@/components/workspace/messages";
|
||||
import { MessageListSkeleton } from "@/components/workspace/messages/skeleton";
|
||||
import { ThreadContext } from "@/components/workspace/messages/context";
|
||||
import { ThreadTitle } from "@/components/workspace/thread-title";
|
||||
import { TodoList } from "@/components/workspace/todo-list";
|
||||
|
|
@ -165,6 +166,10 @@ export default function ChatPage() {
|
|||
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
const suppressExistingThreadPrefetchUi = reuseExistingThread && !hasSubmitted;
|
||||
const suppressNewThreadSubmitUi =
|
||||
isNewThread && createNewSession && hasSubmitted;
|
||||
const suppressConversationUi =
|
||||
suppressExistingThreadPrefetchUi || suppressNewThreadSubmitUi;
|
||||
|
||||
useEffect(() => {
|
||||
const pageTitle = isNewThread
|
||||
|
|
@ -172,7 +177,7 @@ export default function ChatPage() {
|
|||
: thread.values?.title && thread.values.title !== "Untitled"
|
||||
? thread.values.title
|
||||
: t.pages.untitled;
|
||||
if (thread.isThreadLoading && !suppressExistingThreadPrefetchUi) {
|
||||
if (thread.isThreadLoading && !suppressConversationUi) {
|
||||
document.title = `Loading... - ${t.pages.appName}`;
|
||||
} else {
|
||||
document.title = `${pageTitle} - ${t.pages.appName}`;
|
||||
|
|
@ -184,19 +189,21 @@ export default function ChatPage() {
|
|||
t.pages.appName,
|
||||
thread.values.title,
|
||||
thread.isThreadLoading,
|
||||
suppressExistingThreadPrefetchUi,
|
||||
suppressConversationUi,
|
||||
]);
|
||||
|
||||
const [autoSelectFirstArtifact, setAutoSelectFirstArtifact] = useState(true);
|
||||
useEffect(() => {
|
||||
setArtifacts(thread.values.artifacts);
|
||||
if (
|
||||
env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true" &&
|
||||
autoSelectFirstArtifact
|
||||
) {
|
||||
if (thread?.values?.artifacts?.length > 0) {
|
||||
setAutoSelectFirstArtifact(false);
|
||||
selectArtifact(thread.values.artifacts[0]!);
|
||||
if (!suppressConversationUi) {
|
||||
setArtifacts(thread.values.artifacts);
|
||||
if (
|
||||
env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true" &&
|
||||
autoSelectFirstArtifact
|
||||
) {
|
||||
if (thread?.values?.artifacts?.length > 0) {
|
||||
setAutoSelectFirstArtifact(false);
|
||||
selectArtifact(thread.values.artifacts[0]!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [
|
||||
|
|
@ -337,20 +344,21 @@ export default function ChatPage() {
|
|||
)}
|
||||
>
|
||||
<div className="flex size-full justify-center">
|
||||
<MessageList
|
||||
className={cn("size-full", !isNewThread && "pt-10")}
|
||||
threadId={threadId}
|
||||
thread={thread}
|
||||
suppressThreadLoading={suppressExistingThreadPrefetchUi}
|
||||
messagesOverride={
|
||||
suppressExistingThreadPrefetchUi
|
||||
? []
|
||||
: !thread.isLoading && finalState?.messages
|
||||
{suppressConversationUi ? (
|
||||
<MessageListSkeleton />
|
||||
) : (
|
||||
<MessageList
|
||||
className={cn("size-full", !isNewThread && "pt-10")}
|
||||
threadId={threadId}
|
||||
thread={thread}
|
||||
messagesOverride={
|
||||
!thread.isLoading && finalState?.messages
|
||||
? (finalState.messages as Message[])
|
||||
: undefined
|
||||
}
|
||||
paddingBottom={todoListCollapsed ? 160 : 280}
|
||||
/>
|
||||
}
|
||||
paddingBottom={todoListCollapsed ? 160 : 280}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,29 @@ import type {
|
|||
AgentThreadState,
|
||||
} from "./types";
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
async function waitForThreadStateToBeReadable(
|
||||
apiClient: ReturnType<typeof getAPIClient>,
|
||||
threadId: string,
|
||||
timeoutMs = 3000,
|
||||
) {
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
|
||||
while (Date.now() < deadline) {
|
||||
try {
|
||||
const state = await apiClient.threads.getState<AgentThreadState>(threadId);
|
||||
if ((state.values.messages?.length ?? 0) > 0) {
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// Ignore transient 404 / not-ready errors while the new thread is being persisted.
|
||||
}
|
||||
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
export function useThreadStream({
|
||||
threadId,
|
||||
isNewThread,
|
||||
|
|
@ -188,6 +211,11 @@ export function useSubmitThread({
|
|||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (createNewSession && isNewThread && threadId) {
|
||||
await waitForThreadStateToBeReadable(apiClient, threadId);
|
||||
}
|
||||
|
||||
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
|
||||
afterSubmit?.();
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue