feat: Implement clipboard serialization/deserialization for MCP prompts
This commit is contained in:
parent
99d177d442
commit
770f993086
|
|
@ -104,11 +104,18 @@ export function formatMessageForClipboard(
|
|||
extras?: DatabaseMessageExtra[],
|
||||
asPlainText: boolean = false
|
||||
): string {
|
||||
// Filter only text attachments (TEXT type and legacy CONTEXT type)
|
||||
// Filter text-like attachments (TEXT, LEGACY_CONTEXT, and MCP_PROMPT types)
|
||||
const textAttachments =
|
||||
extras?.filter(
|
||||
(extra): extra is DatabaseMessageExtraTextFile | DatabaseMessageExtraLegacyContext =>
|
||||
extra.type === AttachmentType.TEXT || extra.type === AttachmentType.LEGACY_CONTEXT
|
||||
(
|
||||
extra
|
||||
): extra is
|
||||
| DatabaseMessageExtraTextFile
|
||||
| DatabaseMessageExtraLegacyContext
|
||||
| DatabaseMessageExtraMcpPrompt =>
|
||||
extra.type === AttachmentType.TEXT ||
|
||||
extra.type === AttachmentType.LEGACY_CONTEXT ||
|
||||
extra.type === AttachmentType.MCP_PROMPT
|
||||
) ?? [];
|
||||
|
||||
if (textAttachments.length === 0) {
|
||||
|
|
@ -123,11 +130,24 @@ export function formatMessageForClipboard(
|
|||
return parts.join('\n\n');
|
||||
}
|
||||
|
||||
const clipboardAttachments: ClipboardTextAttachment[] = textAttachments.map((att) => ({
|
||||
type: AttachmentType.TEXT,
|
||||
name: att.name,
|
||||
content: att.content
|
||||
}));
|
||||
const clipboardAttachments: ClipboardAttachment[] = textAttachments.map((att) => {
|
||||
if (att.type === AttachmentType.MCP_PROMPT) {
|
||||
const mcpAtt = att as DatabaseMessageExtraMcpPrompt;
|
||||
return {
|
||||
type: AttachmentType.MCP_PROMPT,
|
||||
name: mcpAtt.name,
|
||||
serverName: mcpAtt.serverName,
|
||||
promptName: mcpAtt.promptName,
|
||||
content: mcpAtt.content,
|
||||
arguments: mcpAtt.arguments
|
||||
} as ClipboardMcpPromptAttachment;
|
||||
}
|
||||
return {
|
||||
type: AttachmentType.TEXT,
|
||||
name: att.name,
|
||||
content: att.content
|
||||
} as ClipboardTextAttachment;
|
||||
});
|
||||
|
||||
return `${JSON.stringify(content)}\n${JSON.stringify(clipboardAttachments, null, 2)}`;
|
||||
}
|
||||
|
|
@ -142,7 +162,8 @@ export function formatMessageForClipboard(
|
|||
export function parseClipboardContent(clipboardText: string): ParsedClipboardContent {
|
||||
const defaultResult: ParsedClipboardContent = {
|
||||
message: clipboardText,
|
||||
textAttachments: []
|
||||
textAttachments: [],
|
||||
mcpPromptAttachments: []
|
||||
};
|
||||
|
||||
if (!clipboardText.startsWith('"')) {
|
||||
|
|
@ -184,17 +205,28 @@ export function parseClipboardContent(clipboardText: string): ParsedClipboardCon
|
|||
if (!remainingPart || !remainingPart.startsWith('[')) {
|
||||
return {
|
||||
message,
|
||||
textAttachments: []
|
||||
textAttachments: [],
|
||||
mcpPromptAttachments: []
|
||||
};
|
||||
}
|
||||
|
||||
const attachments = JSON.parse(remainingPart) as unknown[];
|
||||
|
||||
const validAttachments: ClipboardTextAttachment[] = [];
|
||||
const validTextAttachments: ClipboardTextAttachment[] = [];
|
||||
const validMcpPromptAttachments: ClipboardMcpPromptAttachment[] = [];
|
||||
|
||||
for (const att of attachments) {
|
||||
if (isValidTextAttachment(att)) {
|
||||
validAttachments.push({
|
||||
if (isValidMcpPromptAttachment(att)) {
|
||||
validMcpPromptAttachments.push({
|
||||
type: AttachmentType.MCP_PROMPT,
|
||||
name: att.name,
|
||||
serverName: att.serverName,
|
||||
promptName: att.promptName,
|
||||
content: att.content,
|
||||
arguments: att.arguments
|
||||
});
|
||||
} else if (isValidTextAttachment(att)) {
|
||||
validTextAttachments.push({
|
||||
type: AttachmentType.TEXT,
|
||||
name: att.name,
|
||||
content: att.content
|
||||
|
|
@ -204,13 +236,42 @@ export function parseClipboardContent(clipboardText: string): ParsedClipboardCon
|
|||
|
||||
return {
|
||||
message,
|
||||
textAttachments: validAttachments
|
||||
textAttachments: validTextAttachments,
|
||||
mcpPromptAttachments: validMcpPromptAttachments
|
||||
};
|
||||
} catch {
|
||||
return defaultResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard to validate an MCP prompt attachment object
|
||||
* @param obj The object to validate
|
||||
* @returns true if the object is a valid MCP prompt attachment
|
||||
*/
|
||||
function isValidMcpPromptAttachment(obj: unknown): obj is {
|
||||
type: string;
|
||||
name: string;
|
||||
serverName: string;
|
||||
promptName: string;
|
||||
content: string;
|
||||
arguments?: Record<string, string>;
|
||||
} {
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const record = obj as Record<string, unknown>;
|
||||
|
||||
return (
|
||||
(record.type === AttachmentType.MCP_PROMPT || record.type === 'MCP_PROMPT') &&
|
||||
typeof record.name === 'string' &&
|
||||
typeof record.serverName === 'string' &&
|
||||
typeof record.promptName === 'string' &&
|
||||
typeof record.content === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard to validate a text attachment object
|
||||
* @param obj The object to validate
|
||||
|
|
@ -243,5 +304,5 @@ export function hasClipboardAttachments(clipboardText: string): boolean {
|
|||
}
|
||||
|
||||
const parsed = parseClipboardContent(clipboardText);
|
||||
return parsed.textAttachments.length > 0;
|
||||
return parsed.textAttachments.length > 0 || parsed.mcpPromptAttachments.length > 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue