mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-05 08:54:23 +08:00
feat(agent): add site tools support for canvas project listing and media generation
This commit is contained in:
@@ -17,6 +17,7 @@ import { formatBytes, formatDuration, getDataUrlByteSize, readImageMeta } from "
|
||||
import { requestEdit, requestGeneration } from "@/services/api/image";
|
||||
import { deleteStoredImages, resolveImageUrl, uploadImage } from "@/services/image-storage";
|
||||
import { useAssetStore } from "@/stores/use-asset-store";
|
||||
import { useWorkbenchAgentStore } from "@/stores/use-workbench-agent-store";
|
||||
import type { ReferenceImage } from "@/types/image";
|
||||
|
||||
type GeneratedImage = {
|
||||
@@ -88,6 +89,10 @@ export default function ImagePage() {
|
||||
const [selectedLogIds, setSelectedLogIds] = useState<string[]>([]);
|
||||
const [previewLog, setPreviewLog] = useState<GenerationLog | null>(null);
|
||||
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
||||
const [autoRunToken, setAutoRunToken] = useState(0);
|
||||
const imageCommand = useWorkbenchAgentStore((state) => state.imageCommand);
|
||||
const clearImageCommand = useWorkbenchAgentStore((state) => state.clearImageCommand);
|
||||
const processedCommandRef = useRef(0);
|
||||
|
||||
const model = effectiveConfig.imageModel || effectiveConfig.model;
|
||||
const canGenerate = Boolean(prompt.trim());
|
||||
@@ -191,6 +196,21 @@ export default function ImagePage() {
|
||||
}
|
||||
};
|
||||
|
||||
// 响应 Agent 面板下发的生图命令:填入提示词,并按需自动触发生成。
|
||||
useEffect(() => {
|
||||
if (!imageCommand || imageCommand.nonce === processedCommandRef.current) return;
|
||||
processedCommandRef.current = imageCommand.nonce;
|
||||
clearImageCommand();
|
||||
if (typeof imageCommand.prompt === "string") setPrompt(imageCommand.prompt);
|
||||
if (imageCommand.run && !running) setAutoRunToken((value) => value + 1);
|
||||
}, [imageCommand, clearImageCommand, running]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!autoRunToken) return;
|
||||
void generate();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [autoRunToken]);
|
||||
|
||||
const downloadImage = (image: GeneratedImage, index: number) => {
|
||||
saveAs(image.dataUrl, `image-${index + 1}.png`);
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ import { deleteStoredMedia, resolveMediaUrl, uploadMediaFile } from "@/services/
|
||||
import { resolveImageUrl, uploadImage } from "@/services/image-storage";
|
||||
import { createVideoGenerationTask, pollVideoGenerationTask, storeGeneratedVideo, type VideoGenerationTask } from "@/services/api/video";
|
||||
import { useAssetStore } from "@/stores/use-asset-store";
|
||||
import { useWorkbenchAgentStore } from "@/stores/use-workbench-agent-store";
|
||||
import { modelOptionLabel, useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
|
||||
import { useThemeStore } from "@/stores/use-theme-store";
|
||||
import type { ReferenceImage } from "@/types/image";
|
||||
@@ -93,6 +94,10 @@ export default function VideoPage() {
|
||||
const [selectedLogIds, setSelectedLogIds] = useState<string[]>([]);
|
||||
const [previewLog, setPreviewLog] = useState<GenerationLog | null>(null);
|
||||
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
||||
const [autoRunToken, setAutoRunToken] = useState(0);
|
||||
const videoCommand = useWorkbenchAgentStore((state) => state.videoCommand);
|
||||
const clearVideoCommand = useWorkbenchAgentStore((state) => state.clearVideoCommand);
|
||||
const processedCommandRef = useRef(0);
|
||||
|
||||
const model = effectiveConfig.videoModel || effectiveConfig.model;
|
||||
const canGenerate = Boolean(prompt.trim());
|
||||
@@ -187,6 +192,21 @@ export default function VideoPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// 响应 Agent 面板下发的视频命令:填入提示词,并按需自动触发生成。
|
||||
useEffect(() => {
|
||||
if (!videoCommand || videoCommand.nonce === processedCommandRef.current) return;
|
||||
processedCommandRef.current = videoCommand.nonce;
|
||||
clearVideoCommand();
|
||||
if (typeof videoCommand.prompt === "string") setPrompt(videoCommand.prompt);
|
||||
if (videoCommand.run && !running) setAutoRunToken((value) => value + 1);
|
||||
}, [videoCommand, clearVideoCommand, running]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!autoRunToken) return;
|
||||
void generate();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [autoRunToken]);
|
||||
|
||||
const buildRequestSnapshot = () => {
|
||||
const text = prompt.trim();
|
||||
if (!text) {
|
||||
|
||||
Reference in New Issue
Block a user