66a8b7f597
* 补全完整的工具参数 * 调整提示词应对一些bad case * 把attachment的名称/描述纳入上下文 Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/101 Co-authored-by: 王德宇 <kvtodev@outlook.com> Co-committed-by: 王德宇 <kvtodev@outlook.com>
218 lines
5.9 KiB
TypeScript
218 lines
5.9 KiB
TypeScript
// 画布Agent对话契约:会话元数据存 SpacetimeDB,消息正文整体存 OSS(editor-agent/{conversationId}.json)。
|
||
|
||
export const EDITOR_AGENT_MAX_ATTACHMENTS = 9;
|
||
export const EDITOR_AGENT_ATTACHMENT_LABEL_MAX_CODE_POINTS = 24;
|
||
export const EDITOR_AGENT_ERROR_MESSAGE_PREFIX = 'ERROR ';
|
||
|
||
export type EditorAgentMessageRole = 'user' | 'assistant' | 'system';
|
||
|
||
export type EditorAgentToolCallStatus =
|
||
'not_completed' | 'completed' | 'failed' | 'cancelled';
|
||
|
||
export type EditorAgentAttachmentSource = 'canvas_resource' | 'library_asset';
|
||
|
||
function isUnsafeEditorAgentAttachmentLabelCharacter(character: string) {
|
||
const codePoint = character.codePointAt(0) ?? 0;
|
||
const isControlCharacter =
|
||
codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
|
||
const isAsciiPunctuation =
|
||
(codePoint >= 0x21 && codePoint <= 0x2f) ||
|
||
(codePoint >= 0x3a && codePoint <= 0x40) ||
|
||
(codePoint >= 0x5b && codePoint <= 0x60) ||
|
||
(codePoint >= 0x7b && codePoint <= 0x7e);
|
||
const isUnsafeAsciiPunctuation =
|
||
isAsciiPunctuation &&
|
||
character !== '-' &&
|
||
character !== '_' &&
|
||
character !== '.';
|
||
return isControlCharacter || isUnsafeAsciiPunctuation;
|
||
}
|
||
|
||
function normalizeEditorAgentAttachmentLabel(
|
||
label: string | null | undefined,
|
||
fallback: string,
|
||
) {
|
||
const normalizeCandidate = (candidate: string | null | undefined) => {
|
||
const normalized: string[] = [];
|
||
let codePoints = 0;
|
||
let pendingSpace = false;
|
||
for (const character of candidate?.trim() ?? '') {
|
||
if (isUnsafeEditorAgentAttachmentLabelCharacter(character)) {
|
||
continue;
|
||
}
|
||
if (/\s/u.test(character)) {
|
||
pendingSpace = normalized.length > 0;
|
||
continue;
|
||
}
|
||
if (
|
||
pendingSpace &&
|
||
codePoints + 1 < EDITOR_AGENT_ATTACHMENT_LABEL_MAX_CODE_POINTS
|
||
) {
|
||
normalized.push(' ');
|
||
codePoints += 1;
|
||
}
|
||
pendingSpace = false;
|
||
if (codePoints >= EDITOR_AGENT_ATTACHMENT_LABEL_MAX_CODE_POINTS) {
|
||
break;
|
||
}
|
||
normalized.push(character);
|
||
codePoints += 1;
|
||
}
|
||
return normalized.join('').trim();
|
||
};
|
||
|
||
return normalizeCandidate(label) || normalizeCandidate(fallback) || '图片';
|
||
}
|
||
|
||
export interface EditorAgentAttachmentRef {
|
||
source: EditorAgentAttachmentSource;
|
||
referenceId: string;
|
||
objectKey?: string | null;
|
||
imageSrc: string;
|
||
thumbnailSrc?: string | null;
|
||
label?: string | null;
|
||
width?: number | null;
|
||
height?: number | null;
|
||
}
|
||
|
||
export function createEditorAgentAttachmentRef(
|
||
input: EditorAgentAttachmentRef,
|
||
fallbackLabel: string = input.referenceId,
|
||
) {
|
||
return {
|
||
...input,
|
||
label: normalizeEditorAgentAttachmentLabel(input.label, fallbackLabel),
|
||
};
|
||
}
|
||
|
||
export interface EditorAgentGeneratedImage {
|
||
resourceId?: string | null;
|
||
objectKey?: string | null;
|
||
assetObjectId?: string | null;
|
||
imageSrc: string;
|
||
thumbnailSrc?: string | null;
|
||
width?: number | null;
|
||
height?: number | null;
|
||
}
|
||
|
||
export interface EditorAgentGeneratedVideo {
|
||
resourceId?: string | null;
|
||
objectKey?: string | null;
|
||
assetObjectId?: string | null;
|
||
videoSrc: string;
|
||
thumbnailSrc?: string | null;
|
||
width?: number | null;
|
||
height?: number | null;
|
||
}
|
||
|
||
export interface EditorAgentGeneratedAudio {
|
||
resourceId?: string | null;
|
||
objectKey?: string | null;
|
||
assetObjectId?: string | null;
|
||
audioSrc: string;
|
||
}
|
||
|
||
export interface EditorAgentToolCallStringArg {
|
||
name: string;
|
||
label: string;
|
||
value: string;
|
||
}
|
||
|
||
export interface EditorAgentToolCallImageRef {
|
||
imageId: string;
|
||
imageSrc: string;
|
||
objectKey?: string | null;
|
||
thumbnailSrc?: string | null;
|
||
label?: string | null;
|
||
width?: number | null;
|
||
height?: number | null;
|
||
}
|
||
|
||
export interface EditorAgentToolCallImageArg {
|
||
name: string;
|
||
label: string;
|
||
refs: EditorAgentToolCallImageRef[];
|
||
}
|
||
|
||
export interface EditorAgentToolCallDisplayExtras {
|
||
priceMudPoints: number;
|
||
}
|
||
|
||
export interface EditorAgentToolCallDisplayArgs {
|
||
stringArgs: EditorAgentToolCallStringArg[];
|
||
imageArgs: EditorAgentToolCallImageArg[];
|
||
extras: EditorAgentToolCallDisplayExtras;
|
||
}
|
||
|
||
export interface EditorAgentToolCall {
|
||
toolName: string;
|
||
status: EditorAgentToolCallStatus;
|
||
args: unknown;
|
||
displayArgs: EditorAgentToolCallDisplayArgs;
|
||
externalJobId?: string | null;
|
||
images: EditorAgentGeneratedImage[];
|
||
// Older persisted conversation documents do not contain these media fields.
|
||
videos?: EditorAgentGeneratedVideo[];
|
||
audios?: EditorAgentGeneratedAudio[];
|
||
error?: string | null;
|
||
}
|
||
|
||
export interface EditorAgentMessage {
|
||
// Frontend must not use this to organize messages.
|
||
// It is an opaque backend locator for pending tool-call operations.
|
||
id: number;
|
||
// Present only on user messages created from a client send request.
|
||
clientMessageId?: string | null;
|
||
role: EditorAgentMessageRole;
|
||
text: string;
|
||
attachments: EditorAgentAttachmentRef[];
|
||
toolCall: EditorAgentToolCall | null;
|
||
createdAt: string;
|
||
}
|
||
|
||
export interface EditorAgentConversationSummary {
|
||
conversationId: string;
|
||
projectId: string;
|
||
title: string;
|
||
updatedAt: string;
|
||
}
|
||
|
||
export interface EditorAgentConversationDetail {
|
||
conversationId: string;
|
||
projectId: string;
|
||
title: string;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
messages: EditorAgentMessage[];
|
||
}
|
||
|
||
export interface EditorAgentConversationMessagesDocument {
|
||
version: number;
|
||
conversationId: string;
|
||
messages: EditorAgentMessage[];
|
||
}
|
||
|
||
export interface CreateEditorAgentConversationRequest {
|
||
title?: string | null;
|
||
}
|
||
|
||
export interface EditorAgentConversationListResponse {
|
||
conversations: EditorAgentConversationSummary[];
|
||
}
|
||
|
||
export interface EditorAgentConversationResponse {
|
||
conversation: EditorAgentConversationDetail;
|
||
}
|
||
|
||
export interface EditorAgentMessageRequest {
|
||
clientMessageId: string;
|
||
text: string;
|
||
attachments?: EditorAgentAttachmentRef[];
|
||
}
|
||
|
||
export interface EditorAgentMessageResponse {
|
||
conversation: EditorAgentConversationSummary;
|
||
deltaMessages: EditorAgentMessage[];
|
||
errorMessage: string | null;
|
||
}
|