From e857815d79cd196b0d4aa2c6dce141bd09f88d42 Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Sun, 31 May 2026 02:13:40 +0000 Subject: [PATCH] feat(web): paste chips trail the typed message text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 ` rather than `` then the command. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/web/src/lib/attachments.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/web/src/lib/attachments.ts b/apps/web/src/lib/attachments.ts index af06c5c..264448f 100644 --- a/apps/web/src/lib/attachments.ts +++ b/apps/web/src/lib/attachments.ts @@ -56,19 +56,26 @@ export function inferLanguage(filename: string): string | null { export function flattenToMessage(attachments: Attachment[], text: string): string { 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 ``` fence or provenance header. The chip only exists to keep the textarea - // tidy while composing; on send it should be exactly what the user pasted. + // Pasted text is raw context, not code from a file — insert it verbatim with no + // ``` fence or provenance header. It trails the typed text with a leading space + // so a leading slash command / prompt stays first and the paste reads as its + // 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') { - return a.content; + pasteBlocks.push(a.content); + continue; } const fence = '```' + (a.language ?? ''); const header = a.kind === 'lines' ? `// from: ${a.filename}:${a.range?.[0] ?? '?'}-${a.range?.[1] ?? '?'}` : `// from: ${a.filename}`; - return `${fence}\n${header}\n${a.content}\n\`\`\``; - }); - return [...blocks, text].filter(Boolean).join('\n\n'); + fencedBlocks.push(`${fence}\n${header}\n${a.content}\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'); }