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