Add hybrid R4R media conversation mode

This commit is contained in:
jjbrunton committed 2026-08-09 11:45:45 +01:00
1 parent 927636ec8b
commit b73e305cf3
15 files changed
+357 -35

No files matched your search

+30
View File
@@ -5,6 +5,7 @@ import type { AiUsageRecordInput, AiUsageOutcome } from '../database/ai-usage-re
import {
formatConversationAsUntrustedData,
isSafeConversationReply,
isSafeHybridMediaAsk,
type ConversationIntent,
type ConversationState,
} from '../services/conversation-state.js';
@@ -377,6 +378,35 @@ Just write the message, nothing else.`;
}
}
async generateR4RMediaAsk(
conversationHistory: { sender: string; text: string; isSelf: boolean }[],
username: string,
state: ConversationState,
): Promise<string> {
try {
this.logger.debug(`Generating one-time R4R media ask for conversation with ${username}...`);
const intent: ConversationIntent = {
kind: 'media-ask',
reason: 'one optional image invitation after reciprocal rapport',
};
const prompt = this.buildConversationPrompt(conversationHistory, username, state, intent);
const message = await this.generateTextWithFallback('generateR4RMediaAsk', {
system: prompt.system,
user: `${prompt.user}\n\nWrite the single image invitation for this conversation. Acknowledge or answer their latest message first, then naturally ask whether they would be comfortable sharing one ordinary selfie, photo, or short video. Make it explicitly optional and easy to decline. Do not ask for nudity, explicit or sexual media, proof, contact details, or a meeting. Do not pressure, dare, challenge, bargain, guilt, or imply that you will ask again.`,
}, {
max_tokens: 300,
temperature: 0.85,
});
if (!isSafeHybridMediaAsk(message)) {
throw new Error('Generated R4R media ask failed hybrid output safeguards');
}
return message;
} catch (error) {
this.logger.error('R4R media-ask generation failed:', error);
throw error;
}
}
/**
* Check if message content contains upsell/spam keywords (OnlyFans, selling, etc.)
*/