| 728 | } |
| 729 | |
| 730 | func renderManualTitlePrompt( |
| 731 | conversationBlock string, |
| 732 | firstUserText string, |
| 733 | latestUserMsg string, |
| 734 | ) string { |
| 735 | var prompt strings.Builder |
| 736 | write := func(value string) { |
| 737 | _, _ = prompt.WriteString(value) |
| 738 | } |
| 739 | |
| 740 | write("Write a short title for this AI coding conversation.\n") |
| 741 | write("Populate the title field with the result.\n\n") |
| 742 | write("Primary user objective:\n<primary_objective>\n") |
| 743 | write(firstUserText) |
| 744 | write("\n</primary_objective>") |
| 745 | |
| 746 | if conversationBlock != "" { |
| 747 | write("\n\nConversation sample:\n<conversation_sample>\n") |
| 748 | write(conversationBlock) |
| 749 | write("\n</conversation_sample>") |
| 750 | } |
| 751 | |
| 752 | if strings.TrimSpace(latestUserMsg) != strings.TrimSpace(truncateRunes(firstUserText, maxLatestUserMessageRunes)) { |
| 753 | write("\n\nThe user's most recent message:\n<latest_message>\n") |
| 754 | write(latestUserMsg) |
| 755 | write("\n</latest_message>\n") |
| 756 | write("Note: Weight the overall conversation arc more heavily than just the latest message.") |
| 757 | } |
| 758 | |
| 759 | write("\n\nRequirements:\n") |
| 760 | write("- Return only the title text in 2-8 words.\n") |
| 761 | write("- Populate the title field only.\n") |
| 762 | write("- Do not answer the user or describe the title-writing task.\n") |
| 763 | write("- Preserve specific identifiers (PR numbers, repo names, file paths, function names, error messages).\n") |
| 764 | write("- If the conversation is short or vague, stay close to the user's wording.\n") |
| 765 | write("- Sentence case. No quotes, emoji, markdown, or trailing punctuation.\n") |
| 766 | return prompt.String() |
| 767 | } |
| 768 | |
| 769 | func generateManualTitle( |
| 770 | ctx context.Context, |