Fix NSFW reply refusals and media offers

This commit is contained in:
Jamie Brunton committed 2026-08-14 08:59:07 +01:00
1 parent e9a4c965ee
commit 6b2e1bc380
11 files changed
+161 -22

No files matched your search

+32 -5
View File
@@ -17,8 +17,8 @@ function harness(
},
beforeSendLoader?: (conversationId: string, observed: ActiveChat) => Promise<ActiveChat | undefined>,
mediaExchange?: {
detect(conversationId: string, text: string): string | null;
handle(conversationId: string, incomingKey: string, text: string): Promise<object>;
detect(conversationId: string, text: string, previousSelfText?: string): string | null;
handle(conversationId: string, incomingKey: string, text: string, previousSelfText?: string): Promise<object>;
getOutboundAttribution?(conversationId: string): { eventIds: string[]; texts: string[] };
},
options?: ConversationAutomationOptions,
@@ -102,11 +102,38 @@ describe('conversation automation', () => {
expect(result?.kind).toBe('sent');
expect(fixture.rateLimiter.throttle).toHaveBeenCalledOnce();
expect(mediaExchange.handle).toHaveBeenCalledWith('room-alice', 'in-1', 'got any pics?');
expect(mediaExchange.detect).toHaveBeenCalledWith('room-alice', 'got any pics?', 'hello');
expect(mediaExchange.handle).toHaveBeenCalledWith('room-alice', 'in-1', 'got any pics?', 'hello');
expect(fixture.ai.generateReply).not.toHaveBeenCalled();
expect(fixture.getSaved()).toMatchObject({ askedForMedia: true, automation: { turnsUsed: 0, status: 'active' } });
});
it('passes a recipient acceptance and the preceding bot media offer to the exchange path', async () => {
const mediaExchange = {
detect: vi.fn((_room: string, text: string, previous?: string) => (
text === 'yes please' && previous === 'Want me to send you a pic?' ? 'generic' : null
)),
handle: vi.fn().mockResolvedValue({ kind: 'sent', assetId: 'asset-one', requestKind: 'generic' }),
};
const fixture = harness([], [], 0, { mode: 'r4r', maxAutomatedTurns: 5 }, undefined, mediaExchange);
const conversation = incoming(1, 'yes please');
conversation.messages[0].text = 'Want me to send you a pic?';
fixture.openers.getByChatRoomId.mockReturnValue({
sentAt: 0,
subreddit: 'r4r',
message: 'Want me to send you a pic?',
});
await expect(fixture.service.processConversation(conversation)).resolves.toMatchObject({ kind: 'sent' });
expect(mediaExchange.detect).toHaveBeenCalledWith(
'room-alice', 'yes please', 'Want me to send you a pic?',
);
expect(mediaExchange.handle).toHaveBeenCalledWith(
'room-alice', 'in-1', 'yes please', 'Want me to send you a pic?',
);
expect(fixture.ai.generateReply).not.toHaveBeenCalled();
});
it('allows only one autonomous media request and then hands off', async () => {
const { service, chat, getSaved } = harness();
@@ -671,7 +698,7 @@ describe('conversation automation', () => {
expect(ai.generateMediaAsk).not.toHaveBeenCalled();
expect(chat.sendChatMessage).toHaveBeenCalledTimes(2);
expect(getSaved()?.automation).toMatchObject({
policyMode: 'r4r', policyVersion: 3, maxAutomatedTurns: 2, turnsUsed: 2,
policyMode: 'r4r', policyVersion: 4, maxAutomatedTurns: 2, turnsUsed: 2,
});
expect(getSaved()?.askedForMedia).toBe(false);
});
@@ -776,7 +803,7 @@ describe('conversation automation', () => {
expect(fixture.getSaved()?.askedForMedia).toBe(true);
expect(fixture.getSaved()?.automation).toMatchObject({
policyMode: 'r4r-media',
policyVersion: 3,
policyVersion: 4,
rapportTurnsBeforeMediaAsk: 2,
hybridPhase: 'post-media-ask',
turnsUsed: 4,