fix: preserve selected canvas slot context
This commit is contained in:
parent
d548e31063
commit
8c6bd2ad03
@ -115,7 +115,10 @@ import {
|
||||
shouldDeferCanvasAgentViewOperation,
|
||||
} from "@/lib/canvas/agent-view-interaction-guard";
|
||||
import { getCanvasAgentOperationErrorMessage } from "@/lib/canvas/agent-operation-errors";
|
||||
import { shouldBypassCanvasImagePointsPrecheckForAgentControl } from "@/lib/canvas/agent-client-intent";
|
||||
import {
|
||||
shouldBypassCanvasImagePointsPrecheckForAgentControl,
|
||||
shouldPreserveCanvasAgentSlotOnlyContext,
|
||||
} from "@/lib/canvas/agent-client-intent";
|
||||
import { getCanvasSkillIconComponent } from "@/components/canvas/canvas-skill-icons";
|
||||
import { ImageParamsBar, type ImageGenerationParams } from "@/components/image-params-bar";
|
||||
import { VideoParamsBar, type VideoGenerationParams } from "@/components/video-params-bar";
|
||||
@ -5941,6 +5944,20 @@ export function CanvasChatPanel({
|
||||
isDetailGenerationMode,
|
||||
agentEnabled: effectiveAgentEnabled,
|
||||
});
|
||||
const selectedAgentSlotCountForContext = nodes.filter(
|
||||
(node) => String(node.type) === "agent-slot" && selectedNodeIdSet.has(node.id)
|
||||
).length;
|
||||
const shouldPreserveSelectedSlotContext =
|
||||
shouldPreserveCanvasAgentSlotOnlyContext({
|
||||
text: input,
|
||||
activeComposerMode: effectiveComposerMode,
|
||||
selectedAgentSlotCount: selectedAgentSlotCountForContext,
|
||||
attachmentCount: attachments.length,
|
||||
hasSkillTag: Boolean(selectedSkillTag),
|
||||
hasWorkflowContext,
|
||||
isDetailGenerationMode,
|
||||
agentEnabled: effectiveAgentEnabled,
|
||||
});
|
||||
const selectedImageNodesForContext = Array.from(
|
||||
new Map(
|
||||
[
|
||||
@ -5955,7 +5972,8 @@ export function CanvasChatPanel({
|
||||
if (
|
||||
shouldIsolateDirectModeContext &&
|
||||
selectedImageNodesForContext.length === 0 &&
|
||||
!shouldPreserveCanvasControlContext
|
||||
!shouldPreserveCanvasControlContext &&
|
||||
!shouldPreserveSelectedSlotContext
|
||||
) {
|
||||
generationAnchorNodesRef.current = [];
|
||||
return undefined;
|
||||
|
||||
@ -15,6 +15,9 @@ const CANVAS_AGENT_VIEW_CONTROL_REGEX =
|
||||
const CANVAS_AGENT_SLOT_MANAGEMENT_REGEX =
|
||||
/(新建|创建|添加|插入|放置|加一个|建一个).{0,10}(图片|视频|ui|画面|空)?(槽位|slot|空框|占位框|框)|(槽位|slot|空框|占位框).{0,10}(新建|创建|添加|插入|放置)/i;
|
||||
|
||||
const CANVAS_AGENT_SLOT_FILL_CONTEXT_REGEX =
|
||||
/(填充|生成|生图|出图|画一张|来一张|做一张|做图|做视频|视频生成|生成视频|放到|放进|放入|在这里|这个空框|这个槽位|选中槽位|槽位|slot|空框|占位框)/i;
|
||||
|
||||
const CANVAS_AGENT_STRUCTURAL_OPERATION_REGEX =
|
||||
/(删除|移除|移动|挪动|排列|对齐|重命名|改名|连线|连接|添加批注|批注|备注|标注|添加文字|文字节点|更新文字|修改文字).{0,14}(画布|节点|对象|元素|图片|图|文本|便签|选中|这些|它们|这个)|(画布|节点|对象|元素|图片|图|文本|便签|选中|这些|它们|这个).{0,14}(删除|移除|移动|挪动|排列|对齐|重命名|改名|连线|连接|添加批注|批注|备注|标注|添加文字|文字节点|更新文字|修改文字)/i;
|
||||
|
||||
@ -29,6 +32,12 @@ export function hasCanvasAgentNonGenerativeControlIntent(value: unknown) {
|
||||
);
|
||||
}
|
||||
|
||||
export function hasCanvasAgentSlotFillContextIntent(value: unknown) {
|
||||
const text = normalizeCanvasAgentClientIntentText(value);
|
||||
if (!text) return false;
|
||||
return CANVAS_AGENT_SLOT_FILL_CONTEXT_REGEX.test(text);
|
||||
}
|
||||
|
||||
export function shouldBypassCanvasImagePointsPrecheckForAgentControl(params: {
|
||||
text: unknown;
|
||||
activeComposerMode?: string | null;
|
||||
@ -46,3 +55,23 @@ export function shouldBypassCanvasImagePointsPrecheckForAgentControl(params: {
|
||||
}
|
||||
return hasCanvasAgentNonGenerativeControlIntent(params.text);
|
||||
}
|
||||
|
||||
export function shouldPreserveCanvasAgentSlotOnlyContext(params: {
|
||||
text: unknown;
|
||||
activeComposerMode?: string | null;
|
||||
selectedAgentSlotCount?: number;
|
||||
attachmentCount?: number;
|
||||
hasSkillTag?: boolean;
|
||||
hasWorkflowContext?: boolean;
|
||||
isDetailGenerationMode?: boolean;
|
||||
agentEnabled?: boolean;
|
||||
}) {
|
||||
if ((params.selectedAgentSlotCount || 0) <= 0) return false;
|
||||
if (params.activeComposerMode === "agent") return true;
|
||||
if (params.agentEnabled === false) return false;
|
||||
if ((params.attachmentCount || 0) > 0) return false;
|
||||
if (params.hasSkillTag || params.hasWorkflowContext || params.isDetailGenerationMode) {
|
||||
return false;
|
||||
}
|
||||
return hasCanvasAgentSlotFillContextIntent(params.text);
|
||||
}
|
||||
|
||||
@ -116,7 +116,9 @@ import {
|
||||
} from "@/lib/canvas/canvas-save-request";
|
||||
import { canvasService } from "@/services/canvas";
|
||||
import {
|
||||
hasCanvasAgentSlotFillContextIntent,
|
||||
hasCanvasAgentNonGenerativeControlIntent,
|
||||
shouldPreserveCanvasAgentSlotOnlyContext,
|
||||
shouldBypassCanvasImagePointsPrecheckForAgentControl,
|
||||
} from "@/lib/canvas/agent-client-intent";
|
||||
import {
|
||||
@ -312,6 +314,46 @@ test.describe("canvas chat pure helpers", () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("preserves selected slot-only canvas context for fill and generation intents", () => {
|
||||
expect(hasCanvasAgentSlotFillContextIntent("在这里生成一张主图")).toBe(true);
|
||||
expect(hasCanvasAgentSlotFillContextIntent("填充这个槽位")).toBe(true);
|
||||
expect(hasCanvasAgentSlotFillContextIntent("普通聊天")).toBe(false);
|
||||
|
||||
expect(
|
||||
shouldPreserveCanvasAgentSlotOnlyContext({
|
||||
text: "在这里生成一张主图",
|
||||
activeComposerMode: "image",
|
||||
selectedAgentSlotCount: 1,
|
||||
agentEnabled: true,
|
||||
})
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldPreserveCanvasAgentSlotOnlyContext({
|
||||
text: "生成一张主图",
|
||||
activeComposerMode: "image",
|
||||
selectedAgentSlotCount: 0,
|
||||
agentEnabled: true,
|
||||
})
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldPreserveCanvasAgentSlotOnlyContext({
|
||||
text: "在这里生成一张主图",
|
||||
activeComposerMode: "image",
|
||||
selectedAgentSlotCount: 1,
|
||||
attachmentCount: 1,
|
||||
agentEnabled: true,
|
||||
})
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldPreserveCanvasAgentSlotOnlyContext({
|
||||
text: "任意 agent 模式文本",
|
||||
activeComposerMode: "agent",
|
||||
selectedAgentSlotCount: 1,
|
||||
agentEnabled: false,
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("rejects stale autosave bases without blocking fresh or missing revisions", () => {
|
||||
const currentUpdatedAt = new Date("2026-06-22T00:00:05.500Z");
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user