Filter detected sellers from conversations

This commit is contained in:
jjbrunton committed 2026-08-09 14:38:03 +01:00
1 parent d5ebdec076
commit 92c54feedc
14 files changed
+97 -7

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ export interface ActiveChat {
messages?: ChatMessage[];
originMessage?: string;
hasReceivedImages?: boolean;
sellerDetected?: boolean;
}
/**
+1
View File
@@ -126,6 +126,7 @@ export class ConversationAutomationService {
const sellerSignal = findSellerSignal(latest.text, [...this.sellerKeywords], [...this.sellerDomains]);
if (sellerSignal) {
state.sellerDetected = true;
return this.finish(
conversation,
conversationId,
+7
View File
@@ -28,6 +28,8 @@ export interface ConversationPersona {
export interface ConversationState {
persona: ConversationPersona;
boundaries: string[];
/** Durable marker set when configured seller or upsell signals are detected. */
sellerDetected: boolean;
/** Kept for backwards compatibility with state written before automation. */
askedForMedia: boolean;
topics: string[];
@@ -125,6 +127,7 @@ export function buildConversationState(messages: ConversationMessage[]): Convers
return {
persona,
boundaries,
sellerDetected: false,
askedForMedia: /\b(send|show|share)\b[^.\n]{0,40}\b(pic|pics|photo|photos|selfie|selfies|video|videos|nudes?)\b/i.test(ownText),
topics,
automation: createConversationAutomationState(),
@@ -178,6 +181,7 @@ export function mergeConversationState(
: saved.persona.relationshipStatus,
},
boundaries: [...new Set([...saved.boundaries, ...observed.boundaries])],
sellerDetected: saved.sellerDetected || observed.sellerDetected,
askedForMedia: saved.askedForMedia || observed.askedForMedia,
topics: [...new Set([...saved.topics, ...observed.topics])],
automation: saved.automation,
@@ -243,6 +247,9 @@ export function parseConversationState(value: string | null | undefined): Conver
: 'unspecified',
},
boundaries: parsed.boundaries.filter((value): value is string => typeof value === 'string'),
sellerDetected: typeof parsed.sellerDetected === 'boolean'
? parsed.sellerDetected
: automation.handoffReason?.startsWith('Potential upsell detected') === true,
askedForMedia: parsed.askedForMedia,
topics: parsed.topics.filter((value): value is string => typeof value === 'string'),
automation,
+14 -3
View File
@@ -66,6 +66,16 @@ export function createConversationsRouter(ctx: WebContext): Router {
return { messages, state, intent: chooseConversationIntent(messages, state, requestedIntent) };
}
function withSellerMarker(
conversation: OwnedActiveChat,
stateRepo = ctx.services.conversationState,
): OwnedActiveChat {
if (!conversation.roomId) return conversation;
return stateRepo?.get(conversation.roomId)?.sellerDetected === true
? { ...conversation, sellerDetected: true }
: conversation;
}
router.get('/conversations', async (req, res) => {
if (!ctx.services.chat) {
res.status(503).json({ error: 'Chat service not initialized' });
@@ -76,12 +86,12 @@ export function createConversationsRouter(ctx: WebContext): Router {
const conversations: OwnedActiveChat[] = runtimes.length > 0
? (await Promise.all(runtimes.map(async (snapshot) => {
const runtime = ctx.services.accountRuntimes!.get(snapshot.accountId)!;
return (await runtime.resources.chatService.getCachedConversations()).map((conversation) => ({
return (await runtime.resources.chatService.getCachedConversations()).map((conversation) => withSellerMarker({
...conversation,
owner: { accountId: snapshot.accountId, redditUsername: snapshot.redditUsername },
}));
}, runtime.resources.conversationStateRepo));
}))).flat()
: await ctx.services.chat.getCachedConversations();
: (await ctx.services.chat.getCachedConversations()).map((conversation) => withSellerMarker(conversation));
if (req.query.includeImageMetadata !== 'true') {
res.json(conversations.map((conversation) => ({ ...conversation, owner: conversation.owner ?? currentOwner() })));
return;
@@ -228,6 +238,7 @@ export function createConversationsRouter(ctx: WebContext): Router {
res.json({
...conversation,
sellerDetected: intelligence.state.sellerDetected,
...(annotatedMessages ? { messages: annotatedMessages } : {}),
owner: resolved.runtime
? { accountId: resolved.runtime.session.accountId, redditUsername: resolved.runtime.session.redditUsername }