feat: automate bounded image-sharing conversations

This commit is contained in:
jjbrunton committed 2026-08-08 23:10:52 +01:00
1 parent dcf57273e2
commit 3beb8aada2
15 files changed
+477 -19

No files matched your search

+18 -11
View File
@@ -320,30 +320,37 @@ ${this.config.openrouter.imageAnalysisPrompt}`;
.map(msg => `${msg.isSelf ? 'You' : msg.sender}: ${msg.text}`)
.join('\n');
const turnNumber = Math.min(3, (state?.automation.turnsUsed ?? 0) + 1);
const turnGuidance = turnNumber === 1
? 'Make this a light, optional invitation that follows naturally from what they just said.'
: turnNumber === 2
? 'Be a little clearer that you would enjoy seeing them, while keeping the invitation easy to decline.'
: 'Make one final, direct but low-pressure invitation. Do not imply that you will ask again.';
const legacyPrompt = `You are helping continue a Reddit chat conversation. Here is the conversation so far:
${historyText}
Write the next message to send to ${username}. The goal of THIS message is to playfully nudge them into sending a pic or video OF THEMSELVES — their body, face, outfit, what they look like right now, a selfie. NOT a pic of an object, place, food, pet, or scenery. Keep the same tone and style as the previous messages from "You" — casual, flirty, direct, never robotic. Keep it to 1-3 sentences. You can reference something they just said as a hook, but the ask itself must be about seeing THEM.
Write the next message to send to ${username}. This is automated conversation turn ${turnNumber} of 3. Acknowledge or answer their latest message first, then naturally invite them to share an image of themselves if they are comfortable. Keep the same vocabulary, punctuation, message length, and energy as the previous messages from "You". Keep it to 1-3 short sentences.
Pick ONE technique that fits the current vibe — don't combine them, don't telegraph that you're using one:
- Playful dare ("bet you won't send a selfie right now")
- Direct ask for them ("send me a pic", "lemme see you", "selfie?")
- Tease about how they look / sound ("now I have to see what you look like")
- Curiosity hook about their appearance ("ok I need a face to picture here")
- Compliment + ask ("you sound hot, prove it 😏", "show me that smile")
- Outfit / "what are you wearing" angle ("send a pic of the fit")
TURN GUIDANCE: ${turnGuidance}
Use one natural angle that fits the conversation: a selfie, a pic or video of them, their smile, their outfit, or what they look like right now. Vary the wording from any earlier image invitation.
DO NOT:
- Sound like an AI or use formal language
- Use words like "captivating", "alluring", "exquisite", "radiant"
- Beg, sound desperate, or repeat an ask they already declined
- Beg, pressure, guilt, challenge, dare, demand proof, or repeat an ask they declined
- Ask for nudity or explicit content
- Write long elaborate sentences
- Mention OnlyFans, paying, or anything transactional
Just write the message, nothing else.`;
const prompt = this.buildConversationPrompt(conversationHistory, username, state, intent);
const effectiveIntent = intent ?? {
kind: 'media-ask' as const,
reason: `image-sharing turn ${turnNumber} of 3`,
};
const prompt = this.buildConversationPrompt(conversationHistory, username, state, effectiveIntent);
const message = await this.generateTextWithFallback('generateMediaAsk', {
system: prompt.system,
user: `${prompt.user}\n\nMEDIA-ASK REQUIREMENTS (apply only if the intent is media-ask):\n${legacyPrompt}`,
@@ -443,7 +450,7 @@ Just write the message, nothing else.`;
? `Age: ${state.persona.age ?? 'not established'}\nLocation: ${state.persona.location ?? 'not established'}\nRelationship status: ${state.persona.relationshipStatus}`
: 'No durable persona facts have been established.';
const memory = state
? `Boundaries: ${state.boundaries.join('; ') || 'none recorded'}\nPrevious media ask: ${state.askedForMedia ? 'yes' : 'no'}\nTopics: ${state.topics.join(', ') || 'none recorded'}`
? `Boundaries: ${state.boundaries.join('; ') || 'none recorded'}\nPrevious media ask: ${state.askedForMedia ? 'yes' : 'no'}\nAutomated turns used: ${state.automation.turnsUsed} of 3\nTopics: ${state.topics.join(', ') || 'none recorded'}`
: 'No durable conversation state has been established.';
const selectedIntent = intent ?? { kind: 'reciprocate', reason: 'acknowledge their message before advancing the conversation' };
return {