Merge branch 'gzy_iframedf' into 'master'

Gzy iframedf

See merge request knowledge-base-bj/deerflow-server!82
This commit is contained in:
g zy committed 2026-06-03 03:51:09 +00:00
commit d7cb19ee96
3 files changed
+38 -21

No files matched your search

+11 -6
View File
@@ -10,16 +10,13 @@ import {
useSpecificChatMode, useSpecificChatMode,
useThreadChat, useThreadChat,
} from "@/components/workspace/chats"; } from "@/components/workspace/chats";
import { ExportTrigger } from "@/components/workspace/export-trigger";
import { import {
MessageList, MessageList,
MESSAGE_LIST_DEFAULT_PADDING_BOTTOM, MESSAGE_LIST_DEFAULT_PADDING_BOTTOM,
MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM, MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM,
} from "@/components/workspace/messages"; } from "@/components/workspace/messages";
import { ThreadContext } from "@/components/workspace/messages/context"; import { ThreadContext } from "@/components/workspace/messages/context";
import { ThreadTitle } from "@/components/workspace/thread-title";
import { TodoList } from "@/components/workspace/todo-list"; import { TodoList } from "@/components/workspace/todo-list";
import { TokenUsageIndicator } from "@/components/workspace/token-usage-indicator";
import { useI18n } from "@/core/i18n/hooks"; import { useI18n } from "@/core/i18n/hooks";
import { useModels } from "@/core/models/hooks"; import { useModels } from "@/core/models/hooks";
import { useNotification } from "@/core/notification/hooks"; import { useNotification } from "@/core/notification/hooks";
@@ -138,6 +135,7 @@ export default function IframeChatPage() {
( (
message: PromptInputMessage, message: PromptInputMessage,
externalContext?: Record<string, unknown>, externalContext?: Record<string, unknown>,
options?: { additionalKwargs?: Record<string, unknown> },
) => { ) => {
if ( if (
selectedAgentId && selectedAgentId &&
@@ -183,6 +181,7 @@ export default function IframeChatPage() {
threadId, threadId,
message, message,
Object.keys(extraContext).length > 0 ? extraContext : undefined, Object.keys(extraContext).length > 0 ? extraContext : undefined,
options,
); );
}, },
[ [
@@ -213,7 +212,7 @@ export default function IframeChatPage() {
if (data?.source !== "brainy-extension") return; if (data?.source !== "brainy-extension") return;
if (data?.type !== "brainy:chat-submit") return; if (data?.type !== "brainy:chat-submit") return;
const { submitText, files, iframeContext } = const { submitText, files, iframeContext, additionalKwargs } =
parseBrainyChatSubmitMessage(data); parseBrainyChatSubmitMessage(data);
console.log("收到插件消息", { console.log("收到插件消息", {
@@ -229,7 +228,11 @@ export default function IframeChatPage() {
pendingRequestIdRef.current = data.requestId ?? null; pendingRequestIdRef.current = data.requestId ?? null;
handleSubmit({ text: submitText, files }, iframeContext); handleSubmit(
{ text: submitText, files },
iframeContext,
additionalKwargs ? { additionalKwargs } : undefined,
);
}; };
window.addEventListener("message", handleMessage); window.addEventListener("message", handleMessage);
@@ -248,6 +251,7 @@ export default function IframeChatPage() {
<ThreadContext.Provider value={{ thread, isMock }}> <ThreadContext.Provider value={{ thread, isMock }}>
<ChatBox threadId={threadId} disableArtifacts> <ChatBox threadId={threadId} disableArtifacts>
<div className="relative flex size-full min-h-0 justify-between overflow-hidden"> <div className="relative flex size-full min-h-0 justify-between overflow-hidden">
{/*
<header <header
className={cn( className={cn(
"absolute top-0 right-0 left-0 z-30 flex h-12 shrink-0 items-center border-b px-4", "absolute top-0 right-0 left-0 z-30 flex h-12 shrink-0 items-center border-b px-4",
@@ -267,11 +271,12 @@ export default function IframeChatPage() {
<ExportTrigger threadId={threadId} /> <ExportTrigger threadId={threadId} />
</div> </div>
</header> </header>
*/}
<main className="flex min-h-0 max-w-full grow flex-col overflow-hidden"> <main className="flex min-h-0 max-w-full grow flex-col overflow-hidden">
<div className="flex size-full min-w-0"> <div className="flex size-full min-w-0">
{!isLandingState && ( {!isLandingState && (
<MessageList <MessageList
className={cn("size-full", "pt-10")} className="size-full"
contentClassName="mx-0 max-w-full px-3 sm:px-4" contentClassName="mx-0 max-w-full px-3 sm:px-4"
threadId={threadId} threadId={threadId}
thread={thread} thread={thread}
@@ -32,11 +32,16 @@ test("parses iframe text, page context, and screenshot into a prompt message", (
assert.equal(result.submitText, [ assert.equal(result.submitText, [
"提取并翻译", "提取并翻译",
"<attached_image_priority>\nA screenshot image is attached for this message.\nUse the attached image as the primary source of truth.\nUse page context and text prompt only as supporting context.\nIf the image conflicts with page context or text, trust the image.\n</attached_image_priority>",
"<extension_prompt>\n提取图片中的文字并翻译成简体中文\n</extension_prompt>",
"<page_context>\n<title>\nUN News\n</title>\n\n<url>\nhttps://news.un.org/example\n</url>\n\n<content>\nBanning children from social media is not the answer.\n</content>\n</page_context>",
].join("\n\n")); ].join("\n\n"));
assert.deepEqual(result.iframeContext, { brainy_request_id: "iframe-123" }); assert.deepEqual(result.iframeContext, { brainy_request_id: "iframe-123" });
assert.equal(
result.additionalKwargs?.prompt_prefix,
[
"<attached_image_priority>\nA screenshot image is attached for this message.\nUse the attached image as the primary source of truth.\nUse page context and text prompt only as supporting context.\nIf the image conflicts with page context or text, trust the image.\n</attached_image_priority>",
"<extension_prompt>\n提取图片中的文字并翻译成简体中文\n</extension_prompt>",
"<page_context>\n<title>\nUN News\n</title>\n\n<url>\nhttps://news.un.org/example\n</url>\n\n<content>\nBanning children from social media is not the answer.\n</content>\n</page_context>",
].join("\n\n"),
);
assert.equal(result.files.length, 1); assert.equal(result.files.length, 1);
assert.equal(result.files[0]?.type, "file"); assert.equal(result.files[0]?.type, "file");
assert.equal(result.files[0]?.filename, "capture.png"); assert.equal(result.files[0]?.filename, "capture.png");
@@ -65,8 +70,9 @@ test("keeps screenshot-only iframe submissions in the conversation flow", () =>
}, },
}); });
assert.equal(result.submitText, "");
assert.equal( assert.equal(
result.submitText, result.additionalKwargs?.prompt_prefix,
"<attached_image_priority>\nA screenshot image is attached for this message.\nUse the attached image as the primary source of truth.\nUse page context and text prompt only as supporting context.\nIf the image conflicts with page context or text, trust the image.\n</attached_image_priority>", "<attached_image_priority>\nA screenshot image is attached for this message.\nUse the attached image as the primary source of truth.\nUse page context and text prompt only as supporting context.\nIf the image conflicts with page context or text, trust the image.\n</attached_image_priority>",
); );
assert.equal(result.files.length, 1); assert.equal(result.files.length, 1);
+17 -11
View File
@@ -45,6 +45,7 @@ export type ParsedBrainyChatSubmitMessage = {
submitText: string; submitText: string;
files: IframePromptInputFilePart[]; files: IframePromptInputFilePart[];
iframeContext?: Record<string, unknown>; iframeContext?: Record<string, unknown>;
additionalKwargs?: Record<string, unknown>;
}; };
const IMAGE_PRIORITY_INSTRUCTION = [ const IMAGE_PRIORITY_INSTRUCTION = [
@@ -137,30 +138,23 @@ function normalizePageContext(
: undefined; : undefined;
} }
export function buildIframeMessageText({ function buildIframePromptPrefix({
text,
prompt, prompt,
pageContext, pageContext,
hasAttachedImage = false, hasAttachedImage = false,
}: { }: {
text?: string;
prompt?: string; prompt?: string;
pageContext?: BrainyPageContext; pageContext?: BrainyPageContext;
hasAttachedImage?: boolean; hasAttachedImage?: boolean;
}) { }) {
const primaryText = trimToUndefined(text) || trimToUndefined(prompt) || "";
const sections: string[] = []; const sections: string[] = [];
if (primaryText) {
sections.push(primaryText);
}
if (hasAttachedImage) { if (hasAttachedImage) {
sections.push(IMAGE_PRIORITY_INSTRUCTION); sections.push(IMAGE_PRIORITY_INSTRUCTION);
} }
const normalizedPrompt = trimToUndefined(prompt); const normalizedPrompt = trimToUndefined(prompt);
if (normalizedPrompt && normalizedPrompt !== primaryText) { if (normalizedPrompt) {
sections.push( sections.push(
`<extension_prompt>\n${normalizedPrompt}\n</extension_prompt>`, `<extension_prompt>\n${normalizedPrompt}\n</extension_prompt>`,
); );
@@ -190,6 +184,17 @@ export function buildIframeMessageText({
return sections.join("\n\n"); return sections.join("\n\n");
} }
export function buildIframeMessageText({
text,
prompt,
}: {
text?: string;
prompt?: string;
}) {
const primaryText = trimToUndefined(text) || trimToUndefined(prompt) || "";
return primaryText;
}
function buildScreenshotFileParts( function buildScreenshotFileParts(
screenshot: BrainyScreenshot | undefined, screenshot: BrainyScreenshot | undefined,
): IframePromptInputFilePart[] { ): IframePromptInputFilePart[] {
@@ -249,8 +254,8 @@ export function parseBrainyChatSubmitMessage(
const prompt = trimToUndefined(data.payload?.prompt); const prompt = trimToUndefined(data.payload?.prompt);
const pageContext = normalizePageContext(data.payload?.pageContext); const pageContext = normalizePageContext(data.payload?.pageContext);
const files = buildScreenshotFileParts(data.payload?.screenshot); const files = buildScreenshotFileParts(data.payload?.screenshot);
const submitText = buildIframeMessageText({ const submitText = buildIframeMessageText({ text, prompt });
text, const promptPrefix = buildIframePromptPrefix({
prompt, prompt,
pageContext, pageContext,
hasAttachedImage: files.length > 0, hasAttachedImage: files.length > 0,
@@ -263,5 +268,6 @@ export function parseBrainyChatSubmitMessage(
...(requestId ...(requestId
? { iframeContext: { brainy_request_id: requestId } } ? { iframeContext: { brainy_request_id: requestId } }
: {}), : {}),
...(promptPrefix ? { additionalKwargs: { prompt_prefix: promptPrefix } } : {}),
}; };
} }