feat(web): paste chips trail the typed message text

flattenToMessage now places the typed text first and appends pasted-chip
content after it with a single leading space (file/line chips remain fenced
provenance blocks after that), instead of prepending all attachments. A
leading slash command therefore stays first and the paste reads as its
continuation — `/command <pasted>` rather than `<pasted>` then the command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 02:13:40 +00:00
parent 12d31a81a0
commit e857815d79

View File

@@ -56,19 +56,26 @@ export function inferLanguage(filename: string): string | null {
export function flattenToMessage(attachments: Attachment[], text: string): string { export function flattenToMessage(attachments: Attachment[], text: string): string {
if (attachments.length === 0) return text; if (attachments.length === 0) return text;
const blocks = attachments.map(a => { // Pasted text is raw context, not code from a file — insert it verbatim with no
// Pasted text is raw context, not code from a file — insert it verbatim with // ``` fence or provenance header. It trails the typed text with a leading space
// no ``` fence or provenance header. The chip only exists to keep the textarea // so a leading slash command / prompt stays first and the paste reads as its
// tidy while composing; on send it should be exactly what the user pasted. // continuation. File/line chips stay fenced provenance blocks, appended after.
const pasteBlocks: string[] = [];
const fencedBlocks: string[] = [];
for (const a of attachments) {
if (a.kind === 'paste') { if (a.kind === 'paste') {
return a.content; pasteBlocks.push(a.content);
continue;
} }
const fence = '```' + (a.language ?? ''); const fence = '```' + (a.language ?? '');
const header = const header =
a.kind === 'lines' a.kind === 'lines'
? `// from: ${a.filename}:${a.range?.[0] ?? '?'}-${a.range?.[1] ?? '?'}` ? `// from: ${a.filename}:${a.range?.[0] ?? '?'}-${a.range?.[1] ?? '?'}`
: `// from: ${a.filename}`; : `// from: ${a.filename}`;
return `${fence}\n${header}\n${a.content}\n\`\`\``; fencedBlocks.push(`${fence}\n${header}\n${a.content}\n\`\`\``);
}); }
return [...blocks, text].filter(Boolean).join('\n\n'); // Typed text + pasted content on the same logical line (space-joined), then
// any fenced file blocks as separate paragraphs.
const lead = [text, ...pasteBlocks].filter(Boolean).join(' ');
return [lead, ...fencedBlocks].filter(Boolean).join('\n\n');
} }