| 209 | 209 | | .trim(); |
| 210 | 210 | | } |
| 211 | 211 | | |
| 212 | + | /** A turn the harness starts itself, as a tag: `<command-name>`, `<task-notification>`, one with attributes. */ |
| 213 | + | const HARNESS_TAG = /^\s*<[a-z][\w-]*(?:\s[^>]*)?>/i; |
| 214 | + | |
| 212 | 215 | | /** |
| 213 | 216 | | * What a prompt is for, as a session's title: its first line or sentence, |
| 214 | 217 | | * without code blocks or markdown, whitespace collapsed, clipped at |
| ⋯ |
| 219 | 222 | | */ |
| 220 | 223 | | export function intentTitle(prompt) { |
| 221 | 224 | | let text = String(prompt ?? "").replace(/^\uFEFF/, ""); |
| 222 | | − | if (/^\s*\//.test(text) || /^\s*<[a-z][\w-]*>/i.test(text)) return null; |
| 225 | + | // What the harness pasted in or attached is not what the prompt is for: |
| 226 | + | // pasted text (Claude Code's <pasted_content id="…">…</pasted_content>) |
| 227 | + | // and image placeholders ([Image #1], [Image: source: …]) go first. |
| 228 | + | text = text |
| 229 | + | .replace(/<pasted_content\b[^>]*>[\s\S]*?(?:<\/pasted_content[^>]*>|$)/gi, "\n") |
| 230 | + | .replace(/\[Image(?: #\d+)?(?::[^\]\n]*)?\]/g, " "); |
| 231 | + | if (/^\s*\//.test(text) || HARNESS_TAG.test(text)) return null; |
| 223 | 232 | | text = text |
| 224 | 233 | | .replace(/```[\s\S]*?(```|$)/g, "\n") |
| 225 | 234 | | .replace(/~~~[\s\S]*?(~~~|$)/g, "\n") |