feat(agent-ui): add inline skill and canvas references
This commit is contained in:
@@ -2,6 +2,8 @@ import { imageReferenceLabel } from "@/lib/image-reference-prompt";
|
||||
import i18n from "@/i18n";
|
||||
import { seedanceReferenceLabel } from "@/lib/seedance-video";
|
||||
import { getNodeDefinition } from "@/lib/canvas/node-registry";
|
||||
import { getDataUrlByteSize, readImageMeta } from "@/lib/image-utils";
|
||||
import { imageToDataUrl } from "@/services/image-storage";
|
||||
import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "@/types/canvas";
|
||||
|
||||
export type CanvasResourceKind = "image" | "video" | "audio" | "text";
|
||||
@@ -21,6 +23,34 @@ export function buildNodeMentionReferences(node: CanvasNodeData, nodes: CanvasNo
|
||||
return labelResourceNodes(getMentionResourceNodes(node.id, nodes, connections), true);
|
||||
}
|
||||
|
||||
export function buildCanvasResourceReferences(nodes: CanvasNodeData[]) {
|
||||
return labelResourceNodes(nodes, true);
|
||||
}
|
||||
|
||||
export async function resolveCanvasReferenceImages(references: CanvasResourceReference[], nodes: CanvasNodeData[]) {
|
||||
const nodesById = new Map(nodes.map((node) => [node.id, node]));
|
||||
return Promise.all(references.filter((reference) => reference.kind === "image").map(async (reference) => {
|
||||
const node = nodesById.get(reference.nodeId);
|
||||
if (!node) throw new Error(i18n.t("agent.composer.mentions.resourceMissing", { title: reference.title }));
|
||||
const metadata = node.metadata;
|
||||
const dataUrl = await imageToDataUrl({ storageKey: metadata?.storageKey, url: reference.previewUrl });
|
||||
if (!dataUrl.startsWith("data:image/")) throw new Error(i18n.t("agent.composer.mentions.imageReadFailed", { title: reference.title }));
|
||||
const meta = metadata?.naturalWidth && metadata.naturalHeight
|
||||
? { width: metadata.naturalWidth, height: metadata.naturalHeight, mimeType: metadata.mimeType || dataUrl.match(/^data:([^;]+)/)?.[1] || "image/png" }
|
||||
: await readImageMeta(dataUrl);
|
||||
return {
|
||||
id: `canvas:${node.id}`,
|
||||
name: reference.title,
|
||||
type: metadata?.mimeType || meta.mimeType,
|
||||
size: metadata?.bytes || getDataUrlByteSize(dataUrl),
|
||||
width: meta.width,
|
||||
height: meta.height,
|
||||
url: reference.previewUrl || dataUrl,
|
||||
dataUrl,
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
export function getMentionResourceNodes(nodeId: string, nodes: CanvasNodeData[], connections: CanvasConnection[]) {
|
||||
const configInputs = getConnectedConfigResourceNodes(nodeId, nodes, connections);
|
||||
if (configInputs.length) return configInputs;
|
||||
@@ -56,6 +86,7 @@ function labelResourceNodes(nodes: CanvasNodeData[], active: boolean) {
|
||||
return nodes.flatMap((node): CanvasResourceReference[] => {
|
||||
const kind = resourceKind(node);
|
||||
if (!kind) return [];
|
||||
const resource = getNodeDefinition(node.type)?.resource?.(node);
|
||||
const index = counts[kind]++;
|
||||
const label = labelForKind(kind, index);
|
||||
return [
|
||||
@@ -65,7 +96,7 @@ function labelResourceNodes(nodes: CanvasNodeData[], active: boolean) {
|
||||
kind,
|
||||
label,
|
||||
title: node.title || label,
|
||||
previewUrl: node.metadata?.content,
|
||||
previewUrl: node.metadata?.content || resource?.url,
|
||||
text: resourceText(node),
|
||||
active,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user